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/CC2650:UART_WRITE 和 UART_READ、带回调问题

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

https://e2e.ti.com/support/wireless-connectivity/bluetooth-group/bluetooth/f/bluetooth-forum/709340/rtos-cc2650-uart_write-and-uart_read-with-callback-issues

器件型号:CC2650

工具/软件:TI-RTOS

大家好、


我一直在尝试使用 TI-RTOS 驱动程序在 CC2650上使用 UART。 我从"uartecho_CC2650_LAUNCHXL_TI"示例开始。 这个寄存器使用阻塞式写入和读取操作。

因此、我尝试添加到"简单外设示例"中、因为我想在那里使用它。 之后、我将尝试编辑 uartecho 示例、看看它是否与其他内容相关。
我需要具有非阻塞式读操作、以便能够足够快地捕捉到 ISR 中。   
为此、我将读取和写入模式更改为回调并注册回调。 还打开了"UARTCC26XX_RETURE_PARTI_ENABLE"。

为了管理所有内容、在搜索一个位后、我添加了信标。  
问题是、在执行单个 UART_Read 后、UART_WRITE 从未工作过、只需成功调用 UART_Read 即可测试、 甚至使用信标来确保写入发生在读取结束后(请注意、根据我的理解、这不是必需的)。

在另一个测试中、我删除了读取部分、我只是尝试连续发送数据。 已尝试使用字符串"hi\r\n"。 回调会解锁主任务的信号量、该主任务将再次执行 UART_WRITE。 这种情况在6千左右的成功之后出现了冻结。 已尝试添加"Task_sleep (1000)"、这可能是由于"发送速度太快"。 同样的问题、但这次只能发送大约400次-更改 Task_sleep 上的值使它看起来像是一个定时事件、UART_WRITE 在第一次调用后中断 x 秒。 甚至在回调中添加了错误检查、也看不到任何东西。

因此、我有2个问题。 当使用 UART_READ 时、UART_WRITE 不起作用。 UART_WRITE 会在一段时间后中断。



我正在使用:

  • 适用于 CC13xx 和 CC26xx 2.21.1.08的 TI-RTOS
  • BLE_SDK_2_02_02_25
  • 编译器 TI v18.1.0.LTS -尝试安装 v16.9.4.LTS、但它出错、CCS 找不到解决方法。
  • CCS 版本:8.1.0.00011

/* XDCtools 头文件*/
#include 
#include 

/* BIOS 头文件*/
#include 
#include 
#include 
//#include 

#include 
#include 
//#include 
#include 

#include "iCall.h"


#define TASKSTACKSIZE 2048

任务结构任务0Struct;
特性任务0Stack[TASKSTACKSIZE];

Semaphore_StructSemStruct;
Semaphore_Handle readSem;
Semaphore_StructSem; semaphore_StructWrite;
Semaphore_handle writeSem;

UART_Handle UART;
#define UART_buffer_size 128
uint8_t UART_buffer[UART_buffer_size];
#define UART_circe_buffer_size 256
uint8_t UART_receivarBuffer[UART_rend_size];
uint32_t UART_head = 0;uint8_t
uint0_t uint0_t Utend

= uint8;uint32_t uint0_t uinteuint0_unt uintt_




