搜索
bottom↓
回复: 43

STM32 + RT Thread OS 学习笔记

  [复制链接]

出110入93汤圆

发表于 2013-6-24 19:52:14 | 显示全部楼层 |阅读模式

STM32 + RT Thread OS 学习笔记[一]



一、开发环境

操作系统:Windows XP

IDE: Keil MDK 4.71a

开发板:奋斗V3(STM32F103VET6) + 4.3” LCD(SSD1963, 480 X 272)


1.      安装Keil MDK

2.      安装 Python 2.7

3.      安装Scons 2.0.1


第一项,是集成开发环境,第三项是项目构建软件,第二项是第三项依赖的运行环境。安装Scons的目的是自动生成Keil MDK的Project文件,项目初始化。


Scons的下载地址:

http://www.python.org/ftp/python/2.7.1/python-2.7.1.msi
http://www.rt-thread.org/download/scons-2.0.1.win32.exe

请使用此指定版本,最新版本可能无法运行项目生成脚本。

注:具体安装使用说明请参考http://www.rt-thread.org/dokuwiki/doku.php?id=%E9%85%8D%E7%BD%AErt-thread%E5%BC%80%E5%8F%91%E7%8E%AF%E5%A2%83


参考资源:

主要有三个参考资源:

1.      官方PDF说明文档

2.      官方Wiki百科

3.      下载的源代码包中doxygen生成的帮助文档

二、第一个例程

1.      运行Scons脚本,生成MDK Project文件

打开Windows Command命令行窗口,将工作目录cd到c:\mcu\RT-Thread 1.1.0\bsp\stm32f10x目录下。

输入脚本命令:

C:\Python27\script\scons --target=mdk4 -s

(注:以上请使用实际安装路径)

执行完毕后,在bsp目录下生成一个Project.uvproj文件


Project.uvproj这个文件,是复制template.uvproj,并在里面添加指定组件文件。可以比较一下这两个文件:



2.      打开项目文件

3.      修改LED定义

将29行~35行的定义改为奋斗板V3中的实际管脚。

4.      在Option中(按Alt + F7),将Device改为STM32F103VE

5.      使用J-Link,要将Options中的Utilities改为J-LINK/J-Trace Cortex

6.      点击上图中的Settings,添加Device


在下面图中,按“Add”按钮,在弹出的画面中选择“STM32F10x High-density Flash”

7.      编译

8.      下载

下载完成后,Reset一下,可以看到开发板上的V6在闪烁。

9.      修改application.c中的led_thread_entry(),加两句代码,实现两个LED灯交替闪烁。

增加的代码:L65, L73

重新编译;在下载前,我们改一下J-Link设置,勾选Reset and Run,这样下载完成后就直接运行,不要手工去Reset。

10.  完毕

以上是在自动生成的项目基础上,完成简单的LED灯闪烁例程。

出110入93汤圆

 楼主| 发表于 2013-8-12 21:24:56 | 显示全部楼层
STM32 + RT Thread OS 学习笔记 结束了,完整的PDF档下载提供:

站内下载:
http://www.amobbs.com/forum.php? ... TMwMzAyMXw1NTQyNDE5

出0入0汤圆

发表于 2013-6-24 19:53:53 | 显示全部楼层
楼主,我强烈的支持你,楼主坚持下来

出110入93汤圆

 楼主| 发表于 2013-6-24 19:54:24 | 显示全部楼层
STM32 + RT Thread OS 学习笔记[二]

串口通讯例程

通过上面的练习,对STM32项目开发有了一个直观印象,接下来尝试对串口RS232进行操作。

1.   目标需求:

开机打开串口1,侦听上位机(使用电脑串口测试软件)发送的信息,然后原样输送到串口1。

2.   创建项目

a)   禁用Finsh和console

b)   默认情况下,项目文件包含了finsh,它使用COM1来通讯,另外,console输出(rt_kprintf)也使用了COM1。因此,在运行scons命令生成项目文件之前,修改rtconfig.h,禁用这两项。(下图L65, L70)

c)   生成项目文件

运行scons --target=mdk4 –s

打开生成的项目文件,可以看到,文件组finsh已经不再被包含进来了。

d)   创建echo.c

新建一个C文件echo.c,编写RT_Thread任务入口,COM1侦听,以及初始化函数。示例代码如下:


