4126|2

1379

帖子

2

TA的资源

五彩晶圆(初级)

楼主
 

【CC1352P测评】TI-RTOS uartecho小试 [复制链接]

  为了理解 TI-RTOS 的工作方式,我找了 SDK 的例子——rtos下面driver目录中的 uartecho 工程来分析。这个例子的作用很简单,就是从 UART 接收字符再发送出去,从开发板的虚拟串口可以测试(回显效果)。
  SDK 中不包含 TI-RTOS 部分的预编译库代码,所以需要事先编译一下。如果是使用 CCS 开发环境,导入这个工程以后会自动处理。我用命令行直接编译工程,就需要到 SDK 的 kernel/tirtos/builds/CC1352P1_LAUNCHXL/release/gcc 目录下去手动 make 一下。除了GCC的路径,xdc_tools 的路径还需要在 imports.mak 中设置(小改一下,虽然它是随SDK安装的)。

 

  这个例子不用到无线部分,于是文件也简单一些,一共是 uartecho.obj main_tirtos.obj CC1352P1_LAUNCHXL.obj CC1352P1_LAUNCHXL_fxns.obj ccfg.obj 这五个模块。我们只需要重点关注前两个。

  主函数做的也就是初始化 RTOS 环境,比我分析过的 nortos 例子多些代码:

int main(void)
{
    pthread_t           thread;
    pthread_attr_t      attrs;
    struct sched_param  priParam;
    int                 retc;
    /* Call driver init functions */
    Board_initGeneral();
    /* Initialize the attributes structure with default values */
    pthread_attr_init(&attrs);
    /* Set priority, detach state, and stack size attributes */
    priParam.sched_priority = 1;
    retc = pthread_attr_setschedparam(&attrs, &priParam);
    retc |= pthread_attr_setdetachstate(&attrs, PTHREAD_CREATE_DETACHED);
    retc |= pthread_attr_setstacksize(&attrs, THREADSTACKSIZE);
    if (retc != 0) {
        /* failed to set attributes */
        while (1) {}
    }
    retc = pthread_create(&thread, &attrs, mainThread, NULL);
    if (retc != 0) {
        /* pthread_create() failed */
        while (1) {}
    }
    BIOS_start();
    return (0);
}

  照样先用 Board_initGeneral() 初始化板子,这个函数实现和我分析过的 rfEasyLink_nortos 例子当中的一样。然后,是设置线程的属性,使用了 pthread_attr_setschedparam(), pthread_attr_setdetachstate(), pthread_attr_setstacksize() 三个函数,接下来用 pthread_create() 创建线程。最后调用 BIOS_start() 开始运行。

  mainThread() 函数看起来就是常规操作了,没有用到线程相关的 API.

void *mainThread(void *arg0)
{
    char        input;
    const char  echoPrompt[] = "Echoing characters:\r\n";
    UART_Handle uart;
    UART_Params uartParams;
    /* Call driver init functions */
    GPIO_init();
    UART_init();
    /* Configure the LED pin */
    GPIO_setConfig(Board_GPIO_LED0, GPIO_CFG_OUT_STD | GPIO_CFG_OUT_LOW);
    /* Turn on user LED */
    GPIO_write(Board_GPIO_LED0, Board_GPIO_LED_ON);
    /* Create a UART with data processing off. */
    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 = 115200;
    uart = UART_open(Board_UART0, &uartParams);
    if (uart == NULL) {
        /* UART_open() failed */
        while (1);
    }
    UART_write(uart, echoPrompt, sizeof(echoPrompt));
    /* Loop forever echoing */
    while (1) {
        UART_read(uart, &input, 1);
        UART_write(uart, &input, 1);
    }
}

  那么,用 RTOS 的意义怎么体现?其实在 UART_read() 和 UART_write() 函数内部,它们并不是简单地对硬件设备寄存器进行读写操作。比如看 UART_read 是这样实现的:

int_fast32_t UART_read(UART_Handle handle, void *buffer, size_t size)
{
    return (handle->fxnTablePtr->readFxn(handle, buffer, size));
}

UART_Handle 类型是指向 struct UART_Config_ 类型的指针,

typedef struct UART_Config_ {
    /*! Pointer to a table of driver-specific implementations of UART APIs */
    UART_FxnTable const *fxnTablePtr;
    /*! Pointer to a driver specific data object */
    void *object;
    /*! Pointer to a driver specific hardware attributes structure */
    void const *hwAttrs;
} UART_Config;

在主线程中事先对 UART 进行初始化,这里初始化了所有的 UART,是通过 SDK API UART_init().

