Hello, I am not very experienced in embedded systems and I need to develop a program on an LPCXpresso18S37 that is able to communicate with a Python script to send and receive data using UART and the DMA. I am using MCUXpresso IDE and LPCOpen library.
The communication is basically a series of byte exchanges, where the Python script sends commands, to which the MCU responds by performing specific actions.
For example : if the Python scripts sends command "1", the MCU will send it back as an ack, and then wait to receive 16-bytes of plaintext, which will be sent by the Python script, etc...
Here is my problem : when in debug mode and stepping through instructions, the program behaves as expected : bytes are received and sent properly, stored in designated memory.
However, whenever I run the program "full speed", without any breakpoints or without stepping instructions, things get weird and the programs starts behaving in a way I really can not understand : most of the data being sent or received seems to be lost.
I have spent a lot of time trying to debug or at least figure out what's going on, but, I admit, without great success...
I am using the DMA without interruptions, as a different buffer is fulled everytime.
I would gladly welcome any help or ideas. Thank you in advance.
Here is the code in question :
#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 ;
}
It looks like you are just looping through the code at full speed, without checking to see if any data has arrived. When you step through the code, you are allowing time for the data to be received, but you have no checks.
It would be better if you restructured your code to be interrupt based, so that it only responded when you received an interrupt from the data had been received.