/* @file RtoS_cortex_m7.S @author AVI_crak @version V-0.13 @date 1-january-2020 @brief RTOS license Million helicopters and one cent. discussion forum http://forum.ixbt.com/topic.cgi?id=48:11735 repository https://bitbucket.org/AVI-crak/rtos-cortex-m3-gcc */ .syntax unified .cpu cortex-m7 .arch armv7e-m .thumb_func .equ __Test_psp,0 // checking for stack overflow errors .equ __SysTick_CTRL, 0xE000E010 // #0xE010 SysTick->CTRL, #0xE014 SysTick->LOAD, #0xE018 SysTick->VAL .align 2 .section .text.SVC_Handler .globl SVC_Handler .type SVC_Handler, %function SVC_Handler: ldr r12, = os_data tbh [pc, r3, lsl #1] SVC_Table: .hword ((__switch - SVC_Table)/2) // 0 .hword ((__sleep_tasks - SVC_Table)/2) // 1 .hword ((__delay_new - SVC_Table)/2) // 2 .hword ((__ret_service - SVC_Table)/2) // 3 .hword ((__to_service - SVC_Table)/2) // 4 .hword ((__wake - SVC_Table)/2) // 5 .hword ((__task_freeze - SVC_Table)/2) // 6 .hword ((__task_new - SVC_Table)/2) // 7 .hword ((__delete_task - SVC_Table)/2) // 8 .hword ((__EnableIRQ - SVC_Table)/2) // 9 .hword ((__DisableIRQ - SVC_Table)/2) // A __delete_task: // task_status = delete_task, swap_data - адрес структуры ldr r1, [r12, #12] // task* service ldr r0, [r1, #4] ldr r2, [r1] subs r3, r0, r1 iteee eq streq r3, [r12, #12] strne r2, [r12, #12] strne r2, [r0] strne r0, [r2, #4] bx lr __to_service: // task_status уже содержит код операции, swap_data - данные или адрес структуры ldr r0, [r12] // active task mov r3, #12 // list nomer service b __switch_rxx __task_freeze: ldr r0, [r12] // активная задача mov r2, #4 // task_status task_hold strb r2, [r0, #39] mov r3, #8 // list nomer hold b __switch_rxx __delay_new: // //r#16 swap_data = Delay_mc + ldr r3, [r12, #40] // system_us ldr r0, [r12] // active task mov r2, #2 // task_status task_delay strb r2, [r0, #39] ldr r1, [r0, #16] // Delay_mc + add r1, r1, r3 str r1, [r0, #16] // (swap_data) saved the sleep point mov r3, #4 // list nomer delay b __switch_rxx __switch: // переключатель задач ldr r0, [r12] ldr r3, [r0] cmp r0, r3 it eq bxeq lr __switch_rxx: //switch: r0 save, r3<17 r0 move to inactive .ifdef __Test_psp ldrh r1, [r0, #26] // stack area used mrs r2, psp sub r2, r0, r2 add r2, r2, #240 // текущий актуальный размер стека( 200 + 40) cmp r2, r1 ittt hi strhhi r2, [r0, #26] // new stack area used ldrhhi r1, [r0, #24] // stack area size cmphi r2, r1 bls __switch_sawe // no overflow ldrb r1, [r0, #39] add r1, r1, #1 strb r1, [r0, #39] // + _error ldr r1, [r0, #4] ldr r3, [r0] // no free space - delete task str r1, [r3, #4] str r3, [r1] b __switch_read .endif __switch_sawe: //switch: r0 save, r3 read tst lr, #0x04 itte eq mrseq r2, msp ldreq r2, [r2, #20] movne r2, lr mrs r1, psp stmdb r1!, {r4-r11} // save registers tst r2, #0x10 // used math? itt eq vstmdbeq r1!, {s16-s31} // save math registers addeq r1, r1, #1 str r1, [r0, #12] // saved task r0 stack address cmp r3, #17 it hi bhi __switch_read // r3>17 there the task address mov r4, r3 // ldr r3, [r0] // r3 new active ldr r1, [r0, #4] str r1, [r3, #4] str r3, [r1] // removed R0 from active ldr r2, [r12, r4] ldr r1, [r2, #4] cmp r2, #0 itttt eq // inactive list empty streq r0, [r12, r4] streq r0, [r0] streq r0, [r0, #4] beq __switch_read str r0, [r2, #4] str r0, [r1] str r1, [r0, #4] str r2, [r0] __switch_read: // rx3 - new task - data loading dsb str r3, [r12] // new active ldr r12, =__SysTick_CTRL ldr r0, [r3, #12] // read the stack address tst lr, #0x04 // recovery state override beq __switch_r1 tst r0, #0x01 // return recovery for stream ittte ne subne r0, r0, #1 vldmiane r0!, {s16-s31} bicne lr, #0x10 orreq lr, #0x10 b __switch_r2 __switch_r1: mrs r1, msp // restore return for interrupt ldr r2, [r1, #20] tst r0, #0x01 ittte ne subne r0, r0, #1 vldmiane r0!, {s16-s31} bicne r2, #0x10 orreq r2, #0x10 str r2, [r1, #20] __switch_r2: ldmia r0!, {r4-r11} // read stored msr psp, r0 // restore top of task stack ldr r0, [r3, #28] // activ time mov r1, #7 bfc r0, #24, #8 str r0, [r12, #4] // #0xE000E014 SysTick->LOAD str r1, [r12, #8] // #0xE000E018 SysTick->VAL dsb 0xF isb 0xF bx lr __task_new: push {r4, lr} ldr r0, [r12, #16] // адрес новой задачи mov r4, #16 // ссылка на task* task_switch bl __to_activ // __to_activ ldr r0, [r12, #12] mov r4, #12 // ссылка на task* service bl __to_activ // __to_activ pop {r4, pc} __ret_service: push {r4, lr} ldr r0, [r12, #12] mov r4, #12 // ссылка на task* service bl __to_activ // __to_activ pop {r4, pc} __wake: // r0(глобал флаг - адрес *uint8_t номер задачи) разбудить ldrb r3, [r0] // читаем номер задачи mov r1, r0 ldr r0, [r12, #8] // Адрес задачь ожидающих пинка cmp r0, #0 it eq bxeq lr // а там пусто... push {r4, r5, r6, lr} mov r4, #8 // ссылка на task* hold ldr r2, [r0, #4] // task_tail mov r6, r1 __wake_next: ldr r5, [r0, #31] //#31 task_nomer ldr r1, [r0] sub r5, r5, r3 ittt eq strbeq r5, [r6] // обнулить флаг moveq r2, r0 bleq __to_activ // __to_activ cmp r0, r2 it eq popeq {r4, r5, r6, pc} mov r0, r1 b __wake_next __sleep_tasks: // обслуживание задержки ldr r3, [r12, #40] //#40 system_us ldr r0, [r12, #4] //#4 task* delay add r3, r3, #1 str r3, [r12, #40] //#40 system_us++ cmp r0, #0 it eq bxeq lr push {r4, r5, lr} mov r4, #4 // ссылка на task* delay ldr r2, [r0, #4] // task_tail __sleep_next: ldr r5, [r0, #16] //#16 swap_data (delay) ldr r1, [r0] subs r5, r5, r3 itt eq streq r5, [r0, #16] // == 0 bleq __to_activ // __to_activ cmp r0, r2 mov r0, r1 bne __sleep_next pop {r4, r5, pc} __to_activ: // r0 - задача на обмен, r4 - адрес структуры (4-8-12-16) push {r1, r2, lr} ldr r1, [r0] ldr r2, [r0, #4] cmp r0, r1 itttt ne // не единственная strne r1, [r2] // хвост на голову strne r2, [r1, #4] // голова на хвост strne r1, [r12, r4] // новая голова bne __to_activ1 mov r2, #0 str r2, [r12, r4] // закрыли __to_activ1: ldr r2, [r12] // активная задача в потоке ldr r1, [r2, #4] // хвост активной задачи str r2, [r0] str r1, [r0, #4] str r0, [r2, #4] str r0, [r1] // хвост на новую mov r2, #0 strb r2, [r0, #39] // task_activ =0, pop {r1, r2, pc} __EnableIRQ: // ("r0") = IRQn, ("r1") = priority; ++ movw r12, #0xE70C movt r12, #0xE000 and r0, #0xFF //IRQn безопасность and r1, #0xF //Priority безопасность // cmp r1, #15 // it eq //проверка на мин приоритет // moveq r1, #14 // cmp r0, #0xFF //проверка SysTick_IRQn // it eq // moveq r1, #15 //SysTick_IRQn должен иметь минимальный приоритет lsl r1, r1, #4 //сдвиг на границу mov r3, r0 and r3, #0x0F sub r3, r3, #4 cmp r0, #0xF1 ittee cs addwcs r2, r12, #0x60C //SCB->SHPx 0xE000ED18 strbcs r1, [r2, r3] subwcc r2, r12, #0x30c //NVIC->IPx 0xE000E400 strbcc r1, [r2, r0] and r1, r0, #0x1F mov r3, #0x1 lsls r1, r3, r1 lsrs r0, r0, #5 lsls r0, r0, #2 subw r2, r12, #0x60C //NVIC_ISERx 0xE000E100 str r1, [r2, r0] bx lr __DisableIRQ: // ("r0") = IRQn; ++ //NVIC->ICER[((uint32_t)(IRQn) >> 5)] = (1 << ((uint32_t)(IRQn) & 0x1F)); /* disable interrupt */ mov r3, #0x1F and r1, r0, r3 mov r3, #0x1 lsls r2, r3, r1 lsrs r1, r0, #5 lsls r1, r1, #2 movw r3, #0xE180 movt r3, #0xE000 str r2, [r3, r1] bx lr .size SVC_Handler, . - SVC_Handler .align 2 .globl SysTick_Handler .type SysTick_Handler, %function .section .text.SysTick_Handler SysTick_Handler: mov r3, #0x00 svc 0x0 bx lr .size SysTick_Handler, . - SysTick_Handler /* __switch_read: // rx3 - new task - data loading dsb str r3, [r12] // new active ldr r12, =__SysTick_CTRL ldr r0, [r3, #12] // read the stack address tst lr, #0x04 beq __switch_r1 tst r0, #0x01 ittte ne subne r0, r0, #1 vldmiane r0!, {s16-s31} // грузим математику bicne lr, #0x10 orreq lr, #0x10 b __switch_r2 __switch_r1: mrs r1, msp ldr r2, [r1, #20] tst r0, #0x01 ittte ne subne r0, r0, #1 vldmiane r0!, {s16-s31} // грузим математику bicne r2, #0x10 orreq r2, #0x10 str r2, [r1, #20] __switch_r2: ldmia r0!, {r4-r11} // читаем сохранённое msr psp, r0 // переписываем стек ldr r0, [r3, #28] // читаем новое время Task activity timer mov r1, #7 bfc r0, #24, #8 str r0, [r12, #4] // сохранили время #0xE014 SysTick->LOAD str r1, [r12, #8] // перезаруск #0xE018 SysTick->VAL dsb 0xF isb 0xF bx lr */