[cpp] view plaincopyprint?


  • #include "echo.h"  
  •    
  • struct rx_msg  
  • {  
  •     rt_device_t dev;  
  •     rt_size_t   size;  
  • };  
  •    
  • static struct rt_messagequeue  rx_mq;  
  • static char uart_rx_buffer[64];  
  • static char msg_pool[2048];  
  •    
  • // 串口侦听回调函数  
  • rt_err_t uart_input(rt_device_t dev, rt_size_t size)  
  • {  
  •     struct rx_msg msg;  
  •     msg.dev = dev;  
  •     msg.size = size;  
  •      
  •         // 将接收内容放入消息队列  
  •     rt_mq_send(&rx_mq, &msg, sizeof(struct rx_msg));  
  •      
  •     return RT_EOK;  
  • }  
  •    
  • // 任务入口函数  
  • void usr_echo_thread_entry(void* parameter)  
  • {  
  •     struct rx_msg msg;  
  •      
  •     rt_device_t device;  
  •     rt_err_t result = RT_EOK;  
  •      
  •         // 从RT系统中获取串口1设备  
  •     device = rt_device_find("uart1");  
  •     if (device != RT_NULL)  
  •     {  
  •                            // 指定接收串口内容的回调函数  
  •         rt_device_set_rx_indicate(device, uart_input);  
  •                            // 以读写方式打开设备  
  •         rt_device_open(device, RT_DEVICE_OFLAG_RDWR);  
  •     }  
  •      
  •     while(1)  
  •     {  
  •                            // 从消息队列中获取被回调函数放入消息队列中的内容  
  •         result = rt_mq_recv(&rx_mq, &msg, sizeof(struct rx_msg), 50);  
  •         if (result == -RT_ETIMEOUT)  
  •         {  
  •             // timeout, do nothing  
  •         }  
  •          
  •         if (result == RT_EOK)  
  •         {  
  •             rt_uint32_t rx_length;  
  •             
  •             rx_length = (sizeof(uart_rx_buffer) - 1) > msg.size ?  
  •                 msg.size : sizeof(uart_rx_buffer) - 1;  
  •             
  •             rx_length = rt_device_read(msg.dev, 0, &uart_rx_buffer[0], rx_length);  
  •             uart_rx_buffer[rx_length] = '\0';  
  •             // 将内容写回到串口1  
  •             rt_device_write(device, 0, &uart_rx_buffer[0], rx_length);  
  •         }  
  •     }  
  • }  
  • // 串口例程初始化函数  
  • void usr_echo_init()  
  • {  
  •     rt_thread_t thread ;  
  •      
  •     rt_err_t result;   
  •       // 创建消息队列,分配队列存储空间  
  •     result = rt_mq_init(&rx_mq, "mqt", &msg_pool[0], 128 - sizeof(void*), sizeof(msg_pool), RT_IPC_FLAG_FIFO);  
  •      
  •     if (result != RT_EOK)   
  •     {   
  •         rt_kprintf("init message queue failed.\n");   
  •         return;   
  •     }   
  •     // 创建任务线程  
  •     thread = rt_thread_create("devt",  
  •         usr_echo_thread_entry, RT_NULL,  
  •         1024, 25, 7);  
  •     // 启动任务线程  
  •     if (thread != RT_NULL)  
  •         rt_thread_startup(thread);  
  • }  
  •    


在application.c中加入初始化代码(echo.h略)

L189:usr_echo_init()

;


在开始编译前,还要修改board.c,注释掉第183行,不然将报错。因为我们禁用了console,所以不需要设置console输出设备。



e)   测试

编译,下载,测试。

3.   程序分析

a)   内存分布

查看编译生成的 obj/rtthread-stm32.map文件,可以看到代码及常量,被下载到芯片的0x8000000地址段,最前面的是中断矢量表,第一个中断地址是RESET,矢量表共0x130个字节。

有初始值的变量定义,从地址段0x20000000开始


对应的Stm32内存映射表,代码和常量被下载到Flash,已初始化变量定位到SRAM(可能是下载到Flash,开机初始化后复制到RAM,而不是直接下载到RAM,不然下次运行,初始值可能已被修改)


这是MDK中芯片内存区域的地址分配


这是J-Link对芯片的定义,内存是512K,类型是On-chip Flash,地址空间从0x08000000到0x0807FFFF


b)   程序运行流程

