Toggle navigation
首页
问答
文章
积分商城
专家
专区
更多专区...
文档中心
返回主站
搜索
提问
会员
中心
登录
注册
Kernel
stm32l151上移植rt-thread nano笔记
发布于 2019-10-25 17:20:04 浏览:814
订阅该版
* 本帖最后由 bigjmagic 于 2019-10-25 17:26 编辑 * [TOC] ## 1.简介 对于stm32l151来说,首先需要将系统环境搭建起来,所以首先RT-Thread nano。该芯片占用的资源有限,所以移植一个完整的rt_thread,比较耗费资源。所以优先选择RT-Thread nano。在支持semaphore和mailbox特性,并运行两个线程(main线程+idle线程)情况下,ROM和RAM依然保持着极小的尺寸。基于Cortex M0 MCU的一个例子,编译后的大小(ROM: 3.25K, RAM: 1.04K),除去MCU需要的ROM和RAM, RT-Thread Nano本身需要的ROM是2.5K , RAM 是1K。本文主要从移植的角度出发,分析系统的构建过程。 ## 2. 操作流程 ### 2.1 keil中安装rtthread包 首先安装rtthread的包,在MDK5中选择**Pack Istaller** ![](![FastAdmin](http://bigmagic.test.upcdn.net/201909/20191025171034.png)) 接着安装运行环境 ![](![FastAdmin](http://bigmagic.test.upcdn.net/201805/20180525145401.png)) 选择rtthread内核 ![](![FastAdmin](http://bigmagic.test.upcdn.net/201909/20191025171228.png)) 选择完成后,就可以看到工程中多了如下的目录 ![](![FastAdmin](http://bigmagic.test.upcdn.net/201805/20180525150111.png)) 其中文件的含义如下 ![](![FastAdmin](http://bigmagic.test.upcdn.net/201805/20180525150307.png)) ### 2.2 函数接口对接 RT-Thread会用到了异常处理函数`HardFault_Handler()`和悬挂处理函数`PendSV_Handler()`,以及Systick中断服务函数`SysTick_Handler()`,所以用户代码需要保证这几个函数没有被使用,若编译提示函数重复定义,请删除自己定义的函数。 ![](![FastAdmin](http://bigmagic.test.upcdn.net/201805/20180525150607.png)) 用户只需要屏蔽掉自己写的函数即可。也可以采用弱函数的方式 ``` __weak void SysTick_Handler(void) __weak void PendSV_Handler(void) __weak void HardFault_Handler(void) ``` ### 2.3 rtthread系统配置 点击rtconfig.h可以进入系统配置界面 ![](![FastAdmin](http://bigmagic.test.upcdn.net/201805/20180525151556.png)) 选择必要的配置 ![](![FastAdmin](http://bigmagic.test.upcdn.net/201805/20180525151910.png)) ![](![FastAdmin](http://bigmagic.test.upcdn.net/201805/20180525152115.png)) 这样一个rtt工程项目就搭建完成了。 ## 3. 启动流程 ### 3.1 引导过程 ![](![FastAdmin](http://bigmagic.test.upcdn.net/201805/20180525153156.png)) _ _main 能跳转到`int $Sub$$main(void); `然后`$Super$$main();`能跳转到我们正常的main()函数中。 其中有关`$Super$` and `$Sub$` 是mdk的一种链接方式,具体用法可以看 http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0377g/pge1362065967698.html ![](![FastAdmin](http://bigmagic.test.upcdn.net/201805/20180525153825.png)) 然后进入rtthread_startup函数中 ![](![FastAdmin](http://bigmagic.test.upcdn.net/201805/20180525154216.png)) 其中在初始化堆栈是,初始的堆栈空间为4k ![](![FastAdmin](http://bigmagic.test.upcdn.net/201805/20180525154334.png)) 在创建main线程时,可以看到创建的main函数执行入口。 ![](![FastAdmin](http://bigmagic.test.upcdn.net/201805/20180525154519.png)) main函数的优先级为2,占用的堆空间为512字节。 ### 3.2 驱动初始化 对于HAL库函数,主要的初始化是对基本的HAL库函数的初始化。 ![](![FastAdmin](http://bigmagic.test.upcdn.net/201805/20180525165929.png)) 这里,主要对几个驱动进行一下完善: #### 3.2.1 gpio位带操作 单片机操作GPIO口的时候,只用将对应的io口设置为1或者0即可,这样的好处就是直接通过操作一个字来达到控制位的作用。 ![](![FastAdmin](http://bigmagic.test.upcdn.net/201805/20180525174818.png)) ![](![FastAdmin](http://bigmagic.test.upcdn.net/201805/20180525174833.png)) 位带操作的两个区域 0x2000_0000-0x200F_FFFF(SRAM区中最低的1M) 0x4000_0000-0x400F_FFFF(片上外设最低的1M) 对于SRAM位带操作中,若要操作某个比特 那么只需要操作的地址 AliasAddr=0x22000000+((A-0x20000000)\*8+n)\*4=0x22000000+32\*(A-0x20000000)+4\*n 做如下的处理 ```c /////////////////////////////////////////////////////////////// //位带操作,实现51类似的GPIO控制功能 //具体实现思想,参考<
>第五章(87页~92页). //IO口操作宏定义 #define BITBAND(addr, bitnum) ((addr & 0xF0000000)+0x2000000+((addr &0xFFFFF)<<5)+(bitnum<<2)) #define MEM_ADDR(addr) *((volatile unsigned long *)(addr)) #define BIT_ADDR(addr, bitnum) MEM_ADDR(BITBAND(addr, bitnum)) //IO口地址映射 #define GPIOA_ODR_Addr (GPIOA_BASE+12) //0x4001080C #define GPIOB_ODR_Addr (GPIOB_BASE+12) //0x40010C0C #define GPIOC_ODR_Addr (GPIOC_BASE+12) //0x4001100C #define GPIOD_ODR_Addr (GPIOD_BASE+12) //0x4001140C #define GPIOE_ODR_Addr (GPIOE_BASE+12) //0x4001180C #define GPIOF_ODR_Addr (GPIOF_BASE+12) //0x40011A0C #define GPIOG_ODR_Addr (GPIOG_BASE+12) //0x40011E0C #define GPIOA_IDR_Addr (GPIOA_BASE+8) //0x40010808 #define GPIOB_IDR_Addr (GPIOB_BASE+8) //0x40010C08 #define GPIOC_IDR_Addr (GPIOC_BASE+8) //0x40011008 #define GPIOD_IDR_Addr (GPIOD_BASE+8) //0x40011408 #define GPIOE_IDR_Addr (GPIOE_BASE+8) //0x40011808 #define GPIOF_IDR_Addr (GPIOF_BASE+8) //0x40011A08 #define GPIOG_IDR_Addr (GPIOG_BASE+8) //0x40011E08 //IO口操作,只对单一的IO口! //确保n的值小于16! #define PAout(n) BIT_ADDR(GPIOA_ODR_Addr,n) //输出 #define PAin(n) BIT_ADDR(GPIOA_IDR_Addr,n) //输入 #define PBout(n) BIT_ADDR(GPIOB_ODR_Addr,n) //输出 #define PBin(n) BIT_ADDR(GPIOB_IDR_Addr,n) //输入 #define PCout(n) BIT_ADDR(GPIOC_ODR_Addr,n) //输出 #define PCin(n) BIT_ADDR(GPIOC_IDR_Addr,n) //输入 #define PDout(n) BIT_ADDR(GPIOD_ODR_Addr,n) //输出 #define PDin(n) BIT_ADDR(GPIOD_IDR_Addr,n) //输入 #define PEout(n) BIT_ADDR(GPIOE_ODR_Addr,n) //输出 #define PEin(n) BIT_ADDR(GPIOE_IDR_Addr,n) //输入 #define PFout(n) BIT_ADDR(GPIOF_ODR_Addr,n) //输出 #define PFin(n) BIT_ADDR(GPIOF_IDR_Addr,n) //输入 #define PGout(n) BIT_ADDR(GPIOG_ODR_Addr,n) //输出 #define PGin(n) BIT_ADDR(GPIOG_IDR_Addr,n) //输入 ``` #### 3.2.2 timr6做外部定时器 只需要在使用定时器时调用`HAL_TIM_Base_Start(&htim6);`开启定时器,并且在函数中调用`HAL_TIM_Base_Stop(&htim6);`关闭定时器。 所以实现us级别延时函数的代码如下所示: ```c //采用定时器6实现一个us级别的延时函数 void delay_us(uint16_t us) { uint16_t differ=0xffff-us-5; /*为防止因中断打断延时,造成计数错误. 如从0xfffE开始延时1us,但由于中断打断 (此时计数器仍在计数),本因计数至0xffff) 便停止计数,但由于错过计数值,并重载arr值, 导致实际延时(0xffff+1)us */ HAL_TIM_Base_Start(&htim6); __HAL_TIM_SetCounter(&htim6,differ); while(differ<0xffff-5) { differ=__HAL_TIM_GetCounter(&htim6); } HAL_TIM_Base_Stop(&htim6); } ``` #### 3.2.3 wwdg窗口看门狗 窗口看门狗的使用主要是配置与使用,如果由于系统跑飞,应该启动看门狗,让系统复位。在这里,可采用在rtthread的tick中断中喂狗的方式,如果系统程序执行遇到异常,将启动看门狗,让系统复位。 所以在使用看门狗时,首先需初始化`MX_WWDG_Init();`,然后在一定的时间内进行喂狗即可。 在使用休眠模式模式时,该寄存器的值不能自动复位,所以在复位之前可以喂一次狗,在从休眠模式到程序正常运行时,也需要喂狗一次。 根据计算公式: $$ 4096*8*64/2.097\approx1000000 $$ 可以得到超时时间为1s,也就是1000ms。而在rtthread的tick中可以设置10ms喂狗一次也可以设置1ms喂狗一次。 喂狗函数: ```c HAL_WWDG_Refresh(hwwdg, WWDG_CNT); ``` #### 3.2.4 uart接收与发送 可采用dma不定长接收的方式进行处理,也可以采用循环队列的方式,具体情况需要看使用时的具体使用方式。这部分后面单独提出来进行分析。 #### 3.2.5 低功耗运行模式 由于在stop模式下,很多外设都在工作,所以在进入stop模式之前,需要做如下的几件事 * 降低核心电压 * 禁用比较器 * 禁止PVD * 关闭VREFINT(少3uA) * 忽略VREFINT,加快启动速度 * 禁用调试端口 #### 3.2.6 进入stop模式 进入stop模式的代码如下: ```c void power_enter_stop(void) { GPIO_InitTypeDef GPIO_InitStruct={0}; printf("=== Power Down ===
"); LED_OFF; HAL_UART_MspDeInit(&huart1); //UART1; 减少16uA GPIO_InitStruct.Pin = GPIO_PIN_9|GPIO_PIN_10; GPIO_InitStruct.Mode = GPIO_MODE_ANALOG; GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Speed = GPIO_SPEED_VERY_LOW; HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); __GPIOA_CLK_DISABLE(); __GPIOB_CLK_DISABLE(); __GPIOC_CLK_DISABLE(); __GPIOH_CLK_DISABLE(); /* Enter Stop Mode */ // __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE3); // /* Poll VOSF bit of in PWR_CSR. Wait until it is reset to 0 */ // while (__HAL_PWR_GET_FLAG(PWR_FLAG_VOS) != RESET) {}; // PWR_LOWPOWERREGULATOR_ON 少2uA HAL_PWR_EnterSTOPMode(PWR_LOWPOWERREGULATOR_ON, PWR_STOPENTRY_WFI); } ``` 注意的是,在唤醒后,需要重新配置串口,重新配置GPIO时钟以及清除唤醒标记。‘ ```c void power_exit_stop(void) { SystemClock_Config(); __GPIOA_CLK_ENABLE(); __GPIOB_CLK_ENABLE(); // __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1); // /* Poll VOSF bit of in PWR_CSR. Wait until it is reset to 0 */ // while (__HAL_PWR_GET_FLAG(PWR_FLAG_VOS) != RESET) {}; // 清除唤醒标记 减少重复唤醒电流,减少3uA SET_BIT(PWR->CR, PWR_CR_CWUF); //重新初始化串口 HAL_UART_MspInit(&huart1); } ``` ## 4. 总结 目前可以采用rtthread nano进行相关的程序框架设计。对于内存比较小的芯片,使用nano版本将是一个十分不错的选择。 ![20180828215845.png](https://oss-club.rt-thread.org/uploads/201808/29/001224yaryhww1ryfzc19m.png)
查看更多
0
个回答
默认排序
按发布时间排序
暂无答案,快来添加答案吧
撰写答案
登录
注册新账号
关注者
0
被浏览
814
关于作者
bigmagic
这家伙很懒,什么也没写!
提问
4
回答
34
被采纳
6
关注TA
发私信
相关问题
1
请教cpu使用率分析
2
选择FreeRTOS, 还是RT-Thread。
3
thread heap stack overflow ?
4
rtt消息队列delay问题
5
释放被删除线程的内存地方在哪里啊
6
请教:各线程结束后,释放其中的内存的连续性问题
7
STM32F103中断关于信号量、邮箱问题
8
RTT中的线程栈大小如何控制
9
关于线程由执行态变为挂起态的代码实现,,,
10
rt_malloc(rt_size_t size)内存分配函数最小分配尺寸问题
推荐文章
1
RT-Thread应用项目汇总
2
玩转RT-Thread系列教程
3
机器人操作系统 (ROS2) 和 RT-Thread 通信
4
国产MCU移植系列教程汇总,欢迎查看!
5
五分钟玩转RT-Thread新社区
6
【技术三千问】之《玩转ART-Pi》,看这篇就够了!干货汇总
7
关于STM32H7开发板上使用SDIO接口驱动SD卡挂载文件系统的问题总结
8
STM32的“GPU”——DMA2D实例详解
9
RT-Thread隐藏的宝藏之completion
10
【ART-PI】RT-Thread 开启RTC 与 Alarm组件
最新文章
1
【24嵌入式设计大赛】基于RT-Thread火星一号华为云平台储能监测管理系统
2
RVBacktrace RISC-V极简栈回溯组件
3
一文教你如何在VSCODE中搭建RT-Thread开发环境
4
分享第一次PR的经历
5
EtherCAT EOE移植及上手说明
热门标签
RT-Thread Studio
串口
Env
LWIP
SPI
AT
Bootloader
Hardfault
CAN总线
ART-Pi
FinSH
USB
文件系统
DMA
RT-Thread
SCons
RT-Thread Nano
线程
MQTT
STM32
RTC
FAL
rt-smart
ESP8266
I2C_IIC
ota在线升级
WIZnet_W5500
UART
flash
packages_软件包
cubemx
PWM
freemodbus
BSP
潘多拉开发板_Pandora
定时器
ADC
中断
flashDB
socket
Debug
GD32
编译报错
msh
keil_MDK
at_device
rt_mq_消息队列_msg_queue
ulog
C++_cpp
SFUD
本月问答贡献
出出啊
1512
个答案
341
次被采纳
小小李sunny
1437
个答案
289
次被采纳
张世争
774
个答案
167
次被采纳
crystal266
546
个答案
161
次被采纳
whj467467222
1222
个答案
148
次被采纳
本月文章贡献
出出啊
1
篇文章
2
次点赞
小小李sunny
1
篇文章
1
次点赞
张世争
1
篇文章
2
次点赞
crystal266
2
篇文章
1
次点赞
whj467467222
2
篇文章
2
次点赞
回到
顶部
发布
问题
分享
好友
手机
浏览
扫码手机浏览
投诉
建议
回到
底部