This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

[参考译文] TMS320F280039C:与 FreeRTOS 结合使用的地址位多处理器模式

Guru**** 1133960 points
Other Parts Discussed in Thread: SYSCONFIG
请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

https://e2e.ti.com/support/microcontrollers/c2000-microcontrollers-group/c2000/f/c2000-microcontrollers-forum/1340639/tms320f280039c-address-bit-multiprocessor-mode-combined-with-freertos

器件型号:TMS320F280039C
主题中讨论的其他器件:SysConfig

您好!

我有以下情况、我想实施:

我使用地址位多处理器模式来同步 UART 总线上的消息与多个参与者。 FreeRTOS 在每个参与者上运行、其 UART 通信任务由通过"提供"信标中断传入地址字节来触发。 到目前为止、这也有效。

但是、我有一个问题、那就是我可以不正确地读取后续数据字节或根本不读取。 我没有使用 FIFO、因为根据我的编程经验、它不能与地址位模式组合。 目前我的程序工作如下:


1:通过地址字节(地址位= 1)实现中断

2.使用 sci.h 文件中定义的 SCI_readCharBlockingNonFIFO ()函数读取输入缓冲区的输入地址
3.检查地址是否匹配
4.如果地址匹配、请禁用睡眠模式
5.使用 sci.h 文件中定义的 SCI_readCharBlockingNonFIFO()函数读取以下数据(该函数不能正常工作)

在 查看以下数据字节时、是否有任何相关示例?或者我需要考虑哪些特殊事项?

此致

约书亚

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    你好、Joshua、

    遗憾的是、我们没有任何展示多处理器模式的示例、但希望我能提供帮助。 F280039C 是用于传输(作为参与者的指挥官)还是用于接收(作为参与者之一)? 程序中的步骤听起来是正确的、您看到的问题到底是什么? 请注意、在非 FIFO 模式下使用 SCI、如果您使用 F280039C 在发生中断时进行传输、为了获取任何 TX 中断、数据最初需要写入 TX 缓冲区。 这是因为当数据被移出 TX 缓冲区时、而不是当缓冲区为空时、TXRDY 标志会被置位。

    此致、

    德拉尼

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    尊敬的 Delaney:

    感谢您的答复。

    目前、我将 F280039C 同时用于二者(接收器和发送器)、以避免特定于硬件的不兼容问题。 但我有接收/读取接收器中的数据的问题。

    发送工作正常(我完全按照您所讲的方式进行)、接收中断也会在接收器处触发、但我无法正确读取后续数据。

     因为没有使用 FIFO、我是否可能必须注意一些特殊的事情?

    此致、

    约书亚

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    你好、Joshua、

     按照您描述的那样在 RX 中断中调用 SCI_readCharBlockingNonFIFO ()函数应该是解决这一问题的正确方法。 您能否详细说明接收到的数据是如何不正确的? 调试期间 RX 缓冲区中是否显示了正确的数据、但是读取内容损坏了时? 或者 RX 缓冲区中的数据是否错误? 您还能展示接收线的示波器捕获吗? 如果发生中断检测和组帧错误、以及当接收到一个地址字节时、应该触发 RX 中断。 您可以检查 在调用中断时设置了 SCIRXST 寄存器中的哪些错误标志吗?

    此致、

    德拉尼

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    尊敬的 Delaney:

    据我在调试期间所能知、RXBuffer 中的数据已经不正确。 这是接收器侧消息的示波器捕获(工作正常):

    出于调试目的、我基于 FreeRTOS SDK 示例创建了一个新的"小"示例(代码如下)、现在我有一个问题、即开始时只调用一次中断。 它由一个每秒发送一个请求的主站和一个实际将该请求保存到 processData[8]阵列中的从站组成。 主器件的消息已正确发送(已使用示波器进行检查)。
    如果我在没有 FreeRTOS 的情况下使用相同 的示例、它可以正常工作(几乎相同的代码、只是之前在任务中处理的指令直接在 ISR 中处理)。

    我已经怀疑是因为 SCI 模块的 ISR 在硬件中比 Timer2的 ISR 具有更高的优先级、该端口用于节拍中断、因此会引发问题。 但这应该只会延迟调度程序的调用、而不会阻止它。 不是吗?

    代码:
    ________________________________________________________________

    主控软件 (每秒发送一个简单的"请求"):

    /********************************************//**
    * @file Master_Simulator_C2000.c (Master Software)
    *
    * @date 2024-03-21
    *
    * @version 1.2
    *
    ***********************************************/
    
    // Included Files
    #include "driverlib.h"
    #include "device.h"
    #include "board.h"
    
    #include "stdint.h"
    
    // Defines
    
    // Function prototypes
    void sendaddress(uint16_t addr);
    void sendData(uint16_t data[]);
    
    // Globals
    uint16_t address1 = 0x0000;
    uint16_t address2 = 0x008C;
    uint16_t processdata[7] = {0x0003, 0x0030, 0x0033, 0x0044, 0x0055, 0x0000, 0x003E};
    
    // Main
    void main(void) {
    // Configure PLL, disable WD, enable peripheral clocks.
    Device_init();
    
    // Disable pin locks and enable internal pullups.
    Device_initGPIO();
    
    // Initialize interrupt controller and vector table.
    Interrupt_initModule();
    Interrupt_initVectorTable();
    
    // Disable all CPU interrupts and clear all CPU interrupt flags.
    DINT;
    IER = 0x0000;
    IFR = 0x0000;
    
    // Set up CPUTimer1, LEDs
    Board_init();
    
    SCI_setAddrMultiProcessorMode(SCIB_BASE);
    
    SCI_disableSleepMode(SCIB_BASE);
    
    for(;;) {
    
    sendaddress(address1);
    sendData(processdata);
    DEVICE_DELAY_US(1000000);
    
    }
    }
    
    
    
    void sendaddress(uint16_t addr) {
    HWREGH(SCIB_BASE + SCI_O_CTL1) |= SCI_CTL1_TXWAKE; // Next sent byte is an address byte
    SCI_writeCharBlockingNonFIFO(SCIB_BASE, addr);
    HWREGH(SCIB_BASE + SCI_O_CTL1) &= ~SCI_CTL1_TXWAKE; // Clear TXWAKE bit (following bytes are data)
    GPIO_togglePin(22U);
    }
    
    
    
    void sendData(uint16_t data[]) {
    int i;
    for (i = 0; i < 7; i++) {
    SCI_writeCharBlockingNonFIFO(SCIB_BASE, data[i]); // Next sent bytes are process data
    }
    while (SCI_isTransmitterBusy(SCIB_BASE)) {
    // Wait till the transmission is complete
    }
    }
    
    // End of File

    ________________________________________________________________

    从机软件

    Slave Software:
    
    /********************************************//**
    * @file main.c (Slave Software)
    *
    * @date 2024-03-21
    *
    * @version 1.2
    *
    ***********************************************/
    
    // Included Files
    #include "driverlib.h"
    #include "device.h"
    #include "FreeRTOS.h"
    #include "FreeRTOSConfig.h"
    #include "board.h"
    #include "c2000_freertos.h"
    #include "stdint.h"
    
    // Globals
    uint16_t address1 = 0x0000;
    uint16_t address_temp;
    uint16_t processdata[8];
    
    // Function Prototypes
    void vApplicationStackOverflowHook(TaskHandle_t pxTask, char *pcTaskName);
    void vApplicationMallocFailedHook( void );
    __interrupt void AddressBitReceivedISR(void);
    
    // Task Functions
    void ReadMessageTask(void * pvParameters);
    
    // Main
    void main(void)
    {
    Device_init(); // Initialize device clock and peripherals
    
    Device_initGPIO(); // Initialize GPIOs
    Interrupt_disable(INT_SCIB_RX);
    
    Interrupt_initModule(); // Initializes PIE and clears PIE registers. Disables CPU interrupts.
    Interrupt_initVectorTable(); // Initializes the PIE vector table with pointers to the shell Interrupt Service Routines (ISR).
    
    Interrupt_register(INT_SCIB_RX, AddressBitReceivedISR); // Register the SCIB Interrupt Service Routine
    SCI_setAddrMultiProcessorMode(SCIB_BASE); // Enable Address Byte Multiprocessor Mode
    
    Board_init(); // Set up CPUTimer1, LEDs
    
    SCI_enableInterrupt(SCIB_BASE, SCI_INT_RXRDY_BRKDT); // Enable local SCI Interrupt sources
    SCI_disableInterrupt(SCIB_BASE, (SCI_INT_RXERR | SCI_INT_TXRDY |
    SCI_INT_TXFF | SCI_INT_RXFF | SCI_INT_FE | SCI_INT_OE | SCI_INT_PE));
    SCI_performSoftwareReset(SCIB_BASE);
    Interrupt_enable(INT_SCIB_RX); // Enable SCIB RX Interrupt
    Interrupt_clearACKGroup(INTERRUPT_ACK_GROUP9); // Clear the Interrupt acknowledge bits
    
    SCI_enableSleepMode(SCIB_BASE); // SCI in sleep mode, only reacts for Address byte interrupts
    
    // Enable Global Interrupt (INTM) and real time interrupt (DBGM)
    EINT;
    ERTM;
    
    FreeRTOS_init(); // Configure FreeRTOS, start Scheduler
    
    while(1) // Loop forever. This statement should never be reached.
    {
    }
    }
    
    
    
    // ReadMessage FreeRTOS Task
    void ReadMessageTask(void * pvParameters)
    {
    for(;;)
    {
    if (xSemaphoreTake( binarySem1Handle, portMAX_DELAY ) == pdTRUE) // no special waiting time is defined (waits forever if necessary, scheduler can proceed other tasks)
    {
    uint16_t length, i;
    GPIO_togglePin(20U);
    length = SCI_readCharBlockingNonFIFO(SCIB_BASE);
    processdata[1] = length;
    for (i = 2; i < (length + 5); i++) {
    processdata[i] = SCI_readCharBlockingNonFIFO(SCIB_BASE);
    }
    SCI_enableSleepMode(SCIB_BASE);
    }
    }
    }
    
    
    
    // Address Bit Interrupt Service Routine
    __interrupt void AddressBitReceivedISR(void)
    {
    address_temp = SCI_readCharBlockingNonFIFO(SCIB_BASE);
    
    if (address_temp == address1) {
    processdata[0] = address_temp;
    SCI_disableSleepMode(SCIB_BASE);
    
    SCI_clearOverflowStatus(SCIB_BASE); // Not necessary, just for debugging purpose
    SCI_clearInterruptStatus(SCIB_BASE, SCI_INT_RXRDY_BRKDT);
    Interrupt_clearACKGroup(INTERRUPT_ACK_GROUP9);
    
    static BaseType_t xHigherPriorityTaskWoken = pdFALSE; // Local variable for the release of the semaphore
    xSemaphoreGiveFromISR( binarySem1Handle, &xHigherPriorityTaskWoken ); // Give the synchronization semaphore
    portYIELD_FROM_ISR( xHigherPriorityTaskWoken ); // Start Scheduler
    }
    }
    
    // End of File


    通过 SysConfig 对两个模块中的硬件进行初始化编程。

    此致

    约书亚

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    你好、Joshua、

    用于说明:删除 FreeRTOS 后、现在是否已在多处理器模式下通过 SCI 正确发送和接收数据? 如果是这样、问题可能与 FreeRTOS 或中断相关、我可以致电另一位专家来提供帮助。 如果不是、请在 SCI RX ISR 中放置一个断点、并在命中断点时发送 SCIRXST 寄存器视图内容的屏幕截图(启用持续刷新)。

    此致、

    德拉尼  

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    尊敬的 Delaney:

    是的、删除 FreeRTOS 后、在多处理器模式下通过 SCI 正确传输数据。 当我添加 FreeRTOS 时、SCI RX ISR 只需调用一次。

    我已经再次仔细检查了这一点、发现在第二个 RX ISR 调用上设置了所有错误标志(请见屏幕截图)。

    当调用 FreeRTOS 任务时、是否有可能出现时序错误、从而使缓冲区读取得太晚、进而导致成帧错误?

    此致、

    约书亚

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    你好、Joshua、

    一个注意事项是 SCI 模块分支到 RX ISR 需要~7/8个位时间、并且接收到的数据在 RX ISR 完成执行前不会移入 RX 缓冲区。 这意味着如果在 RX ISR 执行期间接收到数据、则将丢失。 如果 FreeRTOS 出于某种原因而进一步延迟对 SCI RX 中断的调用、可能是第二个数据帧的起始位丢失、并且当后续位移入时、帧会被误解。 这将导致您在初始接收后看到的组帧和 BRKDT 错误。  

    F28003x TRM 的下一版本将在"SCI 端口中断"部分包含有关此内容的注意事项。 如果您想了解一下、则到目前为止、它包含在 F28P65x TRM 中。 本说明包括一些关于如何避免这种情况的建议。

    我将在 FreeRTOS 专家的指导下循环操作、以查看 FreeRTOS 实现是否会因任何原因阻塞 SCI RX 中断或延迟该中断。

    此致、

    德拉尼

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    尊敬的 Delaney:

    感谢您的回复和信息。

    我将在接下来的几天里试用 F28P65x TRM 的建议、然后提供反馈。

    是否由于调度程序必须在读取缓冲区之前通过 portYIELD_from_isr( xHigherPriorityTaskWoken )执行,所以 ISR 的处理需要太长的时间? 也许 FreeRTOS 专家可以回答这个问题。

    此致、

    约书亚

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    你好、Joshua、

    我已将该主题发送给 FreeRTOS 专家、供其提供意见。 他们目前在4月2日星期二之前不在办公室、因此请预计他们的回复  会延迟。

    此致、

    德拉尼

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    你好、Joshua、

    关于接收器端实现的几个注意事项:

    1.在 ISR 和读取任务中都执行 SCI 读取操作。 在读取第一个地址字节并且 SCI 退出睡眠模式后、  每个数据字节基本上有两个 SCI_readCharBlockingNonFIFO ()操作(因为一旦 SCI 被唤醒、块中所有后续数据字节都会触发中断)。 这可能会导致不一致。

    2、在读取任务中、在获取初始信号量之后、您可以阻塞对所有后续数据字节的读取。 这会将任务置于忙循环中、等待每个字节。 更好的方法(利用 RTOS 功能)是阻止任务、允许执行其他任务、直到下一个字节可用。

    我建议将所有 SCI 读取操作移动到任务或 ISR、并在它们之间进行适当的同步。 队列/流缓冲区也可能有用。 如果仍然像本线程前面所讨论的那样是计时问题、您可以尝试使用任务通知来加快同步。 运营。

    谢谢。

    阿纳维

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好!

    我现在已经测试了一些东西、并设法解决了问题。 我已经将 UART 格式从8N1扩展到8N2、以便生成更多时间来处理 ISR。 我还将所有读取操作移至任务中、以使 ISR 尽可能短。 现在它起作用了。

    我已经注意到与 FreeRTOS 有关的实施的注释、现在我将在优化代码时考虑这些注释。

    感谢您的帮助、此致、

    约书亚