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 ;
}