查看: 1462|回复: 0
收起左侧

RISC-V单片机快速入门04-基于RT_Thread Nano添加FinSH

[复制链接]
发表于 2020-6-26 20:27:31 | 显示全部楼层 |阅读模式

有人预言,RISC-V或将是继Intel和Arm之后的第三大主流处理器体系。欢迎访问全球首家只专注于RISC-V单片机行业应用的中文网站

您需要 登录 才可以下载或查看,没有帐号?立即注册

x
本帖最后由 小飞飞 于 2020-8-28 19:51 编辑

RISC-V单片机快速入门01-开发环境搭建
RISC-V单片机快速入门02-移植RT_Thread Nano
RISC-V单片机快速入门03-基于RT_Thread Nano添加控制台
RISC-V单片机快速入门04-基于RT_Thread Nano添加FinSH
RISC-V单片机快速入门05-串口助手发送AT指令启动TCP Server
RISC-V单片机快速入门06-控制ESP8266启动Http Server
RISC-V单片机快速入门07-板载LCD显示ESP8266数据


本系列上一篇:RISC-V单片机快速入门03-基于RT_Thread Nano添加控制台

一基础知识

1.FinSH简介

RT-Thread FinSH 是 RT-Thread 的命令行组件(shell),提供一套供用户在命令行调用的操作接口,主要用于调试或查看系统信息。它可以使用串口 / 以太网 / USB 等与 PC 机进行通信,本文使用串口进行通信,使用 FinSH 组件基本命令的效果图如下所示:

基于RT_Thread Nano添加FinSH_01.png

二,添加步骤

1.导入工程

将上一节内容进行复制,修改.project中工程名字为FinSH,然后重新import进来新的工程

基于RT_Thread Nano添加FinSH_02.png

2.添加FinSH源码到工程

将rt-thread-3.1.3/components/finsh下文件添加到RT-Thread下。

基于RT_Thread Nano添加FinSH_03.png


添加成功后结果如下:

基于RT_Thread Nano添加FinSH_04.png


3.添加头文件路径

右击工程,点击 properties 进入下图所示界面,点击 C/C++ Build -> settings ,添加头文件路径

基于RT_Thread Nano添加FinSH_05.png


4.打开宏定义

添加号FinSH组件源码后,可以看到实际功能并没有打开,需要开启RT_USING_FINSH宏定义。

基于RT_Thread Nano添加FinSH_06.png


打开rtconfig.h文件,增加宏定义:#define RT_USING_FINSH

基于RT_Thread Nano添加FinSH_07.png

5.适配FinSH组件接口

(1) 修改GD32VF103xB.lds文件


基于RT_Thread Nano添加FinSH_08.png


在上图.text中添加如下代码:
  1. /* section information for finsh shell */
  2. . = ALIGN(4);
  3. __fsymtab_start = .;
  4. KEEP(*(FSymTab))
  5. __fsymtab_end = .;
  6. . = ALIGN(4);
  7. __vsymtab_start = .;
  8. KEEP(*(VSymTab))
  9. __vsymtab_end = .;
  10. . = ALIGN(4);

  11. /* section information for initial. */
  12. . = ALIGN(4);
  13. __rt_init_start = .;
  14. KEEP(*(SORT(.rti_fn*)))
  15. __rt_init_end = .;
  16. . = ALIGN(4);

  17. /* section information for modules */
  18. . = ALIGN(4);
  19. __rtmsymtab_start = .;
  20. KEEP(*(RTMSymTab))
  21. __rtmsymtab_end = .;
复制代码


修改后如下所示

基于RT_Thread Nano添加FinSH_09.png


(2) 移植函数

本文采用中断方式获取串口接收到字符,原理是,在 uart 接收到数据时产生中断,在中断中把数据存入 ringbuffer 缓冲区,然后释放信号量,tshell 线程接收信号量,然后读取存在 ringbuffer 中的数据。

