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

自制简单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扩展软件包
关注我们
st-img 微信公众号
st-img 手机版