void UART_init(void)
{
    uint_least8_t i;
    uint_fast32_t key;
    key = HwiP_disable();
    if (!isInitialized) {
        isInitialized = (bool) true;
        /* Call each driver's init function */
        for (i = 0; i < UART_count; i++) {
            UART_config[i].fxnTablePtr->initFxn((UART_Handle) &(UART_config[i]));
        }
    }
    HwiP_restore(key);
}

  值得注意的是,UART_init() 要用到的 UART_config[] 结构数组,以及 UART_config 变量都是在 CC1352P1_LAUNCHXL.c 当中定义的:

const UART_Config UART_config[CC1352P1_LAUNCHXL_UARTCOUNT] = {
    {
        .fxnTablePtr = &UARTCC26XX_fxnTable,
        .object      = &uartCC26XXObjects[CC1352P1_LAUNCHXL_UART0],
        .hwAttrs     = &uartCC26XXHWAttrs[CC1352P1_LAUNCHXL_UART0]
    },
    {
        .fxnTablePtr = &UARTCC26XX_fxnTable,
        .object      = &uartCC26XXObjects[CC1352P1_LAUNCHXL_UART1],
        .hwAttrs     = &uartCC26XXHWAttrs[CC1352P1_LAUNCHXL_UART1]
    },
};

  因此 fxnTablePtr 指针是系统预设的常量,指向 UARTCC26XX_fxnTable ——它是driver代码中定义的常量:

const UART_FxnTable UARTCC26XX_fxnTable = {
    UARTCC26XX_close,
    UARTCC26XX_control,
    UARTCC26XX_init,
    UARTCC26XX_open,
    UARTCC26XX_read,
    UARTCC26XX_readPolling,
    UARTCC26XX_readCancel,
    UARTCC26XX_write,
    UARTCC26XX_writePolling,
    UARTCC26XX_writeCancel
};

  所以在主线程调用的 UART_read(), 效果是调用了 UARTCC26XX_read() 函数,其源文件在 UARTCC26XX.c 中,写得还蛮长的,因此就不贴在这里了。其中用到了信号量(Semaphore)相关的函数,已经涉及操作系统方面的特性了。其实 SDK 的 UART 驱动是和 nortos 程序共用的,nortos 程序可以看成 TI-RTOS 的单线程简化版本。为什么还要把单线程程序做这么复杂?为了降低功耗,让 SDK 底层代码去管理省电模式

 

  作为 RTOS 的测试,不妨改写一个点灯的的程序吧。增加一个线程 testThread 如下:

#include <ti/sysbios/knl/Task.h>
void *testThread(void *arg0)
{
	Task_sleep(100000);
    GPIO_setConfig(Board_GPIO_LED1, GPIO_CFG_OUT_STD | GPIO_CFG_OUT_LOW);
    for(;;)
    {
		GPIO_write(Board_GPIO_LED1, Board_GPIO_LED_ON);
		Task_sleep(100000);
		GPIO_write(Board_GPIO_LED1, Board_GPIO_LED_OFF);
		Task_sleep(100000);
	}
}

在 main() 中也多加一行代码来创建它:
 retc |= pthread_create(&thread1, &attrs, testThread, NULL);

  重新编译以后下载,就实现了原来的 uartecho 附带 LED1 间歇亮灭的效果。

此内容由EEWORLD论坛网友cruelfox原创,如需转载或用于商业用途需征得作者同意并注明出处

此帖出自RF/无线论坛

最新回复

是啊,怎么会多出些东西。   详情 回复 发表于 2019-7-8 08:28
点赞 关注
 

回复
举报

1万

帖子

2853

TA的资源

管理员

沙发
 

一行奇怪的图标我看到了,明早就找技术查查看

此帖出自RF/无线论坛
加EE小助手好友,
入技术交流群
EE服务号
精彩活动e手掌握
EE订阅号
热门资讯e网打尽
聚焦汽车电子软硬件开发
认真关注技术本身
个人签名玩板看这里:
https://bbs.eeworld.com.cn/elecplay.html
EEWorld测评频道众多好板等你来玩,还可以来频道许愿树许愿说说你想要玩的板子,我们都在努力为大家实现!
 
 

回复

2618

帖子

0

TA的资源

纯净的硅(高级)

板凳
 

是啊,怎么会多出些东西。

此帖出自RF/无线论坛
 
 
 

回复
您需要登录后才可以回帖 登录 | 注册

随便看看
查找数据手册?

EEWorld Datasheet 技术支持

相关文章 更多>>
快速回复 返回顶部 返回列表