在gd32vf102c_start.c文件中,实现rt_hw_console_getchar如下:
  1. #define UART_RX_BUF_LEN 128
  2. rt_uint8_t uart_rx_buf[UART_RX_BUF_LEN] = {0};
  3. struct rt_ringbuffer uart_rxcb; /* 定义一个 ringbuffer cb */
  4. static struct rt_semaphore shell_rx_sem; /* 定义一个静态信号量 */
  5. void gd_eval_com_init(uint32_t com)
  6. {
  7. uint32_t com_id = 0U;
  8. if(EVAL_COM0 == com){
  9.         com_id = 0U;
  10.     }else if(EVAL_COM1 == com){
  11.         com_id = 1U;
  12.     }

  13. /* 初始化串口接收 ringbuffer  */
  14.     rt_ringbuffer_init(&uart_rxcb, uart_rx_buf, UART_RX_BUF_LEN);

  15. /* 初始化串口接收数据的信号量 */
  16.     rt_sem_init(&(shell_rx_sem), "shell_rx", 0, 0);

  17.     eclic_irq_enable(USART0_IRQn, 1, 0);

  18. /* enable GPIO clock */
  19.     rcu_periph_clock_enable(COM_GPIO_CLK[com_id]);

  20. /* enable USART clock */
  21.     rcu_periph_clock_enable(COM_CLK[com_id]);

  22. /* connect port to USARTx_Tx */
  23.     gpio_init(COM_GPIO_PORT[com_id], GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, COM_TX_PIN[com_id]);

  24. /* connect port to USARTx_Rx */
  25.     gpio_init(COM_GPIO_PORT[com_id], GPIO_MODE_IN_FLOATING, GPIO_OSPEED_50MHZ, COM_RX_PIN[com_id]);

  26. /* USART configure */
  27.     usart_deinit(com);
  28.     usart_baudrate_set(com, 115200U);
  29.     usart_word_length_set(com, USART_WL_8BIT);
  30.     usart_stop_bit_set(com, USART_STB_1BIT);
  31.     usart_parity_config(com, USART_PM_NONE);
  32.     usart_hardware_flow_rts_config(com, USART_RTS_DISABLE);
  33.     usart_hardware_flow_cts_config(com, USART_CTS_DISABLE);
  34.     usart_receive_config(com, USART_RECEIVE_ENABLE);
  35.     usart_transmit_config(com, USART_TRANSMIT_ENABLE);
  36.     usart_enable(com);
  37.     usart_interrupt_enable(com, USART_INT_RBNE);
  38. }

  39. char rt_hw_console_getchar(const char str)
  40. {
  41. int ch = 0;
  42.     / 从 ringbuffer 中拿出数据 */
  43. while (rt_ringbuffer_getchar(&uart_rxcb, (rt_uint8_t *)&ch) != 1)
  44.     {
  45.         rt_sem_take(&shell_rx_sem, RT_WAITING_FOREVER);
  46.     }
  47. return ch;
  48. }

  49. void USART0_IRQHandler() {
  50. int ch = -1;
  51. int recv_flag = 0;
  52. /* enter interrupt /
  53.     rt_interrupt_enter();
  54. if(RESET != usart_interrupt_flag_get(EVAL_COM0, USART_INT_FLAG_RBNE)){
  55. while (1)
  56.         {
  57.             ch = -1;
  58. if (RESET != usart_interrupt_flag_get(EVAL_COM0, USART_INT_FLAG_RBNE))
  59.             {
  60.                 ch =  usart_data_receive(EVAL_COM0);
  61. //                rt_kprintf("recv data is :%x\r\n", ch);
  62.             }
  63. if (ch == -1)
  64.             {
  65. break;
  66.             }
  67.             recv_flag = 1;
  68.             / 读取到数据,将数据存入 ringbuffer */
  69.             rt_ringbuffer_putchar(&uart_rxcb, ch);
  70.         }
  71. //        if (1 == recv_flag)
  72. //        {
  73.             rt_sem_release(&shell_rx_sem);
  74. //        }
  75.     }
  76.     rt_interrupt_leave();
  77. }

  78. 新增ringbuffer.c函数
  79. /* 第一部分:ringbuffer 实现部分 */
  80. #include <rtthread.h>
  81. #include <string.h>
  82. #include "ringbuffer.h"
  83. rt_inline enum rt_ringbuffer_state rt_ringbuffer_status(struct rt_ringbuffer *rb)
  84. {
  85. if (rb->read_index == rb->write_index)
  86.     {
  87. if (rb->read_mirror == rb->write_mirror)
  88. return RT_RINGBUFFER_EMPTY;
  89. else
  90. return RT_RINGBUFFER_FULL;
  91.     }
  92. return RT_RINGBUFFER_HALFFULL;
  93. }
  94. /**
  95. * get the size of data in rb
  96. */
  97. rt_size_t rt_ringbuffer_data_len(struct rt_ringbuffer *rb)
  98. {
  99. switch (rt_ringbuffer_status(rb))
  100.     {
  101. case RT_RINGBUFFER_EMPTY:
  102. return 0;
  103. case RT_RINGBUFFER_FULL:
  104. return rb->buffer_size;
  105. case RT_RINGBUFFER_HALFFULL:
  106. default:
  107. if (rb->write_index > rb->read_index)
  108. return rb->write_index - rb->read_index;
  109. else
  110. return rb->buffer_size - (rb->read_index - rb->write_index);
  111.     };
  112. }

  113. void rt_ringbuffer_init(struct rt_ringbuffer *rb,
  114.                         rt_uint8_t           *pool,
  115.                         rt_int16_t            size)
  116. {
  117.     RT_ASSERT(rb != RT_NULL);
  118.     RT_ASSERT(size > 0);

  119. /* initialize read and write index */
  120.     rb->read_mirror = rb->read_index = 0;
  121.     rb->write_mirror = rb->write_index = 0;

  122. /* set buffer pool and size */
  123.     rb->buffer_ptr = pool;
  124.     rb->buffer_size = RT_ALIGN_DOWN(size, RT_ALIGN_SIZE);
  125. }

  126. /**
  127. * put a character into ring buffer
  128. */
  129. rt_size_t rt_ringbuffer_putchar(struct rt_ringbuffer *rb, const rt_uint8_t ch)
  130. {
  131.     RT_ASSERT(rb != RT_NULL);

  132. /* whether has enough space */
  133. if (!rt_ringbuffer_space_len(rb))
  134. return 0;

  135.     rb->buffer_ptr[rb->write_index] = ch;

  136. /* flip mirror */
  137. if (rb->write_index == rb->buffer_size-1)
  138.     {
  139.         rb->write_mirror = ~rb->write_mirror;
  140.         rb->write_index = 0;
  141.     }
  142. else
  143.     {
  144.         rb->write_index++;
  145.     }

  146. return 1;
  147. }
  148. /**
  149. * get a character from a ringbuffer
  150. */
  151. rt_size_t rt_ringbuffer_getchar(struct rt_ringbuffer *rb, rt_uint8_t *ch)
  152. {
  153.     RT_ASSERT(rb != RT_NULL);

  154. /* ringbuffer is empty */
  155. if (!rt_ringbuffer_data_len(rb))
  156. return 0;

  157. /* put character */
  158.     *ch = rb->buffer_ptr[rb->read_index];

  159. if (rb->read_index == rb->buffer_size-1)
  160.     {
  161.         rb->read_mirror = ~rb->read_mirror;
  162.         rb->read_index = 0;
  163.     }
  164. else
  165.     {
  166.         rb->read_index++;
  167.     }

  168. return 1;
  169. }
复制代码

三,运行结果

使用jlink烧录,通过控制台输入version,运行结果如下所示

基于RT_Thread Nano添加FinSH_10.png

四,结语
如在使用过程中有任何问题,请加QQ群进一步交流。
QQ交流群:728522642 (备注:物联网项目交流)

本篇完,感谢关注:RISC-V单片机中文网
相信自已,未来是自已创造的。
点评回复

使用道具 举报

高级模式
B Color Image Link Quote Code Smilies

本版积分规则

关闭

RISC-V单片机中文网上一条 /2 下一条



版权及免责声明|RISC-V单片机中文网

GMT+8, 2026-1-19 19:32 , Processed in 0.176207 second(s), 33 queries .

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