
以刚拿到手的 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固件库然后下图安装 ![]() ![]() 安装之后 新建一个工程 选择STM32F072RBT6 PINOUT 勾选 FREERTOS和 USART ![]() 因为我们调试可能需要使用 点击软件上方 齿轮键生成 keil 工程 至此 MX基于 HAL的库 生成完毕 使用MDK 打开工程 从上到下 的组依次为 OS 的C文件 .s 启动文件 用户文件 HAL库文件 CMSIS中间件文件 其中 在 第一组中的 cmsis_os.c 中实现了 cmsis_os 到FREERTOS 的中间层转换 稍后会讨论其中一处代码 ![]() 接下来 添加自己的代码 首先添加 072 上面LED吧 板子不在身边 记得是PA5 控制 先看看 main.c 的 64 到 105行
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函数 如下
添加一个 LED 函数
到这里可以编译下载到板子上运行 观察现象了 下面创建 RXT 的工程 新建一个工程 勾选 如下选项 ![]() 红框 不要添加 不知为何 楼主添加 MDK的 startup 编译通不过 F4 的工程没有包含 HAL 接下来 需要自行添加HAL 库 把原来的 main.c 复制一份更名为 rtx_main.c ![]() 文件添加完毕 接下来定义 头文件目录和 系统宏 ![]() 修改 rtx_main.c 下面两处需要修改
修改 stm32f0xx_hal_conf.h 添加 图示内容 不出意外 下面 将可以直接编译了!! ![]() 写的有些多了 本来想 继续写 RTOS 基于串口的 应用 太长了 下次发帖写了 下面提出一个讨论 MX 创建的 工程 FREERTOS 中 cmsis_os.c 中 创建一个信号量 osSemaphoreCreate参数 count 直接 传递给 xSemaphoreCreateCounting的两个形参 ![]() 原型 #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 不懂 这样设计意义何在? ![]() |
不好意思,确实被代码的名称误导了,以前用的基本上只用二值的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
}
你陷在细节里面了,看看人家的API是怎么样写的,osSemaphoreRelease和osSemaphoreWait,我们在生产者里面应该要osSemaphoreRelease,而在消费者里面osSemaphoreWait,是吧?字面理解,相当于生产的人释放了一个东西,然后消费者就等待生产者的这个东西。再看里面的实现,osSemaphoreRelease里面是xSemaphoreGive而不是take,而osSemaphoreWait里面是xSemaphoreTake而不是give。
所谓的反过来理解只是一种理解方法,说take和post的逻辑也反的话是不对的。不要老想着什么时候去post,什么去take。cmsis_os的API意思很明了,生产者生产了东西就应该release,消费者就应该Wait,这不是很好理解吗?
反过来理解是吧,说得通。可是
有个问题。,生产一个就-1的话应该 take获取信号咯? 反过来消费应该post 释放信号咯? 那么问题是 post是非阻塞立即返回的而take是阻塞的?
先不谈消费者应当随时饥饿,处于阻塞态。
生产一般在中断里吧,当take-到0的时候 阻塞线程阻塞谁呢
据说库很大,效率低?求告知!
多谢老大 支持 继续加油
确实 有这个毛病 楼主的贴初始化使用库 LED翻转使用的寄存器 请关注楼主 下篇将 发表 USART基于 OS的应用