Differences

This shows you the differences between two versions of the page.

Link to this comparison view

cybiko:ucosii [2009/11/27 17:54] (current)
Line 1: Line 1:
 +======uC/​OS-II======
  
 +Port of the uC/OS-II Realtime kernel to the cybiko. ​ The trial and tribulations of porting this famous RTOS from http://​www.micrium.com/​ to the cybiko.
 +
 +  * [[http://​www.dbzoo.com/​public/​cybiko-ucos.zip|Cybiko uC/OS-II port]] - Cybiko h8 enhancements to the base ucos distribution.
 +  * [[http://​www.dbzoo.com/​public/​ucos.boot|Compiled .boot sample]]
 +
 +The book, which comes with a CD containing the base uC/OS-II source, can be bought from [[http://​www.micrium.com/​|micrium]]. I cannot re-distribute the uC/OS-II RTOS source, for reference I was using version kernel v2.76. My H8 cybiko port should be upwardly compatible thou. 
 +
 +<note tip>
 +You may find uC/OS-II on a P2P network if you look.
 +</​note>​
 +
 +
 +
 +
 +
 +
 +
 +
 +
 +
 +
 +
 +
 +=====Context Switch=====
 +
 +One of the issues that needs to be resolved is how to generate a software context switch. ​ This would normally be done using the following H8 instruction.
 +<code asm>
 +  TRAPA
 +</​code>​
 +
 +Dissassembling the ROM for the locations of the where TRAPA vectors would be loaded reveal everything is set to 0.
 +<code asm>
 +;Trap instruction Vector 8, 9, 10, 11
 +;​TRAPA ​ #xx:2   ​Instruction has 2 bit vector
 +
 +;Vector 8:
 +      20: 00 00  ; trapa #0 
 +;Vector 9:
 +      24: 00 00  ; trapa #1
 +;Vector 10:
 +      28: 00 00  ; trapa #2
 +;Vector 11:
 +      2C: 00 00  ; trapa #3   
 +</​code>​
 +
 +As this instruction uses a vector that is loaded into ROM that cannot be changed an alternative way needs to be found. ​ Thanks to some tips by the developer of the [[SourceForge>​cybiko-reborn|CyBorn Project]] there is a workaround.
 +
 +The IRQ6 port of the H8 processor is not connect to anything. ​ It is possible to toggle this port in software using a BNOT instruction and trigger an interrupt (IRQ6) that can be intercepted and re-vectored via memory. ​ The trigger will need to be on both the raising and falling edges of the bit, that is; 0->1 and 1->0
 +
 +<code c>
 +void OSInitHookBegin (void)
 +{
 +  asm("​orc #​0xc0,​ccr"​); ​      // Mask interrupts
 +  asm("​bset #4, @0x2c:​8"​); ​   // ISCRH - Trigger on both edges.
 +  asm("​bset #5, @0x2c:​8"​);​
 +                              // IER - Enable IRQ6
 +  asm("​bset #6, @0x2e:​8"​);​
 +                              // ISR - Clear interrupt status
 +  asm("​mov.b @0x2f:8, r0l"​); ​ // Read
 +  asm("​and.b #0xbf, r0l"​); ​   // Clear IRQ6 bit
 +  asm("​mov.b r0l, @0x2f:​8"​); ​ // Write
 +
 +  asm("​mov.b #​0x1f,​r0l"​); ​     // Enable PGDDR pin 0
 +  asm("​mov.b r0l,​@0xfebf:​16"​);​
 +  // IRQ6 can now be software generated via - BNOT #0,@0X6F:8
 +  // This will be used for the OS_TASK_SW() context switch.
 +}
 +</​code>​
 +
 +When IRQ6 is fired it will load the jump vector contained at this location in the ROM.
 +<code asm>
 +;IRQ6 vector 22 - 00 00 11 c8
 +      58: 00 00        00 00             nop
 +      5a: 11 c8        11 c8             ​shar #​0x2,​r0l
 +</​code>​
 +
 +This will result in the following ROM instructions being executed. ​ As you can see the memory address 0xec2c is a RAM location that contains a vector that IRQ6 will be re-directed to.  At this location we will need to load our ContextSwitch vector.
 +
 +<code asm>
 +IRQ6:
 +    11c8: 01 30 6d f0 01 30 6d f0       ​stm.l er0-er3,​@-sp
 +    11cc: 01 20 6d f4 01 20 6d f4       ​stm.l er4-er6,​@-sp
 +    11d0: 01 00 6b 02 01 00 6b 02 ec 2c mov.l @0xec2c:​16,​er2
 +    11d4: ec 2c
 +    11d6: 5d 20        5d 20             ​jsr @er2
 +    11d8: 01 20 6d 76 01 20 6d 76       ​ldm.l @sp+,​er4-er6
 +    11dc: 01 30 6d 73 01 30 6d 73       ​ldm.l @sp+,​er0-er3
 +    11e0: 56 70        56 70             rte
 +</​code>​
 +
 +So assuming we have loaded the vector of our OSCtxSw routine into 0xec2c the next issue we will need to deal with is how the stack is left when our routine is entered.
 +<​code>​
 +On entry OSCtxSw ​   sp--> -  4         IRQ6 ROM vector (jsr pushed vector from 11d6:)
 +                          -  2         IRQ6 ROM vector
 +Move SP to here ---> ​     +  0         ​er6 ​  (H)
 +                          +  2         ​er6 ​  (L)
 +                          +  4         ​er5 ​  (H)
 +                          +  6         ​er5 ​  (L)
 +                          +  8         ​er4 ​  (H)
 +                          + 10         ​er4 ​  (L)
 +                          + 12         ​er3 ​  (H)
 +                          + 14         ​er3 ​  (L)
 +                          + 16         ​er2 ​  (H)
 +                          + 18         ​er2 ​  (L)
 +                          + 20         ​er1 ​  (H)
 +                          + 22         ​er1 ​  (L)
 +                          + 24         ​er0 ​  (H)
 +                          + 26         ​er0 ​  (L)
 +                          + 28         ​task ​ (CCR & Upper 8-bits of PC)
 +                          + 30         ​task ​ (Lower 16-bits of PC)
 +</​code>​
 +
 +Adjusting the Stack pointer to remove the JSR return address should be first thing that the context switch will need to do, after this you need to clear IRQ6.  Then you are free to perform whatever Task Context Block movement are necessary to setup for the next task.
 +<code asm>
 +_OSCtxSw:
 +; Adjust for ROM JSR call
 + ​  ​ ADD.L    #4,sp
 +; Clear IRQ6  - read/​mask/​write
 +   mov.b @0x2f:8, r0l
 +   and.b #0xbf, r0l
 +   mov.b r0l, @0x2f:8
 +
 +; Custom TCB code here..
 +
 +; Replace stack and re-vector to new TCB via RTE
 +   ldm.l @sp+,​er4-er6
 +   ldm.l @sp+,​er0-er3
 +          RTE
 +</​code>​
 +
 +
 +
 +
 +
 +
 +
 +=====Timer Interrupt Service=====
 +
 +The timer is the heartbeat that allows for pre-emptive multitasking.\\ We can use the TNCT0 timer as Vector 66 is redirected to a ROM routine that uses RAM based vector.
 +
 +<code asm>
 +;ROM disassembly
 +;OVI0 Overflow vector 66 - 00 00 13 d0
 +     ​108:​ 00 00        00 00             nop
 +     ​10a:​ 13 d0        13 d0             ​rotr #​0x2,​r0
 +</​code>​
 +
 +Timer 0 overflow interrupt service routine - calls the vector in RAM location 0xFFEC7C\\
 +Disassembly of ROM revectoring code.
 +<code asm>
 +    13d0: 01 30 6d f0 01 30 6d f0       ​stm.l er0-er3,​@-sp
 +    13d4: 01 20 6d f4 01 20 6d f4       ​stm.l er4-er6,​@-sp
 +    13d8: 01 00 6b 02 01 00 6b 02 ec 7c mov.l @0xec7c:​16,​er2
 +    13dc: ec 7c
 +    13de: 5d 20        5d 20             ​jsr @er2
 +    13e0: 01 20 6d 76 01 20 6d 76       ​ldm.l @sp+,​er4-er6
 +    13e4: 01 30 6d 73 01 30 6d 73       ​ldm.l @sp+,​er0-er3
 +    13e8: 56 70        56 70             rte
 +</​code>​
 +
 +So how to setup the ISR?
 +<code c>
 +#define MSTPCR ( *( volatile INT8U *)( 0xFFFFFF3C ) )    /* Module Stop Control */
 +#define TCR0 ( *( volatile INT8U *)( 0xFFFFFFB0 ) )   //  Timer 0 control
 +#define TCNT0 ( *( volatile INT16U *)( 0xFFFFFFB8 ) )   //  Timer 0 counter
 +
 +void AppTickInit(INT16U tick_rate)
 +{
 +  MSTPCR &= 0xef; // enable the 8 bit timer by UnStopping it
 +  TCR0 = 0x23;    // set TCR0 to OVIE interrupts on and clock of internal / 8192
 +  // Note: TCNT0 must be reset to the same number in the OSTickISR()
 +  TCNT0 = 0xe4;   // so interrupts must happen 11059200 / 8192 / (255-228) = 50 times a second  ​
 +  asm("​andc #​0x3f,​ccr"​); ​     // Enable interrupts
 +}
 +</​code>​
 +
 +So assuming we have located the _OSTickISR address into 0xec7c the following code fragment would be representative of an ISR
 +<code asm>
 +;; Vector 66
 +;; The cybiko ROM vector will push er0-er3,​er4-er6
 +;; and a JSR return address (which we want to ignore)
 +_OSTickISR:
 + ​ ADD.L ​   #4,sp
 + JSR @_OSIntEnter ​              ; Call required routine.
 +
 +;; Reload TNCT0
 + mov.b #​0xe4,​r2l ​           ; Reloaded with same value as use in AppTickInit()
 + mov.b r2l,​@0xb8:​8
 +
 +;; clear overflow interrupt bit
 + BCLR #0x5, @0xB2:8
 +
 + JSR @_OSTimeTick ​              ; Call required routine.
 + JSR @_OSIntExit ​               ; Call required routine.
 +
 + ldm.l @sp+,​er4-er6
 + ldm.l @sp+,​er0-er3
 + RTE
 +</​code>​
 +{{tag>​cybiko}}