10

ifconfig · 2022年04月04日

【GD32F310开发板试用】+finsh/shell添加与进程STACK优化

前面

在当前国家对知识产权的重视程度一步步加大的国情下,使用盗版软件的风气会在未来进行打压与限制,尤其会严查企业级的软件侵权。这是综合国力,科技水平发展到一定阶段所必走的一步,也是不断提高创新力的必不可少的保障。
所以,国内芯片(MCU)厂家,如果支持开源免费的开发工具,那是在给企业省钱,也是在未来市场的一大优势。
GD这方面做的似乎不是很好。
GDLink是没有串口功能的,如果支持串口功能就完美了。

开始

上一次只是移植了rt-thread nano的内核,但rt-thread的finsh/shell,是一大很有特点的功能,没有finsh/shell的rt-thread是不完整的,所以,这次开始添加finsh/shell功能。

要实现finsh/shell功能,首先,要实现串口的功能。
添加uart.c与uart.h两个文件到工程中。
添加相应的串口初始化函数。
可以选择增加printf的支持,写上int fputc(int ch, FILE *f)函数;
uart.c文件代码如下:

#include "gd32f3x0.h"
#include "gd32f310k_start.h"
#include "systick.h"
#include <rtthread.h>
#include "uart.h"


static rcu_periph_enum COM_CLK[COMn]  = {EVAL_COM_CLK};
static uint32_t COM_TX_PIN[COMn]      = {EVAL_COM_TX_PIN};

static uint32_t COM_RX_PIN[COMn]      = {EVAL_COM_RX_PIN};

void usart_init(uint32_t com)
{
    uint32_t COM_ID = 0U;
    
    if(EVAL_COM == com){
        COM_ID = 0U;
    }else{
    }
        
        /* enable COM GPIO clock */
    rcu_periph_clock_enable(EVAL_COM_GPIO_CLK);

    /* enable USART clock */
    rcu_periph_clock_enable(COM_CLK[COM_ID]);
        /* connect port to USARTx_Tx */
    gpio_af_set(EVAL_COM_GPIO_PORT, EVAL_COM_AF, COM_TX_PIN[COM_ID]);

    /* connect port to USARTx_Rx */
    gpio_af_set(EVAL_COM_GPIO_PORT, EVAL_COM_AF, COM_RX_PIN[COM_ID]);

    /* configure USART Tx as alternate function push-pull */
    gpio_mode_set(EVAL_COM_GPIO_PORT, GPIO_MODE_AF, GPIO_PUPD_PULLUP, COM_TX_PIN[COM_ID]);
    gpio_output_options_set(EVAL_COM_GPIO_PORT, GPIO_OTYPE_PP, GPIO_OSPEED_10MHZ, COM_TX_PIN[COM_ID]);

    /* configure USART Rx as alternate function push-pull */
    gpio_mode_set(EVAL_COM_GPIO_PORT, GPIO_MODE_AF, GPIO_PUPD_PULLUP, COM_RX_PIN[COM_ID]);
    gpio_output_options_set(EVAL_COM_GPIO_PORT, GPIO_OTYPE_PP, GPIO_OSPEED_10MHZ, COM_RX_PIN[COM_ID]);

    /* USART configure */
    usart_deinit(com);
    usart_baudrate_set(com, 115200U);
    usart_receive_config(com, USART_RECEIVE_ENABLE);
    usart_transmit_config(com, USART_TRANSMIT_ENABLE);

    usart_enable(com);
}
int fputc(int ch, FILE *f)
{
    usart_data_transmit(EVAL_COM, (uint8_t)ch);
    while(RESET == usart_flag_get(EVAL_COM, USART_FLAG_TBE));
    return ch;
}

uart.h代码如下:


#ifndef UART_H
#define UART_H