开机后,从Flash 0x080000000处的中断矢量表,取得RESET中断的处理函数入口地址,跳转到入口函数开始执行RESET中断服务,如下图,RESET中断服务函数定义在startup_stm32f10x_hd.s中,先执行了stm32类库中的SystemInit(),再然后转到main()函数。


SystemInit()主要是对芯片的基本设置,如时钟频率。

RT-Thread中,在BSP目录下提供了startup.c,包含了main()函数,它调用了同文件中的rtthread_startup(),再然后rtthread_startup()调用了rt_application_init(),rt_application_init()则在application.c中定义,用户代码就从这里开始。

另外还有一个重要文件是stm32f10x_it.c,这里面定义了中断服务例程,中断矢量表中的地址指向这个文件中相应的服务函数入口地址。比如,我们的串口1收到上位机的消息后,会产生USART1_IRQ,这时芯片就会在0x08000000开始的中断向量表中找到USART1_IRQHandler()的入口地址,跳转后开始执行中断服务函数USART1_IRQHandler()。



当然,要产生中断,需要在初始化代码中开启中断。


<echo.c>

上面贴出了这个文件的源代码,除了uart_input(),其它都比较直观。在RTT系统中,uart_input()只是USART1_IRQHandler()的一部分,在echo.c的初始化代码中,被注册为uart1这个device(RTT封装对象)的回调函数:

L34:rt_device_set_rx_indicate(device, uart_input);

流程参照下图:


出110入93汤圆

 楼主| 发表于 2013-6-24 19:59:09 | 显示全部楼层
Eric2013 发表于 2013-6-24 19:53
楼主,我强烈的支持你,楼主坚持下来

thanks.

出0入0汤圆

发表于 2013-6-24 20:03:27 | 显示全部楼层
顶一顶!!!

出0入0汤圆

发表于 2013-6-24 20:09:34 | 显示全部楼层
为嘛路径分隔符是 ¥ 呢?

出0入0汤圆

发表于 2013-6-24 20:52:33 | 显示全部楼层
有没有实验工程源码呢

出0入8汤圆

发表于 2013-6-24 21:14:04 | 显示全部楼层
LZ用的是日语系统

出0入0汤圆

发表于 2013-6-24 21:57:31 | 显示全部楼层
好贴 一定要顶一下

出0入0汤圆

发表于 2013-6-24 22:05:33 | 显示全部楼层
LZ讲的很明白,我先做个示例看看。

谢分享

出0入0汤圆

发表于 2013-6-24 22:32:55 | 显示全部楼层
不错,可以借鉴

出0入0汤圆

发表于 2013-6-25 10:33:26 | 显示全部楼层
好多¥¥,那个流程图很不错,明了,很具备日系的风范

出110入93汤圆

 楼主| 发表于 2013-6-25 15:31:28 | 显示全部楼层
aozima 发表于 2013-6-24 20:09
为嘛路径分隔符是 ¥ 呢?

楼下有朋友已经回答了,因为日文系统默认分隔符是¥

出110入93汤圆

 楼主| 发表于 2013-6-25 15:33:14 | 显示全部楼层
SNOOKER 发表于 2013-6-24 20:52
有没有实验工程源码呢

因为这里的两个例程,非常简单,个人觉得没必要提供源码。

出110入93汤圆

 楼主| 发表于 2013-6-25 15:35:10 | 显示全部楼层
ffxz 发表于 2013-6-25 10:33
好多¥¥,那个流程图很不错,明了,很具备日系的风范

大拿出现了,呵呵。
我所写的,只是个人理解,有些内容,我也不是很明白,有不正确的地方,都指教。

出0入0汤圆

发表于 2013-6-26 08:51:11 | 显示全部楼层
不错,支持。。。。

出0入0汤圆

发表于 2013-6-26 10:28:05 | 显示全部楼层
楼主写的很不详细。

出110入93汤圆

 楼主| 发表于 2013-6-26 11:15:20 | 显示全部楼层
shotstar 发表于 2013-6-26 10:28
楼主写的很不详细。

作为嵌入开发的新手,其实很多底层的原理,所知有限,因此做练习项目总是一头雾水。
但手头的资料,又是要有一定基础才能明白的,因此对我来说学习难度比较大。

相信有些新人的状况和我差不多,所以在学习时有些收获,我尽力记录下来,并作出自己的分析,希望对大家有帮助。因此在我看来,我写这两份笔记,还是花了不少心思的。

