umouse

umouse.git
git clone git://git.lenczewski.org/umouse.git
Log | Files | Refs | Submodules | README

IntCortex.fth (9694B)


      1 \ Cortex exception (interrupt) handlers
      2 
      3 ((
      4 Copyright (c) 2010, 2011
      5 MicroProcessor Engineering
      6 133 Hill Lane
      7 Southampton SO15 5AF
      8 England
      9 
     10 tel: +44 (0)23 8063 1441
     11 fax: +44 (0)23 8033 9691
     12 net: mpe@mpeforth.com
     13      tech-support@mpeforth.com
     14 web: www.mpeforth.com
     15 
     16 From North America, our telephone and fax numbers are:
     17   011 44 23 8063 1441
     18   011 44 23 8033 9691
     19 
     20 
     21 To do
     22 =====
     23 
     24 Change history
     25 ==============
     26 20110627 SFP001 Cortex M0/M1 changes.
     27 ))
     28 
     29 only forth definitions  decimal
     30 
     31 \ ============
     32 \ *! intcortex
     33 \ *T Exception and Interrupt handlers
     34 \ ============
     35 \ *P The file *\i{Cortex\IntCortex.fth} contains generic interrupt
     36 \ ** handlers for Cortex-M0/M1/M3/M4 processors.
     37 \ ** *\i{IntCortex.fth} requires *\i{Cortex\CortexDef} to be compiled
     38 \ ** before the *\i{SFRxxxx} file for your particular CPU. The file
     39 \ ** *\i{Cortex/StackDef.fth} provides default main task and stack
     40 \ ** layouts and should be compiled from the control file or copied
     41 \ ** into your control file. Default stack initialisation code is
     42 \ ** provided in *\i{Cortex/StackDef.fth}.
     43 
     44 \ *P The high-level interrupt handlers all share a common "stack
     45 \ ** of stacks". On entry to the interrupt handler, Forth system
     46 \ ** registers are allocated. Your initialisation code *\b{must}
     47 \ ** set up R13. This is normally provided by the MPE wrapper code
     48 \ ** for each exception.
     49 
     50 \ *P In order to support exception nesting the equate *\fo{#IRQs} in the
     51 \ ** control file must be set to the maximum number of nestings
     52 \ ** required.
     53 \ ** The equate *\fo{#IRQs} is used to calculate the size  of the
     54 \ ** required exception stack, together with the equate *\fo{#SVCs}.
     55 \ ** in the control file.
     56 
     57 \ *P Each interrupt has its own *\fo{USER} area. No user variables
     58 \ ** are initialised except for *\fo{S0} and *\fo{R0} in SVC
     59 \ ** handlers.
     60 
     61 \ *P It is assumed that the banked stack pointers have
     62 \ ** already been set up by the hardware initialisation code.
     63 
     64 \ *P It is implicit throughout the code that the three
     65 \ ** system registers UP, PSP, RSP are always set so that:
     66 \ *C   UP > PSP > RSP
     67 \ *P Because of this layout, data stack underflows may corrupt
     68 \ ** the first part of the *\fo{USER} area. You have been warned.
     69 \ ** During testing, it may be as well to set the equate
     70 \ ** *\fo{SP-GUARD} to 2 or 3 in your control file to leave a few
     71 \ ** guard cells on the data stack.
     72 
     73 
     74 \ ************************************
     75 \ *S Cortex-M3 NVIC Exception handlers
     76 \ ************************************
     77 \ *P This section is not a treatise on the Nested Vectored
     78 \ ** Interrupt Controller. These words provide a fairly basic
     79 \ ** set of tools for using the NVIC, which is fully
     80 \ ** documented in the Cortex-M3 Technical Reference Manual
     81 \ ** (ARM DDI 0337)from *\i{www.arm.com}.
     82 
     83 \ *P This code requires *\i{Kernel62.fth} and the equate
     84 \ ** *\fo{COLDCHAIN?} must be set non-zero in the control file.
     85 \ ** The NVIC address and register offsets are defined in the
     86 \ ** file *\i{Cortex/CortexDef.fth}.
     87 
     88 \ *P The MPE code works in terms of vector numbers, which are
     89 \ ** 16 greater than the external interrupt numbers.
     90 
     91 Not-M0/M1? [if]
     92 PROC ExcEntry	\ --
     93 \ *G This is the template code for M3+ vectored exception handlers.
     94 \ --- CPU has saved ----
     95 \   xPSR PC LR R12 R3 R2 R1 R0
     96 \ --- save state ---
     97   push    { r4-r11, r14 }		\ registers not saved by core + link
     98   sub     rsp, rsp, # up-size sp-size +	\ make space for USER area and data stack
     99 
    100 \ --- set up Forth ---
    101   add   up, rsp, # sp-size		\ USER area at top
    102   sub	psp, up, # sp-guard cells	\ generate new PSP
    103   sub	r4, psp, # tos-cached? cells	\ generate new S0
    104   str   r4, [ up, # s0-offset ]		\   that is compatible with SP!
    105   str   rsp, [ up, # r0-offset ]	\ set R0
    106 \ --- call high level handler ---
    107 l: ExcCall
    108   bl      ' noop			\ call the high level handler
    109 \ --- restore state ---
    110   add     rsp, rsp, # up-size sp-size +	\ remove space for USER area and data stack
    111   pop     { r4-r11, pc }		\ restore and exit
    112 end-code
    113 chere ExcEntry - equ /ExcEntry		\ size of template
    114 ExcCall ExcEntry - equ /ExcCall		\ offset to call instruction
    115 [else]
    116 sp-size 3 and [if]  cr ." bad SP-SIZE" abort  [then]
    117 sp-size 2 rshift equ sp-cells
    118 up-size 3 and [if]  cr ." bad UP-SIZE" abort  [then]
    119 up-size 2 rshift equ up-cells
    120 
    121 SP-SIZE #256 u< 0=  UP-SIZE #256 u< 0= or  equ LargeISR?  \ -- flag
    122 \ *G The interrupt is often larger than 256 bytes, which requires
    123 \ ** larger ISR entry code.
    124 
    125 LargeISR? [if]
    126 PROC ExcEntry	\ --
    127 \ *G This is the template code for M0/M1 vectored exception handlers
    128 \ ** with a large ISR frame.
    129 \ --- CPU has saved ----
    130 \   xPSR PC LR R12 R3 R2 R1 R0
    131 \ --- save state ---
    132   push    { r4-r7, r14 }			\ registers not saved by core + link
    133   mov     r0, r8
    134   mov     r1, r9
    135   mov     r2, r10
    136   mov     r3, r11
    137   push    { r0-r3 }
    138 
    139 \ --- set up Forth ---
    140 \ calculate the offsets
    141   mov .s  r0, # up-cells		\ R0 = UP-SIZE
    142   lsl .s  r0, r0, # 2
    143   mov .s  r2, # sp-cells		\ R2 = SP-SIZE
    144   lsl .s  r2, r2, # 2
    145   add .s  r3, r0, r2			\ R3 = SP-SIZE + UP-SIZE
    146 \ set new RSP
    147   mov     r1, rsp
    148   sub .s  r1, r3
    149   mov     rsp, r1			\ RSP = RSP - SP-SIZE - UP-SIZE
    150   push    { r3 }			\ how much we dropped the stack by
    151 \ set new UP
    152   add .s  r1, r1, r2			\ UP = RSP + SP-SIZE
    153   mov     up, r1			\ will need R1 later
    154 \ set new PSP
    155   mov     psp, r1			\ generate new PSP
    156   sub .s  psp, # sp-guard cells
    157 \ set new S0 and R0 user vars
    158   sub .s  r4, psp, # tos-cached? cells	\ generate new S0
    159   str     r4, [ r1, # s0-offset ]	\   that is compatible with SP!
    160   mov     r0, rsp
    161   str     r0, [ r1, # r0-offset ]	\ set R0
    162 \ --- call high level handler ---
    163 l: ExcCall
    164   bl      ' noop			\ call the high level handler
    165 \ --- restore state ---
    166 \ restore RSP
    167   pop     { r3 }			\ amount by which stack was dropped
    168   mov     r1, rsp
    169   add .s  r1, r3
    170   mov     rsp, r1
    171 \ restore regs
    172   pop     { r0-r3 }
    173   mov     r8, r0
    174   mov     r9, r1
    175   mov     r10, r2
    176   mov     r11, r3
    177   pop     { r4-r7, pc }			\ restore and exit
    178 end-code
    179 chere ExcEntry - equ /ExcEntry		\ size of template
    180 ExcCall ExcEntry - equ /ExcCall		\ offset to call instruction
    181 [else]
    182 PROC ExcEntry	\ --
    183 \ *G This is the template code for M0/M1 vectored exception handlers
    184 \ ** with a small ISR frame.
    185 \ --- CPU has saved ----
    186 \   xPSR PC LR R12 R3 R2 R1 R0
    187 \ --- save state ---
    188   push    { r4-r7, r14 }			\ registers not saved by core + link
    189   mov     r0, r8
    190   mov     r1, r9
    191   mov     r2, r10
    192   mov     r3, r11
    193   push    { r0-r3 }
    194 
    195 \ --- set up Forth ---
    196 \ set new UP
    197   mov     r1, rsp
    198   sub .s  r1, # UP-SIZE
    199   mov     up, r1			\ will need R1 later
    200 \ set new RSP
    201   mov .s  r2, r1
    202   sub .s  r2, # SP-SIZE
    203   mov     rsp, r2			\ RSP = RSP - SP-SIZE - UP-SIZE
    204 \ set new PSP
    205   mov     psp, r1			\ generate new PSP = UP - abit
    206   sub .s  psp, # sp-guard cells
    207 \ set new S0 and R0 user vars
    208   sub .s  r4, psp, # tos-cached? cells	\ generate new S0
    209   str     r4, [ r1, # s0-offset ]	\   that is compatible with SP!
    210   mov     r0, rsp
    211   str     r0, [ r1, # r0-offset ]	\ set R0
    212 \ --- call high level handler ---
    213 l: ExcCall
    214   bl      ' noop			\ call the high level handler
    215 \ --- restore state ---
    216 \ restore RSP
    217   mov     r1, rsp
    218   add .s  r1, # SP-SIZE
    219   add .s  r1, # UP-SIZE
    220   mov     rsp, r1
    221 \ restore regs
    222   pop     { r0-r3 }
    223   mov     r8, r0
    224   mov     r9, r1
    225   mov     r10, r2
    226   mov     r11, r3
    227   pop     { r4-r7, pc }		\ restore and exit
    228 end-code
    229 chere ExcEntry - equ /ExcEntry		\ size of template
    230 ExcCall ExcEntry - equ /ExcCall		\ offset to call instruction
    231 [then]					\ LargeISR?
    232 
    233 [then]					\ Not-M0/M1?
    234 
    235 interpreter
    236 : EXC:		\ xt vec# -- ; -- isr
    237 \ *G Creates an exception handler that runs the given Forth word.
    238 \ ** At run time the entry point of the ISR is returned. Use in
    239 \ ** the form:
    240 \ *C   ' <action> <vec#> EXC: <actionISR>
    241 \ *P The example below will define a handler for the SysTick
    242 \ ** interrupt/exception that runs the Forth word *\fo{SysTickHandler}.
    243 \ *C   ' SysTickHandler #15 EXC: SysTickEntry
    244   swap align  chere /ExcEntry callot	\ -- vec# xt isr ; reserve space
    245   ExcEntry over /ExcEntry move		\ copy template
    246   tuck /ExcCall + !call			\ -- vec# isr ; form call instruction
    247   tuck swap setExcVec
    248   label					\ returns entry point
    249 ;
    250 target
    251 
    252 : int>bit	\ int# -- mask offset
    253 \ Convert an interrupt number into its bit mask and ofset
    254 \ into an array of 32 bit registers.
    255   dup $1F and 1 swap lshift
    256   swap 5 rshift 2 lshift
    257 ;
    258 
    259 : EnInt		\ vec# --
    260 \ *G Enable the requested NVIC interrupt source.
    261 \ ** NVIC interrupts have vector numbers in the range 16..255.
    262   dup #15 u> if
    263     #16 - int>bit _SCS + nvSetEnR0 + !
    264     exit
    265   endif
    266   drop
    267 ;
    268 
    269 : DisInt	\ vec# --
    270 \ *G Disable the requested NVIC interrupt source.
    271 \ ** NVIC interrupts have vector numbers in the range 16..255.
    272   dup #15 u> if
    273     #16 - int>bit _SCS + nvClrEnR0 + !
    274     exit
    275   endif
    276   drop
    277 ;
    278 
    279 : SetPri	\ pri vec#
    280 \ *G Set the priority of the given NVIC interrupt source.
    281 \ ** NVIC interrupts have vector numbers in the range 16..255.
    282 \ ** The priority numbers are in the range 0..255, where 0 is
    283 \ ** the highest priority. The number of bits actually used
    284 \ ** is implementation dependent, but unused bits are always
    285 \ ** the low-order bits. Hence, using $10, $20 and so on is
    286 \ ** fairly portable.
    287   dup #15 u> if
    288     16 - _SCS + nvPR0 + c!  exit
    289   endif
    290   drop
    291 ;
    292 
    293 : SWINT		\ vec# --
    294 \ *G Generate interrupt from software.
    295   dup #15 u> if
    296     #16 - int>bit _SCS + nvSetPendR0 + !
    297     exit
    298   endif
    299   drop
    300 ;
    301 
    302 
    303 \ ======
    304 \ *> ###
    305 \ ======
    306