首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >程序仅在单步执行时有效- LPCXpresso18S37

程序仅在单步执行时有效- LPCXpresso18S37
EN

Stack Overflow用户
提问于 2020-06-26 17:51:00
回答 1查看 87关注 0票数 1

我对嵌入式系统不是很有经验,我需要在LPCXpresso18S37上开发一个能够与Python脚本通信的程序,以便使用通用异步收发器和直接存储器访问发送和接收数据。我使用的是MCUXpresso集成开发环境和LPCOpen库。

通信基本上是一系列字节交换,其中Python脚本发送命令,MCU通过执行特定操作来响应命令。

例如:如果Python脚本发送命令"1",MCU会将其作为ack发送回来,然后等待接收16字节的明文,这将由Python脚本发送,依此类推……

这就是我的问题:当处于调试模式和单步执行指令时,程序的行为与预期一样:字节被正确地接收和发送,并存储在指定的内存中。

然而,每当我“全速”运行程序时,没有任何断点或步进指令,事情就变得奇怪,程序开始以一种我真的不能理解的方式运行:大多数发送或接收的数据似乎都丢失了。

我花了很多时间尝试调试,或者至少弄清楚发生了什么,但是,我承认,没有取得很大的成功……

我在没有中断的情况下使用DMA,因为每次都会充满一个不同的缓冲区。

我已经看到一些开发人员遇到了一些类似的问题,但我无法将解决方案转换为适合我的情况。

我很高兴地欢迎任何帮助或想法。提前谢谢你。

下面是有问题的代码:

代码语言:javascript
复制
#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 ;
}
EN

回答 1

Stack Overflow用户

发布于 2020-06-26 18:16:31

很难确切地说是什么原因造成的,这听起来像是一个与时间相关的bug。首先要考虑的是:在没有DMA的情况下,你得到了你想要做的事情了吗?如果DMA只有1个字节的数据,而且你的程序没有做太多的其他工作,你为什么要使用DMA呢?

发现了一些潜在问题:

你是否真的应该从for-ever循环内部初始化DMA,而不是只初始化一次?

  • 你的DMA缓冲区不是易失性限定的,这可能导致堆栈分配的DMA缓冲区不正确,这是完全错误的。

  • 我不知道这个库,但是如果有一个Chip_UART_TXEnable,不是也应该有一个用于RX的吗?或者这是由先进先出function?

  • Your做的,当调用你自己的函数时,各种类型的转换都是可疑的。你为什么选演员?如果你发现自己需要它,一定要怀疑有bug。

  • 这不是一台PC,所以int main(void)没有任何意义。你要把什么还给谁?“程序完成后进行清理”也没有任何意义。微控制器程序不会结束。如果使用的是void main (void).

  • Watchdog?,则应该使用-ffreestanding编译它在哪里?它是开着的,还是关着的,你在哪里喂它?
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/62592204

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档