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.

CC3220SF-LAUNCHXL: UART2_read或UART2_readTimeout都收不到UART2_STATUS_ECANCELLED

Part Number: CC3220SF-LAUNCHXL

环境:simplelink_cc32xx_sdk_6_10_00_05

CCS Version: 12.2.0.00009 

UART2,BLOCKING模式下,A线程调用UART2_readCancel,B线程UART2_read或UART2_readTimeout都收不到UART2_STATUS_ECANCELLED,UART2_readTimeout可以收到UART2_STATUS_ETIMEOUT

void uart2_init(void)
{
    UART2_Params uartParams;
    // 确保调用UART_Params_init之前有调UART_init
    UART2_Params_init(&uartParams);
    uartParams.readMode = UART2_Mode_BLOCKING;  // 回调模式
    uartParams.writeMode = UART2_Mode_BLOCKING; // 写模式使用回调模式
    uartParams.readCallback = NULL;             // 回调函数
    uartParams.writeCallback = NULL;            // 回调函数
    uartParams.readReturnMode = UART2_ReadReturnMode_PARTIAL;
    uartParams.baudRate = 2000000;             // 波特率
    uartParams.dataLength = UART2_DataLen_8;   // 数据长度为8位
    uartParams.stopBits = UART2_StopBits_1;    // 1位停止位
    uartParams.parityType = UART2_Parity_NONE; // 奇偶校验位
    app_CB.paramUartHandle = NULL;
    // 到时候这里使用为UART调试口的初始化
    app_CB.paramUartHandle = UART2_open(CONFIG_UART2_PARAM, &uartParams);
}
  • 文档中的定义是:

    取消 UART2_read() 函数调用的函数。

    此函数取消 UART2_Mode_CALLBACK 中的异步 UART2_read() 操作,或取消阻止 UART2_Mode_BLOCKING 中的 UART2_read() 调用。在 UART2_Mode_CALLBACK 中,UART2_readCancel() 使用目前接收到的字节数调用已注册的读取回调函数。应用程序负责检查回调函数中的计数参数并处理仅接收到一部分字节的情况。回调函数将传递 UART2_STATUS_ECANCELLED 状态。

    UART2_Mode_BLOCKING 中,UART2_read( 将返回 UART2_STATUS_ECANCELLE,bytesRead 参数将设置为目前接收到的字节数。

    此 API 对 UART2_Mode_NONBLOCKING 没有影响。

    So for blocking mode you should get the event, I haven't tested it myself though.

    Just to understand, you are calling the UART2_read() on one task in blocking mode (and thus blocked) and on another task you cancel the read but the read operation stays blocked?

    参数

    [in] handle A UART2_Handle returned by UART2_open()

    所以对于阻塞模式您应该得到事件,虽然我自己没有测试过。

    为了确认我理解得是否正确,您在一个任务上以阻塞模式调用 UART2_read()(因此被阻塞),而在另一个任务上您取消读取但读取操作保持阻塞?

  • /*
     * Copyright (c) 2017-2019, Texas Instruments Incorporated
     * All rights reserved.
     *
     * Redistribution and use in source and binary forms, with or without
     * modification, are permitted provided that the following conditions
     * are met:
     *
     * *  Redistributions of source code must retain the above copyright
     *    notice, this list of conditions and the following disclaimer.
     *
     * *  Redistributions in binary form must reproduce the above copyright
     *    notice, this list of conditions and the following disclaimer in the
     *    documentation and/or other materials provided with the distribution.
     *
     * *  Neither the name of Texas Instruments Incorporated nor the names of
     *    its contributors may be used to endorse or promote products derived
     *    from this software without specific prior written permission.
     *
     * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
     * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
     * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
     * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
     * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
     * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
     * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
     * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
     * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
     * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     */
    
    /*
     *  ======== mailbox.c ========
     */
    
    /* XDC module Headers */
    #include <xdc/std.h>
    #include <xdc/runtime/System.h>
    
    /* BIOS module Headers */
    #include <ti/sysbios/BIOS.h>
    #include <ti/sysbios/knl/Task.h>
    #include <ti/sysbios/knl/Mailbox.h>
    #include <ti/sysbios/knl/Clock.h>
    #include <ti/drivers/Board.h>
    #include <ti/drivers/Uart2.h>
    #include "ti_drivers_config.h"
    #define NUMMSGS         5
    #define TASKSTACKSIZE   512
    
    /*
     * This type is accessed by the application. When changing the data members of
     * this structure, considerations should be made for padding and data alignment.
     */
    typedef struct MsgObj {
        Int     id;
        Char    val;
    } MsgObj;
    
    /*
     * Mailbox messages are stored in a queue that requires a header in front of
     * each message. Mailbox_MbxElem is defined such that the header and its size
     * are factored into the total data size requirement for a mailbox instance.
     * Because Mailbox_MbxElem contains Int data types, padding may be added to
     * this struct depending on the data members defined in MsgObj.
     */
    typedef struct MailboxMsgObj {
        Mailbox_MbxElem  elem;      /* Mailbox header        */
        MsgObj           obj;       /* Application's mailbox */
    } MailboxMsgObj;
    
    /* This buffer is not directly accessed by the application */
    MailboxMsgObj mailboxBuffer[NUMMSGS];
    
    Mailbox_Struct mbxStruct;
    Mailbox_Handle mbxHandle;
    
    Task_Struct task0Struct, task1Struct;
    Char task0Stack[TASKSTACKSIZE], task1Stack[TASKSTACKSIZE];
    
    Void readerTask(UArg arg0, UArg arg1);
    Void writerTask(UArg arg0, UArg arg1);
    UART2_Handle UartHandle;
    void uart2_init(void)
    {
        UART2_Params uartParams;
        // 确保调用UART_Params_init之前有调UART_init
        UART2_Params_init(&uartParams);
        uartParams.readMode = UART2_Mode_BLOCKING;  // 回调模式
        uartParams.writeMode = UART2_Mode_BLOCKING; // 写模式使用回调模式
        uartParams.readCallback = NULL;             // 回调函数
        uartParams.writeCallback = NULL;            // 回调函数
        uartParams.readReturnMode = UART2_ReadReturnMode_FULL;
        uartParams.baudRate = 2000000;             // 波特率
        uartParams.dataLength = UART2_DataLen_8;   // 数据长度为8位
        uartParams.stopBits = UART2_StopBits_1;    // 1位停止位
        uartParams.parityType = UART2_Parity_NONE; // 奇偶校验位
        // 到时候这里使用为UART调试口的初始化
        UartHandle = UART2_open(CONFIG_UART2_0, &uartParams);
    
        /* remove uart receive from LPDS dependency */
        // UART2_control(app_CB.paramUartHandle, UART_CMD_RXDISABLE, NULL);
    }
    /*
     *  ======== main ========
     */
    int main()
    {
        Task_Params taskParams;
        Mailbox_Params mbxParams;
    
        /* Call Driver init functions */
        Board_init();
        uart2_init();
        /* Construct read and writer tasks */
        Task_Params_init(&taskParams);
        taskParams.stackSize = TASKSTACKSIZE;
        taskParams.stack = &task0Stack;
        Task_construct(&task0Struct, (Task_FuncPtr)writerTask, &taskParams, NULL);
        taskParams.stack = &task1Stack;
        Task_construct(&task1Struct, (Task_FuncPtr)readerTask, &taskParams, NULL);
    
        /* Construct a Mailbox instance */
        Mailbox_Params_init(&mbxParams);
        mbxParams.buf = (Ptr)mailboxBuffer;
        mbxParams.bufSize = sizeof(mailboxBuffer);
        Mailbox_construct(&mbxStruct, sizeof(MsgObj), NUMMSGS, &mbxParams, NULL);
        mbxHandle = Mailbox_handle(&mbxStruct);
    
        BIOS_start();
    
        return(0);
    }
    
    
    /*
     *  ======== readerTask ========
     */
    Void readerTask(UArg arg0, UArg arg1)
    {
        size_t bytesRead = 0;
        char   input[16];
        while (1) {
            System_printf("UART2_read Enter\n");
            System_flush();
            int status = UART2_read(UartHandle, &input, 16, &bytesRead);
            System_printf("UART2_read return:%d,bytesRead:%d\n",status,bytesRead);
            System_flush();
        }
        System_printf("All messages received. Exiting...\n");
    
        BIOS_exit(0);
    }
    
    /*
     *  ======== writerTask ========
     */
    Void writerTask(UArg arg0, UArg arg1)
    {
    
        while (1) {
            System_printf("UART2_readCancel Enter\n");
            System_flush();
            UART2_readCancel(UartHandle);
            System_printf("UART2_readCancel return\n");
            System_flush();
            Task_sleep((10000 / Clock_tickPeriod)*100);
           }
    
    }

    上面的代码是在mailbox工程,修改mailbox.c文件来测试,运行结果如下,UART2_read没有被cancel 

    运行结果:

    UART2_readCancel Enter
    UART2_readCancel return
    UART2_read Enter
    UART2_readCancel Enter
    UART2_readCancel return
    UART2_readCancel Enter
    UART2_readCancel return

    除非uartParams.readReturnMode = UART2_ReadReturnMode_PARTIAL,但UART2_read反回的是UART2_STATUS_SUCCESS,不是UART2_STATUS_ECANCELLED

    运行结果:

    UART2_readCancel Enter
    UART2_readCancel return
    UART2_read Enter
    UART2_readCancel Enter
    UART2_readCancel return
    UART2_read return:0,bytesRead:0
    UART2_read Enter
    UART2_readCancel Enter
    UART2_readCancel return
    UART2_read return:0,bytesRead:0

  • 是的,您说的对。

    我深入研究了 UART2 驱动程序的执行,似乎 ECANCELLED 错误仅在 CALLBACK 模式下传播。

    在 BLOCKING 模式下,将发布 readSem 并且读取将中断直到该点为止收到的字节数(在您的情况下为 0)。

    void __attribute__((weak)) UART2_readCancel(UART2_Handle handle)
    {
    UART2_Object *object = handle->object;
    uintptr_t key;

    if ((object->state.readMode != UART2_Mode_BLOCKING) &&
    (object->state.readMode != UART2_Mode_CALLBACK)) {
    return;
    }

    key = HwiP_disable();

    if (object->readInUse == false) {
    HwiP_restore(key);
    return;
    }

    object->readInUse = false;
    object->readCount = 0;

    if (object->state.rxCancelled == false) {
    object->state.rxCancelled = true;
    SemaphoreP_post(&object->readSem);

    if (object->state.readMode == UART2_Mode_CALLBACK) {
    object->readCallback(handle, object->readBuf, object->bytesRead,
    object->userArg, UART2_STATUS_ECANCELLED);
    }
    }

    HwiP_restore(key);
    }