#ifdef __cplusplus
 extern "C" {
#endif

#include "gd32f3x0.h"
#include <stdio.h>

#define COMn                             1U

#define EVAL_COM                         USART0
#define EVAL_COM_CLK                     RCU_USART0

#define EVAL_COM_TX_PIN                  GPIO_PIN_9
#define EVAL_COM_RX_PIN                  GPIO_PIN_10

#define EVAL_COM_GPIO_PORT               GPIOA
#define EVAL_COM_GPIO_CLK                RCU_GPIOA
#define EVAL_COM_AF                      GPIO_AF_1
     
     
     
void usart_init(uint32_t com);
     
     
     
#ifdef __cplusplus
}
#endif

#endif /* GD32F310C_EVAL_H */

使用printf 测试串口功能

6.png

添加finsh组件

clipboard.png

rtconfig.h中,去掉#include "finsh_config.h"的注释,这个在添加了组件后,是不会自动去掉的。

clipboard.png

增加三个了函数的实际函数。

board.c
void rt_hw_console_output(const char *str)
static int uart_init(void)

static int uart_init(void)
{
    usart_init(EVAL_COM);
//#error "TODO 2: Enable the hardware uart and config baudrate."
    return 0;
}
INIT_BOARD_EXPORT(uart_init);

void rt_hw_console_output(const char *str)
{
    rt_size_t i = 0, size = 0;
     char a = '\r';
     size = rt_strlen(str);
    
    for (i = 0; i < size; i++){
        if (*(str + i) == '\n'){
            usart_data_transmit(EVAL_COM,a);
            while(RESET == usart_flag_get(EVAL_COM, USART_FLAG_TBE));
        }
        usart_data_transmit(EVAL_COM, *(str + i));
    while(RESET == usart_flag_get(EVAL_COM, USART_FLAG_TBE));
    }
        
//#error "TODO 3: Output the string 'str' through the uart."
}

finsh_port.c
RT_WEAK char rt_hw_console_getchar(void)

RT_WEAK char rt_hw_console_getchar(void)
{
    /* Note: the initial value of ch must < 0 */
    int ch = -1;

//#error "TODO 4: Read a char from the uart and assign it to 'ch'."
    if(RESET != usart_flag_get(EVAL_COM,USART_FLAG_RBNE))
    {
        ch=usart_data_receive(EVAL_COM);
    }
    else //USART_FLAG_ORERR
    {
        if(RESET !=usart_flag_get(EVAL_COM,USART_FLAG_ORERR))
            usart_flag_clear(EVAL_COM,USART_FLAG_ORERR);
        rt_thread_mdelay(10);
    }
    
    return ch;
}

注意,这里的rt_thread_mdelay(10);是必须要有的,因为shell也是做为一个进程在OS中运行的,RTOS的进程不能一直占用CPU,所以,都是要添加延时的。

去掉board.c中static int uart_init(void)函数中的
#error "TODO 2: Enable the hardware uart and config baudrate."
去掉finsh_port.c中RT_WEAK char rt_hw_console_getchar(void)函数中的
#error "TODO 4: Read a char from the uart and assign it to 'ch'."
并添加相应 的头文件 ,#include "uart.h"
编译后烧写到板子上,串口输出如下,并使用了ps命令的结果。
clipboard.png

下面就是要进行进程stack的优化了,从ps命令的显示可以看出,每个进程占用的stack的大小,这样就可以方便的进行调整,从而不浪费掉STACK,毕竟,这个芯片的RAM本来就很小,只有8K。
优化后的结果。
捕股份制获.PNG
在如上的这种优化下,整个工程的RAM与ROM使用情况如下:
捕获手.PNG
调试时,可以先给进程分配一个比较大的stack,等功能调试好后,通过ps看一下使用情况,再进行相应的调整,当然,要适当注意一下字节的对齐情况。

推荐阅读
关注数
10708
内容数
187
中国高性能通用微控制器领域的领跑者兆易创新GD系列芯片技术专栏。
目录
极术微信服务号
关注极术微信号
实时接收点赞提醒和评论通知
安谋科技学堂公众号
关注安谋科技学堂
实时获取安谋科技及 Arm 教学资源
安谋科技招聘公众号
关注安谋科技招聘
实时获取安谋科技中国职位信息