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

View File

@ -1,14 +1,14 @@
/**************************************************************************//** /**************************************************************************//**
* @file system_MBRZA1H.c * @file system_MBRZA1H.c
* @brief CMSIS Device System Source File for * @brief CMSIS Device System Source File for
* ARMCA9 Device Series * ARM Cortex-A9 Device Series
* @version V1.00 * @version V1.00
* @date 19 Sept 2013 * @date 09 January 2015
* *
* @note * @note
* *
******************************************************************************/ ******************************************************************************/
/* Copyright (c) 2011 - 2013 ARM LIMITED /* Copyright (c) 2011 - 2015 ARM LIMITED
All rights reserved. All rights reserved.
Redistribution and use in source and binary forms, with or without Redistribution and use in source and binary forms, with or without
@ -50,9 +50,9 @@ void FPUEnable(void);
#endif #endif
uint32_t IRQNestLevel; 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. * 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. * @brief Initialise caches. Requires PL1, so implemented as an SVC in case threads are USR mode.
*/ */
#if defined(__ARMCC_VERSION)
#pragma push #pragma push
#pragma arm #pragma arm
@ -189,7 +190,7 @@ void SystemInit (void)
//Fault Status Register (IFSR/DFSR) definitions //Fault Status Register (IFSR/DFSR) definitions
#define FSR_ALIGNMENT_FAULT 0x01 //DFSR only. Fault on first lookup #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_FIRST 0x0c //sync/external
#define FSR_SYNC_EXT_TTB_WALK_SECOND 0x0e //sync/external #define FSR_SYNC_EXT_TTB_WALK_SECOND 0x0e //sync/external
#define FSR_SYNC_PARITY_TTB_WALK_FIRST 0x1c //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. //Your code here. Value in DFAR is invalid for some fault statuses.
case FSR_ALIGNMENT_FAULT: 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_FIRST:
case FSR_SYNC_EXT_TTB_WALK_SECOND: case FSR_SYNC_EXT_TTB_WALK_SECOND:
case FSR_TRANSLATION_FAULT_FIRST: 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 //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 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 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 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) { uint32_t CUndefHandler(uint32_t opcode, uint32_t state, uint32_t LR) {
const unsigned int THUMB = 2; const unsigned int THUMB = 2;
const unsigned int ARM = 4; const unsigned int ARM = 4;
//Lazy VFP/NEON initialisation and switching //Lazy VFP/NEON initialisation and switching
if ((state == ARM && ((opcode & 0x0C000000)) >> 26 == 0x03) ||
(state == THUMB && ((opcode & 0xEC000000)) >> 26 == 0x3B)) { // (ARM ARM section A7.5) VFP data processing instruction?
if (((opcode & 0x00000E00) >> 9) == 5) { //fp 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(); FPUEnable();
return state; 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 //Add code here for other Undef cases
while(1); while(1);
} }
@ -304,18 +320,22 @@ uint32_t CUndefHandler(uint32_t opcode, uint32_t state, uint32_t LR) {
__asm void FPUEnable(void) { __asm void FPUEnable(void) {
ARM 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 MRC p15,0,R1,c1,c0,2
ORR R1,R1,#0x00F00000 ORR R1,R1,#0x00F00000
MCR p15,0,R1,c1,c0,2 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 VMRS R1,FPEXC
ORR R1,R1,#0x40000000 ORR R1,R1,#0x40000000
VMSR FPEXC,R1 VMSR FPEXC,R1
//Initialise VFP registers to 0 //Initialise VFP/NEON registers to 0
MOV R2,#0 MOV R2,#0
//Initialise D16 registers to 0
VMOV D0, R2,R2 VMOV D0, R2,R2
VMOV D1, R2,R2 VMOV D1, R2,R2
VMOV D2, R2,R2 VMOV D2, R2,R2
@ -332,7 +352,23 @@ __asm void FPUEnable(void) {
VMOV D13,R2,R2 VMOV D13,R2,R2
VMOV D14,R2,R2 VMOV D14,R2,R2
VMOV D15,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 //Initialise FPSCR to a known state
VMRS R2,FPSCR VMRS R2,FPSCR
LDR R3,=0x00086060 //Mask off all bits that do not have to be preserved. Non-preserved bits can/should be zero. 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 #pragma pop
#elif defined(__GNUC__) #elif defined(__GNUC__)
void FPUEnable(void) void FPUEnable(void) {
{ __asm__ (
__asm__ __volatile__ ( ".ARM;"
".align 2 \n\t"
".arm \n\t" //Permit access to VFP/NEON, registers by modifying CPACR
"mrc p15,0,r1,c1,c0,2 \n\t" "MRC p15,0,R1,c1,c0,2;"
"orr r1,r1,#0x00f00000 \n\t" "ORR R1,R1,#0x00F00000;"
"mcr p15,0,r1,c1,c0,2 \n\t" "MCR p15,0,R1,c1,c0,2;"
"vmrs r1,fpexc \n\t"
"orr r1,r1,#0x40000000 \n\t" //Ensure that subsequent instructions occur in the context of VFP/NEON access permitted
"vmsr fpexc,r1 \n\t" "ISB;"
"mov r2,#0 \n\t"
"vmov d0, r2,r2 \n\t" //Enable VFP/NEON
"vmov d1, r2,r2 \n\t" "VMRS R1,FPEXC;"
"vmov d2, r2,r2 \n\t" "ORR R1,R1,#0x40000000;"
"vmov d3, r2,r2 \n\t" "VMSR FPEXC,R1;"
"vmov d4, r2,r2 \n\t"
"vmov d5, r2,r2 \n\t" //Initialise VFP/NEON registers to 0
"vmov d6, r2,r2 \n\t" "MOV R2,#0;"
"vmov d7, r2,r2 \n\t" //Initialise D16 registers to 0
"vmov d8, r2,r2 \n\t" "VMOV D0, R2,R2;"
"vmov d9, r2,r2 \n\t" "VMOV D1, R2,R2;"
"vmov d10,r2,r2 \n\t" "VMOV D2, R2,R2;"
"vmov d11,r2,r2 \n\t" "VMOV D3, R2,R2;"
"vmov d12,r2,r2 \n\t" "VMOV D4, R2,R2;"
"vmov d13,r2,r2 \n\t" "VMOV D5, R2,R2;"
"vmov d14,r2,r2 \n\t" "VMOV D6, R2,R2;"
"vmov d15,r2,r2 \n\t" "VMOV D7, R2,R2;"
"vmrs r2,fpscr \n\t" "VMOV D8, R2,R2;"
"ldr r3,=0x00086060 \n\t" "VMOV D9, R2,R2;"
"and r2,r2,r3 \n\t" "VMOV D10,R2,R2;"
"vmsr fpscr,r2 \n\t" "VMOV D11,R2,R2;"
"bx lr \n\t" "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 #else
#endif #endif

View File

@ -2,12 +2,12 @@
* @file core_caFunc.h * @file core_caFunc.h
* @brief CMSIS Cortex-A Core Function Access Header File * @brief CMSIS Cortex-A Core Function Access Header File
* @version V3.10 * @version V3.10
* @date 9 May 2013 * @date 30 Oct 2013
* *
* @note * @note
* *
******************************************************************************/ ******************************************************************************/
/* Copyright (c) 2009 - 2012 ARM LIMITED /* Copyright (c) 2009 - 2013 ARM LIMITED
All rights reserved. All rights reserved.
Redistribution and use in source and binary forms, with or without 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 /** \brief Set User Mode
This function changes the processor state to 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) __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. 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) __STATIC_INLINE void __set_CPACR(uint32_t cpacr)
{ {
@ -275,7 +273,7 @@ __STATIC_INLINE uint32_t __get_CBAR() {
/** \brief Get TTBR0 /** \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 \return Translation Table Base Register 0 value
*/ */
@ -286,7 +284,7 @@ __STATIC_INLINE uint32_t __get_TTBR0() {
/** \brief Set 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 \param [in] ttbr0 Translation Table Base Register 0 value to set
*/ */
@ -309,7 +307,7 @@ __STATIC_INLINE uint32_t __get_DACR() {
/** \brief Set 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 \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. 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) __STATIC_INLINE void __set_SCTLR(uint32_t sctlr)
{ {
@ -397,9 +395,9 @@ __STATIC_INLINE void __enable_mmu(void) {
__ISB(); __ISB();
} }
/** \brief Enable MMU /** \brief Disable MMU
Enable MMU Disable MMU
*/ */
__STATIC_INLINE void __disable_mmu(void) { __STATIC_INLINE void __disable_mmu(void) {
// Clear M bit 0 to disable the MMU // 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 __DMB(); //ensure the ordering of data cache maintenance operations and their effects
} }
/** \brief /** \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.
Generic mechanism for cleaning/invalidating the entire data or unified cache to the point of coherency.
*/ */
#pragma push #pragma push
#pragma arm #pragma arm
@ -522,12 +521,12 @@ Dccsw CMP R0, #1
BNE Dccisw BNE Dccisw
MCR p15, 0, R11, c7, c10, 2 // DCCSW. Clean by Set/Way MCR p15, 0, R11, c7, c10, 2 // DCCSW. Clean by Set/Way
B cont 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 cont SUBS R9, R9, #1 // Decrement the Way number
BGE Loop3 BGE Loop3
SUBS R7, R7, #1 // Decrement the Set number SUBS R7, R7, #1 // Decrement the Set number
BGE Loop2 BGE Loop2
Skip ADD R10, R10, #2 // increment the cache number Skip ADD R10, R10, #2 // Increment the cache number
CMP R3, R10 CMP R3, R10
BGT Loop1 BGT Loop1
@ -539,9 +538,6 @@ Finished
} }
#pragma pop #pragma pop
/** \brief __v7_all_cache - helper function
*/
/** \brief Invalidate the whole D$ /** \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 #error IAR Compiler support not implemented for Cortex-A
#elif (defined (__GNUC__)) /*------------------ GNU Compiler ---------------------*/ #elif (defined (__GNUC__)) /*------------------ GNU Compiler ---------------------*/
/* GNU gcc specific functions */ /* GNU gcc specific functions */
#define MODE_USR 0x10 #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) __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_APSR(void)
{ {
#if 1 #if 1
uint32_t result; register uint32_t __regAPSR;
__ASM volatile ("mrs %0, apsr" : "=r" (__regAPSR) );
__ASM volatile ("mrs %0, apsr" : "=r" (result) );
return (result);
#else #else
register uint32_t __regAPSR __ASM("apsr"); register uint32_t __regAPSR __ASM("apsr");
return(__regAPSR);
#endif #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 \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 /** \brief Set User Mode
This function changes the processor state to 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 /** \brief Enable FIQ
This function enables FIQ interrupts by clearing the F-bit in the CPSR. This function enables FIQ interrupts by clearing the F-bit in the CPSR.
Can only be executed in Privileged modes. Can only be executed in Privileged modes.
*/ */
#define __enable_fault_irq __enable_fiq #define __enable_fault_irq() __asm__ volatile ("cpsie f")
/** \brief Disable FIQ /** \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. This function disables FIQ interrupts by setting the F-bit in the CPSR.
Can only be executed in Privileged modes. Can only be executed in Privileged modes.
*/ */
#define __disable_fault_irq __disable_fiq #define __disable_fault_irq() __asm__ volatile ("cpsid f")
/** \brief Get FPSCR /** \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. 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) __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 /** \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 \return Translation Table Base Register 0 value
*/ */
@ -872,7 +892,7 @@ __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_TTBR0() {
/** \brief Set 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 \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 /** \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 \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. 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) __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(); __ISB();
} }
/** \brief Enable MMU /** \brief Disable MMU
Enable MMU Disable MMU
*/ */
__attribute__( ( always_inline ) ) __STATIC_INLINE void __disable_mmu(void) { __attribute__( ( always_inline ) ) __STATIC_INLINE void __disable_mmu(void) {
// Clear M bit 0 to disable the MMU // 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 __DMB(); //ensure the ordering of data cache maintenance operations and their effects
} }
/** \brief /** \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.
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); extern void __v7_all_cache(uint32_t op);

View File

@ -1,14 +1,13 @@
;/**************************************************************************//** ;/**************************************************************************//**
; * @file core_ca_mmu.h ; * @file core_ca_mmu.h
; * @brief MMU Startup File for ; * @brief MMU Startup File for A9_MP Device Series
; * VE_A9_MP Device Series
; * @version V1.01 ; * @version V1.01
; * @date 25 March 2013 ; * @date 10 Sept 2014
; * ; *
; * @note ; * @note
; * ; *
; ******************************************************************************/ ; ******************************************************************************/
;/* Copyright (c) 2012 ARM LIMITED ;/* Copyright (c) 2012-2014 ARM LIMITED
; ;
; All rights reserved. ; All rights reserved.
; Redistribution and use in source and binary forms, with or without ; 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 == READ)) { ap = 0x2; }
else if ((priv == RW) && (user == RW)) { ap = 0x3; } else if ((priv == RW) && (user == RW)) { ap = 0x3; }
else if ((priv == READ) && (user == NO_ACCESS)) { ap = 0x5; } 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 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. The function creates a section descriptor.
Assumptions: 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 - TEX remap disabled, so memory type and attributes are described directly by bits in the descriptor
- Functions always return 0 - Functions always return 0

View File

@ -57,8 +57,12 @@ private:
osMutexId _osMutexId; osMutexId _osMutexId;
osMutexDef_t _osMutexDef; osMutexDef_t _osMutexDef;
#ifdef CMSIS_OS_RTX #ifdef CMSIS_OS_RTX
#ifdef __MBED_CMSIS_RTOS_CA9
int32_t _mutex_data[4];
#else
int32_t _mutex_data[3]; int32_t _mutex_data[3];
#endif #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) { static __inline U32 *rt_ret_regs (P_TCB p_TCB) {
/* Get pointer to task return value registers (R0..R3) in Stack */ /* Get pointer to task return value registers (R0..R3) in Stack */
#if (__TARGET_FPU_VFP) if (p_TCB->stack_frame & 0x4) {
if (p_TCB->stack_frame & 0x2) { /* NEON/D32 Stack Frame: D0-31,FPSCR,Reserved,R4-R11,R0-R3,R12,LR,PC,xPSR */
/* Extended Stack Frame: S0-31,FPSCR,Reserved,R4-R11,R0-R3,R12,LR,PC,xPSR */ return (U32 *)(p_TCB->tsk_stack + 8*4 + 2*4 + 32*8);
return (U32 *)(p_TCB->tsk_stack + 8*4 + 34*4); } 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 { } else {
/* Basic Stack Frame: R4-R11,R0-R3,R12,LR,PC,xPSR */ /* Basic Stack Frame: R4-R11,R0-R3,R12,LR,PC,xPSR */
return (U32 *)(p_TCB->tsk_stack + 8*4); 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) { void rt_ret_val (P_TCB p_TCB, U32 v0) {

View File

@ -3,10 +3,10 @@
*---------------------------------------------------------------------------- *----------------------------------------------------------------------------
* Name: RTX_CM_LIB.H * Name: RTX_CM_LIB.H
* Purpose: RTX Kernel System Configuration * 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. * All rights reserved.
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met: * 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_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 _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 #define OS_TMR_SIZE 8
#if defined (__CC_ARM) && !defined (__MICROLIB) #if defined (__CC_ARM) && !defined (__MICROLIB)
typedef void *OS_ID; typedef void *OS_ID;
typedef uint32_t OS_TID; typedef uint32_t OS_TID;
typedef uint32_t OS_MUT[3]; typedef uint32_t OS_MUT[4];
typedef uint32_t OS_RESULT; typedef uint32_t OS_RESULT;
#define runtask_id() rt_tsk_self() #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); uint32_t const os_stackinfo = (OS_STKCHECK<<24)| (OS_PRIV_CNT<<16) | (OS_STKSIZE*4);
#endif #endif
uint32_t const os_rrobin = (OS_ROBIN << 16) | OS_ROBINTOUT; 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; uint32_t const os_trv = OS_TRV;
uint8_t const os_flags = OS_RUNPRIV; uint8_t const os_flags = OS_RUNPRIV;
/* Export following defines to uVision debugger. */ /* 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_clockrate = OS_TICK;
__USED uint32_t const os_timernum = 0; __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 }; osThreadDef_t os_thread_def_main = {(os_pthread)main, osPriorityNormal, 1, 4*OS_MAINSTKSIZE };
#endif #endif
#if defined (__CC_ARM) #if defined (__CC_ARM)
#ifdef __MICROLIB #ifdef __MICROLIB

View File

@ -3,10 +3,10 @@
*---------------------------------------------------------------------------- *----------------------------------------------------------------------------
* Name: RTX_CONFIG.H * Name: RTX_CONFIG.H
* Purpose: Exported functions of RTX_Config.c * 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. * All rights reserved.
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met: * modification, are permitted provided that the following conditions are met:
@ -67,6 +67,8 @@ extern U8 const os_fifo_size;
/* Functions */ /* Functions */
extern void os_idle_demon (void); extern void os_idle_demon (void);
extern int os_tick_init (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_tick_irqack (void);
extern void os_tmr_call (U16 info); extern void os_tmr_call (U16 info);
extern void os_error (U32 err_code); extern void os_error (U32 err_code);

View File

@ -3,10 +3,10 @@
*---------------------------------------------------------------------------- *----------------------------------------------------------------------------
* Name: HAL_CA9.c * Name: HAL_CA9.c
* Purpose: Hardware Abstraction Layer for Cortex-A9 * 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. * All rights reserved.
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met: * modification, are permitted provided that the following conditions are met:
@ -114,6 +114,7 @@ __asm void SVC_Handler (void) {
IMPORT SVC_Table IMPORT SVC_Table
IMPORT rt_stk_check IMPORT rt_stk_check
IMPORT FPUEnable IMPORT FPUEnable
IMPORT scheduler_suspended ; flag set by rt_suspend, cleared by rt_resume, read by SVC_Handler
Mode_SVC EQU 0x13 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) */ /* Here we will be in SVC mode (even if coming in from PendSV_Handler or OS_Tick_Handler) */
Sys_Switch Sys_Switch
LDR LR,=__cpp(&os_tsk) 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 CMP R4,LR
BNE switching BNE switching
@ -170,7 +171,13 @@ Sys_Switch
PUSH {R12, LR} ; Store stack adjustment and dummy LR to SVC stack PUSH {R12, LR} ; Store stack adjustment and dummy LR to SVC stack
CPSID i 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 BLX rt_tsk_unlock
dont_unlock
POP {R12, LR} ; Get stack adjustment & discard dummy LR POP {R12, LR} ; Get stack adjustment & discard dummy LR
ADD SP, SP, R12 ; Unadjust stack ADD SP, SP, R12 ; Unadjust stack
@ -188,7 +195,7 @@ switching
PUSH {R8-R11} //R4 and LR already stacked PUSH {R8-R11} //R4 and LR already stacked
MOV R10,R4 ; Preserve os_tsk.run 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 ADD R8,SP,#16 ; Unstack R4,LR
LDMIA R8,{R4,LR} LDMIA R8,{R4,LR}
@ -204,21 +211,22 @@ switching
SUB R8,R8,#4 ; No writeback for store of User LR SUB R8,R8,#4 ; No writeback for store of User LR
STMDB R8!,{R0-R3,R12} ; User R0-R3,R12 STMDB R8!,{R0-R3,R12} ; User R0-R3,R12
MOV R3,R10 ; os_tsk.run MOV R3,R10 ; os_tsk.run
MOV LR,R11 ; os_tsk.new MOV LR,R11 ; os_tsk.new_tsk
POP {R9-R12} POP {R9-R12}
ADD SP,SP,#12 ; Fix up SP for unstack of R4, LR & SPSR ADD SP,SP,#12 ; Fix up SP for unstack of R4, LR & SPSR
STMDB R8!,{R4-R7,R9-R12} ; User R4-R11 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) MRC p15,0,R1,c1,c0,2 ; VFP/NEON access enabled? (CPACR)
AND R2,R1,#0x00F00000 AND R2,R1,#0x00F00000
CMP R2,#0x00F00000 CMP R2,#0x00F00000
BNE no_outgoing_vfp BNE no_outgoing_vfp
VMRS R2,FPSCR VMRS R2,FPSCR
STMDB R8!,{R2,R4} ; Push FPSCR, maintain 8-byte alignment STMDB R8!,{R2,R4} ; Push FPSCR, maintain 8-byte alignment
VSTMDB R8!,{S0-S31} VSTMDB R8!,{D0-D15}
LDRB R2,[R3,#TCB_STACKF] ; Record in TCB that VFP state is stacked VSTMDB R8!,{D16-D31}
ORR R2,#2 LDRB R2,[R3,#TCB_STACKF] ; Record in TCB that NEON/D32 state is stacked
ORR R2,#4
STRB R2,[R3,#TCB_STACKF] STRB R2,[R3,#TCB_STACKF]
no_outgoing_vfp no_outgoing_vfp
@ -238,8 +246,8 @@ no_outgoing_vfp
MOV LR,R4 MOV LR,R4
SVC_Next //R4 == os_tsk.run, LR == os_tsk.new, R0-R3, R5-R12 corruptible 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 LDR R1,=__cpp(&os_tsk) ; os_tsk.run = os_tsk.new_tsk
STR LR,[R1] STR LR,[R1]
LDRB R1,[LR,#TCB_TID] ; os_tsk.run->task_id LDRB R1,[LR,#TCB_TID] ; os_tsk.run->task_id
LSL R1,#8 ; Store PROCID 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 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] LDRB R3,[LR,#TCB_STACKF]
TST R3,#0x2 ANDS R3, R3, #0x6
MRC p15,0,R1,c1,c0,2 ; Read CPACR 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 ANDEQ R1,R1,#0xFF0FFFFF ; Disable VFP/NEON access if incoming task does not have stacked VFP/NEON state
ORRNE R1,R1,#0x00F00000 ; Enable VFP access if incoming task does have stacked VFP 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 MCR p15,0,R1,c1,c0,2 ; Write CPACR
BEQ no_incoming_vfp BEQ no_incoming_vfp
ISB ; We only need the sync if we enabled, otherwise we will context switch before next VFP instruction anyway ISB ; We only need the sync if we enabled, otherwise we will context switch before next VFP/NEON instruction anyway
VLDMIA R0!,{S0-S31} VLDMIA R0!,{D16-D31}
VLDMIA R0!,{D0-D15}
LDR R2,[R0] LDR R2,[R0]
VMSR FPSCR,R2 VMSR FPSCR,R2
ADD R0,R0,#8 ADD R0,R0,#8
@ -343,7 +352,8 @@ __asm void PendSV_Handler (U32 IRQn) {
ARM ARM
IMPORT rt_tsk_lock 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) 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] LDR R1, [R1, #0]
STR R0, [R1, #0x10] 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 R0, =IRQNestLevel ; Get address of nesting counter
LDR R1, [R0] LDR R1, [R0]
SUB R1, R1, #1 ; Decrement nesting counter SUB R1, R1, #1 ; Decrement nesting counter
@ -380,7 +395,8 @@ __asm void OS_Tick_Handler (U32 IRQn) {
ARM ARM
IMPORT rt_tsk_lock 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) 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] LDR R1, [R1, #0]
STR R0, [R1, #0x10] 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 R0, =IRQNestLevel ; Get address of nesting counter
LDR R1, [R0] LDR R1, [R0]
SUB R1, R1, #1 ; Decrement nesting counter SUB R1, R1, #1 ; Decrement nesting counter

View File

@ -3,10 +3,10 @@
; *---------------------------------------------------------------------------- ; *----------------------------------------------------------------------------
; * Name: SVC_TABLE.S ; * Name: SVC_TABLE.S
; * Purpose: Pre-defined SVC Table for Cortex-M ; * 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. ; * All rights reserved.
; * Redistribution and use in source and binary forms, with or without ; * Redistribution and use in source and binary forms, with or without
; * modification, are permitted provided that the following conditions are met: ; * modification, are permitted provided that the following conditions are met:

View File

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

View File

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

View File

@ -1,6 +1,6 @@
/* ---------------------------------------------------------------------- /* ----------------------------------------------------------------------
* $Date: 5. June 2012 * $Date: 5. February 2013
* $Revision: V1.01 * $Revision: V1.02
* *
* Project: CMSIS-RTOS API * Project: CMSIS-RTOS API
* Title: cmsis_os.h RTX header file * Title: cmsis_os.h RTX header file
@ -18,9 +18,13 @@
* - const attribute added to the osXxxxDef macros * - const attribute added to the osXxxxDef macros
* Added: osTimerDelete, osMutexDelete, osSemaphoreDelete * Added: osTimerDelete, osMutexDelete, osSemaphoreDelete
* Added: osKernelInitialize * 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. * All rights reserved.
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met: * modification, are permitted provided that the following conditions are met:
@ -127,13 +131,13 @@ used throughout the whole project.
#define _CMSIS_OS_H #define _CMSIS_OS_H
/// \note MUST REMAIN UNCHANGED: \b osCMSIS identifies the CMSIS-RTOS API version. /// \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. /// \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. /// \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
#define CMSIS_OS_RTX_CA /* new define for Coretex-A */ #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_Signals 16 ///< maximum number of Signal Flags available per thread
#define osFeature_Semaphore 65535 ///< maximum count for \ref osSemaphoreCreate function #define osFeature_Semaphore 65535 ///< maximum count for \ref osSemaphoreCreate function
#define osFeature_Wait 0 ///< osWait function: 1=available, 0=not available #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) #if defined (__CC_ARM)
#define os_InRegs __value_in_regs // Compiler specific: force struct in registers #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. /// \return 0 RTOS is not started, 1 RTOS is started.
int32_t osKernelRunning(void); 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 ==== // ==== 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. /// \note MUST REMAIN UNCHANGED: \b osSignalClear shall be consistent in every CMSIS-RTOS.
int32_t osSignalClear (osThreadId thread_id, int32_t signals); 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. /// 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] 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. /// \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 extern const osMutexDef_t os_mutex_def_##name
#else // define the object #else // define the object
#define osMutexDef(name) \ #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) } const osMutexDef_t os_mutex_def_##name = { (os_mutex_cb_##name) }
#endif #endif
@ -579,7 +602,7 @@ osStatus osMutexDelete (osMutexId mutex_id);
extern const osSemaphoreDef_t os_semaphore_def_##name extern const osSemaphoreDef_t os_semaphore_def_##name
#else // define the object #else // define the object
#define osSemaphoreDef(name) \ #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) } const osSemaphoreDef_t os_semaphore_def_##name = { (os_semaphore_cb_##name) }
#endif #endif
@ -689,7 +712,7 @@ osStatus osPoolFree (osPoolId pool_id, void *block);
extern const osMessageQDef_t os_messageQ_def_##name extern const osMessageQDef_t os_messageQ_def_##name
#else // define the object #else // define the object
#define osMessageQDef(name, queue_sz, type) \ #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 = \ const osMessageQDef_t os_messageQ_def_##name = \
{ (queue_sz), (os_messageQ_q_##name) } { (queue_sz), (os_messageQ_q_##name) }
#endif #endif
@ -741,7 +764,7 @@ os_InRegs osEvent osMessageGet (osMessageQId queue_id, uint32_t millisec);
extern const osMailQDef_t os_mailQ_def_##name extern const osMailQDef_t os_mailQ_def_##name
#else // define the object #else // define the object
#define osMailQDef(name, queue_sz, type) \ #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)]; \ 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 }; \ void * os_mailQ_p_##name[2] = { (os_mailQ_q_##name), os_mailQ_m_##name }; \
const osMailQDef_t os_mailQ_def_##name = \ const osMailQDef_t os_mailQ_def_##name = \
@ -800,6 +823,15 @@ osStatus osMailFree (osMailQId queue_id, void *mail);
#endif // Mail Queues available #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 #ifdef __cplusplus
} }
#endif #endif

View File

@ -3,10 +3,10 @@
*---------------------------------------------------------------------------- *----------------------------------------------------------------------------
* Name: rt_CMSIS.c * Name: rt_CMSIS.c
* Purpose: CMSIS RTOS API * 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. * All rights reserved.
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met: * modification, are permitted provided that the following conditions are met:
@ -100,6 +100,14 @@ static __inline t __##f (void) { \
return _##f(f); \ 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,...) \ #define SVC_1_1(f,t,t1,...) \
__svc_indirect(0) t _##f (t(*)(t1),t1); \ __svc_indirect(0) t _##f (t(*)(t1),t1); \
t f (t1 a1); \ t f (t1 a1); \
@ -280,6 +288,13 @@ static inline t __##f (void) { \
return (t) rv; \ 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) \ #define SVC_1_1(f,t,t1,rv) \
__attribute__((always_inline)) \ __attribute__((always_inline)) \
static inline t __##f (t1 a1) { \ static inline t __##f (t1 a1) { \
@ -353,6 +368,14 @@ static inline t __##f (void) { \
return _##f(); \ 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,...) \ #define SVC_1_1(f,t,t1,...) \
t f (t1 a1); \ t f (t1 a1); \
_Pragma("swi_number=0") __swi 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(svcKernelInitialize, osStatus, RET_osStatus)
SVC_0_1(svcKernelStart, osStatus, RET_osStatus) SVC_0_1(svcKernelStart, osStatus, RET_osStatus)
SVC_0_1(svcKernelRunning, int32_t, RET_int32_t) SVC_0_1(svcKernelRunning, int32_t, RET_int32_t)
SVC_0_1(svcKernelSysTick, uint32_t, RET_uint32_t)
static void sysThreadError (osStatus status); static void sysThreadError (osStatus status);
osThreadId svcThreadCreate (const osThreadDef_t *thread_def, void *argument); osThreadId svcThreadCreate (const osThreadDef_t *thread_def, void *argument);
@ -577,6 +601,7 @@ osStatus svcKernelInitialize (void) {
sysThreadError(osOK); sysThreadError(osOK);
os_initialized = 1; os_initialized = 1;
os_running = 0;
return osOK; return osOK;
} }
@ -586,8 +611,10 @@ osStatus svcKernelStart (void) {
if (os_running) return osOK; if (os_running) return osOK;
rt_tsk_prio(0, 0); // Lowest priority rt_tsk_prio(0, os_tsk.run->prio_base); // Restore priority
__set_PSP(os_tsk.run->tsk_stack + 8*4); // New context 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 os_tsk.run = NULL; // Force context switch
rt_sys_start(); rt_sys_start();
@ -602,6 +629,22 @@ int32_t svcKernelRunning(void) {
return os_running; 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 // Kernel Control Public API
/// Initialize the RTOS Kernel for creating objects /// 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 ==== // ==== Thread Management ====
@ -1047,6 +1096,7 @@ osTimerId svcTimerCreate (const osTimerDef_t *timer_def, os_timer_type type, voi
return NULL; return NULL;
} }
pt->next = NULL;
pt->state = osTimerStopped; pt->state = osTimerStopped;
pt->type = (uint8_t)type; pt->type = (uint8_t)type;
pt->arg = argument; 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 // Timer Management Public API
@ -1237,7 +1311,6 @@ __NO_RETURN void osTimerThread (void const *argument) {
// Signal Service Calls declarations // Signal Service Calls declarations
SVC_2_1(svcSignalSet, int32_t, osThreadId, int32_t, RET_int32_t) 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_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) SVC_2_3(svcSignalWait, os_InRegs osEvent, int32_t, uint32_t, RET_osEvent)
// Signal Service Calls // Signal Service Calls
@ -1276,16 +1349,6 @@ int32_t svcSignalClear (osThreadId thread_id, int32_t signals) {
return sig; 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 /// 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_InRegs osEvent_type svcSignalWait (int32_t signals, uint32_t millisec) {
OS_RESULT res; OS_RESULT res;
@ -1361,12 +1424,6 @@ int32_t osSignalClear (osThreadId thread_id, int32_t signals) {
return __svcSignalClear(thread_id, 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 /// 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) { os_InRegs osEvent osSignalWait (int32_t signals, uint32_t millisec) {
osEvent ret; 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)); rt_mbx_init(pmcb, 4*(queue_def->queue_sz + 4));
return queue_def->pool; return queue_def->pool;
} }
@ -2020,7 +2076,7 @@ osStatus sysMailFree (osMailQId queue_id, void *mail, uint32_t isr) {
if (res != 0) return osErrorValue; if (res != 0) return osErrorValue;
if (pmcb->state == 3) { if ((pmcb->p_lnk != NULL) && (pmcb->state == 3)) {
// Task is waiting to allocate a message // Task is waiting to allocate a message
if (isr) { if (isr) {
rt_psq_enq (pmcb, (U32)pool); 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); mem = rt_alloc_box(pool);
if (mem != NULL) { if (mem != NULL) {
ptcb = rt_get_first((P_XCB)pmcb); ptcb = rt_get_first((P_XCB)pmcb);
if (pmcb->p_lnk == NULL) {
pmcb->state = 0;
}
rt_ret_val(ptcb, (U32)mem); rt_ret_val(ptcb, (U32)mem);
rt_rmv_dly(ptcb); rt_rmv_dly(ptcb);
rt_dispatch(ptcb); rt_dispatch(ptcb);
@ -2111,3 +2164,23 @@ os_InRegs osEvent osMailGet (osMailQId queue_id, uint32_t millisec) {
#ifdef __CC_ARM #ifdef __CC_ARM
#pragma pop #pragma pop
#endif // __arm__ #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 * Name: RT_EVENT.C
* Purpose: Implements waits and wake-ups for event flags * 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. * All rights reserved.
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met: * modification, are permitted provided that the following conditions are met:

View File

@ -3,10 +3,10 @@
*---------------------------------------------------------------------------- *----------------------------------------------------------------------------
* Name: RT_EVENT.H * Name: RT_EVENT.H
* Purpose: Implements waits and wake-ups for event flags * 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. * All rights reserved.
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met: * modification, are permitted provided that the following conditions are met:

View File

@ -1,9 +1,9 @@
/*---------------------------------------------------------------------------- /*----------------------------------------------------------------------------
* RL-ARM - RTX * RL-ARM - RTX
*---------------------------------------------------------------------------- *----------------------------------------------------------------------------
* Name: RT_HAL_CM.H * Name: RT_HAL_CA.H
* Purpose: Hardware Abstraction Layer for Cortex-A definitions * 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 * 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- */ /* 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) { __inline static void rt_svc_init (void) {
/* Register pendSV - through SGI */ /* Register pendSV - through SGI */
volatile char *reg; volatile char *reg;

View File

@ -3,10 +3,10 @@
*---------------------------------------------------------------------------- *----------------------------------------------------------------------------
* Name: RT_HAL_CM.H * Name: RT_HAL_CM.H
* Purpose: Hardware Abstraction Layer for Cortex-M definitions * 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. * All rights reserved.
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met: * modification, are permitted provided that the following conditions are met:
@ -40,7 +40,7 @@
#if defined (__CC_ARM) /* ARM Compiler */ #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 #define __USE_EXCLUSIVE_ACCESS
#else #else
#undef __USE_EXCLUSIVE_ACCESS #undef __USE_EXCLUSIVE_ACCESS
@ -228,6 +228,14 @@ __inline static void rt_systick_init (void) {
NVIC_SYS_PRI3 |= 0xFF000000; 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) { __inline static void rt_svc_init (void) {
#if !(__TARGET_ARCH_6S_M) #if !(__TARGET_ARCH_6S_M)
int sh,prigroup; int sh,prigroup;
@ -262,7 +270,7 @@ extern void dbg_task_switch (U32 task_id);
#ifdef DBG_MSG #ifdef DBG_MSG
#define DBG_INIT() dbg_init() #define DBG_INIT() dbg_init()
#define DBG_TASK_NOTIFY(p_tcb,create) if (dbg_msg) dbg_task_notify(p_tcb,create) #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) dbg_task_switch(task_id)
#else #else
#define DBG_INIT() #define DBG_INIT()

View File

@ -3,10 +3,10 @@
*---------------------------------------------------------------------------- *----------------------------------------------------------------------------
* Name: RT_LIST.C * Name: RT_LIST.C
* Purpose: Functions for the management of different lists * 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. * All rights reserved.
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met: * modification, are permitted provided that the following conditions are met:

View File

@ -3,10 +3,10 @@
*---------------------------------------------------------------------------- *----------------------------------------------------------------------------
* Name: RT_LIST.H * Name: RT_LIST.H
* Purpose: Functions for the management of different lists * 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. * All rights reserved.
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met: * modification, are permitted provided that the following conditions are met:

View File

@ -3,10 +3,10 @@
*---------------------------------------------------------------------------- *----------------------------------------------------------------------------
* Name: RT_MAILBOX.C * Name: RT_MAILBOX.C
* Purpose: Implements waits and wake-ups for mailbox messages * 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. * All rights reserved.
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met: * modification, are permitted provided that the following conditions are met:

View File

@ -3,10 +3,10 @@
*---------------------------------------------------------------------------- *----------------------------------------------------------------------------
* Name: RT_MAILBOX.H * Name: RT_MAILBOX.H
* Purpose: Implements waits and wake-ups for mailbox messages * 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. * All rights reserved.
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met: * modification, are permitted provided that the following conditions are met:

View File

@ -3,10 +3,10 @@
*---------------------------------------------------------------------------- *----------------------------------------------------------------------------
* Name: RT_MEMBOX.C * Name: RT_MEMBOX.C
* Purpose: Interface functions for fixed memory block management system * 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. * All rights reserved.
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met: * modification, are permitted provided that the following conditions are met:

View File

@ -3,10 +3,10 @@
*---------------------------------------------------------------------------- *----------------------------------------------------------------------------
* Name: RT_MEMBOX.H * Name: RT_MEMBOX.H
* Purpose: Interface functions for fixed memory block management system * 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. * All rights reserved.
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met: * modification, are permitted provided that the following conditions are met:

View File

@ -3,10 +3,10 @@
*---------------------------------------------------------------------------- *----------------------------------------------------------------------------
* Name: RT_MEMORY.C * Name: RT_MEMORY.C
* Purpose: Interface functions for Dynamic Memory Management System * 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. * All rights reserved.
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met: * modification, are permitted provided that the following conditions are met:

View File

@ -3,10 +3,10 @@
*---------------------------------------------------------------------------- *----------------------------------------------------------------------------
* Name: RT_MEMORY.H * Name: RT_MEMORY.H
* Purpose: Interface functions for Dynamic Memory Management System * 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. * All rights reserved.
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met: * modification, are permitted provided that the following conditions are met:

View File

@ -3,10 +3,10 @@
*---------------------------------------------------------------------------- *----------------------------------------------------------------------------
* Name: RT_MUTEX.C * Name: RT_MUTEX.C
* Purpose: Implements mutex synchronization objects * 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. * All rights reserved.
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met: * 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_MUCB p_MCB = mutex;
p_MCB->cb_type = MUCB; p_MCB->cb_type = MUCB;
p_MCB->prio = 0;
p_MCB->level = 0; p_MCB->level = 0;
p_MCB->p_lnk = NULL; p_MCB->p_lnk = NULL;
p_MCB->owner = 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 */ /* Delete a mutex object */
P_MUCB p_MCB = mutex; P_MUCB p_MCB = mutex;
P_TCB p_TCB; P_TCB p_TCB;
P_MUCB p_mlnk;
U8 prio;
__DMB(); __DMB();
/* Restore owner task's priority. */ /* Restore owner task's priority. */
if (p_MCB->level != 0) { if (p_MCB->level != 0) {
p_MCB->owner->prio = p_MCB->prio;
if (p_MCB->owner != os_tsk.run) { p_TCB = p_MCB->owner;
rt_resort_prio (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) { while (p_MCB->p_lnk != NULL) {
@ -109,6 +142,8 @@ OS_RESULT rt_mut_release (OS_ID mutex) {
/* Release a mutex object */ /* Release a mutex object */
P_MUCB p_MCB = mutex; P_MUCB p_MCB = mutex;
P_TCB p_TCB; P_TCB p_TCB;
P_MUCB p_mlnk;
U8 prio;
if (p_MCB->level == 0 || p_MCB->owner != os_tsk.run) { if (p_MCB->level == 0 || p_MCB->owner != os_tsk.run) {
/* Unbalanced mutex release or task is not the owner */ /* 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) { if (--p_MCB->level != 0) {
return (OS_R_OK); 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. */ /* 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) { if (p_MCB->p_lnk != NULL) {
/* A task is waiting for mutex. */ /* A task is waiting for mutex. */
p_TCB = rt_get_first ((P_XCB)p_MCB); 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. */ /* A waiting task becomes the owner of this mutex. */
p_MCB->level = 1; p_MCB->level = 1;
p_MCB->owner = p_TCB; 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. */ /* Priority inversion, check which task continues. */
if (os_tsk.run->prio >= rt_rdy_prio()) { if (os_tsk.run->prio >= rt_rdy_prio()) {
rt_dispatch (p_TCB); rt_dispatch (p_TCB);
@ -147,7 +209,7 @@ OS_RESULT rt_mut_release (OS_ID mutex) {
} }
} }
else { 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) { if (rt_rdy_prio() > os_tsk.run->prio) {
rt_put_prio (&os_rdy, os_tsk.run); rt_put_prio (&os_rdy, os_tsk.run);
os_tsk.run->state = READY; os_tsk.run->state = READY;
@ -166,7 +228,8 @@ OS_RESULT rt_mut_wait (OS_ID mutex, U16 timeout) {
if (p_MCB->level == 0) { if (p_MCB->level == 0) {
p_MCB->owner = os_tsk.run; 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; goto inc;
} }
if (p_MCB->owner == os_tsk.run) { 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. */ /* Raise the owner task priority if lower than current priority. */
/* This priority inversion is called priority inheritance. */ /* 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; p_MCB->owner->prio = os_tsk.run->prio;
rt_resort_prio (p_MCB->owner); rt_resort_prio (p_MCB->owner);
} }

View File

@ -3,10 +3,10 @@
*---------------------------------------------------------------------------- *----------------------------------------------------------------------------
* Name: RT_MUTEX.H * Name: RT_MUTEX.H
* Purpose: Implements mutex synchronization objects * 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. * All rights reserved.
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met: * modification, are permitted provided that the following conditions are met:

View File

@ -3,10 +3,10 @@
*---------------------------------------------------------------------------- *----------------------------------------------------------------------------
* Name: RT_ROBIN.C * Name: RT_ROBIN.C
* Purpose: Round Robin Task switching * 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. * All rights reserved.
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met: * modification, are permitted provided that the following conditions are met:

View File

@ -3,10 +3,10 @@
*---------------------------------------------------------------------------- *----------------------------------------------------------------------------
* Name: RT_ROBIN.H * Name: RT_ROBIN.H
* Purpose: Round Robin Task switching definitions * 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. * All rights reserved.
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met: * modification, are permitted provided that the following conditions are met:

View File

@ -3,10 +3,10 @@
*---------------------------------------------------------------------------- *----------------------------------------------------------------------------
* Name: RT_SEMAPHORE.C * Name: RT_SEMAPHORE.C
* Purpose: Implements binary and counting semaphores * 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. * All rights reserved.
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met: * 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 ----------------------------------*/ /*--------------------------- isr_sem_send ----------------------------------*/
void isr_sem_send (OS_ID semaphore) { 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; P_SCB p_SCB = semaphore;
rt_psq_enq (p_SCB, 0); rt_psq_enq (p_SCB, 0);

View File

@ -3,10 +3,10 @@
*---------------------------------------------------------------------------- *----------------------------------------------------------------------------
* Name: RT_SEMAPHORE.H * Name: RT_SEMAPHORE.H
* Purpose: Implements binary and counting semaphores * 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. * All rights reserved.
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met: * modification, are permitted provided that the following conditions are met:

View File

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

View File

@ -3,10 +3,10 @@
*---------------------------------------------------------------------------- *----------------------------------------------------------------------------
* Name: RT_SYSTEM.H * Name: RT_SYSTEM.H
* Purpose: System Task Manager definitions * 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. * All rights reserved.
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met: * modification, are permitted provided that the following conditions are met:

View File

@ -3,10 +3,10 @@
*---------------------------------------------------------------------------- *----------------------------------------------------------------------------
* Name: RT_TASK.C * Name: RT_TASK.C
* Purpose: Task functions and system start up. * 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. * All rights reserved.
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met: * 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->cb_type = TCB;
p_TCB->state = READY; p_TCB->state = READY;
p_TCB->prio = priority; p_TCB->prio = priority;
p_TCB->prio_base = priority;
p_TCB->p_lnk = NULL; p_TCB->p_lnk = NULL;
p_TCB->p_rlnk = NULL; p_TCB->p_rlnk = NULL;
p_TCB->p_dlnk = NULL; p_TCB->p_dlnk = NULL;
p_TCB->p_blnk = NULL; p_TCB->p_blnk = NULL;
p_TCB->p_mlnk = NULL;
p_TCB->delta_time = 0; p_TCB->delta_time = 0;
p_TCB->interval_time = 0; p_TCB->interval_time = 0;
p_TCB->events = 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) { void rt_switch_req (P_TCB p_new) {
/* Switch to next task (identified by "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; p_new->state = RUNNING;
DBG_TASK_SWITCH(p_new->task_id); 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) { if (task_id == 0) {
/* Change execution priority of calling task. */ /* Change execution priority of calling task. */
os_tsk.run->prio = new_prio; os_tsk.run->prio = new_prio;
os_tsk.run->prio_base = new_prio;
run:if (rt_rdy_prio() > new_prio) { run:if (rt_rdy_prio() > new_prio) {
rt_put_prio (&os_rdy, os_tsk.run); rt_put_prio (&os_rdy, os_tsk.run);
os_tsk.run->state = READY; 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 = os_active_TCB[task_id-1];
p_task->prio = new_prio; p_task->prio = new_prio;
p_task->prio_base = new_prio;
if (p_task == os_tsk.run) { if (p_task == os_tsk.run) {
goto 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) { OS_RESULT rt_tsk_delete (OS_TID task_id) {
/* Terminate the task identified with "task_id". */ /* Terminate the task identified with "task_id". */
P_TCB task_context; 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) { if (task_id == 0 || task_id == os_tsk.run->task_id) {
/* Terminate itself. */ /* Terminate itself. */
os_tsk.run->state = INACTIVE; os_tsk.run->state = INACTIVE;
os_tsk.run->tsk_stack = rt_get_PSP (); os_tsk.run->tsk_stack = rt_get_PSP ();
rt_stk_check (); 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; os_active_TCB[os_tsk.run->task_id-1] = NULL;
rt_free_box (mp_stk, os_tsk.run->stack); rt_free_box (mp_stk, os_tsk.run->stack);
os_tsk.run->stack = NULL; 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]; task_context = os_active_TCB[task_id-1];
rt_rmv_list (task_context); rt_rmv_list (task_context);
rt_rmv_dly (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; os_active_TCB[task_id-1] = NULL;
rt_free_box (mp_stk, task_context->stack); rt_free_box (mp_stk, task_context->stack);
task_context->stack = NULL; task_context->stack = NULL;
DBG_TASK_NOTIFY(task_context, __FALSE); DBG_TASK_NOTIFY(task_context, __FALSE);
rt_free_box (mp_tcb, task_context); 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); return (OS_R_OK);
} }

View File

@ -3,10 +3,10 @@
*---------------------------------------------------------------------------- *----------------------------------------------------------------------------
* Name: RT_TASK.H * Name: RT_TASK.H
* Purpose: Task functions and system start up. * 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. * All rights reserved.
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met: * modification, are permitted provided that the following conditions are met:

View File

@ -3,10 +3,10 @@
*---------------------------------------------------------------------------- *----------------------------------------------------------------------------
* Name: RT_TIME.C * Name: RT_TIME.C
* Purpose: Delay and interval wait functions * 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. * All rights reserved.
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met: * modification, are permitted provided that the following conditions are met:

View File

@ -3,10 +3,10 @@
*---------------------------------------------------------------------------- *----------------------------------------------------------------------------
* Name: RT_TIME.H * Name: RT_TIME.H
* Purpose: Delay and interval wait functions definitions * 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. * All rights reserved.
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met: * modification, are permitted provided that the following conditions are met:

View File

@ -3,10 +3,10 @@
*---------------------------------------------------------------------------- *----------------------------------------------------------------------------
* Name: RT_TIMER.H * Name: RT_TIMER.H
* Purpose: User timer functions * 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. * All rights reserved.
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met: * modification, are permitted provided that the following conditions are met:

View File

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

View File

@ -52,7 +52,7 @@ class GCC(mbedToolchain):
self.cpu.append("-mthumb-interwork") self.cpu.append("-mthumb-interwork")
self.cpu.append("-marm") self.cpu.append("-marm")
self.cpu.append("-march=armv7-a") 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("-mfloat-abi=hard")
self.cpu.append("-mno-unaligned-access") self.cpu.append("-mno-unaligned-access")