ВходНаше всё Теги codebook 无线电组件 Поиск Опросы Закон Понедельник
23 декабря
911387
IBAH (19.03.2019 14:22 - 14:24, просмотров: 27318)
Опять к вопросу об ОС для МК. Чтобы понять для чего нужны ОС для МК, решил написать собственную кооперативную оську. Краткое описание Каждой задаче выделяется область сохранения контекста и стек. Определяются константами MaxKolvoZadach и RazmerSteka Задачи не загружаются и не выгружаются! При попытке выгрузки случится катастрофия! Если задачу надо завершить, использовать функцию EndTask() Интерфейсы ОС #define MaxKolvoZadach (5) //максимальное количество задач #define RazmerSteka (32) //размер стека //инициализация задачи void InitTask(void (*TaskPointer)(void)); //инициализация операционной системы void InitOS(void); //передать управление операционной системе //аргумент время в мимлисекундах void Sleep(unsigned long ms); //завершение задачи static inline void EndTask(void){while(1)Sleep(0xFFFFFFFF);} Функции //тип данных задача typedef struct { unsigned long TaskSleep;//время до запуска задачи в мС unsigned long R4; unsigned long R5; unsigned long R6; unsigned long R7; unsigned long R8; unsigned long R9; unsigned long R10; unsigned long R11; unsigned long R12; unsigned long SP; void (*TaskPointer)(void);//указатель на задачу }Task_t; unsigned long KolvoTask;//количество задач unsigned long TaskNum;//номер текущей задачи Task_t TaskList[MaxKolvoZadach];//список задач unsigned long TaskStek[MaxKolvoZadach][RazmerSteka];//стек //инициализация задачи void InitTask(void (*TaskPointer)(void)) { TaskList[KolvoTask].TaskSleep=0; TaskList[KolvoTask].TaskPointer=TaskPointer; TaskList[KolvoTask].SP=(unsigned long)(&(TaskStek[KolvoTask][RazmerSteka-1])); KolvoTask++; return; } //инициализация операционой системы void InitOS(void) { TaskNum=0;//номер стартовой задачи SysTick_Config(SystemCoreClock/1000);//запускаем таймер задержки вызова задач квант 1мС __set_SP(TaskList[TaskNum].SP);//установить указатель стека (*(TaskList[TaskNum].TaskPointer))();//передаем управление в задачу TaskNum //если произошло завершение задачи Delay(1000);//ожидаем секунду NVIC_SystemReset();//ресет } //преравание системного таймера void SysTick_Handler(void); void SysTick_Handler(void) { TimingDelay++; for(int i=0;i<KolvoTask;i++) { if((TaskList[i].TaskSleep)!=0) { (TaskList[i].TaskSleep)--; } } return; } Планировщик #define SHT_PROGBITS 0x1 EXTERN KolvoTask EXTERN TaskList EXTERN TaskNum PUBLIC Sleep SECTION `.text`:CODE:NOROOT(2) THUMB // 5 //передать управление операционной системе // 6 //аргумент время в лимлисекундах // 7 void Sleep(unsigned long ms) // 8 { Sleep: PUSH {R4} // 9 //сохраняем контекст // 10 TaskList[TaskNum].TaskSleep=ms;//сохраняем время через которое произойдет возврат управления LDR R1,??Sleep_0 LDR R2,??Sleep_0+0x4 LDR R3,[R1, #+0] MOVS R4,#+48 MULS R3,R4,R3 STR R0,[R2, R3] // 11 TaskList[TaskNum].R4 =__get_R4();//сохраняем R4 POP {R0} LDR R3,[R1, #+0] MULS R3,R4,R3 ADDS R3,R2,R3 STR R0,[R3, #+4] // 12 TaskList[TaskNum].R5 =__get_R5();//сохраняем R5 MOV R0,R5 LDR R3,[R1, #+0] MULS R3,R4,R3 ADDS R3,R2,R3 STR R0,[R3, #+8] // 13 TaskList[TaskNum].R6 =__get_R6();//сохраняем R6 MOV R0,R6 LDR R3,[R1, #+0] MULS R3,R4,R3 ADDS R3,R2,R3 STR R0,[R3, #+12] // 14 TaskList[TaskNum].R7 =__get_R7();//сохраняем R7 MOV R0,R7 LDR R3,[R1, #+0] MULS R3,R4,R3 ADDS R3,R2,R3 STR R0,[R3, #+16] // 15 TaskList[TaskNum].R8 =__get_R8();//сохраняем R8 MOV R0,R8 LDR R3,[R1, #+0] MULS R3,R4,R3 ADDS R3,R2,R3 STR R0,[R3, #+20] // 16 TaskList[TaskNum].R9 =__get_R9();//сохраняем R9 MOV R0,R9 LDR R3,[R1, #+0] MULS R3,R4,R3 ADDS R3,R2,R3 STR R0,[R3, #+24] // 17 TaskList[TaskNum].R10=__get_R10();//сохраняем R10 MOV R0,R10 LDR R3,[R1, #+0] MULS R3,R4,R3 ADDS R3,R2,R3 STR R0,[R3, #+28] // 18 TaskList[TaskNum].R11=__get_R11();//сохраняем R11 MOV R0,R11 LDR R3,[R1, #+0] MULS R3,R4,R3 ADDS R3,R2,R3 STR R0,[R3, #+32] // 19 TaskList[TaskNum].R12=__get_R12();//сохраняем R12 MOV R0,R12 LDR R3,[R1, #+0] MULS R3,R4,R3 ADDS R3,R2,R3 STR R0,[R3, #+36] // 20 TaskList[TaskNum].SP =__get_SP();//сохраняем SP MOV R0,SP LDR R3,[R1, #+0] MULS R3,R4,R3 ADDS R3,R2,R3 STR R0,[R3, #+40] // 21 TaskList[TaskNum].TaskPointer=((void(*)(void))__get_LR());//сохраняем адрес возврата MOV R0,LR LDR R3,[R1, #+0] MULS R3,R4,R3 ADDS R3,R2,R3 STR R0,[R3, #+44] // 22 // 23 while(1) // 24 { // 25 TaskNum++;if(TaskNum==KolvoTask)TaskNum=0;//инкрементируем номер текущей задачи ??Sleep_1: LDR R0,[R1, #+0] ADDS R0,R0,#+1 LDR R3,??Sleep_0+0x8 LDR R3,[R3, #+0] CMP R0,R3 BNE ??Sleep_2 MOVS R0,#+0 ??Sleep_2: STR R0,[R1, #+0] MOVS R3,#+48 MULS R0,R3,R0 ADDS R0,R2,R0 LDR R3,[R0, #+0] CMP R3,#+0 BNE ??Sleep_1 // 26 //проверяем готовность задачи к выполнению // 27 if(TaskList[TaskNum].TaskSleep==0) // 28 {//задача готова к выполнению // 29 //востанавливаем контекст // 30 __set_R4(TaskList[TaskNum].R4);//востанавливаем R4 LDR R0,[R0, #+4] MOV R4,R0 // 31 __set_R5(TaskList[TaskNum].R5);//востанавливаем R5 LDR R0,[R1, #+0] MOVS R3,#+48 MULS R0,R3,R0 ADDS R0,R2,R0 LDR R0,[R0, #+8] MOV R5,R0 // 32 __set_R6(TaskList[TaskNum].R6);//востанавливаем R6 LDR R0,[R1, #+0] MULS R0,R3,R0 ADDS R0,R2,R0 LDR R0,[R0, #+12] MOV R6,R0 // 33 __set_R7(TaskList[TaskNum].R7);//востанавливаем R7 LDR R0,[R1, #+0] MULS R0,R3,R0 ADDS R0,R2,R0 LDR R0,[R0, #+16] MOV R7,R0 // 34 __set_R8(TaskList[TaskNum].R8);//востанавливаем R8 LDR R0,[R1, #+0] MULS R0,R3,R0 ADDS R0,R2,R0 LDR R0,[R0, #+20] MOV R8,R0 // 35 __set_R9(TaskList[TaskNum].R9);//востанавливаем R9 LDR R0,[R1, #+0] MULS R0,R3,R0 ADDS R0,R2,R0 LDR R0,[R0, #+24] MOV R9,R0 // 36 __set_R10(TaskList[TaskNum].R10);//востанавливаем R10 LDR R0,[R1, #+0] MULS R0,R3,R0 ADDS R0,R2,R0 LDR R0,[R0, #+28] MOV R10,R0 // 37 __set_R11(TaskList[TaskNum].R11);//востанавливаем R11 LDR R0,[R1, #+0] MULS R0,R3,R0 ADDS R0,R2,R0 LDR R0,[R0, #+32] MOV R11,R0 // 38 __set_R12(TaskList[TaskNum].R12);//востанавливаем R12 LDR R0,[R1, #+0] MULS R0,R3,R0 ADDS R0,R2,R0 LDR R0,[R0, #+36] MOV R12,R0 // 39 __set_SP(TaskList[TaskNum].SP);//востанавливаем SP LDR R0,[R1, #+0] MULS R0,R3,R0 ADDS R0,R2,R0 LDR R0,[R0, #+40] MOV SP,R0 // 40 __set_LR((unsigned long)TaskList[TaskNum].TaskPointer);//установить адрес возврата LDR R0,[R1, #+0] MOVS R1,#+48 MULS R0,R1,R0 ADDS R0,R2,R0 LDR R0,[R0, #+44] MOV LR,R0 // 41 //The End // 42 return; BX LR Nop DATA ??Sleep_0: DC32 TaskNum DC32 TaskList DC32 KolvoTask // 43 } // 44 } // 45 } SECTION `.iar_vfe_header`:DATA:NOALLOC:NOROOT(2) SECTION_TYPE SHT_PROGBITS, 0 DATA DC32 0 SECTION __DLIB_PERTHREAD:DATA:REORDER:NOROOT(0) SECTION_TYPE SHT_PROGBITS, 0 SECTION __DLIB_PERTHREAD_init:DATA:REORDER:NOROOT(0) SECTION_TYPE SHT_PROGBITS, 0 END Тест void Task0(void); void Task0(void) { int i=0; while(1) { PutDecuFifo0(i++); putstrfifo0(" Task0 0.5sek\r\n"); Sleep(500); if(i==5)break; } EndTask(); } void Task1(void); void Task1(void) { int i=0; while(1) { PutDecuFifo0(i++); putstrfifo0(" Task1 1sek\r\n"); Sleep(1000); } } void Task2(void); void Task2(void) { putstrfifo0("Task2 Запущена\r\n"); for(int i=10;i>0;i--) { putstrfifo0("Task2 2sek. До останова "); PutDecuFifo0(i); putstrfifo0(" выполнений\r\n"); Sleep(2000); } putstrfifo0("Task2 Закончена\r\n"); //The End EndTask(); } int main(void) { // MCU Configuration //Reset of all peripherals, Initializes the Flash interface and the Systick. LL_Init(); //Configure the system clock SystemClock_Config(); InitTask(Task0); InitTask(Task1); InitTask(Task2); InitOS(); } Выводы. Главный вывод. Операционные системы нужны тем кто не умет писать неблокирующий код и конечные автоматы! Хня все эти ОС, не знаю как вытесняющие, кооперативные точно хня! Зачем тратить ресурсы на сохранение-востановление контекста, если можно прекрасно обойтись без этих хлопот. Вытесняющие ОС требуют ресурсов на переключение еще больше. Стек каждой задаче?!!! А не жирно ли? Планировщик можно написать только на ассемблере. Как написать на чистом Си не представляю.