但每个人的看法不同,你的意见,可能对我以后作记录会有帮助。希望你能告诉我,哪些内容是我忽略的,谢谢。

出0入0汤圆

发表于 2013-6-26 13:36:20 | 显示全部楼层
memstone 发表于 2013-6-26 11:15
作为嵌入开发的新手,其实很多底层的原理,所知有限,因此做练习项目总是一头雾水。
但手头的资料,又是 ...

不好意思,楼主写得很详细了,刚刚才发现我回复的时候中间多了一个“不”字,真是不好意,向楼主致歉。

出110入93汤圆

 楼主| 发表于 2013-6-26 14:02:25 | 显示全部楼层
shotstar 发表于 2013-6-26 13:36
不好意思,楼主写得很详细了,刚刚才发现我回复的时候中间多了一个“不”字,真是不好意,向楼主致歉。 ...

哈哈,谢谢。

出0入0汤圆

发表于 2013-7-5 13:56:39 | 显示全部楼层
shotstar 发表于 2013-6-26 13:36
不好意思,楼主写得很详细了,刚刚才发现我回复的时候中间多了一个“不”字,真是不好意,向楼主致歉。 ...

你的回复好坑呀,哈哈!

出0入0汤圆

发表于 2013-7-5 14:05:32 | 显示全部楼层
wolfdong7 发表于 2013-7-5 13:56
你的回复好坑呀,哈哈!

有点坑,把自己也坑了!

出0入0汤圆

发表于 2013-7-5 21:26:04 | 显示全部楼层
LZ,加油!
期待更多的例程,呵呵!
刚刚点灯成功了,哈哈!

出0入0汤圆

发表于 2013-7-7 09:24:08 | 显示全部楼层
支持楼主,学习了,期待更多的教程

出0入0汤圆

发表于 2013-7-8 08:17:40 | 显示全部楼层
楼主牛B

出0入0汤圆

发表于 2013-7-12 11:13:56 | 显示全部楼层
学习中,早日修炼满级

出0入0汤圆

发表于 2013-7-13 16:22:11 | 显示全部楼层
强烈支持,学习中!

出0入0汤圆

发表于 2013-7-30 17:09:22 | 显示全部楼层
LZ能不能每一个例程  出个例程文件~我是不是要求的太多了。。。。

出110入93汤圆

 楼主| 发表于 2013-8-3 07:47:33 | 显示全部楼层
chinalcy1989 发表于 2013-7-30 17:09
LZ能不能每一个例程  出个例程文件~我是不是要求的太多了。。。。

确实多了,呵呵。
初学要多动手,而且这些例程都很简单的。

出0入0汤圆

发表于 2013-8-7 08:42:16 | 显示全部楼层
其实是在在你的文档的时候,看见省略了H文件,所以才想让LZ出个例程的,后来自己改改也能实现了  还是多谢LZ~

出0入0汤圆

发表于 2013-8-12 21:12:30 来自手机 | 显示全部楼层
mark……
顶一个…

出0入0汤圆

发表于 2013-10-16 16:00:39 | 显示全部楼层
太强大了!!详细到不行!!

出0入0汤圆

发表于 2013-12-11 12:19:31 | 显示全部楼层
先顶一下,我也准备开学了

出0入0汤圆

发表于 2013-12-22 19:47:55 | 显示全部楼层
MARK下

出0入0汤圆

发表于 2014-1-8 23:05:36 | 显示全部楼层
很牛逼啊!

出0入0汤圆

发表于 2014-2-22 12:04:43 | 显示全部楼层
RT Thread OS有在新塘M0上移植成功的吗?

出0入0汤圆

发表于 2014-3-7 10:46:12 | 显示全部楼层
学习了,很好

出0入0汤圆

发表于 2014-5-23 15:17:04 | 显示全部楼层
楼主牛B

出0入0汤圆

发表于 2014-5-30 10:30:29 | 显示全部楼层
表示支持!

出0入0汤圆

发表于 2015-1-15 13:15:12 | 显示全部楼层
先收藏一下,在学习中。。。。。。。

出0入0汤圆

发表于 2015-2-1 22:26:27 | 显示全部楼层
RTT 与freeRTOS有什么不同了?

出0入0汤圆

发表于 2015-2-8 11:50:25 | 显示全部楼层
强力推荐!!!

出0入0汤圆

发表于 2015-6-9 13:07:44 | 显示全部楼层
学习中,不胜感激
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-4-20 06:38

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

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