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

自制简单OS(仅任务调度) 精华  

[复制链接]
QianFan 发布时间:2015-6-28 15:36
本帖最后由 QianFan 于 2015-6-30 18:02 编辑

    之前简单的学习了下ucos,仅仅是会用,并没有深究。毕竟平时用的不是很多。最近闲来无事,好好的阅读了一下ucos的源码,看了下任务调度的内部细节,感觉挺有意思。许多问题在QQ社区群请教了橙子大哥,感谢橙子大哥的不吝赐教。

    但是不满足于ucos的代码,太复杂,函数太长。虽然功能强大,但是像我这样的懒人,不想敲那么多次键盘。于是开始自己DIY一个任务调度器。目前只是简单的实现了任务调度。在今后还要添加其余的功能。但是毕竟一个人的能力太弱,自己DIY的仅供娱乐和学习,不能满足于商业化的使用。

    在DIY的时候使用了303Nucleo,这个板子有80K的内存,所以给堆提供了10K的内存,这些足够malloc消遣了。所以有关任务的栈使用了malloc来进行分配。在测试的时候创建了两个任务(空闲任务除外),用来控制两个led灯。一个间隔1s闪烁,另一个间隔2s闪烁。视频效果可以点击这里查看:https://v.youku.com/v_show/id_XMTI3MjQ2NTQyNA==.html?firsttime=0&from=y1.4-2 请自觉忽略视频的声音,因为在录制的时候有人在讨论电源的问题。测试用的工程可以在附件中下载。


  1. #include "QSys.h"
  2. #include "stm32f30x.h"
  3. #include "stm32f30x_rcc.h"
  4. #include "stm32f30x_gpio.h"

  5. GPIO_InitTypeDef ioIt =
  6. {
  7.         GPIO_Pin_5 | GPIO_Pin_6,
  8.         GPIO_Mode_OUT,GPIO_Speed_50MHz,
  9.         GPIO_OType_PP,GPIO_PuPd_NOPULL,
  10. };

  11. void PA5On(void);
  12. void PA6On(void);

  13. #define pidPA5                        5
  14. #define pidPA6                        6
  15.         
  16. int main(void)
  17. {
  18.         RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA,ENABLE);
  19.         GPIO_Init(GPIOA,&ioIt);
  20.         SysTick_Config(64000000 / 20  ); //50ms
  21.         
  22.         taskCreate(pidPA5,PA5On,"PA5");
  23.         taskCreate(pidPA6,PA6On,"PA6");
  24.         
  25.         QSysStart();
  26. }

  27. void PA5On(void)
  28. {
  29.         while(1)
  30.         {
  31.                 GPIO_SetBits(GPIOA,GPIO_Pin_5);
  32.                 delay(pidPA5,20);
  33.                 GPIO_ResetBits(GPIOA,GPIO_Pin_5);
  34.                 delay(pidPA5,20);
  35.         }
  36. }

  37. void PA6On(void)
  38. {
  39.         while(1)
  40.         {
  41.                 GPIO_SetBits(GPIOA,GPIO_Pin_6);
  42.                 delay(pidPA6,40);
  43.                 GPIO_ResetBits(GPIOA,GPIO_Pin_6);
  44.                 delay(pidPA6,40);
  45.         }
  46. }

复制代码

Update:0.0.2
  • 改进taskCreate,不再使用malloc和free进行自动内存分配。
  • 删除void delay(unsigned int pid,unsigned int ticks);
  • 新增函数void suspend(void),用于挂起任务本身。
  • 新增函数void resume(unsigned int pid),用于恢复已经被挂起的任务或者被sleep阻塞的任务。

   Example:
   将Nucleo的按键设置成为下降沿触发中断的方式。建立一个任务,每隔2s闪烁一次led,闪烁完1次之后将自身挂起,当按键按下的时候,在按键中断中 恢复任务。视频地址:https://v.youku.com/v_show/id_XMTI3MzUwMjQ4OA==.html
