📄 os_cpu_a.tri
字号:
;********************************************************************************************************
;
; File : os_cpu_a.tri for UCOS-II RTOS by Jean Labrosse.
; By : Andre' Gompel Andre.Gompel@Infineon.com agompel@bigfoot.com
;
; (c) Copyright 2000, Infineon Technology
; BETA (UNRELEASED CODE): DO NOT COPY WITOUT AUTHORIZATION
; Tricore TC10
;
; THIS SOFTWARE IS PROVIDED "AS IS" WITHOUT ANY EXPRESS OR
; IMPLIED WARRANTY. BOTH INFINEON TECHNOLOGIES CORPORATION AND
; MICRIUM INC. DISCLAIMS ALL REPRESENTATIONS AND WARRANTIES WITH
; REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF
; MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT
; SHALL INFINEON TECHNOLOGIES CORPORATION OR MICRIUM INC. BE LIABLE
; FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
; WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
; AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACT OR
; OMISSION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
; PERFORMANCE OF THIS SOFTWARE.
;
;********************************************************************************************************
#include "os_cfg.h"
#include <RegDef.h>
#include "TC10GP.h"
;; .nodebug
;; .file "os_cpu_a.tri"
.text
.align 4
;
; Set up of the PSW See Architecture manual, section "core registers"
;
;psw_prs PRS : Protection Register Set Selection
;psw_io IO : I/O Access Permission Mode: 2=Supervisor mode.
;psw_is IS : interrupt stak. 1=USe interrupt stack
;psw_gw GW : Global Register Write 1=permitted
;psw_cde CDE : Call Depth Enable
;psw_cdc CDC note 7F equ disabled
PSW_V0 .equ psw_prs | psw_io | psw_is | psw_gw | psw_cde | psw_cdc
;
; Useful References:
;
; 1) TriCore Special functions Registers and Bits, Chapter 2.
; 2) TriCore architecture manual, chapter 7: Protection system
;
; 3) Also User's Manual, Section: General Purpose Timer Unit
; Section: Interrupt System
;
; 4) TriCore AppNote: AP3224: Using the Timer Interrupt System
;
;
; IMPORTANT: To modify tick period, adjust OS_TICKS_PER_SEC in file "os_cfg.h"
;
;
.globl OSInitGptu
OSInitGptu: ; void OSInitGptu(void)
LD_IOREG16 GPTU0_GTCLC, 0xff00 ; rmc=0xff
LD_IOREG16 GPTU0_T012RUN, 0x440 ; Stop all timers, 2 B safe.
LD_IOREG16 GPTU0_T01IRS, 0x100C ;Input and reload, use T01 and T0B concatenated.
LD_IOREG16 GPTU0_T01OTS, 0x0100 ;SSR00=01 : T0B overflow-> SRC0
LD_IOREG32 GPTU0_T0RCBA, ~(1000000/OS_TICKS_PER_SEC) ; reload value cntr BA of timer 0
LD_IOREG32 GPTU0_T0CBA, ~(1000000/OS_TICKS_PER_SEC) ; Start Value
LD_IOREG32 GPTU0_GTSRSEL, 0xC0000000 ;OverFlow Timer 0 B to Service Request 0
LD_IOREG16 GPTU0_GTSRC0, 0x1002 ;SRE + TOS=CPU + Priority =2
LD_IOREG16 GPTU0_T012RUN, 3 ; Run Timer 0, A and B counters.
ret16
.globl OSStopGptu
OSStopGptu:
LD_IOREG16 GPTU0_T012RUN, 0x440
ret16
.globl OSStartGptu
OSStartGptu:
LD_IOREG16 GPTU0_T012RUN, 3
ret16
.globl OSTickISR
OSTickISR: ; void OSTickISR (void)
call OSTimeTick ; Call uC/OS-II's tick updating function
ret ; OSIntExit may set the ReqTskSwitch
;********************************************************************************************************
; START HIGHEST PRIORITY TASK READY-TO-RUN
; Description : This function is called by OSStart() to start the highest priority task that was created
; by your application before calling OSStart().
; OSStartHighRdy() MUST:
; a) Call OSTaskSwHook() then,
; b) Set OSRunning to TRUE,
; c) Switch to the highest priority task.
;********************************************************************************************************
;; Need to define OS_TASK_CREATE_EXT_EN in os_cfg.h to have proper access
.globl OSStartHighRdy
OSStartHighRdy: ; void OSStartHighRdy (void)
mov16 d0,1 ; GHS would have used D0 : not portable (lwr ctxt)
LD_AREG a12, OSRunning ; Does not hurt if already running
st16.b [a12],d0 ; Indicate that we are multitasking
j OSLaunchHigh
;; OsIntCtxSw is called by OSIntExit to perform a context switch from am ISR
;; at this time all the nested interrupts have been completed.
;; We are in a critical section
;
; For TriCore, because of the availabily of the interrupt stack
; OSIntCtxSw and OSCtxSw are the same code.
; I used two labels, to keep full compatibility with the UCOS-II code
; and also to emphasize this fact.
; Andre Gompel.
;
; void OSIntCtxSw (void) Is now inlined, see os_cpu.h
; Not yet: due to bug.
.globl OSIntCtxSw
OSIntCtxSw: ; void OSIntCtxSw (void)
mov16 d15, 1
st.w %zdaoff(flg_sw),d15
ret16
.globl OSCtxSw
OSCtxSw: ; void OSCtxSw (void)
svlcx
LD_AREG a12,OSTCBCur ; Get ptr to Curent TCB
ld.w d0, [a12] ; OSTCBCur is a ptr
mov.a a12, d0
mfcr d0,(PCXI & 0xffff)
st.w [a12], d0 ; Save PCXI to TCB->pcxi
mfcr d0, (FCX & 0xffff)
st.w [a12]4, d0 ; Save FCX to TCB->lcx
mfcr d0, (LCX & 0xffff)
st.w [a12]8, d0 ; Save LCX to TCB->lcx
;; Enable next line as needed (avoid increasing context switch latency)
;; call OSTaskSwHook ; Invoke user defined context switch hook
;; Now restore task context, from task to be activated TCB
;; We need the contexts (Upper & lower), and also the context ptrs
;;
.globl OSLaunchHigh
OSLaunchHigh:
LD_AREG a13, OSTCBHighRdy ; Get a ptr to highest pty task
ld.w d0, [a13]
mov.a a13, d0
LD_AREG a12, OSTCBCur
st16.w [a12], d0 ; OSTCBCur = OSTCBHighRdy
LD_AREG a14, OSPrioHighRdy
ld16.bu d0,[a14]
LD_AREG a14, OSPrioCur
st16.b [a14], d0 ; OSPrioCur = OSPrioHighRdy
ld.w d0, [a13] ; Get PCXI from task TCB
mtcr (PCXI & 0xffff),d0
isync
ld.w d0, [a13]4
mtcr (FCX & 0xffff), d0
isync
ld.w d0, [a13]8
mtcr (LCX & 0xffff), d0
isync
rslcx
mfcr d0,(PCXI & 0xffff)
insert d0,d0,1,22,1 ; Say UL=UC
mtcr %lo(PCXI),d0
isync
mov.u d0,PSW_V0 ; Use PSW.v0
mtcr (PSW & 0xffff),d0
isync
rfe ; go 4 it
;;.globl os_vectors ; just for the debugger
;;os_vectors: 2 B DELETED
.globl OSInitTricoreInt
; We will enable interrupts at a later time
; Logically we should also set btv here.
OSInitTricoreInt: ; void OSInitTricoreInt(void)
; Initialize BIV
movh d15,%hi(int_vectors)
addi d15,d15,%lo(int_vectors)
mtcr (BIV & 0xffff),d15 ; Init BIV=Base of Interrupts Vectors
isync
; Set ICR initial value.
mov.u d2, 1 ; disable interrupts and set CCPN to 1
mtcr (ICR & 0xffff), d2
isync
; Set the SYSCON register
mov.u d2, 0x1
mtcr (SYSCON & 0xffff), d2
isync
ret16
.globl OSInitFlags
OSInitFlags:
; void OSInitFlags(void)
xor d0, d0,d0
st.w %zdaoff(flg_sw),d0
ret16
;*******************************************************************************************
;
; void *OSTaskStkInit (void (*task)(void *pd), //)
; void *pdata,
; OS_STK *ptos,
; uint16_t opt )
;
; The name OSTaskStkInit was used to keep UCOS terminology
; However for Infineon TriCore OSContextInit would have been more appropriate.
; THe TriCore architecture actually make context swithing very simple..and very fast
; so the code is really simple.
; This is due to the implicit and context save/restore.
; The upper context is saved/restored implicitly
; The lower context has to be saved restored explicitly.
; A good understanding of this mecahnism, as well as the TriCore ve 1.4 EABI specification
; are required to understand this code:
; See TriCore architechture manual and EABI Ve 1.4 Specification.
;
; So far we do not use params: ptos and opt
;
; apology: using global variables for fcx, lcx, pcxi is not very satisfactory
; The main reason is to keep the code in os_core.c unmodified.(Mostly)
;
;*******************************************************************************************
;
; Each task has its private CSA free list.
; We need to initialize the two first CSA for lauching the task.
; This is is what the following code is doing.
; The name OSTaskStkInit was keept for UCOS-II compatibility, but it is misleading
; It should rather be something like OSTaskCtxtListInit.
;
; Note: this works with the CSA format of GHS where the PCXI points to the next (higher) ctx
; void *OSTaskStkInit (void (*task)(void *pd), void *pdata, OS_STK *ptos,uint16_t opt)
.globl OSTaskStkInit
OSTaskStkInit: ; void *OSTaskStkInit(see_above)
movh.a a12, %hi(g_tsk_ctx0) ; Translate g_tsk_ctx0 into an effective address
ld.w d8,[a12]%lo(g_tsk_ctx0) ; d8 has g_tsk_ctx0 in "fcx format"
mov.aa a13, a12 ; keep a13= g_tsk_ctx0 in fcx format
mov.u d9,0xffff
and d10,d9,d8 ;
sh d10,d10,6 ; d10[21:6]=offset
movh d9,0x000f ; mask seg adr, upper 16 bits
and d11,d9,d8 ;
sh d11,d11,12 ; d11[31:28]=seg
or d10,d11, d10 ; d10 has EA of 1st ctxt
mov.a a12,d10 ; a12: ptr to task 1st ctxt (UC)
ld.w d0,[a12] ;
LD_DREG d2, 0x000fffff ; keep pcx0, pcxs, ul
and d0,d0,d2 ;
movh d2, 0x0180 ; setup v0_tsk_pcxi for pie, pcpn
or d0, d2, d0
st.w [a12], d0 ; LC.PCXI
mov.d d10,a4 ; get 1st param (tsk addr)
st.w [a12]4, d10 ; Init LC.A11/RA
mov.u d9,64 ; Ctx_ptr += sizeof(context)
addsc.a a12,a12,d9,0
xor d0,d0,d0 ;
st.w [a12],d0 ; UC.PCXI= d0
mov.u d0, PSW_V0 ; Task default PSW
st.w [a12]4, d0 ; UC.PSW=
mov.d d0,a6 ; get 3rd parameter (tsk sp)
st.w [a12]8, d0 ; UC.A10/SP=
ret16 ; Of OSTaskStkInit
.globl infinite_loop
infinite_loop: ; We use this as a very crude trap handler.
j infinite_loop ; Later we will issue an error explicit message.
.section ".traps","a"
.globl trap_vectors
trap_vectors:
trapdbg 0
trapdbg 1
trapdbg 2
trapdbg 3
trapdbg 4
trapdbg 5
trapvec 6, OSCtxSw
trapdbg 7
trapend
.section ".interrupts", "a"
;
; Note 1: it is safer to create an interrupt entry for each
; of the 256 possible interrupts, just in cas of dummy interrupts (noise etc...)
; Note 2: So far a static allocation of interrupt vectors has been chosen.
; Beside being a little simpler to implement, it give full visibility to the programmer.
; If need arise, a service to hook an interrupt vector could be added.
;
.globl OS_ASC0_TxISR ; Interrupt when char has been sent
.globl OS_ASC0_TxISR ; Interrupt when a char has been received.
; interrupts vectors: ISRname, SRPN (Service request priority number)
int_vectors:
intvec unused_interrupt_isr,0
intvec unused_interrupt_isr,1
intvec OSTimeTick,2
intvec OS_ASC0_TxISR, 3
intvec OS_ASC0_RxISR,4
intvec unused_interrupt_isr,5
intvec unused_interrupt_isr,6
intvec unused_interrupt_isr,7
.section .spad, "ab"
.align 4
.globl flg_sw
flg_sw:
.word 0 ; flag sw (request)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -