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.

[参考译文] RTOS/TM4C1294NCPDT:在不丢弃数据的情况下无法读取 TI-RTOS 中的全部8个 UART

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

https://e2e.ti.com/support/microcontrollers/arm-based-microcontrollers-group/arm-based-microcontrollers/f/arm-based-microcontrollers-forum/729134/rtos-tm4c1294ncpdt-unable-to-read-all-8-uarts-in-ti-rtos-without-dropping-data

器件型号:TM4C1294NCPDT
Thread 中讨论的其他部件:SYSBIOS、ENERGIA

工具/软件:TI-RTOS

您好!

我已经尝试过多种方法来使用 TI-RTOS 读取全部8个 UART、但在读取时不会丢失数据、每次读取的数据不能超过3-4个。 如果您有任何建议来处理使用 TI-RTOS (必须是 TI-RTOS)读取全部8个 UART 的内容、我将不胜感激。

每个 UART 每1到4秒以19200波特接收20-64字节数据。 我的目标是能够将每个 UART 的数据存储在缓冲区中、直到接收到一个终止字符来表示数据包的末尾、然后复制缓冲区并在其他地方使用。

我已经尝试了以下许多不同的方法:

1) 1)最初修改了 Enet_s2E 示例、该示例使用 FreeRTOS 使用8个 UART。 它可以工作、但由于 USB/插座要求、必须使用 TI-RTOS。

2) 2)修改了针对多个 UART 的 TI-RTOS 示例"uartecho"

a)每个 UART 一个任务、无需回调即可进行读取

a1)通过队列发送字符,以便由单独的任务聚合

a1)将字符复制到 char[]缓冲区中、以由 单独的任务聚合

b)每个 UART 一个任务、通过回调任务进行读取

b1)在回调中、通过队列发送字符、以由 单独的任务聚合

b2)在回调中、将字符复制到 char[]缓冲区中、以便由 单独的任务聚合

B3)调用读取的计时器

B4)信标和缓冲区、以最大程度地缩短回调时间

基本上、我已经尝试了很多方法和选项的变体、一次读取的字节数、没有一个接近全部8次读取、没有丢失数据。 有人知道 TI-RTOS 中可以无问题地处理全部8个 UART 的任何方法吗? 在调度方面、我们需要能够在一侧运行一些额外的低优先级任务、例如 USB 和套接字。

谢谢!

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

    您可以附加示例项目吗? 当您尝试一次执行8操作时、所有 UART 都是在丢失数据、还是仅在特定数据时丢失?

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

    您好 Todd、

    看起来先前初始化的 UART 与数据损坏相关的问题更少。 当我仅设置1至3个 UART 时、所有数据均已正确接收。 当使用 UART 的任意组合(例如:1/2/3或2/5/6)时、此功能有效。 当我设置3个或4个以上的 UART 时、字符开始丢失。 在8个 UART 设置中、只有前5个设置将接收数据、最后几个设置将几乎没有接收到数据(UART 1-2错过了几个字符、3-5个丢失的字符、6-8个收到的字符非常少)。

    我还注意到、当任务或回调运行更多代码并花费更长的时间来执行时、会丢弃更多数据。 在尝试了许多方法之后、我目前正在尝试最大程度地减少读取任务和回调函数的开销。 单独在项目中运行代码或同时运行其他任务(例如:USB 和以太网套接字任务)时、没有太大的区别(如果有)。

    下面是一个示例、说明我当前如何在环路中设置 UART 以及如何读取/处理数据。 希望您有一些神奇的公式、例如"使用回调和队列、将 XYZ 设置为___"。 我感觉自己很近!

    非常感谢您的帮助!

    #define UART_READ_TASK_STACK_SIZE 1024
    #define MAX_NUM_RX_Bytes 8 //一次性接收的最大 RX 字节
    
    // 在 Task_Structurt uartReadTaskStruct[UART_count]下的读取任务创建中使用的结构和堆栈; 字符 uartReadTaskStack[UART_count][UART_READ_TASK_STACK_SIZE];
    //除了回调函数 UART_Params 之外、UART 参数是相同的 UARTParams; UART_Params_init (&UARTParams); UARTParams.baudrate = UART_baud_rate;// 19200 UARTParams.writeDataMode = UART_DATA_binary; UARTParams.readEcho = UART_ECHO_OFF; UARTParams.readMode = UART_MODE_UART0;/ UART+= UART0+= UARTRAT0+设置为接收 任务;UART0+设置为等待 UART0+回调拨;UART0+等待 UART0+(UART0+ )

    //回调函数将端口号添加到读取回调任务 args UARTParams.readCallback = UARTRxCallbackFuncs[uartLoop; UARTHandles[uartLoop ]= UART_OPEN (UARTsAvailable[uartLoop ]、&UARTParams); if (!UARTHandles[uartloop]){ System_printf ("UART%d 未打开"、uartLoop);// UART 始终未打开问题 } //创建任务以定期读取 UART taskParams.STACKSIZE = UART_READ_TASK_STACK_SIZE; taskParams.priority = 3; taskParams.arg0 = uartLoop; taskParams.stack =&uartReadTaskStack[uartLoop; Task_construction (&uartReadTaskStruct[uartLoop)、(Task_funcPtr) UARTReadTask、&taskParams、NULL); } //回调函数 静态 void multipleByteReadCallback (UART_Handle handle、void * rxBuf、size_t size、uint8_t port) { //将 rxBuf 复制到 txBuf memset (UARTRxBufCopy[port]、0、MAX_NUM_RX_Bytes); memcpy (UARTRxBufCopy[port]、rxBuf、size); Semaphore_post (readSemaphore[port]); } //读取函数 静态空 UARTReadTask (UARg arg0、UARg arg1){ int port =(int) arg0; size_t charsReceivedSize; while (1){ UART_READ (UARTHandles[port]、UARTRxBuf[port]、MAX_NUM_RX_Bytes); Semaphore_pend (readSemaphore[port]、BIOS_wait_forever); charsReceivedSize = strlen (UARTRxBufCopy[port]); //将接收到的字符复制到部分数据包缓冲区 //如果接收到数据字符结束,打印数据(或添加到队列) Task_sleep (10);//在有睡眠和没有睡眠的情况下尝试,不同的时间,5-25似乎有所帮助 } }

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

    您好、请选择用户名、

    您是否为每个 UART 配置了 M3模块或特定的中断优先级? ROV 是否指示分配给每个 UART 的任何类型的 FIFO 中断优先级? 如果 FIF0未受限制或仅轮询、我们如何预计串行数据不会丢失?

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

    您好、用户:

    您还可以尝试查看 CPU 负载、看看您是否有周期以该波特率处理来自8个 UART 的数据。
    只需将以下内容添加到.cfg 文件中即可:

    xdc.useModule('ti.uia.sysbios.LoggingSetup');

    然后在 CCS 中使用 RTOS 分析器来查看 CPU 负载。

    此致、

    Janet

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

    Janet、您好!

    我目前正在旅行、无法测试系统。 通常、仅读取8个 UART 时、CPU 负载是否会成为一个问题?

    我知道代码和设置的差异可能会显著改变性能、但总的来说 TM4C1294NCPDT 应该没有足够的 CPU? 通过使用 Arduino sketch、我能够完美读取全部8个 UART、并将数据存储在50行代码中。 我们还能让它与 FreeRTOS 配合使用而不会出现任何问题、还能运行完整的以太网 Web 服务器。


    谢谢你。

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

    我目前正在出差、无法测试系统并查看 ROV、但我非常确信 UART_open 会创建一个 HWI (不确定分配的优先级)。 最近、我一直在想问题是否是触发器使用默认的7/8 Full、而6/8或4/8可能更好。

    我已经使用代码"taskParams.priority = 3;"设置了读取任务优先级、但就是这样。 其他所有内容(包括 RTOS 设置)都是 TI RTOS UART Echo 示例、该示例扩展为8个 UART、而不是1个 UART。 我已经尝试对所有器项使用相同的优先级(有时与 Task_yield 结合使用)、也尝试使用不同的值、但没有成功。 我正在尝试获取读取全部8个 UART 的最小代码项目、但在整个项目中、我们打算以低于 UART 任务的优先级运行以太网和 USB 任务。

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

    您好、用户:

    由于每个 UART 有一个任务、我想知道任务切换是否会产生大量开销。  这就是我认为查看 CPU 负载可能有用的原因。

    此致、

    Janet

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

    Janet、您好!

    感谢您的建议、减少运行的任务会产生很大的影响! 我创建了一个单个读取任务、并在每个 UART 上连续循环。 在循环超过6个 UART 时、大约90%的字符将要到来、但从数据流看、FIFO 缓冲区在被读取前被溢出。

    10%的缺失会导致部分数据包与完整数据包混合、例如<123456 <1234567890>而不是<1234567890><1234567890>。 大约10个数据包可以正常运行、然后是一个混合运行的数据包。 没有明显的 UART 模式。

    数据每4秒发送64个字符、缓冲区大小是128个字符的两倍:

    unsigned FlowuartTivaRingBuffer[EK_TM4C1294XL_UARTCOUNT][128];
    
    /* UART 配置结构*
    / const UARTTiva_HWAttrs uartTivaHWAttrs[EK_TM4C1294XL_UARTCOUNT]={
    
    .baseAddr = UART0_BASE、UART0_Control
    
    ~= UART0_UART24_UART0_UART0_UART24_UR_UR_T.EK-R = T.UART24_UART0_UART24_UART_UART0_UART24_UR_UR_UR_UR_UR_ENTRINT_UART0_U
    
    
    .ringBufSize = sizeof (uartTivaRingBuffer[EK_TM4C1294XL_UART0])
    }、
    {
    .baseAddr = UART1_base、
    .intNum = INT_UART1、
    .intPriority =(~0)、
    .FlowControl = UART_FlowControl_NONE、
    .ringBufPtr = INT_Tiva40XL_TivaUrg环路 缓冲器[EK_UART1494X1]
    .ringBufSize = sizeof (uartTivaRingBuffer[EK_TM4C1294XL_UART1])
    }、... 

    我在测试项目中使用以下最小代码、但仍然无法获取完整数据:

    UART_Params UARTParams;
    UART_PARAMS_INIT (&UARTParams);
    UARTParams.波特 率= UART_BAUD_RATE;
    UARTParams.readReturnMode = UART_RETURN_NEWLINE;
    UARTParams.readEcho = UART_ECHO_OFF;
    
    静态空 UARTReadTask (UARg arg0、UARg arg1){
    int 端口;
    int charsReceivedSize;
    uint8_t sizeLoop;
    字符接收器;
    while (1){
    对于(端口= 0;端口< UART_COUNT;端口++){
    if (!UARTsActivated[port]){
    继续;
    }
    charsReceivedSize = UART_Read (UARTHandles[port]、UARTRxBuf[port]、MAX_NUM_RX_Bytes);
    for (sizeLoop = 0;sizeLoop '="">'){
    System_printf ("UART%d 接收到%s\n"、端口、dataPacketRxBuffer[port]);
    system_flush();
    dataPacketRxBufferIndex[port]= 0;
    }
    }
    
    }
    

    我尝试让 CPU 记录器正常工作、但无法获得任何内容、甚至在查看论坛上的所有提示后、执行相关项目也无法正常工作。 我甚至还尝试了 Resource Explorer 中的新示例、但运气不好。 我想我只是习惯使用常规的计算机和 Linux、在这些计算机和 Linux 中、事情似乎更简单、工作正常。 这些 TI 产品似乎会在每次机会时都出现故障。

    我感谢您的帮助、尤其是对一些简单代码的帮助、因为这看起来应该很简单。

    谢谢你。

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

    我知道 TI-RTOS 要复杂得多、但这就是 Arduino 的易用性(我们如何使用 Energia 在 TM4C1294NCPDT 上进行原型设计)。 TI 只是不发布与 Arduino 配合使用所需的 UART/USB/Ethernet 驱动程序、因此我们不得不用 C 语言编写它...

    char termChart ='>';
    char 字符;
    int baudrate = 19200;
    
    HardwareSerial *Serials[8]={&Serial、&Serial1、&SERIAL2、&Serial3、&Serial4、 &Serial5、&Serial6、&Serial7};
    String rxStrings[8];
    
    String completedRxString;
    string storedRxString ="";
    
    //设置
    void setup(){
    Serial.begin(baudRate);
    Serial.println ("串行测试开始");
    for (int i = 0;i < 8;i++){
    rxStrings[i]="";
    Series[i]->begin (budrate);
    }
    }
    
    void loop(){
    for (int i = 0;i < 8;i++){
    while (Serials[i]->available ()){
    字符=期刊[i]->read();
    rxStrings[i].con概念(字符);
    if (字符== termChart){
    // serial.print ("串行"+字符串(i)+":");
    // serial.println (rxStrings[i]);
    完整的 RxString = String (I)+":"+rxStrings[i]+";";
    storedRxString.conomat (完整的 RxString);
    rxStrings[i]="";
    }
    }
    if (storedRxString.length ()> 2000){
    serial.println (storedRxString);
    storedRxString ="";
    }
    }
    

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

    您好、用户:

    我认为您可以执行与 Arduino 代码中所执行的操作类似的操作、只需执行一项任务即可读取 UART。  有一个 UART_CONTRAIN()命令,您可以使用它来检查 UART 上是否有可用的数据。  以下是我修改 uartecho 示例以使用 UART_CONTINU()调用的方法:

       可        提供内部数据;

       (笑声)

       /*循环永久回显*/
       while (1){
           if ((UART_CONTROL (UART、UART_CMD_ISAVAILABLE、&dataAvailable)=UART_STATUS_SUCCESS)&&
                       (dataAvailable!= 0)){
               UART_READ (UART、INPUT、1);
               UART_WRITE (UART、INPUT、1);
           }
       }

    还有一个 UART_CMD_GETRXCOUNT 控制命令、用于提供可读取的实际字符数。

    此致、

    Janet

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

    Janet、您好!

    您的代码比目前为止的任何代码都更有效、但仍然只能使8个 UART 中的5个正常工作、6个偶尔会丢失数据。

    我们公司已决定 TI-RTOS 的质量和可靠性不够、因此我们将继续处理其他问题。 基本上、除了硬件之外、所有东西都很糟糕:CCS、TI-cloud、TI-RTOS、驱动程序、许可... 许多事情都不能正常工作。

    我还建议我们完全抛弃 TI 的硬件、因为有很多更好的选择。 我们认为 TI 因优质电子组件而享有的声誉将超越其软件和操作系统、但我们发现、与 IBM 和许多其他大型公司一样、TI 并不真正获得它、这是一件麻烦事。

    感谢你的帮助。

    PS:如何能够选择不是您的名字和姓氏以及号码的用户名? 不必注册第二个虚拟帐户、这是没有帮助的。