你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

STM32 如何快速创建 FREERTOS和RTX 工程  

[复制链接]
lovewyufeng 发布时间:2015-1-8 12:08
以刚拿到手的 Nucleo 072为例  其他板子用户 请举一反三哈 (工程文件在帖末


后续帖子:【干货】Nucleo072 usart 基于RTOS的应用  方便AT指令类外设开发

需要工具  MDK5 自行下载:
STM32CUBEMX https://www.stmcu.org.cn/document/detail/index/id-214984
STM32CUBEF0 https://www.stmcu.org.cn/document/detail/index/id-216669


安装 cubeMX  由于使用MX下载固件库速度那是不说了相当慢啊  所以下载 STM32CUBEF0固件库然后下图安装


QQ截图20150108101548.jpg QQ截图20150108101556.jpg

安装之后  新建一个工程 选择STM32F072RBT6

PINOUT 勾选  FREERTOS和 USART
QQ截图20150108101539.jpg
因为我们调试可能需要使用

点击软件上方  齿轮键生成  keil 工程  至此

MX基于 HAL的库 生成完毕

使用MDK 打开工程
从上到下 的组依次为  OS 的C文件
.s 启动文件
用户文件
HAL库文件
CMSIS中间件文件

其中 在 第一组中的 cmsis_os.c 中实现了  cmsis_os  到FREERTOS 的中间层转换   稍后会讨论其中一处代码

QQ截图20150108101924.jpg


接下来  添加自己的代码  首先添加 072 上面LED吧  板子不在身边  记得是PA5 控制

先看看  main.c 的 64 到 105行

  1. int main(void)
  2. {

  3.   /* USER CODE BEGIN 1 */

  4.   /* USER CODE END 1 */

  5.   /* MCU Configuration----------------------------------------------------------*/

  6.   /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  7.   HAL_Init();

  8.   /* Configure the system clock */
  9.   SystemClock_Config();

  10.   /* Initialize all configured peripherals */
  11.   MX_GPIO_Init();
  12.   MX_USART2_UART_Init();

  13.   /* USER CODE BEGIN 2 */

  14.   /* USER CODE END 2 */

  15.   /* Init code generated for FreeRTOS */
  16.   /* Create Start thread */
  17.   osThreadDef(USER_Thread, StartThread, osPriorityNormal, 0, configMINIMAL_STACK_SIZE);
  18.   osThreadCreate (osThread(USER_Thread), NULL);

  19.   /* Start scheduler */
  20.   osKernelStart(NULL, NULL);

  21.   /* We should never get here as control is now taken by the scheduler */

  22.   /* USER CODE BEGIN 3 */
  23.   /* Infinite loop */
  24.   while (1)
  25.   {

  26.   }
  27.   /* USER CODE END 3 */

  28. }
复制代码

mian函数  C代码的入口  初始化一些硬件后
  osThreadDef(USER_Thread, StartThread, osPriorityNormal, 0, configMINIMAL_STACK_SIZE);
  osThreadCreate (osThread(USER_Thread), NULL);
  /* Start scheduler */
  osKernelStart(NULL, NULL);

定义了一个 线程 USER_Thread 然后启动OS  
注意 osThreadDef  是一个宏  定义一个用于描述  线程的结构体  并不是执行函数

宏的第二项参数 StartThread 为线程 入口函数地址。

至此mian函数的工作结束了 OS将转向 就绪线程并永不返回  也就是执行StartThread  

修改  StartThrea函数 如下


  1. /* USER CODE BEGIN 4 */
  2. void Nucleo_072_Led(const void *par);
  3. /* USER CODE END 4 */

  4. static void StartThread(void const * argument)
  5. {

  6.   /* USER CODE BEGIN 5 */
  7.   osThreadDef(LED_Thread, Nucleo_072_Led, osPriorityNormal, 0, configMINIMAL_STACK_SIZE);
  8.   osThreadCreate (osThread(LED_Thread), NULL);
  9.   /* Infinite loop */
  10.   for(;;)
  11.   {
  12.     osDelay(1);
  13.   }

  14.   /* USER CODE END 5 */

  15. }
复制代码

添加一个 LED 函数
  1. void Nucleo_072_Led(const void *par)
  2. {
  3.         GPIO_InitTypeDef GPIO_InitStruct;
  4.   __GPIOA_CLK_ENABLE();
  5.         
  6.            GPIO_InitStruct.Pin = GPIO_PIN_5;
  7.     GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  8.     GPIO_InitStruct.Pull = GPIO_PULLUP;
  9.     GPIO_InitStruct.Speed = GPIO_SPEED_LOW;

  10.     HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
  11.         
  12.         for(;;)
  13.         {
  14.                 GPIOA->ODR^=GPIO_PIN_5;// PA5取反 LED闪烁
  15.                 osDelay(500);
  16.         }

  17. }
复制代码

到这里可以编译下载到板子上运行 观察现象了

下面创建 RXT 的工程  新建一个工程  

勾选 如下选项

QQ截图20150108112304.jpg
红框 不要添加  不知为何  楼主添加 MDK的 startup 编译通不过
F4 的工程没有包含  HAL  接下来 需要自行添加HAL 库

把原来的 main.c 复制一份更名为  rtx_main.c

QQ截图20150108113501.jpg

文件添加完毕

接下来定义 头文件目录和 系统宏

QQ截图20150108112609.jpg

修改 rtx_main.c  下面两处需要修改

  1.   {
  2.   osThreadDef( StartThread, osPriorityNormal, 0, 0);
  3.   osThreadCreate (osThread(StartThread), NULL);
  4.         }

  5. osThreadDef( Nucleo_072_Led, osPriorityNormal, 0, 0);
  6.   osThreadCreate (osThread(Nucleo_072_Led), NULL);
复制代码
不知为何  ST写的 中间件和 MDK的 接口有一点差距  所以 创建线程的地方需要如上修改

修改 stm32f0xx_hal_conf.h
添加 图示内容  不出意外  下面 将可以直接编译了!!
QQ截图20150108112936.jpg

写的有些多了  本来想 继续写 RTOS 基于串口的  应用  太长了 下次发帖写了

下面提出一个讨论 MX 创建的  工程 FREERTOS 中 cmsis_os.c 中 创建一个信号量  
osSemaphoreCreate参数 count 直接

传递给 xSemaphoreCreateCounting的两个形参  
QQ截图20150108115258.jpg
原型
#define xSemaphoreCreateCounting( uxMaxCount, uxInitialCount ) xQueueCreateCountingSemaphore( ( uxMaxCount ), ( uxInitialCount ) )

该宏创建一个 数值型信号量 第一个参数是 信号量最大数值  第二个则为  初始化值

基于串口使用信号量  那么需要如下要求
假设 usart_sem 为串口使用的信号量
每收到一个数据 usart_sem ++  缓冲 1024字节
需要数据的线程 osSemaphoreWait(usart_sem ); 当有数据时 线程被激活  获取数据

如此我们知道 这个信号量的 最大值应为1024
可是使用 ST 的cmsis_os osSemaphoreCreate 创建一个信号亮 osSemaphoreCreate(0,1024);

会出现这样的问题 !  此信号量 被赋予初值1024  意味着 这个信号量将可以被osSemaphoreWait 1024次
显然这不是我们想要

通常  我们需要的数值型信号量  最大值可以很大  但是初值 基本为0,或1

不懂  这样设计意义何在?


FREERTOS.zip (4.76 MB, 下载次数: 809)
收藏 14 评论97 发布时间:2015-1-8 12:08

举报

97个回答
我是东哥 回答时间:2015-1-24 07:31:09
本帖最后由 我是东哥 于 2015-1-24 09:21 编辑
lovewyufeng 发表于 2015-1-23 12:56
事实上  只要这个计数不为0 都能被 wait 到

不好意思,确实被代码的名称误导了,以前用的基本上只用二值的semphore或者直接用queue了。
仔细看了一下内部的实现,确实我说错了。
在init_counter和max_counter一样的情况下,确实整个逻辑是要按照资源池来解释的,也就是确实生产者take(这个take代表获取空闲资源才能生产),消费者release(这个代表空闲资源返回)。我觉得这种情况semphore更像一个可重入的锁,处理线程拿走资源池后,直接处理完后再归还,像是个recursive mutex。
前面说的那个问题,直接用queue可能会更好。另外,今天试了一下最新的stm32cubemx和固件版本,代码已经改了,#if (configUSE_COUNTING_SEMAPHORES == 1 )        
  return xSemaphoreCreateCounting(count, 0);
#else
  return NULL;
#endif
}