void UART_readCB (UART_Handle _handle、void *buf、size_t count)
{

//(((UARTCC26XX_Handle) handle -> object)-> status
//if (((UARTCC26XX_handle) handle -> object)-> status

uint32_t size =((UARTCC26XX_handle)_handle->object)->ReadCount;

uint32_t 可用= 0;
//if (UART_HEAD >= UART_TAIL)
可用= UART_圆形 缓冲区大小- 1 - UART_HEAD + UART_TAIL;
//else
//可用= uart_circed_buffer_size - uart_head + uart_tail;
int i = 0;
对于(i = 0;i < size && i < available;i++){
UART_循环 缓冲器[UART_HEAD]= UART_buffer[i];
UART_HEAD++;
if (uart_head >= uart_circed_buffer_size)
UART_HEAD = 0;
}



Semaphore_post (readSem);
接收计数器++;


/*我知道这是不建议的。 我看到它是在 SDI 中完成的、没有使用 SDI、因为它在某个地方冻结了缓冲器、我不需要任何复杂的东西*
UART_READ (UART、&UART_buffer[0]、UART_buffer_size);

}

uint32_t sentCounter = 0;
void UART_writeCB (UART_Handle _handle、void * buf、size_t count)
{
ICall_CSState 密钥;
键= iCall_enterCriticalSection();
uint8_t errStatus = 0;
if (errStatus =((UARTCC26XX_Handle)_handle -> object)-> status)
{//UART_RXERROR_溢出

while (1);
}
Semaphore_post (writeSem);
sentCounter++;
iCall_leaveCriticalSection (key);
}
//*
===== 回声 Fxn =====
*此函数的任务是静态创建的。 请参阅工程的.cfg 文件。
*/
void echoFxn (UArg0、UArgarg1)
{
字符输入;

UART_Params uartParams;
const char echoPrompt[]="回显字符:\r\n";
Semaphore_Params semParams;

/*构造要用作资源锁定的信标对象,初始计数1 */
Semaphore_Params_init (semParams);
semParams.instance->name ="读取信标";
Semaphore_construction (&semStruct, 0, semParams);
/*获取实例句柄*/
readSem = semaphore_handle (&semStructt);

Semaphore_Params_init (semParams);
semParams.instance->name ="写入信标";
Semaphore_construct(&semStructWrite, 0,&semParams);
/*获取实例句柄*/
writeSem = semaphore_handle (&semStructWrite);

/*创建一个数据处理关闭的 UART。 *
UART_PARAMS_INIT (uartParams);
uartParams.writeDataMode = UART_DATA_BINARY;
uartParams.readDataMode = UART_DATA_BINARY;
uartParams.readReturnMode = UART_return_full;
uartParams.readEcho = UART_ECHO_OFF;
uartParams.baudrate = 921600;
uartParams.readMode = UART_MODE_CALLACK;
uartParams.writeMode = UART_MODE_CALLBACK;

uartParams.readCallback = UART_readCB;
uartParams.writeCallback = UART_writeCB;
UART = UART_OPEN (Board_UART0、uartParams);

if (UART == NULL){
System_abort ("打开 UART 时出错");
}
UART_CONTROL (UART、UARTCC26XX_RETURE_PARTIAL_ENABLE、空);

UART_WRITE (UART、echoPrompt、sizeof (echoPrompt));
Semaphore_pend (writeSem、BIOS_wait_forever);

//读取注释后仅发送测试的代码*/
//UART 读取(UART、&UART_buffer[0]、UART_buffer_size);

while (1){

//读取注释后仅发送测试的代码*/
//semaphore_pend (readSem、BIOS_wait_forever);
//uint32_t tail = UART_tail;
//uint32_t head = UART_HEAD;
//uint32_t toSend = 0;
//if (头部>=尾部)
// toSend =头-尾;
//else
// toSend = head + UART_Circular 缓冲区大小- tail;


char test[]="hi\r\n";
volatile int error = UART_WRITE (UART、test、sizeof (test)));
if (error ==UART_ERROR){
volatile int32_t temp = 0;
temp =((UARTCC26XX_handle) UART->object)->status;
while (1);
}
Semaphore_pend (writeSem、BIOS_wait_forever);
Task_sleep (1000);


//读取注释后仅发送测试的代码*/
//tail += toSend;
//_UART_tail = tail -(tail / UART_circed_buffer_size)* UART_circed_buffer_size;



}
}

