Merge pull request #1326 from TomoYamanaka/master

RZ_A1H - Modify to support NEON for RTOS.
pull/1349/merge
Martin Kojtal 2015-09-25 14:23:28 +02:00
commit e8c24ba90d
41 changed files with 727 additions and 334 deletions

View File

@ -1,8 +1,8 @@
/**************************************************************************//**
* @file pl310.c
* @brief Implementation of pl310 functions
* @brief Implementation of PL310 PrimeCell Level 2 Cache Controller functions
* @version
* @date 11 June 2013
* @date 3 December 2014
*
* @note
*
@ -80,7 +80,7 @@ void PL310_CleanInvAllByWay (void)
assoc = 8;
PL310->CLEAN_INV_WAY = (1 << assoc) - 1;
while(PL310->CLEAN_INV_WAY && ((1 << assoc) - 1)); //poll invalidate
while(PL310->CLEAN_INV_WAY & ((1 << assoc) - 1)); //poll invalidate
PL310_Sync();
}

View File

@ -1,14 +1,14 @@
/**************************************************************************//**
* @file system_MBRZA1H.c
* @brief CMSIS Device System Source File for
* ARMCA9 Device Series
* ARM Cortex-A9 Device Series
* @version V1.00
* @date 19 Sept 2013
* @date 09 January 2015
*
* @note
*
******************************************************************************/
/* Copyright (c) 2011 - 2013 ARM LIMITED
/* Copyright (c) 2011 - 2015 ARM LIMITED
All rights reserved.
Redistribution and use in source and binary forms, with or without
@ -50,9 +50,9 @@ void FPUEnable(void);
#endif
uint32_t IRQNestLevel;
unsigned char seen_id0_active = 0; // single byte to hold a flag used in the workaround for GIC errata 733075
#if defined(__ARMCC_VERSION)
/**
* Initialize the cache.
*
@ -61,6 +61,7 @@ uint32_t IRQNestLevel;
*
* @brief Initialise caches. Requires PL1, so implemented as an SVC in case threads are USR mode.
*/
#if defined(__ARMCC_VERSION)
#pragma push
#pragma arm
@ -189,7 +190,7 @@ void SystemInit (void)
//Fault Status Register (IFSR/DFSR) definitions
#define FSR_ALIGNMENT_FAULT 0x01 //DFSR only. Fault on first lookup
#define FSR_INSTRUCTION_CACHE_MAINTAINANCE 0x04 //DFSR only - async/external
#define FSR_INSTRUCTION_CACHE_MAINTENANCE 0x04 //DFSR only - async/external
#define FSR_SYNC_EXT_TTB_WALK_FIRST 0x0c //sync/external
#define FSR_SYNC_EXT_TTB_WALK_SECOND 0x0e //sync/external
#define FSR_SYNC_PARITY_TTB_WALK_FIRST 0x1c //sync/external
@ -223,7 +224,7 @@ void CDAbtHandler(uint32_t DFSR, uint32_t DFAR, uint32_t LR) {
//Your code here. Value in DFAR is invalid for some fault statuses.
case FSR_ALIGNMENT_FAULT:
case FSR_INSTRUCTION_CACHE_MAINTAINANCE:
case FSR_INSTRUCTION_CACHE_MAINTENANCE:
case FSR_SYNC_EXT_TTB_WALK_FIRST:
case FSR_SYNC_EXT_TTB_WALK_SECOND:
case FSR_TRANSLATION_FAULT_FIRST:
@ -278,21 +279,36 @@ void CPAbtHandler(uint32_t IFSR, uint32_t IFAR, uint32_t LR) {
}
//returns amount to decrement lr by
//this will be 0 when we have emulated the instruction and simply want to execute the next instruction
//this will be 2 when we have performed some maintenance and want to retry the instruction in thumb (state == 2)
//this will be 4 when we have performed some maintenance and want to retry the instruction in arm (state == 4)
//this will be 0 when we have emulated the instruction and want to execute the next instruction
//this will be 2 when we have performed some maintenance and want to retry the instruction in Thumb (state == 2)
//this will be 4 when we have performed some maintenance and want to retry the instruction in ARM (state == 4)
uint32_t CUndefHandler(uint32_t opcode, uint32_t state, uint32_t LR) {
const unsigned int THUMB = 2;
const unsigned int ARM = 4;
//Lazy VFP/NEON initialisation and switching
if ((state == ARM && ((opcode & 0x0C000000)) >> 26 == 0x03) ||
(state == THUMB && ((opcode & 0xEC000000)) >> 26 == 0x3B)) {
if (((opcode & 0x00000E00) >> 9) == 5) { //fp instruction?
// (ARM ARM section A7.5) VFP data processing instruction?
// (ARM ARM section A7.6) VFP/NEON register load/store instruction?
// (ARM ARM section A7.8) VFP/NEON register data transfer instruction?
// (ARM ARM section A7.9) VFP/NEON 64-bit register data transfer instruction?
if ((state == ARM && ((opcode & 0x0C000000) >> 26 == 0x03)) ||
(state == THUMB && ((opcode & 0xEC000000) >> 26 == 0x3B))) {
if (((opcode & 0x00000E00) >> 9) == 5) {
FPUEnable();
return state;
}
}
// (ARM ARM section A7.4) NEON data processing instruction?
if ((state == ARM && ((opcode & 0xFE000000) >> 24 == 0xF2)) ||
(state == THUMB && ((opcode & 0xEF000000) >> 24 == 0xEF)) ||
// (ARM ARM section A7.7) NEON load/store instruction?
(state == ARM && ((opcode >> 24) == 0xF4)) ||
(state == THUMB && ((opcode >> 24) == 0xF9))) {
FPUEnable();
return state;
}
//Add code here for other Undef cases
while(1);
}
@ -304,18 +320,22 @@ uint32_t CUndefHandler(uint32_t opcode, uint32_t state, uint32_t LR) {
__asm void FPUEnable(void) {
ARM
//Permit access to VFP registers by modifying CPACR
//Permit access to VFP/NEON, registers by modifying CPACR
MRC p15,0,R1,c1,c0,2
ORR R1,R1,#0x00F00000
MCR p15,0,R1,c1,c0,2
//Enable VFP
//Ensure that subsequent instructions occur in the context of VFP/NEON access permitted
ISB
//Enable VFP/NEON
VMRS R1,FPEXC
ORR R1,R1,#0x40000000
VMSR FPEXC,R1
//Initialise VFP registers to 0
//Initialise VFP/NEON registers to 0
MOV R2,#0
//Initialise D16 registers to 0
VMOV D0, R2,R2
VMOV D1, R2,R2
VMOV D2, R2,R2
@ -332,7 +352,23 @@ __asm void FPUEnable(void) {
VMOV D13,R2,R2
VMOV D14,R2,R2
VMOV D15,R2,R2
//Initialise D32 registers to 0
VMOV D16,R2,R2
VMOV D17,R2,R2
VMOV D18,R2,R2
VMOV D19,R2,R2
VMOV D20,R2,R2
VMOV D21,R2,R2
VMOV D22,R2,R2
VMOV D23,R2,R2
VMOV D24,R2,R2
VMOV D25,R2,R2
VMOV D26,R2,R2
VMOV D27,R2,R2
VMOV D28,R2,R2
VMOV D29,R2,R2
VMOV D30,R2,R2
VMOV D31,R2,R2
//Initialise FPSCR to a known state
VMRS R2,FPSCR
LDR R3,=0x00086060 //Mask off all bits that do not have to be preserved. Non-preserved bits can/should be zero.
@ -344,40 +380,71 @@ __asm void FPUEnable(void) {
#pragma pop
#elif defined(__GNUC__)
void FPUEnable(void)
{
__asm__ __volatile__ (
".align 2 \n\t"
".arm \n\t"
"mrc p15,0,r1,c1,c0,2 \n\t"
"orr r1,r1,#0x00f00000 \n\t"
"mcr p15,0,r1,c1,c0,2 \n\t"
"vmrs r1,fpexc \n\t"
"orr r1,r1,#0x40000000 \n\t"
"vmsr fpexc,r1 \n\t"
"mov r2,#0 \n\t"
"vmov d0, r2,r2 \n\t"
"vmov d1, r2,r2 \n\t"
"vmov d2, r2,r2 \n\t"
"vmov d3, r2,r2 \n\t"
"vmov d4, r2,r2 \n\t"
"vmov d5, r2,r2 \n\t"
"vmov d6, r2,r2 \n\t"
"vmov d7, r2,r2 \n\t"
"vmov d8, r2,r2 \n\t"
"vmov d9, r2,r2 \n\t"
"vmov d10,r2,r2 \n\t"
"vmov d11,r2,r2 \n\t"
"vmov d12,r2,r2 \n\t"
"vmov d13,r2,r2 \n\t"
"vmov d14,r2,r2 \n\t"
"vmov d15,r2,r2 \n\t"
"vmrs r2,fpscr \n\t"
"ldr r3,=0x00086060 \n\t"
"and r2,r2,r3 \n\t"
"vmsr fpscr,r2 \n\t"
"bx lr \n\t"
);
void FPUEnable(void) {
__asm__ (
".ARM;"
//Permit access to VFP/NEON, registers by modifying CPACR
"MRC p15,0,R1,c1,c0,2;"
"ORR R1,R1,#0x00F00000;"
"MCR p15,0,R1,c1,c0,2;"
//Ensure that subsequent instructions occur in the context of VFP/NEON access permitted
"ISB;"
//Enable VFP/NEON
"VMRS R1,FPEXC;"
"ORR R1,R1,#0x40000000;"
"VMSR FPEXC,R1;"
//Initialise VFP/NEON registers to 0
"MOV R2,#0;"
//Initialise D16 registers to 0
"VMOV D0, R2,R2;"
"VMOV D1, R2,R2;"
"VMOV D2, R2,R2;"
"VMOV D3, R2,R2;"
"VMOV D4, R2,R2;"
"VMOV D5, R2,R2;"
"VMOV D6, R2,R2;"
"VMOV D7, R2,R2;"
"VMOV D8, R2,R2;"
"VMOV D9, R2,R2;"
"VMOV D10,R2,R2;"
"VMOV D11,R2,R2;"
"VMOV D12,R2,R2;"
"VMOV D13,R2,R2;"
"VMOV D14,R2,R2;"
"VMOV D15,R2,R2;"
//Initialise D32 registers to 0
"VMOV D16,R2,R2;"
"VMOV D17,R2,R2;"
"VMOV D18,R2,R2;"
"VMOV D19,R2,R2;"
"VMOV D20,R2,R2;"
"VMOV D21,R2,R2;"
"VMOV D22,R2,R2;"
"VMOV D23,R2,R2;"
"VMOV D24,R2,R2;"
"VMOV D25,R2,R2;"
"VMOV D26,R2,R2;"
"VMOV D27,R2,R2;"
"VMOV D28,R2,R2;"
"VMOV D29,R2,R2;"
"VMOV D30,R2,R2;"
"VMOV D31,R2,R2;"
//Initialise FPSCR to a known state
"VMRS R2,FPSCR;"
"LDR R3,=0x00086060;" //Mask off all bits that do not have to be preserved. Non-preserved bits can/should be zero.
"AND R2,R2,R3;"
"VMSR FPSCR,R2;"
//"BX LR;"
:
:
:"r1", "r2", "r3");
return;
}
#else
#endif

View File

@ -2,12 +2,12 @@
* @file core_caFunc.h
* @brief CMSIS Cortex-A Core Function Access Header File
* @version V3.10
* @date 9 May 2013
* @date 30 Oct 2013
*
* @note
*
******************************************************************************/
/* Copyright (c) 2009 - 2012 ARM LIMITED
/* Copyright (c) 2009 - 2013 ARM LIMITED
All rights reserved.
Redistribution and use in source and binary forms, with or without
@ -147,8 +147,6 @@ __STATIC_ASM void __set_PSP(uint32_t topOfProcStack)
/** \brief Set User Mode
This function changes the processor state to User Mode
\param [in] topOfProcStack USR/SYS Stack Pointer value to set
*/
__STATIC_ASM void __set_CPS_USR(void)
{
@ -253,7 +251,7 @@ __STATIC_INLINE uint32_t __get_CPACR(void)
This function assigns the given value to the Coprocessor Access Control register.
\param [in] cpacr Coporcessor Acccess Control value to set
\param [in] cpacr Coprocessor Acccess Control value to set
*/
__STATIC_INLINE void __set_CPACR(uint32_t cpacr)
{
@ -275,7 +273,7 @@ __STATIC_INLINE uint32_t __get_CBAR() {
/** \brief Get TTBR0
This function returns the value of the Configuration Base Address register.
This function returns the value of the Translation Table Base Register 0.
\return Translation Table Base Register 0 value
*/
@ -286,7 +284,7 @@ __STATIC_INLINE uint32_t __get_TTBR0() {
/** \brief Set TTBR0
This function assigns the given value to the Coprocessor Access Control register.
This function assigns the given value to the Translation Table Base Register 0.
\param [in] ttbr0 Translation Table Base Register 0 value to set
*/
@ -309,7 +307,7 @@ __STATIC_INLINE uint32_t __get_DACR() {
/** \brief Set DACR
This function assigns the given value to the Coprocessor Access Control register.
This function assigns the given value to the Domain Access Control Register.
\param [in] dacr Domain Access Control Register value to set
*/
@ -325,7 +323,7 @@ __STATIC_INLINE void __set_DACR(uint32_t dacr) {
This function assigns the given value to the System Control Register.
\param [in] sctlr System Control Register, value to set
\param [in] sctlr System Control Register value to set
*/
__STATIC_INLINE void __set_SCTLR(uint32_t sctlr)
{
@ -397,9 +395,9 @@ __STATIC_INLINE void __enable_mmu(void) {
__ISB();
}
/** \brief Enable MMU
/** \brief Disable MMU
Enable MMU
Disable MMU
*/
__STATIC_INLINE void __disable_mmu(void) {
// Clear M bit 0 to disable the MMU
@ -477,8 +475,9 @@ __STATIC_INLINE void __v7_clean_inv_dcache_mva(void *va) {
__DMB(); //ensure the ordering of data cache maintenance operations and their effects
}
/** \brief
* Generic mechanism for cleaning/invalidating the entire data or unified cache to the point of coherency.
/** \brief Clean and Invalidate the entire data or unified cache
Generic mechanism for cleaning/invalidating the entire data or unified cache to the point of coherency.
*/
#pragma push
#pragma arm
@ -522,12 +521,12 @@ Dccsw CMP R0, #1
BNE Dccisw
MCR p15, 0, R11, c7, c10, 2 // DCCSW. Clean by Set/Way
B cont
Dccisw MCR p15, 0, R11, c7, c14, 2 // DCCISW, Clean and Invalidate by Set/Way
Dccisw MCR p15, 0, R11, c7, c14, 2 // DCCISW. Clean and Invalidate by Set/Way
cont SUBS R9, R9, #1 // Decrement the Way number
BGE Loop3
SUBS R7, R7, #1 // Decrement the Set number
BGE Loop2
Skip ADD R10, R10, #2 // increment the cache number
Skip ADD R10, R10, #2 // Increment the cache number
CMP R3, R10
BGT Loop1
@ -539,9 +538,6 @@ Finished
}
#pragma pop
/** \brief __v7_all_cache - helper function
*/
/** \brief Invalidate the whole D$
@ -577,7 +573,6 @@ __STATIC_INLINE void __v7_clean_inv_dcache_all(void) {
#error IAR Compiler support not implemented for Cortex-A
#elif (defined (__GNUC__)) /*------------------ GNU Compiler ---------------------*/
/* GNU gcc specific functions */
#define MODE_USR 0x10
@ -620,14 +615,12 @@ __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __disable_irq(void)
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_APSR(void)
{
#if 1
uint32_t result;
__ASM volatile ("mrs %0, apsr" : "=r" (result) );
return (result);
register uint32_t __regAPSR;
__ASM volatile ("mrs %0, apsr" : "=r" (__regAPSR) );
#else
register uint32_t __regAPSR __ASM("apsr");
return(__regAPSR);
#endif
return(__regAPSR);
}
@ -694,22 +687,49 @@ __attribute__( ( always_inline ) ) __STATIC_INLINE void __set_LR(uint32_t lr)
\param [in] topOfProcStack USR/SYS Stack Pointer value to set
*/
extern void __set_PSP(uint32_t topOfProcStack);
__attribute__( ( always_inline ) ) __STATIC_INLINE void __set_PSP(uint32_t topOfProcStack)
{
__asm__ volatile (
".ARM;"
".eabi_attribute Tag_ABI_align8_preserved,1;"
"BIC R0, R0, #7;" /* ;ensure stack is 8-byte aligned */
"MRS R1, CPSR;"
"CPS %0;" /* ;no effect in USR mode */
"MOV SP, R0;"
"MSR CPSR_c, R1;" /* ;no effect in USR mode */
"ISB;"
//"BX LR;"
:
: "i"(MODE_SYS)
: "r0", "r1");
return;
}
/** \brief Set User Mode
This function changes the processor state to User Mode
\param [in] topOfProcStack USR/SYS Stack Pointer value to set
*/
extern void __set_CPS_USR(void);
__attribute__( ( always_inline ) ) __STATIC_INLINE void __set_CPS_USR(void)
{
__asm__ volatile (
".ARM;"
"CPS %0;"
//"BX LR;"
:
: "i"(MODE_USR)
: );
return;
}
/** \brief Enable FIQ
This function enables FIQ interrupts by clearing the F-bit in the CPSR.
Can only be executed in Privileged modes.
*/
#define __enable_fault_irq __enable_fiq
#define __enable_fault_irq() __asm__ volatile ("cpsie f")
/** \brief Disable FIQ
@ -717,7 +737,7 @@ extern void __set_CPS_USR(void);
This function disables FIQ interrupts by setting the F-bit in the CPSR.
Can only be executed in Privileged modes.
*/
#define __disable_fault_irq __disable_fiq
#define __disable_fault_irq() __asm__ volatile ("cpsid f")
/** \brief Get FPSCR
@ -825,7 +845,7 @@ __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_CPACR(void)
This function assigns the given value to the Coprocessor Access Control register.
\param [in] cpacr Coporcessor Acccess Control value to set
\param [in] cpacr Coprocessor Acccess Control value to set
*/
__attribute__( ( always_inline ) ) __STATIC_INLINE void __set_CPACR(uint32_t cpacr)
{
@ -856,7 +876,7 @@ __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_CBAR() {
/** \brief Get TTBR0
This function returns the value of the Configuration Base Address register.
This function returns the value of the Translation Table Base Register 0.
\return Translation Table Base Register 0 value
*/
@ -872,7 +892,7 @@ __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_TTBR0() {
/** \brief Set TTBR0
This function assigns the given value to the Coprocessor Access Control register.
This function assigns the given value to the Translation Table Base Register 0.
\param [in] ttbr0 Translation Table Base Register 0 value to set
*/
@ -904,7 +924,7 @@ __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_DACR() {
/** \brief Set DACR
This function assigns the given value to the Coprocessor Access Control register.
This function assigns the given value to the Domain Access Control Register.
\param [in] dacr Domain Access Control Register value to set
*/
@ -924,7 +944,7 @@ __attribute__( ( always_inline ) ) __STATIC_INLINE void __set_DACR(uint32_t dacr
This function assigns the given value to the System Control Register.
\param [in] sctlr System Control Register, value to set
\param [in] sctlr System Control Register value to set
*/
__attribute__( ( always_inline ) ) __STATIC_INLINE void __set_SCTLR(uint32_t sctlr)
{
@ -1005,9 +1025,9 @@ __attribute__( ( always_inline ) ) __STATIC_INLINE void __enable_mmu(void) {
__ISB();
}
/** \brief Enable MMU
/** \brief Disable MMU
Enable MMU
Disable MMU
*/
__attribute__( ( always_inline ) ) __STATIC_INLINE void __disable_mmu(void) {
// Clear M bit 0 to disable the MMU
@ -1109,14 +1129,10 @@ __attribute__( ( always_inline ) ) __STATIC_INLINE void __v7_clean_inv_dcache_mv
__DMB(); //ensure the ordering of data cache maintenance operations and their effects
}
/** \brief
* Generic mechanism for cleaning/invalidating the entire data or unified cache to the point of coherency.
/** \brief Clean and Invalidate the entire data or unified cache
Generic mechanism for cleaning/invalidating the entire data or unified cache to the point of coherency.
*/
/** \brief __v7_all_cache - helper function
*/
extern void __v7_all_cache(uint32_t op);

View File

@ -1,14 +1,13 @@
;/**************************************************************************//**
; * @file core_ca_mmu.h
; * @brief MMU Startup File for
; * VE_A9_MP Device Series
; * @brief MMU Startup File for A9_MP Device Series
; * @version V1.01
; * @date 25 March 2013
; * @date 10 Sept 2014
; *
; * @note
; *
; ******************************************************************************/
;/* Copyright (c) 2012 ARM LIMITED
;/* Copyright (c) 2012-2014 ARM LIMITED
;
; All rights reserved.
; Redistribution and use in source and binary forms, with or without
@ -298,7 +297,7 @@ __STATIC_INLINE int __ap_section(uint32_t *descriptor_l1, mmu_access_Type user,
else if ((priv == RW) && (user == READ)) { ap = 0x2; }
else if ((priv == RW) && (user == RW)) { ap = 0x3; }
else if ((priv == READ) && (user == NO_ACCESS)) { ap = 0x5; }
else if ((priv == READ) && (user == READ)) { ap = 0x6; }
else if ((priv == READ) && (user == READ)) { ap = 0x7; }
}
else { //Simplified access
@ -647,7 +646,7 @@ __STATIC_INLINE int __memory_page(uint32_t *descriptor_l2, mmu_memory_Type mem,
The function creates a section descriptor.
Assumptions:
- 16MB super sections not suported
- 16MB super sections not supported
- TEX remap disabled, so memory type and attributes are described directly by bits in the descriptor
- Functions always return 0

View File

@ -57,8 +57,12 @@ private:
osMutexId _osMutexId;
osMutexDef_t _osMutexDef;
#ifdef CMSIS_OS_RTX
#ifdef __MBED_CMSIS_RTOS_CA9
int32_t _mutex_data[4];
#else
int32_t _mutex_data[3];
#endif
#endif
};
}

View File

@ -91,18 +91,16 @@ void rt_init_stack (P_TCB p_TCB, FUNCP task_body) {
static __inline U32 *rt_ret_regs (P_TCB p_TCB) {
/* Get pointer to task return value registers (R0..R3) in Stack */
#if (__TARGET_FPU_VFP)
if (p_TCB->stack_frame & 0x2) {
/* Extended Stack Frame: S0-31,FPSCR,Reserved,R4-R11,R0-R3,R12,LR,PC,xPSR */
return (U32 *)(p_TCB->tsk_stack + 8*4 + 34*4);
if (p_TCB->stack_frame & 0x4) {
/* NEON/D32 Stack Frame: D0-31,FPSCR,Reserved,R4-R11,R0-R3,R12,LR,PC,xPSR */
return (U32 *)(p_TCB->tsk_stack + 8*4 + 2*4 + 32*8);
} else if (p_TCB->stack_frame & 0x2) {
/* VFP/D16 Stack Frame: D0-D15/S0-31,FPSCR,Reserved,R4-R11,R0-R3,R12,LR,PC,xPSR */
return (U32 *)(p_TCB->tsk_stack + 8*4 + 2*4 + 32*4);
} else {
/* Basic Stack Frame: R4-R11,R0-R3,R12,LR,PC,xPSR */
return (U32 *)(p_TCB->tsk_stack + 8*4);
}
#else
/* Stack Frame: R4-R11,R0-R3,R12,LR,PC,xPSR */
return (U32 *)(p_TCB->tsk_stack + 8*4);
#endif
}
void rt_ret_val (P_TCB p_TCB, U32 v0) {

View File

@ -3,10 +3,10 @@
*----------------------------------------------------------------------------
* Name: RTX_CM_LIB.H
* Purpose: RTX Kernel System Configuration
* Rev.: V4.60
* Rev.: V4.73
*----------------------------------------------------------------------------
*
* Copyright (c) 1999-2009 KEIL, 2009-2012 ARM Germany GmbH
* Copyright (c) 1999-2009 KEIL, 2009-2013 ARM Germany GmbH
* All rights reserved.
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
@ -50,14 +50,14 @@
#define _declare_box(pool,size,cnt) uint32_t pool[(((size)+3)/4)*(cnt) + 3]
#define _declare_box8(pool,size,cnt) uint64_t pool[(((size)+7)/8)*(cnt) + 2]
#define OS_TCB_SIZE 48
#define OS_TCB_SIZE 52
#define OS_TMR_SIZE 8
#if defined (__CC_ARM) && !defined (__MICROLIB)
typedef void *OS_ID;
typedef uint32_t OS_TID;
typedef uint32_t OS_MUT[3];
typedef uint32_t OS_MUT[4];
typedef uint32_t OS_RESULT;
#define runtask_id() rt_tsk_self()
@ -104,10 +104,15 @@ uint32_t const os_stackinfo = (OS_STKCHECK<<24)| (OS_IDLESTKSIZE*4);
uint32_t const os_stackinfo = (OS_STKCHECK<<24)| (OS_PRIV_CNT<<16) | (OS_STKSIZE*4);
#endif
uint32_t const os_rrobin = (OS_ROBIN << 16) | OS_ROBINTOUT;
uint32_t const os_tickfreq = OS_CLOCK;
uint16_t const os_tickus_i = OS_CLOCK/1000000;
uint16_t const os_tickus_f = (((uint64_t)(OS_CLOCK-1000000*(OS_CLOCK/1000000)))<<16)/1000000;
uint32_t const os_trv = OS_TRV;
uint8_t const os_flags = OS_RUNPRIV;
/* Export following defines to uVision debugger. */
__USED uint32_t const CMSIS_RTOS_API_Version = osCMSIS;
__USED uint32_t const CMSIS_RTOS_RTX_Version = osCMSIS_RTX;
__USED uint32_t const os_clockrate = OS_TICK;
__USED uint32_t const os_timernum = 0;
@ -258,7 +263,6 @@ osThreadDef_t os_thread_def_main = {(os_pthread)main, osPriorityNormal, 1, 4*OS_
osThreadDef_t os_thread_def_main = {(os_pthread)main, osPriorityNormal, 1, 4*OS_MAINSTKSIZE };
#endif
#if defined (__CC_ARM)
#ifdef __MICROLIB

View File

@ -3,10 +3,10 @@
*----------------------------------------------------------------------------
* Name: RTX_CONFIG.H
* Purpose: Exported functions of RTX_Config.c
* Rev.: V4.60
* Rev.: V4.70
*----------------------------------------------------------------------------
*
* Copyright (c) 1999-2009 KEIL, 2009-2012 ARM Germany GmbH
* Copyright (c) 1999-2009 KEIL, 2009-2013 ARM Germany GmbH
* All rights reserved.
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
@ -67,6 +67,8 @@ extern U8 const os_fifo_size;
/* Functions */
extern void os_idle_demon (void);
extern int os_tick_init (void);
extern U32 os_tick_val (void);
extern U32 os_tick_ovf (void);
extern void os_tick_irqack (void);
extern void os_tmr_call (U16 info);
extern void os_error (U32 err_code);

View File

@ -3,10 +3,10 @@
*----------------------------------------------------------------------------
* Name: HAL_CA9.c
* Purpose: Hardware Abstraction Layer for Cortex-A9
* Rev.: 3 Sept 2013
* Rev.: 8 April 2015
*----------------------------------------------------------------------------
*
* Copyright (c) 2012 - 2013 ARM Limited
* Copyright (c) 2012 - 2015 ARM Limited
* All rights reserved.
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
@ -114,6 +114,7 @@ __asm void SVC_Handler (void) {
IMPORT SVC_Table
IMPORT rt_stk_check
IMPORT FPUEnable
IMPORT scheduler_suspended ; flag set by rt_suspend, cleared by rt_resume, read by SVC_Handler
Mode_SVC EQU 0x13
@ -159,7 +160,7 @@ Mode_SVC EQU 0x13
/* Here we will be in SVC mode (even if coming in from PendSV_Handler or OS_Tick_Handler) */
Sys_Switch
LDR LR,=__cpp(&os_tsk)
LDM LR,{R4,LR} ; os_tsk.run, os_tsk.new
LDM LR,{R4,LR} ; os_tsk.run, os_tsk.new_tsk
CMP R4,LR
BNE switching
@ -170,7 +171,13 @@ Sys_Switch
PUSH {R12, LR} ; Store stack adjustment and dummy LR to SVC stack
CPSID i
; Do not unlock scheduler if it has just been suspended by rt_suspend()
LDR R1,=scheduler_suspended
LDRB R0, [R1]
CMP R0, #1
BEQ dont_unlock
BLX rt_tsk_unlock
dont_unlock
POP {R12, LR} ; Get stack adjustment & discard dummy LR
ADD SP, SP, R12 ; Unadjust stack
@ -188,7 +195,7 @@ switching
PUSH {R8-R11} //R4 and LR already stacked
MOV R10,R4 ; Preserve os_tsk.run
MOV R11,LR ; Preserve os_tsk.new
MOV R11,LR ; Preserve os_tsk.new_tsk
ADD R8,SP,#16 ; Unstack R4,LR
LDMIA R8,{R4,LR}
@ -204,21 +211,22 @@ switching
SUB R8,R8,#4 ; No writeback for store of User LR
STMDB R8!,{R0-R3,R12} ; User R0-R3,R12
MOV R3,R10 ; os_tsk.run
MOV LR,R11 ; os_tsk.new
MOV LR,R11 ; os_tsk.new_tsk
POP {R9-R12}
ADD SP,SP,#12 ; Fix up SP for unstack of R4, LR & SPSR
STMDB R8!,{R4-R7,R9-R12} ; User R4-R11
//If applicable, stack VFP state
//If applicable, stack VFP/NEON state
MRC p15,0,R1,c1,c0,2 ; VFP/NEON access enabled? (CPACR)
AND R2,R1,#0x00F00000
CMP R2,#0x00F00000
BNE no_outgoing_vfp
VMRS R2,FPSCR
STMDB R8!,{R2,R4} ; Push FPSCR, maintain 8-byte alignment
VSTMDB R8!,{S0-S31}
LDRB R2,[R3,#TCB_STACKF] ; Record in TCB that VFP state is stacked
ORR R2,#2
VSTMDB R8!,{D0-D15}
VSTMDB R8!,{D16-D31}
LDRB R2,[R3,#TCB_STACKF] ; Record in TCB that NEON/D32 state is stacked
ORR R2,#4
STRB R2,[R3,#TCB_STACKF]
no_outgoing_vfp
@ -238,8 +246,8 @@ no_outgoing_vfp
MOV LR,R4
SVC_Next //R4 == os_tsk.run, LR == os_tsk.new, R0-R3, R5-R12 corruptible
LDR R1,=__cpp(&os_tsk) ; os_tsk.run = os_tsk.new
SVC_Next //R4 == os_tsk.run, LR == os_tsk.new_tsk, R0-R3, R5-R12 corruptible
LDR R1,=__cpp(&os_tsk) ; os_tsk.run = os_tsk.new_tsk
STR LR,[R1]
LDRB R1,[LR,#TCB_TID] ; os_tsk.run->task_id
LSL R1,#8 ; Store PROCID
@ -247,16 +255,17 @@ SVC_Next //R4 == os_tsk.run, LR == os_tsk.new, R0-R3, R5-R12 corruptible
LDR R0,[LR,#TCB_TSTACK] ; os_tsk.run->tsk_stack
//Does incoming task have VFP state in stack?
//Does incoming task have VFP/NEON state in stack?
LDRB R3,[LR,#TCB_STACKF]
TST R3,#0x2
ANDS R3, R3, #0x6
MRC p15,0,R1,c1,c0,2 ; Read CPACR
ANDEQ R1,R1,#0xFF0FFFFF ; Disable VFP access if incoming task does not have stacked VFP state
ORRNE R1,R1,#0x00F00000 ; Enable VFP access if incoming task does have stacked VFP state
ANDEQ R1,R1,#0xFF0FFFFF ; Disable VFP/NEON access if incoming task does not have stacked VFP/NEON state
ORRNE R1,R1,#0x00F00000 ; Enable VFP/NEON access if incoming task does have stacked VFP/NEON state
MCR p15,0,R1,c1,c0,2 ; Write CPACR
BEQ no_incoming_vfp
ISB ; We only need the sync if we enabled, otherwise we will context switch before next VFP instruction anyway
VLDMIA R0!,{S0-S31}
ISB ; We only need the sync if we enabled, otherwise we will context switch before next VFP/NEON instruction anyway
VLDMIA R0!,{D16-D31}
VLDMIA R0!,{D0-D15}
LDR R2,[R0]
VMSR FPSCR,R2
ADD R0,R0,#8
@ -343,7 +352,8 @@ __asm void PendSV_Handler (U32 IRQn) {
ARM
IMPORT rt_tsk_lock
IMPORT IRQNestLevel
IMPORT IRQNestLevel ; Flag indicates whether inside an ISR, and the depth of nesting. 0 = not in ISR.
IMPORT seen_id0_active ; Flag used to workaround GIC 390 errata 733075 - set in startup_Renesas_RZ_A1.s
ADD SP,SP,#8 //fix up stack pointer (R0 has been pushed and will never be popped, R1 was pushed for stack alignment)
@ -355,6 +365,11 @@ __asm void PendSV_Handler (U32 IRQn) {
LDR R1, [R1, #0]
STR R0, [R1, #0x10]
; If it was interrupt ID0, clear the seen flag, otherwise return as normal
CMP R0, #0
LDREQ R1, =seen_id0_active
STRBEQ R0, [R1] ; Clear the seen flag, using R0 (which is 0), to save loading another register
LDR R0, =IRQNestLevel ; Get address of nesting counter
LDR R1, [R0]
SUB R1, R1, #1 ; Decrement nesting counter
@ -380,7 +395,8 @@ __asm void OS_Tick_Handler (U32 IRQn) {
ARM
IMPORT rt_tsk_lock
IMPORT IRQNestLevel
IMPORT IRQNestLevel ; Flag indicates whether inside an ISR, and the depth of nesting. 0 = not in ISR.
IMPORT seen_id0_active ; Flag used to workaround GIC 390 errata 733075 - set in startup_Renesas_RZ_A1.s
ADD SP,SP,#8 //fix up stack pointer (R0 has been pushed and will never be popped, R1 was pushed for stack alignment)
@ -391,6 +407,11 @@ __asm void OS_Tick_Handler (U32 IRQn) {
LDR R1, [R1, #0]
STR R0, [R1, #0x10]
; If it was interrupt ID0, clear the seen flag, otherwise return as normal
CMP R0, #0
LDREQ R1, =seen_id0_active
STRBEQ R0, [R1] ; Clear the seen flag, using R0 (which is 0), to save loading another register
LDR R0, =IRQNestLevel ; Get address of nesting counter
LDR R1, [R0]
SUB R1, R1, #1 ; Decrement nesting counter

View File

@ -3,10 +3,10 @@
; *----------------------------------------------------------------------------
; * Name: SVC_TABLE.S
; * Purpose: Pre-defined SVC Table for Cortex-M
; * Rev.: V4.60
; * Rev.: V4.70
; *----------------------------------------------------------------------------
; *
; * Copyright (c) 1999-2009 KEIL, 2009-2012 ARM Germany GmbH
; * Copyright (c) 1999-2009 KEIL, 2009-2013 ARM Germany GmbH
; * All rights reserved.
; * Redistribution and use in source and binary forms, with or without
; * modification, are permitted provided that the following conditions are met:

View File

@ -3,10 +3,10 @@
*----------------------------------------------------------------------------
* Name: HAL_CA9.c
* Purpose: Hardware Abstraction Layer for Cortex-A9
* Rev.: 3 Sept 2013
* Rev.: 8 April 2015
*----------------------------------------------------------------------------
*
* Copyright (c) 2012 - 2013 ARM Limited
* Copyright (c) 2012 - 2015 ARM Limited
* All rights reserved.
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
@ -36,9 +36,11 @@
.global rt_get_PSP
.global _alloc_box
.global _free_box
.global SVC_Handler
.global PendSV_Handler
.global OS_Tick_Handler
/* macro defines form rt_HAL_CA.h */
.EQU CPSR_T_BIT, 0x20
.EQU CPSR_I_BIT, 0x80
.EQU CPSR_F_BIT, 0x40
@ -51,9 +53,11 @@
.EQU MODE_UND, 0x1B
.EQU MODE_SYS, 0x1F
/* macro defines form rt_TypeDef.h */
.EQU TCB_TID, 3 /* 'task id' offset */
.EQU TCB_STACKF, 32 /* 'stack_frame' offset */
.EQU TCB_TSTACK, 36 /* 'tsk_stack' offset */
.EQU TCB_STACKF, 37 /* 'stack_frame' offset */
.EQU TCB_TSTACK, 44 /* 'tsk_stack' offset for LARGE_STACK */
.extern rt_alloc_box
.extern os_tsk
@ -62,14 +66,16 @@
.extern os_tick_irqack
.extern rt_systick
.text
/*----------------------------------------------------------------------------
* Functions
*---------------------------------------------------------------------------*/
.text
@ For A-class, set USR/SYS stack
@ __asm void rt_set_PSP (U32 stack) {
rt_set_PSP:
.arm
.ARM
MRS R1, CPSR
CPS #MODE_SYS @no effect in USR mode
@ -84,7 +90,7 @@ rt_set_PSP:
@ For A-class, get USR/SYS stack
@ __asm U32 rt_get_PSP (void) {
rt_get_PSP:
.arm
.ARM
MRS R1, CPSR
CPS #MODE_SYS @no effect in USR mode
@ -93,16 +99,15 @@ rt_get_PSP:
MSR CPSR_c, R1 @no effect in USR mode
ISB
BX LR
@ }
/*--------------------------- _alloc_box ------------------------------------*/
@ __asm void *_alloc_box (void *box_mem) {
_alloc_box:
/* Function wrapper for Unprivileged/Privileged mode. */
.arm
.ARM
LDR R12,=rt_alloc_box @ __cpp(rt_alloc_box)
LDR R12,=rt_alloc_box
MRS R2, CPSR
LSLS R2, #28
BXNE R12
@ -115,9 +120,9 @@ _alloc_box:
@ __asm int _free_box (void *box_mem, void *box) {
_free_box:
/* Function wrapper for Unprivileged/Privileged mode. */
.arm
.ARM
LDR R12,=rt_free_box @ __cpp(rt_free_box)
LDR R12,=rt_free_box
MRS R2, CPSR
LSLS R2, #28
BXNE R12
@ -131,25 +136,23 @@ _free_box:
@ #pragma push
@ #pragma arm
@ __asm void SVC_Handler (void) {
.type SVC_Handler, %function
.global SVC_Handler
SVC_Handler:
@ PRESERVE8
.arm
.eabi_attribute Tag_ABI_align8_preserved,1
.ARM
.extern rt_tsk_lock
.extern rt_tsk_unlock
.extern SVC_Count
.extern SVC_Table
.extern rt_stk_check
.extern FPUEnable
.extern scheduler_suspended @ flag set by rt_suspend, cleared by rt_resume, read by SVC_Handler
.EQU Mode_SVC, 0x13
SRSDB SP!, #Mode_SVC @ Push LR_SVC and SPRS_SVC onto SVC mode stack
SRSDB SP!, #Mode_SVC @ Push LR_SVC and SPRS_SVC onto SVC mode stack @ Use SRSDB because SRSFD isn't supported by GCC-ARM.
PUSH {R4} @ Push R4 so we can use it as a temp
MRS R4,SPSR @ Get SPSR
TST R4,#CPSR_T_BIT @ Check Thumb Bit
LDRNEH R4,[LR,#-2] @ Thumb: Load Halfword
@ -188,8 +191,8 @@ SVC_Handler:
/* Here we will be in SVC mode (even if coming in from PendSV_Handler or OS_Tick_Handler) */
Sys_Switch:
LDR LR,=os_tsk @ __cpp(&os_tsk)
LDM LR,{R4,LR} @ os_tsk.run, os_tsk.new
LDR LR,=os_tsk
LDM LR,{R4,LR} @ os_tsk.run, os_tsk.new_tsk
CMP R4,LR
BNE switching
@ -200,7 +203,13 @@ Sys_Switch:
PUSH {R12, LR} @ Store stack adjustment and dummy LR to SVC stack
CPSID i
@ Do not unlock scheduler if it has just been suspended by rt_suspend()
LDR R1,=scheduler_suspended
LDRB R0, [R1]
CMP R0, #1
BEQ dont_unlock
BLX rt_tsk_unlock
dont_unlock:
POP {R12, LR} @ Get stack adjustment & discard dummy LR
ADD SP, SP, R12 @ Unadjust stack
@ -218,7 +227,7 @@ switching:
PUSH {R8-R11} @ R4 and LR already stacked
MOV R10,R4 @ Preserve os_tsk.run
MOV R11,LR @ Preserve os_tsk.new
MOV R11,LR @ Preserve os_tsk.new_tsk
ADD R8,SP,#16 @ Unstack R4,LR
LDMIA R8,{R4,LR}
@ -234,21 +243,22 @@ switching:
SUB R8,R8,#4 @ No writeback for store of User LR
STMDB R8!,{R0-R3,R12} @ User R0-R3,R12
MOV R3,R10 @ os_tsk.run
MOV LR,R11 @ os_tsk.new
MOV LR,R11 @ os_tsk.new_tsk
POP {R9-R12}
ADD SP,SP,#12 @ Fix up SP for unstack of R4, LR & SPSR
STMDB R8!,{R4-R7,R9-R12} @ User R4-R11
@ If applicable, stack VFP state
@ If applicable, stack VFP/NEON state
MRC p15,0,R1,c1,c0,2 @ VFP/NEON access enabled? (CPACR)
AND R2,R1,#0x00F00000
CMP R2,#0x00F00000
BNE no_outgoing_vfp
VMRS R2,FPSCR
STMDB R8!,{R2,R4} @ Push FPSCR, maintain 8-byte alignment
VSTMDB R8!,{S0-S31}
LDRB R2,[R3,#TCB_STACKF] @ Record in TCB that VFP state is stacked
ORR R2,#2
VSTMDB R8!,{D0-D15}
VSTMDB R8!,{D16-D31}
LDRB R2,[R3,#TCB_STACKF] @ Record in TCB that NEON/D32 state is stacked
ORR R2,#4
STRB R2,[R3,#TCB_STACKF]
no_outgoing_vfp:
@ -268,8 +278,8 @@ no_outgoing_vfp:
MOV LR,R4
SVC_Next: @ R4 == os_tsk.run, LR == os_tsk.new, R0-R3, R5-R12 corruptible
LDR R1,=os_tsk @ __cpp(&os_tsk), os_tsk.run = os_tsk.new
SVC_Next: @ R4 == os_tsk.run, LR == os_tsk.new_tsk, R0-R3, R5-R12 corruptible
LDR R1,=os_tsk @ os_tsk.run = os_tsk.new_tsk
STR LR,[R1]
LDRB R1,[LR,#TCB_TID] @ os_tsk.run->task_id
LSL R1,#8 @ Store PROCID
@ -277,16 +287,17 @@ SVC_Next: @ R4 == os_tsk.run, LR == os_tsk.new, R0-R3, R5-R12 corruptible
LDR R0,[LR,#TCB_TSTACK] @ os_tsk.run->tsk_stack
@ Does incoming task have VFP state in stack?
@ Does incoming task have VFP/NEON state in stack?
LDRB R3,[LR,#TCB_STACKF]
TST R3,#0x2
ANDS R3, R3, #0x6
MRC p15,0,R1,c1,c0,2 @ Read CPACR
ANDEQ R1,R1,#0xFF0FFFFF @ Disable VFP access if incoming task does not have stacked VFP state
ORRNE R1,R1,#0x00F00000 @ Enable VFP access if incoming task does have stacked VFP state
ANDEQ R1,R1,#0xFF0FFFFF @ Disable VFP/NEON access if incoming task does not have stacked VFP/NEON state
ORRNE R1,R1,#0x00F00000 @ Enable VFP/NEON access if incoming task does have stacked VFP/NEON state
MCR p15,0,R1,c1,c0,2 @ Write CPACR
BEQ no_incoming_vfp
ISB @ We only need the sync if we enabled, otherwise we will context switch before next VFP instruction anyway
VLDMIA R0!,{S0-S31}
ISB @ We only need the sync if we enabled, otherwise we will context switch before next VFP/NEON instruction anyway
VLDMIA R0!,{D16-D31}
VLDMIA R0!,{D0-D15}
LDR R2,[R0]
VMSR FPSCR,R2
ADD R0,R0,#8
@ -364,20 +375,18 @@ SVC_Done:
POP {R0-R3,R12,LR}
POP {R4}
RFEFD SP! @ Return from exception
@ }
@ #pragma pop
@ #pragma push
@ #pragma arm
@ __asm void PendSV_Handler (U32 IRQn) {
PendSV_Handler:
.arm
.ARM
.extern rt_tsk_lock
.extern IRQNestLevel
.extern IRQNestLevel @ Flag indicates whether inside an ISR, and the depth of nesting. 0 = not in ISR.
.extern seen_id0_active @ Flag used to workaround GIC 390 errata 733075 - set in startup_Renesas_RZ_A1.s
ADD SP,SP,#8 @ fix up stack pointer (R0 has been pushed and will never be popped, R1 was pushed for stack alignment)
@ -385,16 +394,21 @@ PendSV_Handler:
PUSH {R0, R1}
BLX rt_tsk_lock
POP {R0, R1}
LDR R1, =GICInterface_BASE @ __cpp(&GICInterface_BASE)
LDR R1, =GICInterface_BASE
LDR R1, [R1, #0]
STR R0, [R1, #0x10]
@ If it was interrupt ID0, clear the seen flag, otherwise return as normal
CMP R0, #0
LDREQ R1, =seen_id0_active
STREQB R0, [R1] @ Clear the seen flag, using R0 (which is 0), to save loading another register
LDR R0, =IRQNestLevel @ Get address of nesting counter
LDR R1, [R0]
SUB R1, R1, #1 @ Decrement nesting counter
STR R1, [R0]
BLX rt_pop_req @ __cpp(rt_pop_req)
BLX rt_pop_req
POP {R1, LR} @ Get stack adjustment & discard dummy LR
ADD SP, SP, R1 @ Unadjust stack
@ -407,28 +421,38 @@ PendSV_Handler:
@ }
@ #pragma pop
@ #pragma push
@ #pragma arm
@ __asm void OS_Tick_Handler (U32 IRQn) {
OS_Tick_Handler:
.arm
.ARM
.extern rt_tsk_lock
.extern IRQNestLevel @ Flag indicates whether inside an ISR, and the depth of nesting. 0 = not in ISR.
.extern seen_id0_active @ Flag used to workaround GIC 390 errata 733075 - set in startup_Renesas_RZ_A1.s
ADD SP,SP,#8 @ fix up stack pointer (R0 has been pushed and will never be popped, R1 was pushed for stack alignment)
PUSH {R0, R1}
BLX rt_tsk_lock
POP {R0, R1}
LDR R1, =GICInterface_BASE @ __cpp(&GICInterface_BASE)
LDR R1, =GICInterface_BASE
LDR R1, [R1, #0]
STR R0, [R1, #0x10]
@ If it was interrupt ID0, clear the seen flag, otherwise return as normal
CMP R0, #0
LDREQ R1, =seen_id0_active
STREQB R0, [R1] @ Clear the seen flag, using R0 (which is 0), to save loading another register
LDR R0, =IRQNestLevel @ Get address of nesting counter
LDR R1, [R0]
SUB R1, R1, #1 @ Decrement nesting counter
STR R1, [R0]
BLX os_tick_irqack @ __cpp(os_tick_irqack)
BLX rt_systick @ __cpp(rt_systick)
BLX os_tick_irqack
BLX rt_systick
POP {R1, LR} @ Get stack adjustment & discard dummy LR
ADD SP, SP, R1 @ Unadjust stack
@ -441,32 +465,6 @@ OS_Tick_Handler:
@ }
@ #pragma pop
.global __set_PSP
@ __STATIC_ASM void __set_PSP(uint32_t topOfProcStack)
@ {
__set_PSP:
@ PRESERVE8
.arm
BIC R0, R0, #7 @ensure stack is 8-byte aligned
MRS R1, CPSR
CPS #MODE_SYS @no effect in USR mode
MOV SP, R0
MSR CPSR_c, R1 @no effect in USR mode
ISB
BX LR
@ }
.global __set_CPS_USR
@ __STATIC_ASM void __set_CPS_USR(void)
@ {
__set_CPS_USR:
.arm
CPS #MODE_USR
BX LR
@ }
.END
/*----------------------------------------------------------------------------

View File

@ -34,23 +34,20 @@
.section SVC_TABLE @, CODE, READONLY
.align 5
.global SVC_Count
.EQU SVC_Cnt, (SVC_End-SVC_Table)/4
SVC_Count:
.word SVC_Cnt
SVC_Count: .word SVC_Cnt
@ Import user SVC functions here.
@ .extern __SVC_1
.global SVC_Table
SVC_Table:
@ Insert user SVC functions here. SVC 0 used by RTL Kernel.
@ .word __SVC_1 @ InitMemorySubsystem
@SVC_End
SVC_End:
.END

View File

@ -1,6 +1,6 @@
/* ----------------------------------------------------------------------
* $Date: 5. June 2012
* $Revision: V1.01
* $Date: 5. February 2013
* $Revision: V1.02
*
* Project: CMSIS-RTOS API
* Title: cmsis_os.h RTX header file
@ -18,9 +18,13 @@
* - const attribute added to the osXxxxDef macros
* Added: osTimerDelete, osMutexDelete, osSemaphoreDelete
* Added: osKernelInitialize
* Version 1.02
* Control functions for short timeouts in microsecond resolution:
* Added: osKernelSysTick, osKernelSysTickFrequency, osKernelSysTickMicroSec
* Removed: osSignalGet
*----------------------------------------------------------------------------
*
* Copyright (c) 2012 ARM LIMITED
* Copyright (c) 2013 ARM LIMITED
* All rights reserved.
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
@ -127,13 +131,13 @@ used throughout the whole project.
#define _CMSIS_OS_H
/// \note MUST REMAIN UNCHANGED: \b osCMSIS identifies the CMSIS-RTOS API version.
#define osCMSIS 0x10001 ///< API version (main [31:16] .sub [15:0])
#define osCMSIS 0x10002 ///< API version (main [31:16] .sub [15:0])
/// \note CAN BE CHANGED: \b osCMSIS_KERNEL identifies the underlying RTOS kernel and version number.
#define osCMSIS_RTX ((4<<16)|61) ///< RTOS identification and version (main [31:16] .sub [15:0])
#define osCMSIS_RTX ((4<<16)|74) ///< RTOS identification and version (main [31:16] .sub [15:0])
/// \note MUST REMAIN UNCHANGED: \b osKernelSystemId shall be consistent in every CMSIS-RTOS.
#define osKernelSystemId "RTX V4.61" ///< RTOS identification string
#define osKernelSystemId "RTX V4.74" ///< RTOS identification string
#define CMSIS_OS_RTX
#define CMSIS_OS_RTX_CA /* new define for Coretex-A */
@ -155,6 +159,7 @@ used throughout the whole project.
#define osFeature_Signals 16 ///< maximum number of Signal Flags available per thread
#define osFeature_Semaphore 65535 ///< maximum count for \ref osSemaphoreCreate function
#define osFeature_Wait 0 ///< osWait function: 1=available, 0=not available
#define osFeature_SysTick 1 ///< osKernelSysTick functions: 1=available, 0=not available
#if defined (__CC_ARM)
#define os_InRegs __value_in_regs // Compiler specific: force struct in registers
@ -345,6 +350,30 @@ osStatus osKernelStart (void);
/// \return 0 RTOS is not started, 1 RTOS is started.
int32_t osKernelRunning(void);
#if (defined (osFeature_SysTick) && (osFeature_SysTick != 0)) // System Timer available
extern uint32_t const os_tickfreq;
extern uint16_t const os_tickus_i;
extern uint16_t const os_tickus_f;
/// Get the RTOS kernel system timer counter.
/// \note MUST REMAIN UNCHANGED: \b osKernelSysTick shall be consistent in every CMSIS-RTOS.
/// \return RTOS kernel system timer as 32-bit value
uint32_t osKernelSysTick (void);
/// The RTOS kernel system timer frequency in Hz.
/// \note Reflects the system timer setting and is typically defined in a configuration file.
#define osKernelSysTickFrequency os_tickfreq
/// Convert a microseconds value to a RTOS kernel system timer value.
/// \param microsec time value in microseconds.
/// \return time value normalized to the \ref osKernelSysTickFrequency
/*
#define osKernelSysTickMicroSec(microsec) (((uint64_t)microsec * (osKernelSysTickFrequency)) / 1000000)
*/
#define osKernelSysTickMicroSec(microsec) ((microsec * os_tickus_i) + ((microsec * os_tickus_f) >> 16))
#endif // System Timer available
// ==== Thread Management ====
@ -504,12 +533,6 @@ int32_t osSignalSet (osThreadId thread_id, int32_t signals);
/// \note MUST REMAIN UNCHANGED: \b osSignalClear shall be consistent in every CMSIS-RTOS.
int32_t osSignalClear (osThreadId thread_id, int32_t signals);
/// Get Signal Flags status of an active thread.
/// \param[in] thread_id thread ID obtained by \ref osThreadCreate or \ref osThreadGetId.
/// \return previous signal flags of the specified thread or 0x80000000 in case of incorrect parameters.
/// \note MUST REMAIN UNCHANGED: \b osSignalGet shall be consistent in every CMSIS-RTOS.
int32_t osSignalGet (osThreadId thread_id);
/// Wait for one or more Signal Flags to become signaled for the current \b RUNNING thread.
/// \param[in] signals wait until all specified signal flags set or 0 for any single signal flag.
/// \param[in] millisec timeout value or 0 in case of no time-out.
@ -529,7 +552,7 @@ os_InRegs osEvent osSignalWait (int32_t signals, uint32_t millisec);
extern const osMutexDef_t os_mutex_def_##name
#else // define the object
#define osMutexDef(name) \
uint32_t os_mutex_cb_##name[3]; \
uint32_t os_mutex_cb_##name[4] = { 0 }; \
const osMutexDef_t os_mutex_def_##name = { (os_mutex_cb_##name) }
#endif
@ -579,7 +602,7 @@ osStatus osMutexDelete (osMutexId mutex_id);
extern const osSemaphoreDef_t os_semaphore_def_##name
#else // define the object
#define osSemaphoreDef(name) \
uint32_t os_semaphore_cb_##name[2]; \
uint32_t os_semaphore_cb_##name[2] = { 0 }; \
const osSemaphoreDef_t os_semaphore_def_##name = { (os_semaphore_cb_##name) }
#endif
@ -689,7 +712,7 @@ osStatus osPoolFree (osPoolId pool_id, void *block);
extern const osMessageQDef_t os_messageQ_def_##name
#else // define the object
#define osMessageQDef(name, queue_sz, type) \
uint32_t os_messageQ_q_##name[4+(queue_sz)]; \
uint32_t os_messageQ_q_##name[4+(queue_sz)] = { 0 }; \
const osMessageQDef_t os_messageQ_def_##name = \
{ (queue_sz), (os_messageQ_q_##name) }
#endif
@ -741,7 +764,7 @@ os_InRegs osEvent osMessageGet (osMessageQId queue_id, uint32_t millisec);
extern const osMailQDef_t os_mailQ_def_##name
#else // define the object
#define osMailQDef(name, queue_sz, type) \
uint32_t os_mailQ_q_##name[4+(queue_sz)]; \
uint32_t os_mailQ_q_##name[4+(queue_sz)] = { 0 }; \
uint32_t os_mailQ_m_##name[3+((sizeof(type)+3)/4)*(queue_sz)]; \
void * os_mailQ_p_##name[2] = { (os_mailQ_q_##name), os_mailQ_m_##name }; \
const osMailQDef_t os_mailQ_def_##name = \
@ -800,6 +823,15 @@ osStatus osMailFree (osMailQId queue_id, void *mail);
#endif // Mail Queues available
// ==== RTX Extensions ====
/// os_suspend: http://www.keil.com/support/man/docs/rlarm/rlarm_os_suspend.htm
uint32_t os_suspend (void);
/// os_resume: http://www.keil.com/support/man/docs/rlarm/rlarm_os_resume.htm
void os_resume (uint32_t sleep_time);
#ifdef __cplusplus
}
#endif

View File

@ -3,10 +3,10 @@
*----------------------------------------------------------------------------
* Name: rt_CMSIS.c
* Purpose: CMSIS RTOS API
* Rev.: V4.60
* Rev.: V4.74
*----------------------------------------------------------------------------
*
* Copyright (c) 1999-2009 KEIL, 2009-2012 ARM Germany GmbH
* Copyright (c) 1999-2009 KEIL, 2009-2013 ARM Germany GmbH
* All rights reserved.
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
@ -100,6 +100,14 @@ static __inline t __##f (void) { \
return _##f(f); \
}
#define SVC_1_0(f,t,t1,...) \
__svc_indirect(0) t _##f (t(*)(t1),t1); \
t f (t1 a1); \
__attribute__((always_inline)) \
static __inline t __##f (t1 a1) { \
_##f(f,a1); \
}
#define SVC_1_1(f,t,t1,...) \
__svc_indirect(0) t _##f (t(*)(t1),t1); \
t f (t1 a1); \
@ -280,6 +288,13 @@ static inline t __##f (void) { \
return (t) rv; \
}
#define SVC_1_0(f,t,t1) \
__attribute__((always_inline)) \
static inline t __##f (t1 a1) { \
SVC_Arg1(t1); \
SVC_Call(f); \
}
#define SVC_1_1(f,t,t1,rv) \
__attribute__((always_inline)) \
static inline t __##f (t1 a1) { \
@ -353,6 +368,14 @@ static inline t __##f (void) { \
return _##f(); \
}
#define SVC_1_0(f,t,t1,...) \
t f (t1 a1); \
_Pragma("swi_number=0") __swi t _##f (t1 a1); \
static inline t __##f (t1 a1) { \
SVC_Setup(f); \
_##f(a1); \
}
#define SVC_1_1(f,t,t1,...) \
t f (t1 a1); \
_Pragma("swi_number=0") __swi t _##f (t1 a1); \
@ -539,6 +562,7 @@ uint8_t os_running; // Kernel Running flag
SVC_0_1(svcKernelInitialize, osStatus, RET_osStatus)
SVC_0_1(svcKernelStart, osStatus, RET_osStatus)
SVC_0_1(svcKernelRunning, int32_t, RET_int32_t)
SVC_0_1(svcKernelSysTick, uint32_t, RET_uint32_t)
static void sysThreadError (osStatus status);
osThreadId svcThreadCreate (const osThreadDef_t *thread_def, void *argument);
@ -577,6 +601,7 @@ osStatus svcKernelInitialize (void) {
sysThreadError(osOK);
os_initialized = 1;
os_running = 0;
return osOK;
}
@ -586,8 +611,10 @@ osStatus svcKernelStart (void) {
if (os_running) return osOK;
rt_tsk_prio(0, 0); // Lowest priority
__set_PSP(os_tsk.run->tsk_stack + 8*4); // New context
rt_tsk_prio(0, os_tsk.run->prio_base); // Restore priority
if (os_tsk.run->task_id == 0xFF) { // Idle Thread
__set_PSP(os_tsk.run->tsk_stack + 8*4); // Setup PSP
}
os_tsk.run = NULL; // Force context switch
rt_sys_start();
@ -602,6 +629,22 @@ int32_t svcKernelRunning(void) {
return os_running;
}
/// Get the RTOS kernel system timer counter
uint32_t svcKernelSysTick (void) {
uint32_t tick, tick0;
tick = os_tick_val();
if (os_tick_ovf()) {
tick0 = os_tick_val();
if (tick0 < tick) tick = tick0;
tick += (os_trv + 1) * (os_time + 1);
} else {
tick += (os_trv + 1) * os_time;
}
return tick;
}
// Kernel Control Public API
/// Initialize the RTOS Kernel for creating objects
@ -642,6 +685,12 @@ int32_t osKernelRunning(void) {
}
}
/// Get the RTOS kernel system timer counter
uint32_t osKernelSysTick (void) {
if (__exceptional_mode()) return 0; // Not allowed in ISR
return __svcKernelSysTick();
}
// ==== Thread Management ====
@ -1047,6 +1096,7 @@ osTimerId svcTimerCreate (const osTimerDef_t *timer_def, os_timer_type type, voi
return NULL;
}
pt->next = NULL;
pt->state = osTimerStopped;
pt->type = (uint8_t)type;
pt->arg = argument;
@ -1176,6 +1226,30 @@ void sysTimerTick (void) {
}
}
/// Get user timers wake-up time
uint32_t sysUserTimerWakeupTime (void) {
if (os_timer_head) {
return os_timer_head->tcnt;
}
return 0xFFFF;
}
/// Update user timers on resume
void sysUserTimerUpdate (uint32_t sleep_time) {
while (os_timer_head && sleep_time) {
if (sleep_time >= os_timer_head->tcnt) {
sleep_time -= os_timer_head->tcnt;
os_timer_head->tcnt = 1;
sysTimerTick();
} else {
os_timer_head->tcnt -= sleep_time;
break;
}
}
}
// Timer Management Public API
@ -1237,7 +1311,6 @@ __NO_RETURN void osTimerThread (void const *argument) {
// Signal Service Calls declarations
SVC_2_1(svcSignalSet, int32_t, osThreadId, int32_t, RET_int32_t)
SVC_2_1(svcSignalClear, int32_t, osThreadId, int32_t, RET_int32_t)
SVC_1_1(svcSignalGet, int32_t, osThreadId, RET_int32_t)
SVC_2_3(svcSignalWait, os_InRegs osEvent, int32_t, uint32_t, RET_osEvent)
// Signal Service Calls
@ -1276,16 +1349,6 @@ int32_t svcSignalClear (osThreadId thread_id, int32_t signals) {
return sig;
}
/// Get Signal Flags status of an active thread
int32_t svcSignalGet (osThreadId thread_id) {
P_TCB ptcb;
ptcb = rt_tid2ptcb(thread_id); // Get TCB pointer
if (ptcb == NULL) return 0x80000000;
return ptcb->events; // Return event flags
}
/// Wait for one or more Signal Flags to become signaled for the current RUNNING thread
os_InRegs osEvent_type svcSignalWait (int32_t signals, uint32_t millisec) {
OS_RESULT res;
@ -1361,12 +1424,6 @@ int32_t osSignalClear (osThreadId thread_id, int32_t signals) {
return __svcSignalClear(thread_id, signals);
}
/// Get Signal Flags status of an active thread
int32_t osSignalGet (osThreadId thread_id) {
if (__exceptional_mode()) return osErrorISR; // Not allowed in ISR
return __svcSignalGet(thread_id);
}
/// Wait for one or more Signal Flags to become signaled for the current RUNNING thread
os_InRegs osEvent osSignalWait (int32_t signals, uint32_t millisec) {
osEvent ret;
@ -1960,7 +2017,6 @@ osMailQId svcMailCreate (const osMailQDef_t *queue_def, osThreadId thread_id) {
rt_mbx_init(pmcb, 4*(queue_def->queue_sz + 4));
return queue_def->pool;
}
@ -2020,7 +2076,7 @@ osStatus sysMailFree (osMailQId queue_id, void *mail, uint32_t isr) {
if (res != 0) return osErrorValue;
if (pmcb->state == 3) {
if ((pmcb->p_lnk != NULL) && (pmcb->state == 3)) {
// Task is waiting to allocate a message
if (isr) {
rt_psq_enq (pmcb, (U32)pool);
@ -2029,9 +2085,6 @@ osStatus sysMailFree (osMailQId queue_id, void *mail, uint32_t isr) {
mem = rt_alloc_box(pool);
if (mem != NULL) {
ptcb = rt_get_first((P_XCB)pmcb);
if (pmcb->p_lnk == NULL) {
pmcb->state = 0;
}
rt_ret_val(ptcb, (U32)mem);
rt_rmv_dly(ptcb);
rt_dispatch(ptcb);
@ -2111,3 +2164,23 @@ os_InRegs osEvent osMailGet (osMailQId queue_id, uint32_t millisec) {
#ifdef __CC_ARM
#pragma pop
#endif // __arm__
// ==== RTX Extensions ====
// Service Calls declarations
SVC_0_1(rt_suspend, uint32_t, RET_uint32_t)
SVC_1_0(rt_resume, void, uint32_t)
// Public API
/// Suspends the OS task scheduler
uint32_t os_suspend (void) {
return __rt_suspend();
}
/// Resumes the OS task scheduler
void os_resume (uint32_t sleep_time) {
__rt_resume(sleep_time);
}

View File

@ -3,10 +3,10 @@
*----------------------------------------------------------------------------
* Name: RT_EVENT.C
* Purpose: Implements waits and wake-ups for event flags
* Rev.: V4.60
* Rev.: V4.70
*----------------------------------------------------------------------------
*
* Copyright (c) 1999-2009 KEIL, 2009-2012 ARM Germany GmbH
* Copyright (c) 1999-2009 KEIL, 2009-2013 ARM Germany GmbH
* All rights reserved.
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:

View File

@ -3,10 +3,10 @@
*----------------------------------------------------------------------------
* Name: RT_EVENT.H
* Purpose: Implements waits and wake-ups for event flags
* Rev.: V4.60
* Rev.: V4.70
*----------------------------------------------------------------------------
*
* Copyright (c) 1999-2009 KEIL, 2009-2012 ARM Germany GmbH
* Copyright (c) 1999-2009 KEIL, 2009-2013 ARM Germany GmbH
* All rights reserved.
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:

View File

@ -1,9 +1,9 @@
/*----------------------------------------------------------------------------
* RL-ARM - RTX
*----------------------------------------------------------------------------
* Name: RT_HAL_CM.H
* Name: RT_HAL_CA.H
* Purpose: Hardware Abstraction Layer for Cortex-A definitions
* Rev.: 21 Aug 2013
* Rev.: 14th Jan 2014
*----------------------------------------------------------------------------
*
* Copyright (c) 1999-2009 KEIL, 2009-2013 ARM Germany GmbH
@ -169,6 +169,18 @@ __inline static void rt_systick_init (void) {
/* HW initialization needs to be done in os_tick_init (void) -RTX_Conf_CM.c- */
}
__inline static U32 rt_systick_val (void) {
/* Cortex-A doesn't have a Systick. User needs to provide an alternative timer using RTX_Conf_CM configuration */
/* HW initialization needs to be done in os_tick_init (void) -RTX_Conf_CM.c- */
return 0;
}
__inline static U32 rt_systick_ovf (void) {
/* Cortex-A doesn't have a Systick. User needs to provide an alternative timer using RTX_Conf_CM configuration */
/* HW initialization needs to be done in os_tick_init (void) -RTX_Conf_CM.c- */
return 0;
}
__inline static void rt_svc_init (void) {
/* Register pendSV - through SGI */
volatile char *reg;

View File

@ -3,10 +3,10 @@
*----------------------------------------------------------------------------
* Name: RT_HAL_CM.H
* Purpose: Hardware Abstraction Layer for Cortex-M definitions
* Rev.: V4.60
* Rev.: V4.70
*----------------------------------------------------------------------------
*
* Copyright (c) 1999-2009 KEIL, 2009-2012 ARM Germany GmbH
* Copyright (c) 1999-2009 KEIL, 2009-2013 ARM Germany GmbH
* All rights reserved.
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
@ -40,7 +40,7 @@
#if defined (__CC_ARM) /* ARM Compiler */
#if ((__TARGET_ARCH_7_M || __TARGET_ARCH_7E_M) && !NO_EXCLUSIVE_ACCESS)
#if ((__TARGET_ARCH_7_M || __TARGET_ARCH_7E_M) && !defined(NO_EXCLUSIVE_ACCESS))
#define __USE_EXCLUSIVE_ACCESS
#else
#undef __USE_EXCLUSIVE_ACCESS
@ -228,6 +228,14 @@ __inline static void rt_systick_init (void) {
NVIC_SYS_PRI3 |= 0xFF000000;
}
__inline static U32 rt_systick_val (void) {
return (os_trv - NVIC_ST_CURRENT);
}
__inline static U32 rt_systick_ovf (void) {
return ((NVIC_INT_CTRL >> 26) & 1);
}
__inline static void rt_svc_init (void) {
#if !(__TARGET_ARCH_6S_M)
int sh,prigroup;
@ -262,7 +270,7 @@ extern void dbg_task_switch (U32 task_id);
#ifdef DBG_MSG
#define DBG_INIT() dbg_init()
#define DBG_TASK_NOTIFY(p_tcb,create) if (dbg_msg) dbg_task_notify(p_tcb,create)
#define DBG_TASK_SWITCH(task_id) if (dbg_msg && (os_tsk.new!=os_tsk.run)) \
#define DBG_TASK_SWITCH(task_id) if (dbg_msg && (os_tsk.new_tsk!=os_tsk.run)) \
dbg_task_switch(task_id)
#else
#define DBG_INIT()

View File

@ -3,10 +3,10 @@
*----------------------------------------------------------------------------
* Name: RT_LIST.C
* Purpose: Functions for the management of different lists
* Rev.: V4.60
* Rev.: V4.70
*----------------------------------------------------------------------------
*
* Copyright (c) 1999-2009 KEIL, 2009-2012 ARM Germany GmbH
* Copyright (c) 1999-2009 KEIL, 2009-2013 ARM Germany GmbH
* All rights reserved.
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:

View File

@ -3,10 +3,10 @@
*----------------------------------------------------------------------------
* Name: RT_LIST.H
* Purpose: Functions for the management of different lists
* Rev.: V4.60
* Rev.: V4.70
*----------------------------------------------------------------------------
*
* Copyright (c) 1999-2009 KEIL, 2009-2012 ARM Germany GmbH
* Copyright (c) 1999-2009 KEIL, 2009-2013 ARM Germany GmbH
* All rights reserved.
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:

View File

@ -3,10 +3,10 @@
*----------------------------------------------------------------------------
* Name: RT_MAILBOX.C
* Purpose: Implements waits and wake-ups for mailbox messages
* Rev.: V4.60
* Rev.: V4.70
*----------------------------------------------------------------------------
*
* Copyright (c) 1999-2009 KEIL, 2009-2012 ARM Germany GmbH
* Copyright (c) 1999-2009 KEIL, 2009-2013 ARM Germany GmbH
* All rights reserved.
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:

View File

@ -3,10 +3,10 @@
*----------------------------------------------------------------------------
* Name: RT_MAILBOX.H
* Purpose: Implements waits and wake-ups for mailbox messages
* Rev.: V4.60
* Rev.: V4.70
*----------------------------------------------------------------------------
*
* Copyright (c) 1999-2009 KEIL, 2009-2012 ARM Germany GmbH
* Copyright (c) 1999-2009 KEIL, 2009-2013 ARM Germany GmbH
* All rights reserved.
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:

View File

@ -3,10 +3,10 @@
*----------------------------------------------------------------------------
* Name: RT_MEMBOX.C
* Purpose: Interface functions for fixed memory block management system
* Rev.: V4.60
* Rev.: V4.70
*----------------------------------------------------------------------------
*
* Copyright (c) 1999-2009 KEIL, 2009-2012 ARM Germany GmbH
* Copyright (c) 1999-2009 KEIL, 2009-2013 ARM Germany GmbH
* All rights reserved.
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:

View File

@ -3,10 +3,10 @@
*----------------------------------------------------------------------------
* Name: RT_MEMBOX.H
* Purpose: Interface functions for fixed memory block management system
* Rev.: V4.60
* Rev.: V4.70
*----------------------------------------------------------------------------
*
* Copyright (c) 1999-2009 KEIL, 2009-2012 ARM Germany GmbH
* Copyright (c) 1999-2009 KEIL, 2009-2013 ARM Germany GmbH
* All rights reserved.
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:

View File

@ -3,10 +3,10 @@
*----------------------------------------------------------------------------
* Name: RT_MEMORY.C
* Purpose: Interface functions for Dynamic Memory Management System
* Rev.: V4.60
* Rev.: V4.70
*----------------------------------------------------------------------------
*
* Copyright (c) 1999-2009 KEIL, 2009-2012 ARM Germany GmbH
* Copyright (c) 1999-2009 KEIL, 2009-2013 ARM Germany GmbH
* All rights reserved.
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:

View File

@ -3,10 +3,10 @@
*----------------------------------------------------------------------------
* Name: RT_MEMORY.H
* Purpose: Interface functions for Dynamic Memory Management System
* Rev.: V4.60
* Rev.: V4.70
*----------------------------------------------------------------------------
*
* Copyright (c) 1999-2009 KEIL, 2009-2012 ARM Germany GmbH
* Copyright (c) 1999-2009 KEIL, 2009-2013 ARM Germany GmbH
* All rights reserved.
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:

View File

@ -3,10 +3,10 @@
*----------------------------------------------------------------------------
* Name: RT_MUTEX.C
* Purpose: Implements mutex synchronization objects
* Rev.: V4.60
* Rev.: V4.73
*----------------------------------------------------------------------------
*
* Copyright (c) 1999-2009 KEIL, 2009-2012 ARM Germany GmbH
* Copyright (c) 1999-2009 KEIL, 2009-2013 ARM Germany GmbH
* All rights reserved.
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
@ -56,10 +56,10 @@ void rt_mut_init (OS_ID mutex) {
P_MUCB p_MCB = mutex;
p_MCB->cb_type = MUCB;
p_MCB->prio = 0;
p_MCB->level = 0;
p_MCB->p_lnk = NULL;
p_MCB->owner = NULL;
p_MCB->p_mlnk = NULL;
}
@ -70,14 +70,47 @@ OS_RESULT rt_mut_delete (OS_ID mutex) {
/* Delete a mutex object */
P_MUCB p_MCB = mutex;
P_TCB p_TCB;
P_MUCB p_mlnk;
U8 prio;
__DMB();
/* Restore owner task's priority. */
if (p_MCB->level != 0) {
p_MCB->owner->prio = p_MCB->prio;
if (p_MCB->owner != os_tsk.run) {
rt_resort_prio (p_MCB->owner);
p_TCB = p_MCB->owner;
/* Remove mutex from task mutex owner list. */
p_mlnk = p_TCB->p_mlnk;
if (p_mlnk == p_MCB) {
p_TCB->p_mlnk = p_MCB->p_mlnk;
}
else {
while (p_mlnk) {
if (p_mlnk->p_mlnk == p_MCB) {
p_mlnk->p_mlnk = p_MCB->p_mlnk;
break;
}
p_mlnk = p_mlnk->p_mlnk;
}
}
/* Restore owner task's priority. */
prio = p_TCB->prio_base;
p_mlnk = p_TCB->p_mlnk;
while (p_mlnk) {
if (p_mlnk->p_lnk && (p_mlnk->p_lnk->prio > prio)) {
/* A task with higher priority is waiting for mutex. */
prio = p_mlnk->p_lnk->prio;
}
p_mlnk = p_mlnk->p_mlnk;
}
if (p_TCB->prio != prio) {
p_TCB->prio = prio;
if (p_TCB != os_tsk.run) {
rt_resort_prio (p_TCB);
}
}
}
while (p_MCB->p_lnk != NULL) {
@ -109,6 +142,8 @@ OS_RESULT rt_mut_release (OS_ID mutex) {
/* Release a mutex object */
P_MUCB p_MCB = mutex;
P_TCB p_TCB;
P_MUCB p_mlnk;
U8 prio;
if (p_MCB->level == 0 || p_MCB->owner != os_tsk.run) {
/* Unbalanced mutex release or task is not the owner */
@ -118,8 +153,34 @@ OS_RESULT rt_mut_release (OS_ID mutex) {
if (--p_MCB->level != 0) {
return (OS_R_OK);
}
/* Remove mutex from task mutex owner list. */
p_mlnk = os_tsk.run->p_mlnk;
if (p_mlnk == p_MCB) {
os_tsk.run->p_mlnk = p_MCB->p_mlnk;
}
else {
while (p_mlnk) {
if (p_mlnk->p_mlnk == p_MCB) {
p_mlnk->p_mlnk = p_MCB->p_mlnk;
break;
}
p_mlnk = p_mlnk->p_mlnk;
}
}
/* Restore owner task's priority. */
os_tsk.run->prio = p_MCB->prio;
prio = os_tsk.run->prio_base;
p_mlnk = os_tsk.run->p_mlnk;
while (p_mlnk) {
if (p_mlnk->p_lnk && (p_mlnk->p_lnk->prio > prio)) {
/* A task with higher priority is waiting for mutex. */
prio = p_mlnk->p_lnk->prio;
}
p_mlnk = p_mlnk->p_mlnk;
}
os_tsk.run->prio = prio;
if (p_MCB->p_lnk != NULL) {
/* A task is waiting for mutex. */
p_TCB = rt_get_first ((P_XCB)p_MCB);
@ -132,7 +193,8 @@ OS_RESULT rt_mut_release (OS_ID mutex) {
/* A waiting task becomes the owner of this mutex. */
p_MCB->level = 1;
p_MCB->owner = p_TCB;
p_MCB->prio = p_TCB->prio;
p_MCB->p_mlnk = p_TCB->p_mlnk;
p_TCB->p_mlnk = p_MCB;
/* Priority inversion, check which task continues. */
if (os_tsk.run->prio >= rt_rdy_prio()) {
rt_dispatch (p_TCB);
@ -147,7 +209,7 @@ OS_RESULT rt_mut_release (OS_ID mutex) {
}
}
else {
/* Check if own priority raised by priority inversion. */
/* Check if own priority lowered by priority inversion. */
if (rt_rdy_prio() > os_tsk.run->prio) {
rt_put_prio (&os_rdy, os_tsk.run);
os_tsk.run->state = READY;
@ -166,7 +228,8 @@ OS_RESULT rt_mut_wait (OS_ID mutex, U16 timeout) {
if (p_MCB->level == 0) {
p_MCB->owner = os_tsk.run;
p_MCB->prio = os_tsk.run->prio;
p_MCB->p_mlnk = os_tsk.run->p_mlnk;
os_tsk.run->p_mlnk = p_MCB;
goto inc;
}
if (p_MCB->owner == os_tsk.run) {
@ -181,7 +244,7 @@ inc:p_MCB->level++;
}
/* Raise the owner task priority if lower than current priority. */
/* This priority inversion is called priority inheritance. */
if (p_MCB->prio < os_tsk.run->prio) {
if (p_MCB->owner->prio < os_tsk.run->prio) {
p_MCB->owner->prio = os_tsk.run->prio;
rt_resort_prio (p_MCB->owner);
}

View File

@ -3,10 +3,10 @@
*----------------------------------------------------------------------------
* Name: RT_MUTEX.H
* Purpose: Implements mutex synchronization objects
* Rev.: V4.60
* Rev.: V4.70
*----------------------------------------------------------------------------
*
* Copyright (c) 1999-2009 KEIL, 2009-2012 ARM Germany GmbH
* Copyright (c) 1999-2009 KEIL, 2009-2013 ARM Germany GmbH
* All rights reserved.
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:

View File

@ -3,10 +3,10 @@
*----------------------------------------------------------------------------
* Name: RT_ROBIN.C
* Purpose: Round Robin Task switching
* Rev.: V4.60
* Rev.: V4.70
*----------------------------------------------------------------------------
*
* Copyright (c) 1999-2009 KEIL, 2009-2012 ARM Germany GmbH
* Copyright (c) 1999-2009 KEIL, 2009-2013 ARM Germany GmbH
* All rights reserved.
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:

View File

@ -3,10 +3,10 @@
*----------------------------------------------------------------------------
* Name: RT_ROBIN.H
* Purpose: Round Robin Task switching definitions
* Rev.: V4.60
* Rev.: V4.70
*----------------------------------------------------------------------------
*
* Copyright (c) 1999-2009 KEIL, 2009-2012 ARM Germany GmbH
* Copyright (c) 1999-2009 KEIL, 2009-2013 ARM Germany GmbH
* All rights reserved.
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:

View File

@ -3,10 +3,10 @@
*----------------------------------------------------------------------------
* Name: RT_SEMAPHORE.C
* Purpose: Implements binary and counting semaphores
* Rev.: V4.60
* Rev.: V4.70
*----------------------------------------------------------------------------
*
* Copyright (c) 1999-2009 KEIL, 2009-2012 ARM Germany GmbH
* Copyright (c) 1999-2009 KEIL, 2009-2013 ARM Germany GmbH
* All rights reserved.
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
@ -152,7 +152,7 @@ OS_RESULT rt_sem_wait (OS_ID semaphore, U16 timeout) {
/*--------------------------- isr_sem_send ----------------------------------*/
void isr_sem_send (OS_ID semaphore) {
/* Same function as "os_sem"send", but to be called by ISRs */
/* Same function as "os_sem_send", but to be called by ISRs */
P_SCB p_SCB = semaphore;
rt_psq_enq (p_SCB, 0);

View File

@ -3,10 +3,10 @@
*----------------------------------------------------------------------------
* Name: RT_SEMAPHORE.H
* Purpose: Implements binary and counting semaphores
* Rev.: V4.60
* Rev.: V4.70
*----------------------------------------------------------------------------
*
* Copyright (c) 1999-2009 KEIL, 2009-2012 ARM Germany GmbH
* Copyright (c) 1999-2009 KEIL, 2009-2013 ARM Germany GmbH
* All rights reserved.
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:

View File

@ -3,10 +3,10 @@
*----------------------------------------------------------------------------
* Name: RT_SYSTEM.C
* Purpose: System Task Manager
* Rev.: V4.60
* Rev.: 8 April 2015
*----------------------------------------------------------------------------
*
* Copyright (c) 1999-2009 KEIL, 2009-2012 ARM Germany GmbH
* Copyright (c) 1999-2009 KEIL, 2009-2015 ARM Germany GmbH
* All rights reserved.
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
@ -54,6 +54,7 @@
*---------------------------------------------------------------------------*/
int os_tick_irqn;
U8 scheduler_suspended = 0; // flag set by rt_suspend, cleared by rt_resume, read by SVC_Handler
/*----------------------------------------------------------------------------
* Local Variables
@ -68,29 +69,40 @@ static U8 pend_flags;
* Global Functions
*---------------------------------------------------------------------------*/
#define RL_RTX_VER 0x473
#if defined (__CC_ARM)
__asm void $$RTX$$version (void) {
/* Export a version number symbol for a version control. */
EXPORT __RL_RTX_VER
__RL_RTX_VER EQU 0x450
__RL_RTX_VER EQU RL_RTX_VER
}
#endif
/*--------------------------- rt_suspend ------------------------------------*/
extern U32 sysUserTimerWakeupTime(void);
U32 rt_suspend (void) {
/* Suspend OS scheduler */
U32 delta = 0xFFFF;
#ifdef __CMSIS_RTOS
U32 sleep;
#endif
rt_tsk_lock();
scheduler_suspended = 1;
if (os_dly.p_dlnk) {
delta = os_dly.delta_time;
}
#ifndef __CMSIS_RTOS
#ifdef __CMSIS_RTOS
sleep = sysUserTimerWakeupTime();
if (sleep < delta) delta = sleep;
#else
if (os_tmr.next) {
if (os_tmr.tcnt < delta) delta = os_tmr.tcnt;
}
@ -102,6 +114,8 @@ U32 rt_suspend (void) {
/*--------------------------- rt_resume -------------------------------------*/
extern void sysUserTimerUpdate (U32 sleep_time);
void rt_resume (U32 sleep_time) {
/* Resume OS scheduler after suspend */
P_TCB next;
@ -133,8 +147,10 @@ void rt_resume (U32 sleep_time) {
os_time += sleep_time;
}
#ifndef __CMSIS_RTOS
/* Check the user timers. */
#ifdef __CMSIS_RTOS
sysUserTimerUpdate(sleep_time);
#else
if (os_tmr.next) {
delta = sleep_time;
if (delta >= os_tmr.tcnt) {
@ -155,6 +171,7 @@ void rt_resume (U32 sleep_time) {
next = rt_get_first (&os_rdy);
rt_switch_req (next);
scheduler_suspended = 0;
rt_tsk_unlock();
}
@ -163,6 +180,9 @@ void rt_resume (U32 sleep_time) {
void rt_tsk_lock (void) {
/* Prevent task switching by locking out scheduler */
if (os_lock == __TRUE) // don't lock again if already locked
return;
if (os_tick_irqn < 0) {
OS_LOCK();
os_lock = __TRUE;
@ -250,6 +270,19 @@ __weak int os_tick_init (void) {
return (-1); /* Return IRQ number of SysTick timer */
}
/*--------------------------- os_tick_val -----------------------------------*/
__weak U32 os_tick_val (void) {
/* Get SysTick timer current value (0 .. OS_TRV). */
return rt_systick_val();
}
/*--------------------------- os_tick_ovf -----------------------------------*/
__weak U32 os_tick_ovf (void) {
/* Get SysTick timer overflow flag */
return rt_systick_ovf();
}
/*--------------------------- os_tick_irqack --------------------------------*/

View File

@ -3,10 +3,10 @@
*----------------------------------------------------------------------------
* Name: RT_SYSTEM.H
* Purpose: System Task Manager definitions
* Rev.: V4.60
* Rev.: V4.70
*----------------------------------------------------------------------------
*
* Copyright (c) 1999-2009 KEIL, 2009-2012 ARM Germany GmbH
* Copyright (c) 1999-2009 KEIL, 2009-2013 ARM Germany GmbH
* All rights reserved.
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:

View File

@ -3,10 +3,10 @@
*----------------------------------------------------------------------------
* Name: RT_TASK.C
* Purpose: Task functions and system start up.
* Rev.: V4.60
* Rev.: V4.73
*----------------------------------------------------------------------------
*
* Copyright (c) 1999-2009 KEIL, 2009-2012 ARM Germany GmbH
* Copyright (c) 1999-2009 KEIL, 2009-2013 ARM Germany GmbH
* All rights reserved.
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
@ -79,10 +79,12 @@ static void rt_init_context (P_TCB p_TCB, U8 priority, FUNCP task_body) {
p_TCB->cb_type = TCB;
p_TCB->state = READY;
p_TCB->prio = priority;
p_TCB->prio_base = priority;
p_TCB->p_lnk = NULL;
p_TCB->p_rlnk = NULL;
p_TCB->p_dlnk = NULL;
p_TCB->p_blnk = NULL;
p_TCB->p_mlnk = NULL;
p_TCB->delta_time = 0;
p_TCB->interval_time = 0;
p_TCB->events = 0;
@ -101,7 +103,7 @@ static void rt_init_context (P_TCB p_TCB, U8 priority, FUNCP task_body) {
void rt_switch_req (P_TCB p_new) {
/* Switch to next task (identified by "p_new"). */
os_tsk.new = p_new;
os_tsk.new_tsk = p_new;
p_new->state = RUNNING;
DBG_TASK_SWITCH(p_new->task_id);
}
@ -188,6 +190,7 @@ OS_RESULT rt_tsk_prio (OS_TID task_id, U8 new_prio) {
if (task_id == 0) {
/* Change execution priority of calling task. */
os_tsk.run->prio = new_prio;
os_tsk.run->prio_base = new_prio;
run:if (rt_rdy_prio() > new_prio) {
rt_put_prio (&os_rdy, os_tsk.run);
os_tsk.run->state = READY;
@ -203,6 +206,7 @@ run:if (rt_rdy_prio() > new_prio) {
}
p_task = os_active_TCB[task_id-1];
p_task->prio = new_prio;
p_task->prio_base = new_prio;
if (p_task == os_tsk.run) {
goto run;
}
@ -254,12 +258,40 @@ OS_TID rt_tsk_create (FUNCP task, U32 prio_stksz, void *stk, void *argv) {
OS_RESULT rt_tsk_delete (OS_TID task_id) {
/* Terminate the task identified with "task_id". */
P_TCB task_context;
P_TCB p_TCB;
P_MUCB p_MCB, p_MCB0;
if (task_id == 0 || task_id == os_tsk.run->task_id) {
/* Terminate itself. */
os_tsk.run->state = INACTIVE;
os_tsk.run->tsk_stack = rt_get_PSP ();
rt_stk_check ();
p_MCB = os_tsk.run->p_mlnk;
while (p_MCB) {
/* Release mutexes owned by this task */
if (p_MCB->p_lnk) {
/* A task is waiting for mutex. */
p_TCB = rt_get_first ((P_XCB)p_MCB);
#ifdef __CMSIS_RTOS
rt_ret_val(p_TCB, 0/*osOK*/);
#else
rt_ret_val(p_TCB, OS_R_MUT);
#endif
rt_rmv_dly (p_TCB);
p_TCB->state = READY;
rt_put_prio (&os_rdy, p_TCB);
/* A waiting task becomes the owner of this mutex. */
p_MCB0 = p_MCB;
p_MCB->level = 1;
p_MCB->owner = p_TCB;
p_MCB->p_mlnk = p_TCB->p_mlnk;
p_TCB->p_mlnk = p_MCB;
p_MCB = p_MCB0->p_mlnk;
}
else {
p_MCB = p_MCB->p_mlnk;
}
}
os_active_TCB[os_tsk.run->task_id-1] = NULL;
rt_free_box (mp_stk, os_tsk.run->stack);
os_tsk.run->stack = NULL;
@ -278,11 +310,43 @@ OS_RESULT rt_tsk_delete (OS_TID task_id) {
task_context = os_active_TCB[task_id-1];
rt_rmv_list (task_context);
rt_rmv_dly (task_context);
p_MCB = task_context->p_mlnk;
while (p_MCB) {
/* Release mutexes owned by this task */
if (p_MCB->p_lnk) {
/* A task is waiting for mutex. */
p_TCB = rt_get_first ((P_XCB)p_MCB);
#ifdef __CMSIS_RTOS
rt_ret_val(p_TCB, 0/*osOK*/);
#else
rt_ret_val(p_TCB, OS_R_MUT);
#endif
rt_rmv_dly (p_TCB);
p_TCB->state = READY;
rt_put_prio (&os_rdy, p_TCB);
/* A waiting task becomes the owner of this mutex. */
p_MCB0 = p_MCB;
p_MCB->level = 1;
p_MCB->owner = p_TCB;
p_MCB->p_mlnk = p_TCB->p_mlnk;
p_TCB->p_mlnk = p_MCB;
p_MCB = p_MCB0->p_mlnk;
}
else {
p_MCB = p_MCB->p_mlnk;
}
}
os_active_TCB[task_id-1] = NULL;
rt_free_box (mp_stk, task_context->stack);
task_context->stack = NULL;
DBG_TASK_NOTIFY(task_context, __FALSE);
rt_free_box (mp_tcb, task_context);
if (rt_rdy_prio() > os_tsk.run->prio) {
/* Ready task has higher priority than running task. */
os_tsk.run->state = READY;
rt_put_prio (&os_rdy, os_tsk.run);
rt_dispatch (NULL);
}
}
return (OS_R_OK);
}

View File

@ -3,10 +3,10 @@
*----------------------------------------------------------------------------
* Name: RT_TASK.H
* Purpose: Task functions and system start up.
* Rev.: V4.60
* Rev.: V4.70
*----------------------------------------------------------------------------
*
* Copyright (c) 1999-2009 KEIL, 2009-2012 ARM Germany GmbH
* Copyright (c) 1999-2009 KEIL, 2009-2013 ARM Germany GmbH
* All rights reserved.
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:

View File

@ -3,10 +3,10 @@
*----------------------------------------------------------------------------
* Name: RT_TIME.C
* Purpose: Delay and interval wait functions
* Rev.: V4.60
* Rev.: V4.70
*----------------------------------------------------------------------------
*
* Copyright (c) 1999-2009 KEIL, 2009-2012 ARM Germany GmbH
* Copyright (c) 1999-2009 KEIL, 2009-2013 ARM Germany GmbH
* All rights reserved.
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:

View File

@ -3,10 +3,10 @@
*----------------------------------------------------------------------------
* Name: RT_TIME.H
* Purpose: Delay and interval wait functions definitions
* Rev.: V4.60
* Rev.: V4.70
*----------------------------------------------------------------------------
*
* Copyright (c) 1999-2009 KEIL, 2009-2012 ARM Germany GmbH
* Copyright (c) 1999-2009 KEIL, 2009-2013 ARM Germany GmbH
* All rights reserved.
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:

View File

@ -3,10 +3,10 @@
*----------------------------------------------------------------------------
* Name: RT_TIMER.H
* Purpose: User timer functions
* Rev.: V4.60
* Rev.: V4.70
*----------------------------------------------------------------------------
*
* Copyright (c) 1999-2009 KEIL, 2009-2012 ARM Germany GmbH
* Copyright (c) 1999-2009 KEIL, 2009-2013 ARM Germany GmbH
* All rights reserved.
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:

View File

@ -3,10 +3,10 @@
*----------------------------------------------------------------------------
* Name: RT_TYPEDEF.H
* Purpose: Type Definitions
* Rev.: V4.60
* Rev.: V4.73 (plus large stack)
*----------------------------------------------------------------------------
*
* Copyright (c) 1999-2009 KEIL, 2009-2012 ARM Germany GmbH
* Copyright (c) 1999-2009 KEIL, 2009-2015 ARM Germany GmbH
* All rights reserved.
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
@ -64,11 +64,13 @@ typedef struct OS_TCB {
U16 events; /* Event flags */
U16 waits; /* Wait flags */
void **msg; /* Direct message passing when task waits */
struct OS_MUCB *p_mlnk; /* Link pointer for mutex owner list */
U8 prio_base; /* Base priority */
/* Hardware dependant part: specific for Cortex processor */
U8 stack_frame; /* Stack frame: 0x1 Basic/Extended, 0x2 FP stacked/not stacked */
U8 reserved;
U16 priv_stack; /* Private stack size, 0= system assigned */
U8 stack_frame; /* Stack frame: 0x0 Basic, 0x1 Extended, 0x2 VFP/D16 stacked, 0x4 NEON/D32 stacked */
U16 reserved; /* Reserved (padding) */
U32 priv_stack; /* Private stack size for LARGE_STACK, 0= system assigned */
U32 tsk_stack; /* Current task Stack pointer (R13) */
U32 *stack; /* Pointer to Task Stack memory block */
@ -76,8 +78,8 @@ typedef struct OS_TCB {
FUNCP ptask; /* Task entry address */
} *P_TCB;
#define TCB_TID 3 /* 'task id' offset */
#define TCB_STACKF 32 /* 'stack_frame' offset */
#define TCB_TSTACK 36 /* 'tsk_stack' offset */
#define TCB_STACKF 37 /* 'stack_frame' offset */
#define TCB_TSTACK 44 /* 'tsk_stack' offset for LARGE_STACK */
typedef struct OS_PSFE { /* Post Service Fifo Entry */
void *id; /* Object Identification */
@ -94,7 +96,7 @@ typedef struct OS_PSQ { /* Post Service Queue */
typedef struct OS_TSK {
P_TCB run; /* Current running task */
P_TCB new; /* Scheduled task to run */
P_TCB new_tsk; /* Scheduled task to run */
} *P_TSK;
typedef struct OS_ROBIN { /* Round Robin Control */
@ -133,10 +135,10 @@ typedef struct OS_SCB {
typedef struct OS_MUCB {
U8 cb_type; /* Control Block Type */
U8 prio; /* Owner task default priority */
U16 level; /* Call nesting level */
struct OS_TCB *p_lnk; /* Chain of tasks waiting for mutex */
struct OS_TCB *owner; /* Mutex owner task */
struct OS_MUCB *p_mlnk; /* Chain of mutexes by owner task */
} *P_MUCB;
typedef struct OS_XTMR {

View File

@ -52,7 +52,7 @@ class GCC(mbedToolchain):
self.cpu.append("-mthumb-interwork")
self.cpu.append("-marm")
self.cpu.append("-march=armv7-a")
self.cpu.append("-mfpu=vfpv3-d16")
self.cpu.append("-mfpu=vfpv3")
self.cpu.append("-mfloat-abi=hard")
self.cpu.append("-mno-unaligned-access")