我是东哥 回答时间:2015-1-23 07:50:34
lovewyufeng 发表于 2015-1-23 00:48
反过来理解是吧,说得通。可是
有个问题。,生产一个就-1的话应该 take获取信号咯?   反过来消费应该pos ...

你陷在细节里面了,看看人家的API是怎么样写的,osSemaphoreRelease和osSemaphoreWait,我们在生产者里面应该要osSemaphoreRelease,而在消费者里面osSemaphoreWait,是吧?字面理解,相当于生产的人释放了一个东西,然后消费者就等待生产者的这个东西。再看里面的实现,osSemaphoreRelease里面是xSemaphoreGive而不是take,而osSemaphoreWait里面是xSemaphoreTake而不是give。
所谓的反过来理解只是一种理解方法,说take和post的逻辑也反的话是不对的。不要老想着什么时候去post,什么去take。cmsis_os的API意思很明了,生产者生产了东西就应该release,消费者就应该Wait,这不是很好理解吗?
lovewyufeng 回答时间:2015-1-23 00:48:46
我是东哥 发表于 2015-1-21 12:18
这个其实也没有不合理,看你怎么理解,资源一开始为0,也可以理解为空闲池一开始是满的。生产者生产了一 ...

反过来理解是吧,说得通。可是
有个问题。,生产一个就-1的话应该 take获取信号咯?   反过来消费应该post 释放信号咯? 那么问题是 post是非阻塞立即返回的而take是阻塞的?
先不谈消费者应当随时饥饿,处于阻塞态。
生产一般在中断里吧,当take-到0的时候 阻塞线程阻塞谁呢
lovewyufeng 回答时间:2015-1-8 12:08:29
先把沙发占掉
oipk 回答时间:2015-1-8 12:11:23
楼上的,额,我第二个小板凳。楼主写的好,张姿势了。
liuqihui-347226 回答时间:2015-1-8 12:12:11
不错不错,看起来蛮好用的,支持一下
cqtnheyao 回答时间:2015-1-8 12:12:59
地板要站住
麟狮蕟 回答时间:2015-1-8 12:13:04
手指一抖经验到手
harvardx 回答时间:2015-1-8 12:13:49
有钱为何不顶帖 .何况还是高质量的 .cubemx 势在必得的趋势.支持一下.
木易-357428 回答时间:2015-1-8 12:16:11
看看 顶一下
cqtnheyao 回答时间:2015-1-8 12:19:01
harvardx 发表于 2015-1-8 12:13
有钱为何不顶帖 .何况还是高质量的 .cubemx 势在必得的趋势.支持一下.

据说库很大,效率低?求告知!
netlhx 回答时间:2015-1-8 12:19:08
很好,图文并茂
lovewyufeng 回答时间:2015-1-8 12:19:26
harvardx 发表于 2015-1-8 12:13
有钱为何不顶帖 .何况还是高质量的 .cubemx 势在必得的趋势.支持一下.

多谢老大 支持  继续加油
lovewyufeng 回答时间:2015-1-8 12:23:05
cqtnheyao 发表于 2015-1-8 12:19
据说库很大,效率低?求告知!

确实 有这个毛病  楼主的贴初始化使用库  LED翻转使用的寄存器  请关注楼主 下篇将 发表 USART基于 OS的应用
wamcncn 回答时间:2015-1-8 12:38:19
不错,刚好 072的板子快到了
cxtarm 回答时间:2015-1-8 12:50:20
cubemx 好用吗
木易-357428 回答时间:2015-1-8 12:51:24
看看 路过

所属标签

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
st-img 微信公众号
st-img 手机版