在视频中可以看到,第一次按键的时候,亮的时间特别短。这个是按键有抖动导致的,另一方面,sleep这个函数做的也不行。即使任务被sleep阻塞了,resume也能够恢复它。这个也算是bug吧。在之后会继续改进的。
  1. #include "QSys.h"
  2. #include "stm32f30x.h"
  3. #include "stm32f30x_rcc.h"
  4. #include "stm32f30x_gpio.h"
  5. #include "stm32f30x_exti.h"
  6. #include "stm32f30x_syscfg.h"

  7. EXTI_InitTypeDef EXTI_InitStructure;
  8. GPIO_InitTypeDef ioIt =
  9. {
  10.         GPIO_Pin_5 | GPIO_Pin_6,
  11.         GPIO_Mode_OUT,GPIO_Speed_50MHz,
  12.         GPIO_OType_PP,GPIO_PuPd_NOPULL,
  13. };

  14. void PA5On(void);
  15. void PA6On(void);

  16. #define pidPA5                        HIGHEST_PID
  17. #define pidPA6                        LOWEST_PID

  18. unsigned int spPA5[128];
  19. unsigned int spPA6[128];
  20. struct task taskPA5,taskPA6;
  21.         
  22. int main(void)
  23. {
  24.         RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA,ENABLE);
  25.         RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOC,ENABLE);
  26.         RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE);
  27.         
  28.         GPIO_Init(GPIOA,&ioIt);
  29.         ioIt.GPIO_Pin = GPIO_Pin_13;
  30.         ioIt.GPIO_Mode = GPIO_Mode_IN;
  31.         GPIO_Init(GPIOC,&ioIt);
  32.         
  33.         /* Connect EXTI13 Line to PC13 pin */
  34.   SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOC, EXTI_PinSource13);
  35.   
  36.   /* Configure EXTI13 line */
  37.   EXTI_InitStructure.EXTI_Line = EXTI_Line13;
  38.   EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
  39.   EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising;
  40.   EXTI_InitStructure.EXTI_LineCmd = ENABLE;
  41.   EXTI_Init(&EXTI_InitStructure);
  42.         
  43.         NVIC_EnableIRQ(EXTI15_10_IRQn);
  44.         SysTick_Config(64000000 / 20  ); //50ms
  45.         
  46.         taskCreate(&taskPA5,pidPA5,PA5On,spPA5,128,"PA5");
  47.         taskCreate(&taskPA6,pidPA6,PA6On,spPA6,128,"PA6");
  48.         
  49.         QSysStart();
  50. }

  51. void PA5On(void)
  52. {
  53.         while(1)
  54.         {
  55.                 for(int i=0;i<2;i++)
  56.                 {
  57.                         GPIO_SetBits(GPIOA,GPIO_Pin_5);
  58.                         sleep(20);
  59.                         GPIO_ResetBits(GPIOA,GPIO_Pin_5);
  60.                         sleep(20);
  61.                 }
  62.         }
  63. }

  64. void PA6On(void)
  65. {
  66.         suspend();
  67.         while(1)
  68.         {
  69.                 GPIO_SetBits(GPIOA,GPIO_Pin_6);
  70.                 sleep(40);
  71.                 GPIO_ResetBits(GPIOA,GPIO_Pin_6);
  72.                 sleep(40);
  73.                
  74.                 suspend();//suspend itself,watting next exti interrupe
  75.         }
  76. }

  77. void EXTI15_10_IRQHandler(void)
  78. {
  79.         resume(pidPA6);
  80.         EXTI_ClearITPendingBit(EXTI_Line13);
  81. }
复制代码


Bug Report:
||
||
\\//

\/


QSys.rar

下载

853.41 KB, 下载次数: 126

0.0.1

QSys.rar

下载

1 MB, 下载次数: 229

0.0.2

收藏 8 评论93 发布时间:2015-6-28 15:36

举报

93个回答
Mandelbrot_Set 最优答案 回答时间:2015-6-30 10:50:48
QianFan 发表于 2015-6-29 21:40
Update:0.0.2

    改进taskCreate,不再使用malloc和free进行自动内存分配。

我又来了哈...
example1:
void sleep(int delayTicks)中
在if((taskList[pid]==NULL)||(pid==IDLE_PID)||(delayTicks==0))
                return ;
之前taskSwOn();之后产生调度
并不能确保taskList[pid]不是NULL(taskList[curpid]本不应该NULL.)
(调度后来了个changePid).
example2:
updateNextTask执行中产生调度,
每一个taskList[pid]都有被其它任务修改的可能,应该有风险.


QianFan 最优答案 回答时间:2015-6-30 12:45:21
Mandelbrot_Set 发表于 2015-6-30 10:50
我又来了哈...
example1:
void sleep(int delayTicks)中

请教个问题,比如当前OS的节拍数是100,有一个任务Task1,调用了自身的sleep,sleep的时间是1000个节拍。也就是到1100个节拍的时候这个任务应该被唤醒。

假设到了第200个OS节拍的时候,另一个任务Task2更改了Task1的优先级,将他的优先级提高了。你说这个时候是应该让Task1立即执行呢,还是到1100个节拍的时候才能再次执行?
Mandelbrot_Set 最优答案 回答时间:2015-6-30 13:23:06
QianFan 发表于 2015-6-30 12:45
请教个问题,比如当前OS的节拍数是100,有一个任务Task1,调用了自身的sleep,sleep的时间是1000个节拍。 ...

我觉得Task1既然sleep(1000)了,那就应该有sleep(1000)的样子,在1100节拍之前就不应该是就绪状态吧...

Paderboy 回答时间:2015-6-28 16:02:57
多谢分享。。。学习了
moyanming2013 回答时间:2015-6-28 16:17:44
看看。。。
lkl0305 回答时间:2015-6-28 17:46:47
不错,学习学习
JackieLaura 回答时间:2015-6-28 17:56:21
看看作者的作品
jinyi7016 回答时间:2015-6-28 19:56:08
有空也研究研究
u=3562947110,4225194727&amp;fm=21&amp;gp=0.jpg
mark0668 回答时间:2015-6-28 21:31:08
多谢分享。。。学习了..
wtliu 回答时间:2015-6-28 21:35:59
不错,学习了。
slotg 回答时间:2015-6-28 22:34:30
OS系统,感谢分享
wakojosin 回答时间:2015-6-28 22:35:30
感谢楼主分享,关注学习一下。

所属标签

STM32团队

意法半导体微控制器和微处理器拥有广泛的产品线,包含低成本的8位单片机和基于ARM® Cortex®-M0、M0+、M3、M4、M33、M7及A7内核并具备丰富外设选择的32位微控制器及微处理器


最新内容

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