我对嵌入式系统不是很有经验,我需要在LPCXpresso18S37上开发一个能够与Python脚本通信的程序,以便使用通用异步收发器和直接存储器访问发送和接收数据。我使用的是MCUXpresso集成开发环境和LPCOpen库。
通信基本上是一系列字节交换,其中Python脚本发送命令,MCU通过执行特定操作来响应命令。
例如:如果Python脚本发送命令"1",MCU会将其作为ack发送回来,然后等待接收16字节的明文,这将由Python脚本发送,依此类推……
这就是我的问题:当处于调试模式和单步执行指令时,程序的行为与预期一样:字节被正确地接收和发送,并存储在指定的内存中。
然而,每当我“全速”运行程序时,没有任何断点或步进指令,事情就变得奇怪,程序开始以一种我真的不能理解的方式运行:大多数发送或接收的数据似乎都丢失了。
我花了很多时间尝试调试,或者至少弄清楚发生了什么,但是,我承认,没有取得很大的成功……
我在没有中断的情况下使用DMA,因为每次都会充满一个不同的缓冲区。
我已经看到一些开发人员遇到了一些类似的问题,但我无法将解决方案转换为适合我的情况。
我很高兴地欢迎任何帮助或想法。提前谢谢你。
下面是有问题的代码:
#if defined (__USE_LPCOPEN)
#if defined(NO_BOARD_LIB)
#include "chip.h"
#else
#include "board.h"
#endif
#endif
#include <cr_section_macros.h>
uint8_t dmaChannelNumTx, dmaChannelNumRx;
FunctionalState isDMATx = ENABLE;
static void App_DMA_Init(void)
{
/* Initialize GPDMA controller */
Chip_GPDMA_Init(LPC_GPDMA);
}
static void App_DMA_DeInit(void)
{
Chip_GPDMA_Stop(LPC_GPDMA, dmaChannelNumTx);
Chip_GPDMA_Stop(LPC_GPDMA, dmaChannelNumRx);
}
//Send data via USART0 and DMA
void Send_DMA(uint8_t *data_array, uint32_t data_size, uint8_t dmaChannelNumTx)
{
isDMATx = ENABLE;
while(Chip_GPDMA_Transfer(LPC_GPDMA,
dmaChannelNumTx,
(uint32_t) data_array,
GPDMA_CONN_UART0_Tx,
GPDMA_TRANSFERTYPE_M2P_CONTROLLER_DMA, //Memory to peripheral
data_size) != SUCCESS) {}
}
void Receive_DMA(uint8_t *data_array, uint32_t data_size, uint8_t dmaChannelNumRx)
{
isDMATx = DISABLE;
while(Chip_GPDMA_Transfer(LPC_GPDMA,
dmaChannelNumRx,
GPDMA_CONN_UART0_Rx,
(uint32_t) data_array,
GPDMA_TRANSFERTYPE_P2M_CONTROLLER_DMA, //peripheral to memory
data_size) != SUCCESS) {}
}
int main(void) {
#if defined (__USE_LPCOPEN)
// Read clock settings and update SystemCoreClock variable
SystemCoreClockUpdate();
#if !defined(NO_BOARD_LIB)
// Set up and initialize all required blocks and
// functions related to the board hardware
Board_Init();
Board_UART_Init(LPC_USART0);
//Initialise USART with 115200 baudrate, 8-bits length, no parity and 1-bit stop
Chip_UART_Init(LPC_USART0);
Chip_UART_SetBaud(LPC_USART0, 115200);
Chip_UART_ConfigData(LPC_USART0, (UART_LCR_WLEN8 | UART_LCR_SBS_1BIT | UART_LCR_PARITY_DIS));
Chip_UART_TXEnable(LPC_USART0);
#endif
#endif
//Setting up communication using DMA
Chip_UART_SetupFIFOS(LPC_USART0, (UART_FCR_FIFO_EN | UART_FCR_RX_RS |
UART_FCR_TX_RS | UART_FCR_DMAMODE_SEL | UART_FCR_TRG_LEV0));
//=======================================================================//
/* Init command, receiver and trasmitter buffers ------------------------*/
//=======================================================================//
uint8_t command[1];
uint8_t RX_plaintext[16];
uint8_t RX_key[16];
uint8_t TX_ciphertext[16];
command[0] = 0;
//=======================================================================//
while(1)
{
App_DMA_Init();
dmaChannelNumTx = Chip_GPDMA_GetFreeChannel(LPC_GPDMA, GPDMA_CONN_UART0_Tx);
dmaChannelNumRx = Chip_GPDMA_GetFreeChannel(LPC_GPDMA, GPDMA_CONN_UART0_Rx);
//Receive and send back command
Receive_DMA((uint8_t*) command, 1, dmaChannelNumRx);
Send_DMA((uint8_t*) command, 1, dmaChannelNumTx);
//Obey the command
switch(command[0])
{
//Command to receive plaintext and send back first byte for ack
case 1:
Receive_DMA((uint8_t*) RX_plaintext, 16, dmaChannelNumRx);
Send_DMA((uint8_t*) &RX_plaintext[0], 1, dmaChannelNumTx);
command[0] = 0;
break;
//Command to receive key and send back first byte for ack
case 2:
Receive_DMA((uint8_t*) RX_key, 16, dmaChannelNumRx);
Send_DMA((uint8_t*) &RX_key[0], 1, dmaChannelNumTx);
command[0] = 0;
break;
//Command to XOR key and plaintext
case 3:
for(int i = 0; i<16; i++)
TX_ciphertext[i] = RX_plaintext[i] ^ RX_key[i];
command[0] = 0;
break;
//Command to send ciphertext
case 4:
Send_DMA((uint8_t*) TX_ciphertext, 16, dmaChannelNumTx);
command[0] = 0;
break;
default:
break;
}
}
App_DMA_DeInit();
Chip_UART_DeInit(LPC_USART0);
return 0 ;
}发布于 2020-06-26 18:16:31
很难确切地说是什么原因造成的,这听起来像是一个与时间相关的bug。首先要考虑的是:在没有DMA的情况下,你得到了你想要做的事情了吗?如果DMA只有1个字节的数据,而且你的程序没有做太多的其他工作,你为什么要使用DMA呢?
发现了一些潜在问题:
你是否真的应该从for-ever循环内部初始化DMA,而不是只初始化一次?
Chip_UART_TXEnable,不是也应该有一个用于RX的吗?或者这是由先进先出function?
int main(void)没有任何意义。你要把什么还给谁?“程序完成后进行清理”也没有任何意义。微控制器程序不会结束。如果使用的是void main (void).
-ffreestanding编译它在哪里?它是开着的,还是关着的,你在哪里喂它?https://stackoverflow.com/questions/62592204
复制相似问题