野火电子论坛

 找回密码
 注册

QQ登录

只需一步,快速开始

查看: 19982|回复: 2

记一次使用CLion移植rt-thread的过程

[复制链接]
发表于 2020-12-27 14:21:19 | 显示全部楼层 |阅读模式

由于CLion出色的代码提示和现代化的工具界面,就想着在CLion下开发stm32-RTT的开发

> 环境: > > 1. 工具链:arm-none-eabi-gcc > 2. IDE: CLion > 3. 生成工具: stm32cubemx cmake > 4. 开发板: 野火指南者 > 5. 下载工具: openocd

  1. 新建工程

064dc221.png

在新建完成后,点击 open with stm32cubemx

  1. 选择stm32f103VETx

2e317f0a.png

  1. 参数配置

RCC时钟选择外部晶振

9a2fca11.png

由于野火使用的是CMISI-DAP,所以选择Debug 选择 Serial Wire

seriald

如果不选择的话,可能会导致无法再次烧写.需要进行一次重置 LED灯配置 选择Pin口,置为GPIO_Output

2c42ded8.png

29c93aea.png

配置时钟

0767c24d.png

串口配置,选择USART1作为Debug口,选择异步实现

bcbd2053.png

  1. RTT第三方组件加入 点击Additional Software

82647f7c.png

选择RTT并配置参数

选择

由于RTT重写了HardFault_Handler 、 PendSV_Handler 、 SysTick_Handler 中断,所以需要取消生成三个中断

a75bb251.png

  1. 其他配置

将每个外设作为独立的文件输出 305ec169.png 选择SW4STM32 IDE

1260f171.png

stm32cube配置结束

回到CLion,CLion会自动为项目生成CmakeFile,之后会弹出一个串口选择openocd的配置参数.这里先退出选择.在后面会给出详细的参数配置

  1. 初始化 在boart.c中的rt_hw_board_init中进行初始化,将main函数的中初始化函数移入到rt_hw_board_init
/**
 * This function will initial your board.
 */
void rt_hw_board_init()
{
    HAL_Init();        // from main

    SystemClock_Config();// from main

    SystemCoreClockUpdate();

    /* System Tick Configuration */
    _SysTick_Config(SystemCoreClock / RT_TICK_PER_SECOND);

    /* Call components board initial (use INIT_BOARD_EXPORT()) */
#ifdef RT_USING_COMPONENTS_INIT
    rt_components_board_init();
#endif

#if defined(RT_USING_USER_MAIN) && defined(RT_USING_HEAP)
    rt_system_heap_init(rt_heap_begin_get(), rt_heap_end_get());
#endif


    /* Initialize all configured peripherals */
    MX_GPIO_Init();
    MX_USART1_UART_Init();
}

由于RTT中不是从main函数开始执行的,若想要初始化RTT,需要修改文件 startup_stm32f103xe.sbl main,将其修改为 bl entry或者添加编译参数-eentry指定c入口函数 原因如下:

在RTT中的 components.c中,有这样一段代码

#if defined(__CC_ARM) || defined(__CLANG_ARM)
extern int $Super$$main(void);
/* re-define main function */
int $Sub$$main(void)
{
    rtthread_startup();
    return 0;
}
#elif defined(__ICCARM__)
extern int main(void);
/* __low_level_init will auto called by IAR cstartup */
extern void __iar_data_init3(void);
int __low_level_init(void)
{
    // call IAR table copy function.
    __iar_data_init3();
    rtthread_startup();
    return 0;
}
#elif defined(__GNUC__)
extern int main(void);
/* Add -eentry to arm-none-eabi-gcc argument */
int entry(void)
{
    rtthread_startup();
    return 0;
}
#endif

在上面这段中,使用了编译器宏进行条件编译,由于我使用的是 arm-none-eabi-gcc,内置宏为GNUC,执行的就是最后一段代码,entry中调用了rtthread_startup()函数,在此函数中指定了初始化,初始化完成后创建一个main线程执行main函数,entry线程中自然死亡.

  1. finsh移植 在rtconfig.h中打开宏#define RT_USING_FINSH 定义void rt_hw_console_output(const char *str)char rt_hw_console_getchar(void)函数