void UART_CreateTask(){
//Board_initGeneral();这是 main 已经调用的 PIN_Init
Board_initUART();

Task_Params taskParams;

/*构造 BIOS 对象*/
Task_Params_init (&taskParams);
taskParams.STACKSIZE = TASKSTACKSIZE;
taskParams.priority = 2;
taskParams.stack =_task0Stack;
Task_construct(&task0Struct,(Task_Functr) echoFxn、&taskParams、NULL);

}

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

    一些额外信息:

    在 UART_WRITE 测试中运行、而不使用 UART_READ、我在其中持续发送。 代码在地址"0x10000486"处停止、并设置 UART 忙标志。

    我忘记添加、但波特率为921600。 它在提供的代码中、但可能值得强调。

    CTS 和 RTS 引脚已设置,因此它应该可以正常工作,但我在 CTS....中有一个内部下拉电阻 在我写这篇文章时、我决定检查在所有驱动程序中、它是否会覆盖该下拉配置。  因此我将 CTS 引脚连接到 GND、看起来下拉电阻不起作用。

    它发送了更多数据、但这次在3.4k 传输时停止(在 Task_sleep (1000)中、它在400停止)、调试器连接不好、传输停止:

    "Cortex_M3_0:目标 CPU 停止时出现问题:(错误-2062 @ 0x0)无法停止器件。 重置设备、然后重试此操作。 如果错误仍然存在、请确认配置、对电路板进行下电上电和/或尝试更可靠的 JTAG 设置(例如、较低的 TCLK)。 (仿真包8.0.27.9)"

    请注意,我正在使用表达式的自动刷新来检查一个变量,该变量指出发生了多少次传输,不知道这是否重要。

    在未连接编译器的情况下进行了测试、发送了递增的数字、而不是用固定的20个数字"高"、并且它没有冻结高达20k 的传输(没有进一步测试)。

    此 CTS 外部下拉业务似乎也解决了 UART_READ 冻结 UART_WRITE 问题。

    甚至尝试添加完全预期的回调代码、但效果很好。

    奇怪的是、它只会在使用 UART_READ 后发生、并且仅在使用 UART_WRITE 时才会在一段时间后冻结。

    我之前尝试过内部下拉、看起来工作正常。  

    CTS 是否有下拉电阻? 我们拥有的电路板在 CC2650中实际上并不需要 CTS、它也未连接任何部件。

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

    您好、Luis、

    让我们从 CTS 下拉开始、UART 驱动程序不会配置 CTS、在分配引脚时会出现下拉。
    如果您不需要 CTS、我建议您在电路板文件中将 CTS 引脚设置为未分配、并查看这是否适合您(这也意味着如果您不需要该引脚、则保存物理引脚)。

    自动刷新可能会在较高波特率下导致一些 UART 问题、因为它涉及通过 JTAG 进行调试交互、而 JTAG 本身可能会影响器件。 如果您没有自动刷新功能并且 CTS 下拉电阻器处于打开状态、是否正常工作?

    有关 CC2650和 UART 驱动程序的另一个注意事项。 CC2650 SDK 提供了一个相当旧的 UART 驱动程序版本。 驱动程序本身已有多个错误修复、我建议您下载并使用更新版本的驱动程序。 遗憾的是、您必须下载另一个器件 SDK (如 CC13x0 2.20 SDK)并从该 SDK 中提取 UARTCC26XX。[c/h]文件、然后将其直接添加到您的 CC2650项目中以执行此操作。

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

    您好、M-W、

    感谢您的回复。 关于驱动器。 我没有遇到任何不好的问题(尽管升级可能会解决一些问题)。 您说 CC13x0 SDK 是否具有 CC26xx 驱动程序? 我已经下载了这个:

    CC2650的这种使用将非常简单、现在似乎正在进行(经过一些工作)。 CC2652的使用时间将更长、等待其中一个模块推出。 因此、我可能会保持原样。


    下拉的更多信息。 我想禁用 CTS、但这是否正常? 我需要为此编辑驱动程序。 CC26xx.c 初始化中的这段代码仅在分配了两个引脚时才允许流控制。 这段代码位于函数  UARTCC26XX_initHw 中。

    /*如果启用了流控制,则配置硬件控制的流控制*/
    if (isFlowControlEnabled (hwAttrs)){
    HWREG (UART0_BASE + UART_O_CTL)|=(UART_CTL_CTSEN | UART_CTL_RTSEN);
    }
    
    
    ///------------------------
    //isFlowControlEnabled (/isFlowControlEnabled):
    静态内联 bool isFlowControlEnabled (UARTCC26XX_HWAttrsV2 const * hwAttrs){
    返回((hwAttrs->ctsPin!= PIN_Unassigned)&&(hwAttrs->rtsPin!= PIN_Unassigned));
    } 

    
    

    我要将其更改为

    if (hwAttrs->ctsPin!= PIN_Unassigned)
    HWREG (UART0_BASE + UART_O_CTL)|=(UART_CTL_CTSEN);
    if (hwAttrs->rtsPin!= PIN_Unassigned)
    HWREG (UART0_BASE + UART_O_CTL)|=(UART_CTL_RTSEN); 






    如果这正常工作、UART 的工作实际上是在项目中完成的。 我让它工作、可能不如团队那么优雅、但它不会冻结、数据丢失或溢出。


    编辑:这个+然后未分配的 CTSpin 解决了我的问题。


  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    在大多数情况下、所有 CC26x0和 CC13x0器件共享相同的外设驱动程序、例如 UART 驱动程序。
    但是、您所使用的堆栈中未提供最新的驱动程序、因此您必须从另一个 SDK (例如 CC13x0的 SDK)中获取这些驱动程序。

    没错、我忘记了流控制检查、需要同时分配 CTS 和 RST 引脚。 在这种情况下、您的更改看起来是合乎逻辑的(根据您的观点、它似乎也是这样!)。