查看: 2684|回复: 1

[原创] 让rtt运行起来

[复制链接]
  • TA的每日心情
    开心
    2023-2-20 03:47
  • 签到天数: 2 天

    连续签到: 1 天

    [LV.1]初来乍到

    10

    主题

    30

    帖子

    0

    中级会员

    Rank: 3Rank: 3

    积分
    332
    最后登录
    2025-3-13
    发表于 2023-2-17 00:36:54 | 显示全部楼层 |阅读模式
    本帖最后由 supenghou 于 2023-2-17 01:09 编辑

    使rtt运行起来关键要素两个:
    1、 led灯闪烁起来—main函数
    2、 让串口进行命令行调试信息
    首先led亮起来
    Led关键信息
    代码:
    IO引脚声明
    1. /* defined the LED pin: GPIO1_IO4 */
    2. /* GPIO1_4 is Blue LED */
    3. #define LEDB_PIN      GET_PINS(1, 4)
    复制代码

    IO所声明的引脚

    1. rt_pin_write(LEDB_PIN, PIN_HIGH);   /* Set GPIO output 1 */
    2. rt_thread_mdelay(500);                     /* Delay 500mS */
    3. rt_pin_write(LEDB_PIN, PIN_LOW);    /* Set GPIO output 0 */
    4. rt_thread_mdelay(500);                     /* Delay 500mS */
    复制代码


    驱动说明,这里巧妙在宏定义
    #define GET_PINS(PORTx, PINx)   (32 * PORTx + PINx + 1) /* PORTx:0,1, PINx:0,1...31 */
    (1,4) 代入既是32*1+4+1=37
    在驱动drv_pin.c中查表lpc_pin_map[],(在其他芯片有叫pin[]的或者其他名字的)
    列表实现:
    1. static struct lpc_pin lpc_pin_map[] =
    2. {
    3.        __LPC55S69_PIN_DEFAULT,//代表0无效
    4. __LPC55S69_PIN(1, GPIO, 0,  0),    /* PIO0_00 */
    5.       __LPC55S69_PIN( 2, GPIO, 0, 1),    /* PIO0_01 */
    6.       __LPC55S69_PIN( 3, GPIO, 0, 2),    /* PIO0_02 */
    7.       __LPC55S69_PIN( 4, GPIO, 0, 3),    /* PIO0_04 */
    8.       __LPC55S69_PIN( 5, GPIO, 0, 4),    /* PIO0_04 */
    9. ……
    10. /* PIO1 / GPIO,1 */
    11.       __LPC55S69_PIN(33, GPIO, 1, 0),    /* PIO1_00 */
    12.       __LPC55S69_PIN(34, GPIO, 1, 1),    /* PIO1_01 */
    13.       __LPC55S69_PIN(35, GPIO, 1, 2),    /* PIO1_02 */
    14.       __LPC55S69_PIN(36, GPIO, 1, 3),    /* PIO1_03 */
    15. <font color="#ff0000">      __LPC55S69_PIN(37, GPIO, 1, 4),    /* PIO1_04 */</font>
    16.       __LPC55S69_PIN(38, GPIO, 1, 5),    /* PIO1_05 */
    17. ……

    18. }
    复制代码

    #define __LPC55S69_PIN(INDEX, REG, PORT,PIN) {INDEX, REG, PORT, PIN}
                                          序号    属性   大类  分类IO序号
    通过宏定义得知给驱动拼凑字符的,这里不明显,引用其他的芯片特性
    比如单片机es8p5086驱动相关
    __ES8P_PIN(3, B, 2)
    则宏定义为#define __ES8P_PIN(index, gpio,gpio_index) {index, GPIO##gpio, GPIO_Pin_##gpio_index}
    使用#把宏参数变为一个字符串,用##把两个宏参数贴合在一起,既为(3,GPIOB,GPIO_Pin_2)
    关键字符GPIOB和GPIO_Pin_2,这样驱动,有转义字符对应的数字好处具有直视感。
    操作方法和芯片给与的驱动有关系,他要什么,程序就要给什么。
    我这里用的自己板子,led1是P1.1
    我就把上面的GET_PINS(1, 4)该成了GET_PINS(1, 1)。

    第二个需要改的是命令调试串口,这里板子和例程对应上去了无需更改,但是也说以下
    更改串口,主要三个位置
    1、启用对应串口驱动,2、串口对应的io脚位的对应,3、命令控制台挂在串口上
    1、在rt_config.h

    1

    1
    2、在drv_uart.c
    实际上对外输出驱动具有寄存器,数据缓存操作区,然后针对io的映射设置三大项
    上面开启串口0就是寄存器和数据缓存区打通了,然后这里对io映射进行打通,因为一个模块比如串口0可以映射到多个io口进行对外操作。
    啰嗦语:实际上驱动关键信息是以结构体形式封装为整体,由系统进行发起,驱动对结构体进行实现,而驱动之际占用数据存储内存为通用内存池,驱 动实现了结构体的操作地址,换句话说是操作系统通过结构体的动作操作地址来找驱动操作方法,这里进行包含与反包含的操作,而驱动的中断也由驱动实现,尽可能的短暂的把操作把寄存器数据存储到数据缓存操作区,可以通知系统后续操作。重点在那个驱动结构体,也叫类,而动用驱动的句柄就是指引到这个类的。Find句柄得驱动,也得到驱动的“操作”。
    但是io的定义在上述文件drv_uart.c未找到,那整个板子得io口都是整板声明了,很板级化,在下述文件pin_mux.c中找到了io定义位置:
    1. void BOARD_InitPins(void)
    2. {
    3.    /* Enables the clock for the I/O controller.: Enable Clock. */
    4.     CLOCK_EnableClock(kCLOCK_Iocon);
    5.     ... ...
    6.     const uint32_t port0_pin29_config = (/* Pinis configured as FC0_RXD_SDA_MOSI_DATA */ <font color="#ff0000">//串口P0.29_UART_RXD</font>
    7.                                         IOCON_PIO_FUNC1 |
    8.                                          /* Noaddition pin function */
    9.                                          IOCON_PIO_MODE_INACT|
    10.                                          /*Standard mode, output slew rate control is enabled */
    11.                                         IOCON_PIO_SLEW_STANDARD |
    12.                                          /* Input function is not inverted */
    13.                                         IOCON_PIO_INV_DI |
    14.                                          /*Enables digital function */
    15.                                         IOCON_PIO_DIGITAL_EN |
    16.                                          /* Open drain isdisabled */
    17.                                         IOCON_PIO_OPENDRAIN_DI);
    18.     /* PORT0 PIN29 (coords: 92) is configuredas FC0_RXD_SDA_MOSI_DATA */
    19.     IOCON_PinMuxSet(IOCON, 0U, 29U,port0_pin29_config);

    20.     const uint32_t port0_pin30_config = (/* Pinis configured as FC0_TXD_SCL_MISO_WS */<font color="#ff0000"> //串口P0.30_UART_TXD</font>
    21.                                         IOCON_PIO_FUNC1 |
    22.                                          /* Noaddition pin function */
    23.                                         IOCON_PIO_MODE_INACT |
    24.                                          /*Standard mode, output slew rate control is enabled */
    25.                                          IOCON_PIO_SLEW_STANDARD |
    26.                                          /*Input function is not inverted */
    27.                                         IOCON_PIO_INV_DI |
    28.                                          /*Enables digital function */
    29.                                         IOCON_PIO_DIGITAL_EN |
    30.                                          /*Open drain is disabled */
    31.                                         IOCON_PIO_OPENDRAIN_DI);
    32.     /* PORT0 PIN30 (coords: 94) is configuredas FC0_TXD_SCL_MISO_WS */
    33.     IOCON_PinMuxSet(IOCON, 0U, 30U,port0_pin30_config);
    34.     ... ...
    35. }
    复制代码
    在这个函数调用
    1. void BOARD_InitBootPins(void)
    2. {      //主板初始化引导
    3. <font color="#ff0000">   BOARD_InitPins();</font>
    4. }
    复制代码

    这里就涉及到芯片引脚定义工具了,不是人为的写入。实用了io引脚定义化工具来勾选是arm高级芯片常规操作,一个程序直接对应一套板子,io固定。
    实际上上面函数没用,属于批量生成函数。
    而在board.c中用初始化函数调用了 BOARD_InitPins();  。
    1. void rt_hw_board_init()
    2. {
    3.    /* Hardware Initialization */
    4. <font color="#ff0000">    BOARD_InitPins();         //调用在这里</font>
    5.     ... ...
    6. }
    复制代码
    而函数rt_hw_board_init()又被components.c中的如下函数调用
    1. int rtthread_startup(void)
    2. {
    3.     ... ...
    4. <font color="#ff0000">    rt_hw_board_init();</font>
    5.     ... ...
    6. }
    复制代码

    而上述函数又被main截胡函数引用
    1. int $Sub$main(void)
    2. {
    3. <font color="#ff0000">   rtthread_startup();</font>
    4.    return 0;
    5. }
    复制代码

    我一直以为会被组件初始化宏接口调用比如INIT_BOARD_EXPORT(rt_hw_board_init);初始化结果如此简单粗暴,实际用了int $Sub$$main(void)函数,函数作用是在执行main前截胡,执行这个函数,然后再通过对应语句回去,但是众所周知,是回不去的,rtt把main函数当成线程了,启动main线程了,也就是rtt不会像前后台那样执行main函数,而是做成了优先级为20的线程,main函数只有象征意义了。
    3、使用uart0为控制台输出
    也在rt_config.h里定义

    2

    2
    这里直接引用了设备名称,因为在调用串口之前,会find到串口句柄,后续命令控制台就可以操作了。

    罗嗦语:其实find有好多种,驱动find,就是在容器内找对应名字的句柄,除了驱动find外还有通用find,只要知道名字你就能找到线程然后继续操作,或者找寻信号量,只要知道名字,因为任何类都在大统一容器内,而容器分类后所有的东西都是通过链表挂连的.
    其实rtt就是一种c面向对象的编程方法教材。
    在github下载的5.0遇到的问题
    回复

    使用道具 举报

  • TA的每日心情
    开心
    2025-7-11 08:53
  • 签到天数: 301 天

    连续签到: 2 天

    [LV.8]以坛为家I

    3887

    主题

    7494

    帖子

    0

    管理员

    Rank: 9Rank: 9Rank: 9

    积分
    39457
    最后登录
    2025-7-25
    发表于 2023-2-20 14:01:01 | 显示全部楼层
    可以可以
    qiandao qiandao
    回复

    使用道具 举报

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

    本版积分规则

    关闭

    站长推荐上一条 /3 下一条

    Archiver|手机版|小黑屋|恩智浦技术社区

    GMT+8, 2025-7-27 08:26 , Processed in 0.083457 second(s), 21 queries , MemCache On.

    Powered by Discuz! X3.4

    Copyright © 2001-2024, Tencent Cloud.

    快速回复 返回顶部 返回列表