void rt_hw_console_output(const char *str) {
    rt_size_t i = 0, size = 0;
    char      a = '\r';
    __HAL_UNLOCK(&huart1);
    size = rt_strlen(str);
    for (i = 0; i < size; i++) {
        if (*(str + i) == '\n') {
            HAL_UART_Transmit(&huart1, (uint8_t *)&a, 1, 1);
        }
        HAL_UART_Transmit(&huart1, (uint8_t *)(str + i), 1, 1);
    }
}

char rt_hw_console_getchar(void) {
    int ch = -1;

    if (__HAL_UART_GET_FLAG(&huart1, UART_FLAG_RXNE) != RESET) {
        ch = huart1.Instance->DR & 0xff;
    } else {
        if (__HAL_UART_GET_FLAG(&huart1, UART_FLAG_ORE) != RESET) {
            __HAL_UART_CLEAR_OREFLAG(&huart1);
        }
        rt_thread_mdelay(10);
    }
    return ch;
}

在rtthread_startup中初始化finsh->调用finsh_system_init.注:初始化需要放在 rt_system_scheduler_start();函数后面,否则会有异常. 在finsh_system_init中有

extern const int __fsymtab_start;
extern const int __fsymtab_end;
extern const int __vsymtab_start;
extern const int __vsymtab_end;

此时编译会出现未定义的错误 所以需要在STM32F103VETx_FLASH.ld文件定义字段

/* The program code and other data goes into FLASH */
  .text :
  {
    . = ALIGN(4);
    *(.text)           /* .text sections (code) */
    *(.text*)          /* .text* sections (code) */
    *(.glue_7)         /* glue arm to thumb code */
    *(.glue_7t)        /* glue thumb to arm code */
    *(.eh_frame)

    /* section information for finsh shell */
    . = ALIGN(4);
    __fsymtab_start = .;
    KEEP(*(FSymTab))
    __fsymtab_end = .;
    . = ALIGN(4);
    __vsymtab_start = .;
    KEEP(*(VSymTab))
    __vsymtab_end = .;
    . = ALIGN(4);

    /* section information for initial. */
    . = ALIGN(4);
    __rt_init_start = .;
    KEEP(*(SORT(.rti_fn*)))
    __rt_init_end = .;
    . = ALIGN(4);

    KEEP (*(.init))
    KEEP (*(.fini))

    . = ALIGN(4);
    _etext = .;        /* define a global symbols at end of code */
  } >FLASH

最后异步,在main函数主循环中,使用 rt_thread_mdelay(1000);函数,让出CPU控制器,否则while循环会一直持有cpu控制权,其他线程堵塞.

  1. 下载验证 下载调试程序使用openocd,openocd需要使用配置文件进行下载.以下是我的配置文件
adapter driver cmsis-dap
transport select swd
source [find target/stm32f1x.cfg]

最后的最后,成果图:

3856e38f.png

项目工程路径→ RTT_CLion

回复

使用道具 举报

发表于 2020-12-28 08:53:41 | 显示全部楼层


有两个图好像没了
回复 支持 反对

使用道具 举报

 楼主| 发表于 2020-12-28 14:08:48 | 显示全部楼层
本帖最后由 sastar 于 2020-12-28 14:14 编辑
WishWish 发表于 2020-12-28 08:53


有两个图好像没了

补上缺失的图片
serial wire

RTT参数


回复 支持 反对

使用道具 举报

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

本版积分规则

联系站长|手机版|野火电子官网|野火淘宝店铺|野火电子论坛 ( 粤ICP备14069197号 ) 大学生ARM嵌入式2群

GMT+8, 2024-11-25 01:39 , Processed in 0.051805 second(s), 27 queries , Gzip On.

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

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