Pull in CMSIS 5 files

Pull in unmodified CMSIS5 files from the repository
https://github.com/ARM-software/CMSIS_5.git from the commit
c1b4232f4a98275dd79ebc99cf9b5da5053def4d.

The files were copied as shown below with source->dest_dir.
CMSIS_5/CMSIS/Core/Include/core_*.h -> mbed-os/cmsis/
CMSIS_5/CMSIS/Core_A/Include/core_*.h -> mbed-os/cmsis/
CMSIS_5/CMSIS/DSP/Include/arm_math.h -> mbed-os/cmsis/
CMSIS_5/CMSIS/Core/Include/tz_context.h -> mbed-os/cmsis/
CMSIS_5/CMSIS/Core/Include/cmsis_compiler.h -> mbed-os/cmsis/TARGET_CORTEX_M/
CMSIS_5/CMSIS/Core/Include/cmsis_arm*.h -> mbed-os/cmsis/TARGET_CORTEX_M/TOOLCHAIN_ARM/
CMSIS_5/CMSIS/Core/Include/cmsis_gcc*.h -> mbed-os/cmsis/TARGET_CORTEX_M/TOOLCHAIN_GCC/
CMSIS_5/CMSIS/Core_A/Include/cmsis_compiler.h -> mbed-os/cmsis/TARGET_CORTEX_A/
CMSIS_5/CMSIS/Core_A/Include/cmsis_arm*.h -> mbed-os/cmsis/TARGET_CORTEX_A/TOOLCHAIN_ARM/
CMSIS_5/CMSIS/RTOS2/RTX/Library/cmsis_os1.c -> mbed-os/rtos/rtx/
CMSIS_5/CMSIS/RTOS2/Include/cmsis_os2.h -> mbed-os/rtos/rtx2/TARGET_CORTEX_M/
CMSIS_5/CMSIS/RTOS2/RTX/Config/* -> mbed-os/rtos/rtx2/TARGET_CORTEX_M/
CMSIS_5/CMSIS/RTOS2/RTX/Include1/* -> mbed-os/rtos/rtx/
CMSIS_5/CMSIS/RTOS2/RTX/Include/* -> mbed-os/rtos/rtx2/TARGET_CORTEX_M/
CMSIS_5/CMSIS/RTOS2/RTX/Source/rtx_* -> mbed-os/rtos/rtx2/TARGET_CORTEX_M/
CMSIS_5/CMSIS/RTOS2/RTX/Source/core_cm.h -> mbed-os/rtos/rtx2/TARGET_CORTEX_M/
CMSIS_5/CMSIS/RTOS2/RTX/Source/ARM/irq_cm0.s -> mbed-os/rtos/rtx2/TARGET_CORTEX_M/TARGET_M0/TOOLCHAIN_ARM/
CMSIS_5/CMSIS/RTOS2/RTX/Source/GCC/irq_cm0.s -> mbed-os/rtos/rtx2/TARGET_CORTEX_M/TARGET_M0/TOOLCHAIN_GCC/
CMSIS_5/CMSIS/RTOS2/RTX/Source/IAR/irq_cm0.s -> mbed-os/rtos/rtx2/TARGET_CORTEX_M/TARGET_M0/TOOLCHAIN_IAR/
CMSIS_5/CMSIS/RTOS2/RTX/Source/ARM/irq_cm0.s -> mbed-os/rtos/rtx2/TARGET_CORTEX_M/TARGET_M0P/TOOLCHAIN_ARM/
CMSIS_5/CMSIS/RTOS2/RTX/Source/GCC/irq_cm0.s -> mbed-os/rtos/rtx2/TARGET_CORTEX_M/TARGET_M0P/TOOLCHAIN_GCC/
CMSIS_5/CMSIS/RTOS2/RTX/Source/IAR/irq_cm0.s -> mbed-os/rtos/rtx2/TARGET_CORTEX_M/TARGET_M0P/TOOLCHAIN_IAR/
CMSIS_5/CMSIS/RTOS2/RTX/Source/ARM/irq_cm3.s -> mbed-os/rtos/rtx2/TARGET_CORTEX_M/TARGET_M3/TOOLCHAIN_ARM/
CMSIS_5/CMSIS/RTOS2/RTX/Source/GCC/irq_cm3.s -> mbed-os/rtos/rtx2/TARGET_CORTEX_M/TARGET_M3/TOOLCHAIN_GCC/
CMSIS_5/CMSIS/RTOS2/RTX/Source/IAR/irq_cm3.s -> mbed-os/rtos/rtx2/TARGET_CORTEX_M/TARGET_M3/TOOLCHAIN_IAR/
CMSIS_5/CMSIS/RTOS2/RTX/Source/ARM/irq_cm4f.s -> mbed-os/rtos/rtx2/TARGET_CORTEX_M/TARGET_RTOS_M4_M7/TOOLCHAIN_ARM/
CMSIS_5/CMSIS/RTOS2/RTX/Source/GCC/irq_cm4f.s -> mbed-os/rtos/rtx2/TARGET_CORTEX_M/TARGET_RTOS_M4_M7/TOOLCHAIN_GCC/
CMSIS_5/CMSIS/RTOS2/RTX/Source/IAR/irq_cm4f.s -> mbed-os/rtos/rtx2/TARGET_CORTEX_M/TARGET_RTOS_M4_M7/TOOLCHAIN_IAR/
pull/4294/head
Bartek Szatkowski 2017-05-15 11:26:55 -05:00 committed by Martin Kojtal
parent fd233778db
commit a9a29a4529
55 changed files with 54144 additions and 0 deletions

View File

@ -0,0 +1,673 @@
/**************************************************************************//**
* @file cmsis_armcc.h
* @brief CMSIS compiler specific macros, functions, instructions
* @version V1.00
* @date 22. Feb 2017
******************************************************************************/
/*
* Copyright (c) 2009-2017 ARM Limited. All rights reserved.
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the License); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an AS IS BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef __CMSIS_ARMCC_H
#define __CMSIS_ARMCC_H
#if defined(__ARMCC_VERSION) && (__ARMCC_VERSION < 400677)
#error "Please use ARM Compiler Toolchain V4.0.677 or later!"
#endif
/* CMSIS compiler control architecture macros */
#if (defined (__TARGET_ARCH_7_A ) && (__TARGET_ARCH_7_A == 1))
#define __ARM_ARCH_7A__ 1
#endif
/* CMSIS compiler specific defines */
#ifndef __ASM
#define __ASM __asm
#endif
#ifndef __INLINE
#define __INLINE __inline
#endif
#ifndef __STATIC_INLINE
#define __STATIC_INLINE static __inline
#endif
#ifndef __STATIC_ASM
#define __STATIC_ASM static __asm
#endif
#ifndef __NO_RETURN
#define __NO_RETURN __declspec(noreturn)
#endif
#ifndef __USED
#define __USED __attribute__((used))
#endif
#ifndef __WEAK
#define __WEAK __attribute__((weak))
#endif
#ifndef __UNALIGNED_UINT32
#define __UNALIGNED_UINT32(x) (*((__packed uint32_t *)(x)))
#endif
#ifndef __ALIGNED
#define __ALIGNED(x) __attribute__((aligned(x)))
#endif
#ifndef __PACKED
#define __PACKED __attribute__((packed))
#endif
/* ########################### Core Function Access ########################### */
/**
\brief Get FPSCR
\return Floating Point Status/Control register value
*/
__STATIC_INLINE uint32_t __get_FPSCR(void)
{
#if ((defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U)) && \
(defined (__FPU_USED ) && (__FPU_USED == 1U)) )
register uint32_t __regfpscr __ASM("fpscr");
return(__regfpscr);
#else
return(0U);
#endif
}
/**
\brief Set FPSCR
\param [in] fpscr Floating Point Status/Control value to set
*/
__STATIC_INLINE void __set_FPSCR(uint32_t fpscr)
{
#if ((defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U)) && \
(defined (__FPU_USED ) && (__FPU_USED == 1U)) )
register uint32_t __regfpscr __ASM("fpscr");
__regfpscr = (fpscr);
#else
(void)fpscr;
#endif
}
/* ########################## Core Instruction Access ######################### */
/**
\brief No Operation
*/
#define __NOP __nop
/**
\brief Wait For Interrupt
*/
#define __WFI __wfi
/**
\brief Wait For Event
*/
#define __WFE __wfe
/**
\brief Send Event
*/
#define __SEV __sev
/**
\brief Instruction Synchronization Barrier
*/
#define __ISB() do {\
__schedule_barrier();\
__isb(0xF);\
__schedule_barrier();\
} while (0U)
/**
\brief Data Synchronization Barrier
*/
#define __DSB() do {\
__schedule_barrier();\
__dsb(0xF);\
__schedule_barrier();\
} while (0U)
/**
\brief Data Memory Barrier
*/
#define __DMB() do {\
__schedule_barrier();\
__dmb(0xF);\
__schedule_barrier();\
} while (0U)
/**
\brief Reverse byte order (32 bit)
\param [in] value Value to reverse
\return Reversed value
*/
#define __REV __rev
/**
\brief Reverse byte order (16 bit)
\param [in] value Value to reverse
\return Reversed value
*/
#ifndef __NO_EMBEDDED_ASM
__attribute__((section(".rev16_text"))) __STATIC_INLINE __ASM uint32_t __REV16(uint32_t value)
{
rev16 r0, r0
bx lr
}
#endif
/**
\brief Reverse byte order in signed short value
\param [in] value Value to reverse
\return Reversed value
*/
#ifndef __NO_EMBEDDED_ASM
__attribute__((section(".revsh_text"))) __STATIC_INLINE __ASM int32_t __REVSH(int32_t value)
{
revsh r0, r0
bx lr
}
#endif
/**
\brief Rotate Right in unsigned value (32 bit)
\param [in] op1 Value to rotate
\param [in] op2 Number of Bits to rotate
\return Rotated value
*/
#define __ROR __ror
/**
\brief Breakpoint
\param [in] value is ignored by the processor.
If required, a debugger can use it to store additional information about the breakpoint.
*/
#define __BKPT(value) __breakpoint(value)
/**
\brief Reverse bit order of value
\param [in] value Value to reverse
\return Reversed value
*/
#define __RBIT __rbit
/**
\brief Count leading zeros
\param [in] value Value to count the leading zeros
\return number of leading zeros in value
*/
#define __CLZ __clz
/** \brief Get CPSR Register
\return CPSR Register value
*/
__STATIC_INLINE uint32_t __get_CPSR(void)
{
register uint32_t __regCPSR __ASM("cpsr");
return(__regCPSR);
}
/** \brief Set CPSR Register
\param [in] cpsr CPSR value to set
*/
__STATIC_INLINE void __set_CPSR(uint32_t cpsr)
{
register uint32_t __regCPSR __ASM("cpsr");
__regCPSR = cpsr;
}
/** \brief Get Mode
\return Processor Mode
*/
__STATIC_INLINE uint32_t __get_mode(void) {
return (__get_CPSR() & 0x1FU);
}
/** \brief Set Mode
\param [in] mode Mode value to set
*/
__STATIC_INLINE __ASM void __set_mode(uint32_t mode) {
MOV r1, lr
MSR CPSR_C, r0
BX r1
}
/** \brief Set Stack Pointer
\param [in] stack Stack Pointer value to set
*/
__STATIC_INLINE __ASM void __set_SP(uint32_t stack)
{
MOV sp, r0
BX lr
}
/** \brief Set Process Stack Pointer
\param [in] topOfProcStack USR/SYS Stack Pointer value to set
*/
__STATIC_INLINE __ASM void __set_PSP(uint32_t topOfProcStack)
{
ARM
PRESERVE8
BIC R0, R0, #7 ;ensure stack is 8-byte aligned
MRS R1, CPSR
CPS #0x1F ;no effect in USR mode
MOV SP, R0
MSR CPSR_c, R1 ;no effect in USR mode
ISB
BX LR
}
/** \brief Set User Mode
*/
__STATIC_INLINE __ASM void __set_CPS_USR(void)
{
ARM
CPS #0x10
BX LR
}
/** \brief Get FPEXC
\return Floating Point Exception Control register value
*/
__STATIC_INLINE uint32_t __get_FPEXC(void)
{
#if (__FPU_PRESENT == 1)
register uint32_t __regfpexc __ASM("fpexc");
return(__regfpexc);
#else
return(0);
#endif
}
/** \brief Set FPEXC
\param [in] fpexc Floating Point Exception Control value to set
*/
__STATIC_INLINE void __set_FPEXC(uint32_t fpexc)
{
#if (__FPU_PRESENT == 1)
register uint32_t __regfpexc __ASM("fpexc");
__regfpexc = (fpexc);
#endif
}
/** \brief Get CPACR
\return Coprocessor Access Control register value
*/
__STATIC_INLINE uint32_t __get_CPACR(void)
{
register uint32_t __regCPACR __ASM("cp15:0:c1:c0:2");
return __regCPACR;
}
/** \brief Set CPACR
\param [in] cpacr Coprocessor Acccess Control value to set
*/
__STATIC_INLINE void __set_CPACR(uint32_t cpacr)
{
register uint32_t __regCPACR __ASM("cp15:0:c1:c0:2");
__regCPACR = cpacr;
}
/** \brief Get CBAR
\return Configuration Base Address register value
*/
__STATIC_INLINE uint32_t __get_CBAR() {
register uint32_t __regCBAR __ASM("cp15:4:c15:c0:0");
return(__regCBAR);
}
/** \brief Get TTBR0
This function returns the value of the Translation Table Base Register 0.
\return Translation Table Base Register 0 value
*/
__STATIC_INLINE uint32_t __get_TTBR0() {
register uint32_t __regTTBR0 __ASM("cp15:0:c2:c0:0");
return(__regTTBR0);
}
/** \brief Set TTBR0
This function assigns the given value to the Translation Table Base Register 0.
\param [in] ttbr0 Translation Table Base Register 0 value to set
*/
__STATIC_INLINE void __set_TTBR0(uint32_t ttbr0) {
register uint32_t __regTTBR0 __ASM("cp15:0:c2:c0:0");
__regTTBR0 = ttbr0;
}
/** \brief Get DACR
This function returns the value of the Domain Access Control Register.
\return Domain Access Control Register value
*/
__STATIC_INLINE uint32_t __get_DACR() {
register uint32_t __regDACR __ASM("cp15:0:c3:c0:0");
return(__regDACR);
}
/** \brief Set DACR
This function assigns the given value to the Domain Access Control Register.
\param [in] dacr Domain Access Control Register value to set
*/
__STATIC_INLINE void __set_DACR(uint32_t dacr) {
register uint32_t __regDACR __ASM("cp15:0:c3:c0:0");
__regDACR = dacr;
}
/** \brief Set SCTLR
This function assigns the given value to the System Control Register.
\param [in] sctlr System Control Register value to set
*/
__STATIC_INLINE void __set_SCTLR(uint32_t sctlr)
{
register uint32_t __regSCTLR __ASM("cp15:0:c1:c0:0");
__regSCTLR = sctlr;
}
/** \brief Get SCTLR
\return System Control Register value
*/
__STATIC_INLINE uint32_t __get_SCTLR() {
register uint32_t __regSCTLR __ASM("cp15:0:c1:c0:0");
return(__regSCTLR);
}
/** \brief Set ACTRL
\param [in] actrl Auxiliary Control Register value to set
*/
__STATIC_INLINE void __set_ACTRL(uint32_t actrl)
{
register uint32_t __regACTRL __ASM("cp15:0:c1:c0:1");
__regACTRL = actrl;
}
/** \brief Get ACTRL
\return Auxiliary Control Register value
*/
__STATIC_INLINE uint32_t __get_ACTRL(void)
{
register uint32_t __regACTRL __ASM("cp15:0:c1:c0:1");
return(__regACTRL);
}
/** \brief Get MPIDR
This function returns the value of the Multiprocessor Affinity Register.
\return Multiprocessor Affinity Register value
*/
__STATIC_INLINE uint32_t __get_MPIDR(void)
{
register uint32_t __regMPIDR __ASM("cp15:0:c0:c0:5");
return(__regMPIDR);
}
/** \brief Get VBAR
This function returns the value of the Vector Base Address Register.
\return Vector Base Address Register
*/
__STATIC_INLINE uint32_t __get_VBAR(void)
{
register uint32_t __regVBAR __ASM("cp15:0:c12:c0:0");
return(__regVBAR);
}
/** \brief Set VBAR
This function assigns the given value to the Vector Base Address Register.
\param [in] vbar Vector Base Address Register value to set
*/
__STATIC_INLINE void __set_VBAR(uint32_t vbar)
{
register uint32_t __regVBAR __ASM("cp15:0:c12:c0:0");
__regVBAR = vbar;
}
/** \brief Set CNTP_TVAL
This function assigns the given value to PL1 Physical Timer Value Register (CNTP_TVAL).
\param [in] value CNTP_TVAL Register value to set
*/
__STATIC_INLINE void __set_CNTP_TVAL(uint32_t value) {
register uint32_t __regCNTP_TVAL __ASM("cp15:0:c14:c2:0");
__regCNTP_TVAL = value;
}
/** \brief Get CNTP_TVAL
This function returns the value of the PL1 Physical Timer Value Register (CNTP_TVAL).
\return CNTP_TVAL Register value
*/
__STATIC_INLINE uint32_t __get_CNTP_TVAL() {
register uint32_t __regCNTP_TVAL __ASM("cp15:0:c14:c2:0");
return(__regCNTP_TVAL);
}
/** \brief Set CNTP_CTL
This function assigns the given value to PL1 Physical Timer Control Register (CNTP_CTL).
\param [in] value CNTP_CTL Register value to set
*/
__STATIC_INLINE void __set_CNTP_CTL(uint32_t value) {
register uint32_t __regCNTP_CTL __ASM("cp15:0:c14:c2:1");
__regCNTP_CTL = value;
}
/** \brief Set TLBIALL
TLB Invalidate All
*/
__STATIC_INLINE void __set_TLBIALL(uint32_t value) {
register uint32_t __TLBIALL __ASM("cp15:0:c8:c7:0");
__TLBIALL = value;
}
/** \brief Set BPIALL.
Branch Predictor Invalidate All
*/
__STATIC_INLINE void __set_BPIALL(uint32_t value) {
register uint32_t __BPIALL __ASM("cp15:0:c7:c5:6");
__BPIALL = value;
}
/** \brief Set ICIALLU
Instruction Cache Invalidate All
*/
__STATIC_INLINE void __set_ICIALLU(uint32_t value) {
register uint32_t __ICIALLU __ASM("cp15:0:c7:c5:0");
__ICIALLU = value;
}
/** \brief Set DCCMVAC
Data cache clean
*/
__STATIC_INLINE void __set_DCCMVAC(uint32_t value) {
register uint32_t __DCCMVAC __ASM("cp15:0:c7:c10:1");
__DCCMVAC = value;
}
/** \brief Set DCIMVAC
Data cache invalidate
*/
__STATIC_INLINE void __set_DCIMVAC(uint32_t value) {
register uint32_t __DCIMVAC __ASM("cp15:0:c7:c6:1");
__DCIMVAC = value;
}
/** \brief Set DCCIMVAC
Data cache clean and invalidate
*/
__STATIC_INLINE void __set_DCCIMVAC(uint32_t value) {
register uint32_t __DCCIMVAC __ASM("cp15:0:c7:c14:1");
__DCCIMVAC = value;
}
/** \brief Clean and Invalidate the entire data or unified cache
Generic mechanism for cleaning/invalidating the entire data or unified cache to the point of coherency
*/
#pragma push
#pragma arm
__STATIC_INLINE __ASM void __L1C_CleanInvalidateCache(uint32_t op) {
ARM
PUSH {R4-R11}
MRC p15, 1, R6, c0, c0, 1 // Read CLIDR
ANDS R3, R6, #0x07000000 // Extract coherency level
MOV R3, R3, LSR #23 // Total cache levels << 1
BEQ Finished // If 0, no need to clean
MOV R10, #0 // R10 holds current cache level << 1
Loop1 ADD R2, R10, R10, LSR #1 // R2 holds cache "Set" position
MOV R1, R6, LSR R2 // Bottom 3 bits are the Cache-type for this level
AND R1, R1, #7 // Isolate those lower 3 bits
CMP R1, #2
BLT Skip // No cache or only instruction cache at this level
MCR p15, 2, R10, c0, c0, 0 // Write the Cache Size selection register
ISB // ISB to sync the change to the CacheSizeID reg
MRC p15, 1, R1, c0, c0, 0 // Reads current Cache Size ID register
AND R2, R1, #7 // Extract the line length field
ADD R2, R2, #4 // Add 4 for the line length offset (log2 16 bytes)
LDR R4, =0x3FF
ANDS R4, R4, R1, LSR #3 // R4 is the max number on the way size (right aligned)
CLZ R5, R4 // R5 is the bit position of the way size increment
LDR R7, =0x7FFF
ANDS R7, R7, R1, LSR #13 // R7 is the max number of the index size (right aligned)
Loop2 MOV R9, R4 // R9 working copy of the max way size (right aligned)
Loop3 ORR R11, R10, R9, LSL R5 // Factor in the Way number and cache number into R11
ORR R11, R11, R7, LSL R2 // Factor in the Set number
CMP R0, #0
BNE Dccsw
MCR p15, 0, R11, c7, c6, 2 // DCISW. Invalidate by Set/Way
B cont
Dccsw CMP R0, #1
BNE Dccisw
MCR p15, 0, R11, c7, c10, 2 // DCCSW. Clean by Set/Way
B cont
Dccisw MCR p15, 0, R11, c7, c14, 2 // DCCISW. Clean and Invalidate by Set/Way
cont SUBS R9, R9, #1 // Decrement the Way number
BGE Loop3
SUBS R7, R7, #1 // Decrement the Set number
BGE Loop2
Skip ADD R10, R10, #2 // Increment the cache number
CMP R3, R10
BGT Loop1
Finished
DSB
POP {R4-R11}
BX lr
}
#pragma pop
/** \brief Enable Floating Point Unit
Critical section, called from undef handler, so systick is disabled
*/
#pragma push
#pragma arm
__STATIC_INLINE __ASM void __FPU_Enable(void) {
ARM
//Permit access to VFP/NEON, registers by modifying CPACR
MRC p15,0,R1,c1,c0,2
ORR R1,R1,#0x00F00000
MCR p15,0,R1,c1,c0,2
//Ensure that subsequent instructions occur in the context of VFP/NEON access permitted
ISB
//Enable VFP/NEON
VMRS R1,FPEXC
ORR R1,R1,#0x40000000
VMSR FPEXC,R1
//Initialise VFP/NEON registers to 0
MOV R2,#0
IF {TARGET_FEATURE_EXTENSION_REGISTER_COUNT} >= 16
//Initialise D16 registers to 0
VMOV D0, R2,R2
VMOV D1, R2,R2
VMOV D2, R2,R2
VMOV D3, R2,R2
VMOV D4, R2,R2
VMOV D5, R2,R2
VMOV D6, R2,R2
VMOV D7, R2,R2
VMOV D8, R2,R2
VMOV D9, R2,R2
VMOV D10,R2,R2
VMOV D11,R2,R2
VMOV D12,R2,R2
VMOV D13,R2,R2
VMOV D14,R2,R2
VMOV D15,R2,R2
ENDIF
IF {TARGET_FEATURE_EXTENSION_REGISTER_COUNT} == 32
//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
ENDIF
//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
}
#pragma pop
#endif /* __CMSIS_ARMCC_H */

View File

@ -0,0 +1,646 @@
/**************************************************************************//**
* @file cmsis_armclang.h
* @brief CMSIS compiler specific macros, functions, instructions
* @version V1.00
* @date 05. Apr 2017
******************************************************************************/
/*
* Copyright (c) 2009-2017 ARM Limited. All rights reserved.
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the License); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an AS IS BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef __CMSIS_ARMCLANG_H
#define __CMSIS_ARMCLANG_H
#ifndef __ARM_COMPAT_H
#include <arm_compat.h> /* Compatibility header for ARM Compiler 5 intrinsics */
#endif
/* CMSIS compiler specific defines */
#ifndef __ASM
#define __ASM __asm
#endif
#ifndef __INLINE
#define __INLINE __inline
#endif
#ifndef __STATIC_INLINE
#define __STATIC_INLINE static __inline
#endif
#ifndef __STATIC_ASM
#define __STATIC_ASM static __asm
#endif
#ifndef __NO_RETURN
#define __NO_RETURN __declspec(noreturn)
#endif
#ifndef __USED
#define __USED __attribute__((used))
#endif
#ifndef __WEAK
#define __WEAK __attribute__((weak))
#endif
#ifndef __UNALIGNED_UINT32
#define __UNALIGNED_UINT32(x) (*((__packed uint32_t *)(x)))
#endif
#ifndef __ALIGNED
#define __ALIGNED(x) __attribute__((aligned(x)))
#endif
#ifndef __PACKED
#define __PACKED __attribute__((packed))
#endif
/* ########################### Core Function Access ########################### */
/**
\brief Get FPSCR
\return Floating Point Status/Control register value
*/
__STATIC_INLINE uint32_t __get_FPSCR(void)
{
#if ((defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U)) && \
(defined (__FPU_USED ) && (__FPU_USED == 1U)) )
uint32_t result;
__ASM volatile("MRS %0, fpscr" : "=r" (result) );
return(result);
#else
return(0U);
#endif
}
/**
\brief Set FPSCR
\param [in] fpscr Floating Point Status/Control value to set
*/
__STATIC_INLINE void __set_FPSCR(uint32_t fpscr)
{
#if ((defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U)) && \
(defined (__FPU_USED ) && (__FPU_USED == 1U)) )
__ASM volatile ("MSR fpscr, %0" : : "r" (fpscr) : "memory");
#else
(void)fpscr;
#endif
}
/* ########################## Core Instruction Access ######################### */
/**
\brief No Operation
*/
#define __NOP __builtin_arm_nop
/**
\brief Wait For Interrupt
*/
#define __WFI __builtin_arm_wfi
/**
\brief Wait For Event
*/
#define __WFE __builtin_arm_wfe
/**
\brief Send Event
*/
#define __SEV __builtin_arm_sev
/**
\brief Instruction Synchronization Barrier
*/
#define __ISB() do {\
__schedule_barrier();\
__builtin_arm_isb(0xF);\
__schedule_barrier();\
} while (0U)
/**
\brief Data Synchronization Barrier
*/
#define __DSB() do {\
__schedule_barrier();\
__builtin_arm_dsb(0xF);\
__schedule_barrier();\
} while (0U)
/**
\brief Data Memory Barrier
*/
#define __DMB() do {\
__schedule_barrier();\
__builtin_arm_dmb(0xF);\
__schedule_barrier();\
} while (0U)
/**
\brief Reverse byte order (32 bit)
\param [in] value Value to reverse
\return Reversed value
*/
#define __REV __builtin_bswap32
/**
\brief Reverse byte order (16 bit)
\param [in] value Value to reverse
\return Reversed value
*/
#ifndef __NO_EMBEDDED_ASM
__attribute__((section(".rev16_text"))) __STATIC_INLINE uint32_t __REV16(uint32_t value)
{
uint32_t result;
__ASM volatile("rev16 %0, %1" : "=r" (result) : "r" (value));
return result;
}
#endif
/**
\brief Reverse byte order in signed short value
\param [in] value Value to reverse
\return Reversed value
*/
#ifndef __NO_EMBEDDED_ASM
__attribute__((section(".revsh_text"))) __STATIC_INLINE int32_t __REVSH(int32_t value)
{
int32_t result;
__ASM volatile("revsh %0, %1" : "=r" (result) : "r" (value));
return result;
}
#endif
/**
\brief Rotate Right in unsigned value (32 bit)
\details Rotate Right (immediate) provides the value of the contents of a register rotated by a variable number of bits.
\param [in] op1 Value to rotate
\param [in] op2 Number of Bits to rotate
\return Rotated value
*/
__attribute__((always_inline)) __STATIC_INLINE uint32_t __ROR(uint32_t op1, uint32_t op2)
{
return (op1 >> op2) | (op1 << (32U - op2));
}
/**
\brief Breakpoint
\param [in] value is ignored by the processor.
If required, a debugger can use it to store additional information about the breakpoint.
*/
#define __BKPT(value) __ASM volatile ("bkpt "#value)
/**
\brief Reverse bit order of value
\param [in] value Value to reverse
\return Reversed value
*/
#define __RBIT __builtin_arm_rbit
/**
\brief Count leading zeros
\param [in] value Value to count the leading zeros
\return number of leading zeros in value
*/
#define __CLZ __builtin_clz
/** \brief Get CPSR Register
\return CPSR Register value
*/
__STATIC_INLINE uint32_t __get_CPSR(void)
{
uint32_t result;
__ASM volatile("MRS %0, cpsr" : "=r" (result) );
return(result);
}
/** \brief Get Mode
\return Processor Mode
*/
__STATIC_INLINE uint32_t __get_mode(void) {
return (__get_CPSR() & 0x1FU);
}
/** \brief Set Mode
\param [in] mode Mode value to set
*/
__STATIC_INLINE void __set_mode(uint32_t mode) {
__ASM volatile("MSR cpsr_c, %0" : : "r" (mode) : "memory");
}
/** \brief Set Stack Pointer
\param [in] stack Stack Pointer value to set
*/
__STATIC_INLINE void __set_SP(uint32_t stack)
{
__ASM volatile("MOV sp, %0" : : "r" (stack) : "memory");
}
/** \brief Set Process Stack Pointer
\param [in] topOfProcStack USR/SYS Stack Pointer value to set
*/
__STATIC_INLINE void __set_PSP(uint32_t topOfProcStack)
{
__ASM volatile(
".preserve8 \n"
"BIC r0, r0, #7 \n" // ensure stack is 8-byte aligned
"MRS r1, cpsr \n"
"CPS #0x1F \n" // no effect in USR mode
"MOV sp, r0 \n"
"MSR cpsr_c, r1 \n" // no effect in USR mode
"ISB"
);
}
/** \brief Set User Mode
*/
__STATIC_INLINE void __set_CPS_USR(void)
{
__ASM volatile("CPS #0x10");
}
/** \brief Get FPEXC
\return Floating Point Exception Control register value
*/
__STATIC_INLINE uint32_t __get_FPEXC(void)
{
#if (__FPU_PRESENT == 1)
uint32_t result;
__ASM volatile("MRS %0, fpexc" : "=r" (result) );
return(result);
#else
return(0);
#endif
}
/** \brief Set FPEXC
\param [in] fpexc Floating Point Exception Control value to set
*/
__STATIC_INLINE void __set_FPEXC(uint32_t fpexc)
{
#if (__FPU_PRESENT == 1)
__ASM volatile ("MSR fpexc, %0" : : "r" (fpexc) : "memory");
#endif
}
/** \brief Get CPACR
\return Coprocessor Access Control register value
*/
__STATIC_INLINE uint32_t __get_CPACR(void)
{
uint32_t result;
__ASM volatile("MRC p15, 0, %0, c1, c0, 2" : "=r"(result));
return result;
}
/** \brief Set CPACR
\param [in] cpacr Coprocessor Acccess Control value to set
*/
__STATIC_INLINE void __set_CPACR(uint32_t cpacr)
{
__ASM volatile("MCR p15, 0, %0, c1, c0, 2" : : "r"(cpacr) : "memory");
}
/** \brief Get CBAR
\return Configuration Base Address register value
*/
__STATIC_INLINE uint32_t __get_CBAR() {
uint32_t result;
__ASM volatile("MRC p15, 4, %0, c15, c0, 0" : "=r"(result));
return result;
}
/** \brief Get TTBR0
This function returns the value of the Translation Table Base Register 0.
\return Translation Table Base Register 0 value
*/
__STATIC_INLINE uint32_t __get_TTBR0() {
uint32_t result;
__ASM volatile("MRC p15, 0, %0, c2, c0, 0" : "=r"(result));
return result;
}
/** \brief Set TTBR0
This function assigns the given value to the Translation Table Base Register 0.
\param [in] ttbr0 Translation Table Base Register 0 value to set
*/
__STATIC_INLINE void __set_TTBR0(uint32_t ttbr0) {
__ASM volatile("MCR p15, 0, %0, c2, c0, 0" : : "r"(ttbr0) : "memory");
}
/** \brief Get DACR
This function returns the value of the Domain Access Control Register.
\return Domain Access Control Register value
*/
__STATIC_INLINE uint32_t __get_DACR() {
uint32_t result;
__ASM volatile("MRC p15, 0, %0, c3, c0, 0" : "=r"(result));
return result;
}
/** \brief Set DACR
This function assigns the given value to the Domain Access Control Register.
\param [in] dacr Domain Access Control Register value to set
*/
__STATIC_INLINE void __set_DACR(uint32_t dacr) {
__ASM volatile("MCR p15, 0, %0, c3, c0, 0" : : "r"(dacr) : "memory");
}
/** \brief Set SCTLR
This function assigns the given value to the System Control Register.
\param [in] sctlr System Control Register value to set
*/
__STATIC_INLINE void __set_SCTLR(uint32_t sctlr)
{
__ASM volatile("MCR p15, 0, %0, c1, c0, 0" : : "r"(sctlr) : "memory");
}
/** \brief Get SCTLR
\return System Control Register value
*/
__STATIC_INLINE uint32_t __get_SCTLR() {
uint32_t result;
__ASM volatile("MRC p15, 0, %0, c1, c0, 0" : "=r"(result));
return result;
}
/** \brief Set ACTRL
\param [in] actrl Auxiliary Control Register value to set
*/
__STATIC_INLINE void __set_ACTRL(uint32_t actrl)
{
__ASM volatile("MCR p15, 0, %0, c1, c0, 1" : : "r"(actrl) : "memory");
}
/** \brief Get ACTRL
\return Auxiliary Control Register value
*/
__STATIC_INLINE uint32_t __get_ACTRL(void)
{
uint32_t result;
__ASM volatile("MRC p15, 0, %0, c1, c0, 1" : "=r"(result));
return result;
}
/** \brief Get MPIDR
This function returns the value of the Multiprocessor Affinity Register.
\return Multiprocessor Affinity Register value
*/
__STATIC_INLINE uint32_t __get_MPIDR(void)
{
uint32_t result;
__ASM volatile("MRC p15, 0, %0, c0, c0, 5" : "=r"(result));
return result;
}
/** \brief Get VBAR
This function returns the value of the Vector Base Address Register.
\return Vector Base Address Register
*/
__STATIC_INLINE uint32_t __get_VBAR(void)
{
uint32_t result;
__ASM volatile("MRC p15, 0, %0, c12, c0, 0" : "=r"(result));
return result;
}
/** \brief Set VBAR
This function assigns the given value to the Vector Base Address Register.
\param [in] vbar Vector Base Address Register value to set
*/
__STATIC_INLINE void __set_VBAR(uint32_t vbar)
{
__ASM volatile("MCR p15, 0, %0, c12, c0, 1" : : "r"(vbar) : "memory");
}
/** \brief Set CNTP_TVAL
This function assigns the given value to PL1 Physical Timer Value Register (CNTP_TVAL).
\param [in] value CNTP_TVAL Register value to set
*/
__STATIC_INLINE void __set_CNTP_TVAL(uint32_t value) {
__ASM volatile("MCR p15, 0, %0, c14, c2, 0" : : "r"(value) : "memory");
}
/** \brief Get CNTP_TVAL
This function returns the value of the PL1 Physical Timer Value Register (CNTP_TVAL).
\return CNTP_TVAL Register value
*/
__STATIC_INLINE uint32_t __get_CNTP_TVAL() {
uint32_t result;
__ASM volatile("MRC p15, 0, %0, c14, c2, 0" : "=r"(result));
return result;
}
/** \brief Set CNTP_CTL
This function assigns the given value to PL1 Physical Timer Control Register (CNTP_CTL).
\param [in] value CNTP_CTL Register value to set
*/
__STATIC_INLINE void __set_CNTP_CTL(uint32_t value) {
__ASM volatile("MCR p15, 0, %0, c14, c2, 1" : : "r"(value) : "memory");
}
/** \brief Set TLBIALL
TLB Invalidate All
*/
__STATIC_INLINE void __set_TLBIALL(uint32_t value) {
__ASM volatile("MCR p15, 0, %0, c8, c7, 0" : : "r"(value) : "memory");
}
/** \brief Set BPIALL.
Branch Predictor Invalidate All
*/
__STATIC_INLINE void __set_BPIALL(uint32_t value) {
__ASM volatile("MCR p15, 0, %0, c7, c5, 6" : : "r"(value) : "memory");
}
/** \brief Set ICIALLU
Instruction Cache Invalidate All
*/
__STATIC_INLINE void __set_ICIALLU(uint32_t value) {
__ASM volatile("MCR p15, 0, %0, c7, c5, 0" : : "r"(value) : "memory");
}
/** \brief Set DCCMVAC
Data cache clean
*/
__STATIC_INLINE void __set_DCCMVAC(uint32_t value) {
__ASM volatile("MCR p15, 0, %0, c7, c10, 1" : : "r"(value) : "memory");
}
/** \brief Set DCIMVAC
Data cache invalidate
*/
__STATIC_INLINE void __set_DCIMVAC(uint32_t value) {
__ASM volatile("MCR p15, 0, %0, c7, c6, 1" : : "r"(value) : "memory");
}
/** \brief Set DCCIMVAC
Data cache clean and invalidate
*/
__STATIC_INLINE void __set_DCCIMVAC(uint32_t value) {
__ASM volatile("MCR p15, 0, %0, c7, c14, 1" : : "r"(value) : "memory");
}
/** \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
*/
__STATIC_INLINE void __L1C_CleanInvalidateCache(uint32_t op) {
__ASM volatile(
" PUSH {R4-R11} \n"
" MRC p15, 1, R6, c0, c0, 1 \n" // Read CLIDR
" ANDS R3, R6, #0x07000000 \n" // Extract coherency level
" MOV R3, R3, LSR #23 \n" // Total cache levels << 1
" BEQ Finished \n" // If 0, no need to clean
" MOV R10, #0 \n" // R10 holds current cache level << 1
"Loop1: ADD R2, R10, R10, LSR #1 \n" // R2 holds cache "Set" position
" MOV R1, R6, LSR R2 \n" // Bottom 3 bits are the Cache-type for this level
" AND R1, R1, #7 \n" // Isolate those lower 3 bits
" CMP R1, #2 \n"
" BLT Skip \n" // No cache or only instruction cache at this level
" MCR p15, 2, R10, c0, c0, 0 \n" // Write the Cache Size selection register
" ISB \n" // ISB to sync the change to the CacheSizeID reg
" MRC p15, 1, R1, c0, c0, 0 \n" // Reads current Cache Size ID register
" AND R2, R1, #7 \n" // Extract the line length field
" ADD R2, R2, #4 \n" // Add 4 for the line length offset (log2 16 bytes)
" LDR R4, =0x3FF \n"
" ANDS R4, R4, R1, LSR #3 \n" // R4 is the max number on the way size (right aligned)
" CLZ R5, R4 \n" // R5 is the bit position of the way size increment
" LDR R7, =0x7FFF \n"
" ANDS R7, R7, R1, LSR #13 \n" // R7 is the max number of the index size (right aligned)
"Loop2: MOV R9, R4 \n" // R9 working copy of the max way size (right aligned)
"Loop3: ORR R11, R10, R9, LSL R5 \n" // Factor in the Way number and cache number into R11
" ORR R11, R11, R7, LSL R2 \n" // Factor in the Set number
" CMP R0, #0 \n"
" BNE Dccsw \n"
" MCR p15, 0, R11, c7, c6, 2 \n" // DCISW. Invalidate by Set/Way
" B cont \n"
"Dccsw: CMP R0, #1 \n"
" BNE Dccisw \n"
" MCR p15, 0, R11, c7, c10, 2 \n" // DCCSW. Clean by Set/Way
" B cont \n"
"Dccisw: MCR p15, 0, R11, c7, c14, 2 \n" // DCCISW. Clean and Invalidate by Set/Way
"cont: SUBS R9, R9, #1 \n" // Decrement the Way number
" BGE Loop3 \n"
" SUBS R7, R7, #1 \n" // Decrement the Set number
" BGE Loop2 \n"
"Skip: ADD R10, R10, #2 \n" // Increment the cache number
" CMP R3, R10 \n"
" BGT Loop1 \n"
"Finished: \n"
" DSB \n"
" POP {R4-R11} "
);
}
/** \brief Enable Floating Point Unit
Critical section, called from undef handler, so systick is disabled
*/
__STATIC_INLINE void __FPU_Enable(void) {
__ASM volatile(
//Permit access to VFP/NEON, registers by modifying CPACR
" MRC p15,0,R1,c1,c0,2 \n"
" ORR R1,R1,#0x00F00000 \n"
" MCR p15,0,R1,c1,c0,2 \n"
//Ensure that subsequent instructions occur in the context of VFP/NEON access permitted
" ISB \n"
//Enable VFP/NEON
" VMRS R1,FPEXC \n"
" ORR R1,R1,#0x40000000 \n"
" VMSR FPEXC,R1 \n"
//Initialise VFP/NEON registers to 0
" MOV R2,#0 \n"
#if 0 // TODO: Initialize FPU registers according to available register count
".if {TARGET_FEATURE_EXTENSION_REGISTER_COUNT} >= 16 \n"
//Initialise D16 registers to 0
" VMOV D0, R2,R2 \n"
" VMOV D1, R2,R2 \n"
" VMOV D2, R2,R2 \n"
" VMOV D3, R2,R2 \n"
" VMOV D4, R2,R2 \n"
" VMOV D5, R2,R2 \n"
" VMOV D6, R2,R2 \n"
" VMOV D7, R2,R2 \n"
" VMOV D8, R2,R2 \n"
" VMOV D9, R2,R2 \n"
" VMOV D10,R2,R2 \n"
" VMOV D11,R2,R2 \n"
" VMOV D12,R2,R2 \n"
" VMOV D13,R2,R2 \n"
" VMOV D14,R2,R2 \n"
" VMOV D15,R2,R2 \n"
".endif \n"
".if {TARGET_FEATURE_EXTENSION_REGISTER_COUNT} == 32 \n"
//Initialise D32 registers to 0
" VMOV D16,R2,R2 \n"
" VMOV D17,R2,R2 \n"
" VMOV D18,R2,R2 \n"
" VMOV D19,R2,R2 \n"
" VMOV D20,R2,R2 \n"
" VMOV D21,R2,R2 \n"
" VMOV D22,R2,R2 \n"
" VMOV D23,R2,R2 \n"
" VMOV D24,R2,R2 \n"
" VMOV D25,R2,R2 \n"
" VMOV D26,R2,R2 \n"
" VMOV D27,R2,R2 \n"
" VMOV D28,R2,R2 \n"
" VMOV D29,R2,R2 \n"
" VMOV D30,R2,R2 \n"
" VMOV D31,R2,R2 \n"
".endif \n"
#endif
//Initialise FPSCR to a known state
" VMRS R2,FPSCR \n"
" LDR R3,=0x00086060 \n" //Mask off all bits that do not have to be preserved. Non-preserved bits can/should be zero.
" AND R2,R2,R3 \n"
" VMSR FPSCR,R2 "
);
}
#endif /* __CMSIS_ARMCC_H */

View File

@ -0,0 +1,211 @@
/**************************************************************************//**
* @file cmsis_compiler.h
* @brief CMSIS compiler specific macros, functions, instructions
* @version V1.00
* @date 22. Feb 2017
******************************************************************************/
/*
* Copyright (c) 2009-2017 ARM Limited. All rights reserved.
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the License); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an AS IS BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef __CMSIS_COMPILER_H
#define __CMSIS_COMPILER_H
#include <stdint.h>
/*
* ARM Compiler 4/5
*/
#if defined ( __CC_ARM )
#include "cmsis_armcc.h"
/*
* ARM Compiler 6 (armclang)
*/
#elif defined (__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050)
#include "cmsis_armclang.h"
/*
* GNU Compiler
*/
#elif defined ( __GNUC__ )
#include "cmsis_gcc.h"
/*
* IAR Compiler
*/
#elif defined ( __ICCARM__ )
#ifndef __ASM
#define __ASM __asm
#endif
#ifndef __INLINE
#define __INLINE inline
#endif
#ifndef __STATIC_INLINE
#define __STATIC_INLINE static inline
#endif
#include <cmsis_iar.h>
#ifndef __NO_RETURN
#define __NO_RETURN __noreturn
#endif
#ifndef __USED
#define __USED __root
#endif
#ifndef __WEAK
#define __WEAK __weak
#endif
#ifndef __UNALIGNED_UINT32
__packed struct T_UINT32 { uint32_t v; };
#define __UNALIGNED_UINT32(x) (((struct T_UINT32 *)(x))->v)
#endif
#ifndef __ALIGNED
#warning No compiler specific solution for __ALIGNED. __ALIGNED is ignored.
#define __ALIGNED(x)
#endif
#ifndef __PACKED
#define __PACKED __packed
#endif
/*
* TI ARM Compiler
*/
#elif defined ( __TI_ARM__ )
#include <cmsis_ccs.h>
#ifndef __ASM
#define __ASM __asm
#endif
#ifndef __INLINE
#define __INLINE inline
#endif
#ifndef __STATIC_INLINE
#define __STATIC_INLINE static inline
#endif
#ifndef __NO_RETURN
#define __NO_RETURN __attribute__((noreturn))
#endif
#ifndef __USED
#define __USED __attribute__((used))
#endif
#ifndef __WEAK
#define __WEAK __attribute__((weak))
#endif
#ifndef __UNALIGNED_UINT32
struct __attribute__((packed)) T_UINT32 { uint32_t v; };
#define __UNALIGNED_UINT32(x) (((struct T_UINT32 *)(x))->v)
#endif
#ifndef __ALIGNED
#define __ALIGNED(x) __attribute__((aligned(x)))
#endif
#ifndef __PACKED
#define __PACKED __attribute__((packed))
#endif
/*
* TASKING Compiler
*/
#elif defined ( __TASKING__ )
/*
* The CMSIS functions have been implemented as intrinsics in the compiler.
* Please use "carm -?i" to get an up to date list of all intrinsics,
* Including the CMSIS ones.
*/
#ifndef __ASM
#define __ASM __asm
#endif
#ifndef __INLINE
#define __INLINE inline
#endif
#ifndef __STATIC_INLINE
#define __STATIC_INLINE static inline
#endif
#ifndef __NO_RETURN
#define __NO_RETURN __attribute__((noreturn))
#endif
#ifndef __USED
#define __USED __attribute__((used))
#endif
#ifndef __WEAK
#define __WEAK __attribute__((weak))
#endif
#ifndef __UNALIGNED_UINT32
struct __packed__ T_UINT32 { uint32_t v; };
#define __UNALIGNED_UINT32(x) (((struct T_UINT32 *)(x))->v)
#endif
#ifndef __ALIGNED
#define __ALIGNED(x) __align(x)
#endif
#ifndef __PACKED
#define __PACKED __packed__
#endif
/*
* COSMIC Compiler
*/
#elif defined ( __CSMC__ )
#include <cmsis_csm.h>
#ifndef __ASM
#define __ASM _asm
#endif
#ifndef __INLINE
#define __INLINE inline
#endif
#ifndef __STATIC_INLINE
#define __STATIC_INLINE static inline
#endif
#ifndef __NO_RETURN
// NO RETURN is automatically detected hence no warning here
#define __NO_RETURN
#endif
#ifndef __USED
#warning No compiler specific solution for __USED. __USED is ignored.
#define __USED
#endif
#ifndef __WEAK
#define __WEAK __weak
#endif
#ifndef __UNALIGNED_UINT32
@packed struct T_UINT32 { uint32_t v; };
#define __UNALIGNED_UINT32(x) (((struct T_UINT32 *)(x))->v)
#endif
#ifndef __ALIGNED
#warning No compiler specific solution for __ALIGNED. __ALIGNED is ignored.
#define __ALIGNED(x)
#endif
#ifndef __PACKED
#define __PACKED @packed
#endif
#else
#error Unknown compiler.
#endif
#endif /* __CMSIS_COMPILER_H */

View File

@ -0,0 +1,809 @@
/**************************************************************************//**
* @file cmsis_armcc.h
* @brief CMSIS compiler ARMCC (ARM compiler V5) header file
* @version V5.0.2
* @date 13. February 2017
******************************************************************************/
/*
* Copyright (c) 2009-2017 ARM Limited. All rights reserved.
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the License); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an AS IS BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef __CMSIS_ARMCC_H
#define __CMSIS_ARMCC_H
#if defined(__ARMCC_VERSION) && (__ARMCC_VERSION < 400677)
#error "Please use ARM Compiler Toolchain V4.0.677 or later!"
#endif
/* CMSIS compiler control architecture macros */
#if ((defined (__TARGET_ARCH_6_M ) && (__TARGET_ARCH_6_M == 1)) || \
(defined (__TARGET_ARCH_6S_M ) && (__TARGET_ARCH_6S_M == 1)) )
#define __ARM_ARCH_6M__ 1
#endif
#if (defined (__TARGET_ARCH_7_M ) && (__TARGET_ARCH_7_M == 1))
#define __ARM_ARCH_7M__ 1
#endif
#if (defined (__TARGET_ARCH_7E_M) && (__TARGET_ARCH_7E_M == 1))
#define __ARM_ARCH_7EM__ 1
#endif
/* __ARM_ARCH_8M_BASE__ not applicable */
/* __ARM_ARCH_8M_MAIN__ not applicable */
/* CMSIS compiler specific defines */
#ifndef __ASM
#define __ASM __asm
#endif
#ifndef __INLINE
#define __INLINE __inline
#endif
#ifndef __STATIC_INLINE
#define __STATIC_INLINE static __inline
#endif
#ifndef __NO_RETURN
#define __NO_RETURN __declspec(noreturn)
#endif
#ifndef __USED
#define __USED __attribute__((used))
#endif
#ifndef __WEAK
#define __WEAK __attribute__((weak))
#endif
#ifndef __PACKED
#define __PACKED __attribute__((packed))
#endif
#ifndef __PACKED_STRUCT
#define __PACKED_STRUCT __packed struct
#endif
#ifndef __UNALIGNED_UINT32 /* deprecated */
#define __UNALIGNED_UINT32(x) (*((__packed uint32_t *)(x)))
#endif
#ifndef __UNALIGNED_UINT16_WRITE
#define __UNALIGNED_UINT16_WRITE(addr, val) ((*((__packed uint16_t *)(addr))) = (val))
#endif
#ifndef __UNALIGNED_UINT16_READ
#define __UNALIGNED_UINT16_READ(addr) (*((const __packed uint16_t *)(addr)))
#endif
#ifndef __UNALIGNED_UINT32_WRITE
#define __UNALIGNED_UINT32_WRITE(addr, val) ((*((__packed uint32_t *)(addr))) = (val))
#endif
#ifndef __UNALIGNED_UINT32_READ
#define __UNALIGNED_UINT32_READ(addr) (*((const __packed uint32_t *)(addr)))
#endif
#ifndef __ALIGNED
#define __ALIGNED(x) __attribute__((aligned(x)))
#endif
/* ########################### Core Function Access ########################### */
/** \ingroup CMSIS_Core_FunctionInterface
\defgroup CMSIS_Core_RegAccFunctions CMSIS Core Register Access Functions
@{
*/
/**
\brief Enable IRQ Interrupts
\details Enables IRQ interrupts by clearing the I-bit in the CPSR.
Can only be executed in Privileged modes.
*/
/* intrinsic void __enable_irq(); */
/**
\brief Disable IRQ Interrupts
\details Disables IRQ interrupts by setting the I-bit in the CPSR.
Can only be executed in Privileged modes.
*/
/* intrinsic void __disable_irq(); */
/**
\brief Get Control Register
\details Returns the content of the Control Register.
\return Control Register value
*/
__STATIC_INLINE uint32_t __get_CONTROL(void)
{
register uint32_t __regControl __ASM("control");
return(__regControl);
}
/**
\brief Set Control Register
\details Writes the given value to the Control Register.
\param [in] control Control Register value to set
*/
__STATIC_INLINE void __set_CONTROL(uint32_t control)
{
register uint32_t __regControl __ASM("control");
__regControl = control;
}
/**
\brief Get IPSR Register
\details Returns the content of the IPSR Register.
\return IPSR Register value
*/
__STATIC_INLINE uint32_t __get_IPSR(void)
{
register uint32_t __regIPSR __ASM("ipsr");
return(__regIPSR);
}
/**
\brief Get APSR Register
\details Returns the content of the APSR Register.
\return APSR Register value
*/
__STATIC_INLINE uint32_t __get_APSR(void)
{
register uint32_t __regAPSR __ASM("apsr");
return(__regAPSR);
}
/**
\brief Get xPSR Register
\details Returns the content of the xPSR Register.
\return xPSR Register value
*/
__STATIC_INLINE uint32_t __get_xPSR(void)
{
register uint32_t __regXPSR __ASM("xpsr");
return(__regXPSR);
}
/**
\brief Get Process Stack Pointer
\details Returns the current value of the Process Stack Pointer (PSP).
\return PSP Register value
*/
__STATIC_INLINE uint32_t __get_PSP(void)
{
register uint32_t __regProcessStackPointer __ASM("psp");
return(__regProcessStackPointer);
}
/**
\brief Set Process Stack Pointer
\details Assigns the given value to the Process Stack Pointer (PSP).
\param [in] topOfProcStack Process Stack Pointer value to set
*/
__STATIC_INLINE void __set_PSP(uint32_t topOfProcStack)
{
register uint32_t __regProcessStackPointer __ASM("psp");
__regProcessStackPointer = topOfProcStack;
}
/**
\brief Get Main Stack Pointer
\details Returns the current value of the Main Stack Pointer (MSP).
\return MSP Register value
*/
__STATIC_INLINE uint32_t __get_MSP(void)
{
register uint32_t __regMainStackPointer __ASM("msp");
return(__regMainStackPointer);
}
/**
\brief Set Main Stack Pointer
\details Assigns the given value to the Main Stack Pointer (MSP).
\param [in] topOfMainStack Main Stack Pointer value to set
*/
__STATIC_INLINE void __set_MSP(uint32_t topOfMainStack)
{
register uint32_t __regMainStackPointer __ASM("msp");
__regMainStackPointer = topOfMainStack;
}
/**
\brief Get Priority Mask
\details Returns the current state of the priority mask bit from the Priority Mask Register.
\return Priority Mask value
*/
__STATIC_INLINE uint32_t __get_PRIMASK(void)
{
register uint32_t __regPriMask __ASM("primask");
return(__regPriMask);
}
/**
\brief Set Priority Mask
\details Assigns the given value to the Priority Mask Register.
\param [in] priMask Priority Mask
*/
__STATIC_INLINE void __set_PRIMASK(uint32_t priMask)
{
register uint32_t __regPriMask __ASM("primask");
__regPriMask = (priMask);
}
#if ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \
(defined (__ARM_ARCH_7EM__) && (__ARM_ARCH_7EM__ == 1)) )
/**
\brief Enable FIQ
\details Enables FIQ interrupts by clearing the F-bit in the CPSR.
Can only be executed in Privileged modes.
*/
#define __enable_fault_irq __enable_fiq
/**
\brief Disable FIQ
\details Disables FIQ interrupts by setting the F-bit in the CPSR.
Can only be executed in Privileged modes.
*/
#define __disable_fault_irq __disable_fiq
/**
\brief Get Base Priority
\details Returns the current value of the Base Priority register.
\return Base Priority register value
*/
__STATIC_INLINE uint32_t __get_BASEPRI(void)
{
register uint32_t __regBasePri __ASM("basepri");
return(__regBasePri);
}
/**
\brief Set Base Priority
\details Assigns the given value to the Base Priority register.
\param [in] basePri Base Priority value to set
*/
__STATIC_INLINE void __set_BASEPRI(uint32_t basePri)
{
register uint32_t __regBasePri __ASM("basepri");
__regBasePri = (basePri & 0xFFU);
}
/**
\brief Set Base Priority with condition
\details Assigns the given value to the Base Priority register only if BASEPRI masking is disabled,
or the new value increases the BASEPRI priority level.
\param [in] basePri Base Priority value to set
*/
__STATIC_INLINE void __set_BASEPRI_MAX(uint32_t basePri)
{
register uint32_t __regBasePriMax __ASM("basepri_max");
__regBasePriMax = (basePri & 0xFFU);
}
/**
\brief Get Fault Mask
\details Returns the current value of the Fault Mask register.
\return Fault Mask register value
*/
__STATIC_INLINE uint32_t __get_FAULTMASK(void)
{
register uint32_t __regFaultMask __ASM("faultmask");
return(__regFaultMask);
}
/**
\brief Set Fault Mask
\details Assigns the given value to the Fault Mask register.
\param [in] faultMask Fault Mask value to set
*/
__STATIC_INLINE void __set_FAULTMASK(uint32_t faultMask)
{
register uint32_t __regFaultMask __ASM("faultmask");
__regFaultMask = (faultMask & (uint32_t)1U);
}
#endif /* ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \
(defined (__ARM_ARCH_7EM__) && (__ARM_ARCH_7EM__ == 1)) ) */
#if ((defined (__ARM_ARCH_7EM__) && (__ARM_ARCH_7EM__ == 1)) )
/**
\brief Get FPSCR
\details Returns the current value of the Floating Point Status/Control register.
\return Floating Point Status/Control register value
*/
__STATIC_INLINE uint32_t __get_FPSCR(void)
{
#if ((defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U)) && \
(defined (__FPU_USED ) && (__FPU_USED == 1U)) )
register uint32_t __regfpscr __ASM("fpscr");
return(__regfpscr);
#else
return(0U);
#endif
}
/**
\brief Set FPSCR
\details Assigns the given value to the Floating Point Status/Control register.
\param [in] fpscr Floating Point Status/Control value to set
*/
__STATIC_INLINE void __set_FPSCR(uint32_t fpscr)
{
#if ((defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U)) && \
(defined (__FPU_USED ) && (__FPU_USED == 1U)) )
register uint32_t __regfpscr __ASM("fpscr");
__regfpscr = (fpscr);
#else
(void)fpscr;
#endif
}
#endif /* ((defined (__ARM_ARCH_7EM__) && (__ARM_ARCH_7EM__ == 1)) ) */
/*@} end of CMSIS_Core_RegAccFunctions */
/* ########################## Core Instruction Access ######################### */
/** \defgroup CMSIS_Core_InstructionInterface CMSIS Core Instruction Interface
Access to dedicated instructions
@{
*/
/**
\brief No Operation
\details No Operation does nothing. This instruction can be used for code alignment purposes.
*/
#define __NOP __nop
/**
\brief Wait For Interrupt
\details Wait For Interrupt is a hint instruction that suspends execution until one of a number of events occurs.
*/
#define __WFI __wfi
/**
\brief Wait For Event
\details Wait For Event is a hint instruction that permits the processor to enter
a low-power state until one of a number of events occurs.
*/
#define __WFE __wfe
/**
\brief Send Event
\details Send Event is a hint instruction. It causes an event to be signaled to the CPU.
*/
#define __SEV __sev
/**
\brief Instruction Synchronization Barrier
\details Instruction Synchronization Barrier flushes the pipeline in the processor,
so that all instructions following the ISB are fetched from cache or memory,
after the instruction has been completed.
*/
#define __ISB() do {\
__schedule_barrier();\
__isb(0xF);\
__schedule_barrier();\
} while (0U)
/**
\brief Data Synchronization Barrier
\details Acts as a special kind of Data Memory Barrier.
It completes when all explicit memory accesses before this instruction complete.
*/
#define __DSB() do {\
__schedule_barrier();\
__dsb(0xF);\
__schedule_barrier();\
} while (0U)
/**
\brief Data Memory Barrier
\details Ensures the apparent order of the explicit memory operations before
and after the instruction, without ensuring their completion.
*/
#define __DMB() do {\
__schedule_barrier();\
__dmb(0xF);\
__schedule_barrier();\
} while (0U)
/**
\brief Reverse byte order (32 bit)
\details Reverses the byte order in integer value.
\param [in] value Value to reverse
\return Reversed value
*/
#define __REV __rev
/**
\brief Reverse byte order (16 bit)
\details Reverses the byte order in two unsigned short values.
\param [in] value Value to reverse
\return Reversed value
*/
#ifndef __NO_EMBEDDED_ASM
__attribute__((section(".rev16_text"))) __STATIC_INLINE __ASM uint32_t __REV16(uint32_t value)
{
rev16 r0, r0
bx lr
}
#endif
/**
\brief Reverse byte order in signed short value
\details Reverses the byte order in a signed short value with sign extension to integer.
\param [in] value Value to reverse
\return Reversed value
*/
#ifndef __NO_EMBEDDED_ASM
__attribute__((section(".revsh_text"))) __STATIC_INLINE __ASM int32_t __REVSH(int32_t value)
{
revsh r0, r0
bx lr
}
#endif
/**
\brief Rotate Right in unsigned value (32 bit)
\details Rotate Right (immediate) provides the value of the contents of a register rotated by a variable number of bits.
\param [in] op1 Value to rotate
\param [in] op2 Number of Bits to rotate
\return Rotated value
*/
#define __ROR __ror
/**
\brief Breakpoint
\details Causes the processor to enter Debug state.
Debug tools can use this to investigate system state when the instruction at a particular address is reached.
\param [in] value is ignored by the processor.
If required, a debugger can use it to store additional information about the breakpoint.
*/
#define __BKPT(value) __breakpoint(value)
/**
\brief Reverse bit order of value
\details Reverses the bit order of the given value.
\param [in] value Value to reverse
\return Reversed value
*/
#if ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \
(defined (__ARM_ARCH_7EM__) && (__ARM_ARCH_7EM__ == 1)) )
#define __RBIT __rbit
#else
__attribute__((always_inline)) __STATIC_INLINE uint32_t __RBIT(uint32_t value)
{
uint32_t result;
int32_t s = (4 /*sizeof(v)*/ * 8) - 1; /* extra shift needed at end */
result = value; /* r will be reversed bits of v; first get LSB of v */
for (value >>= 1U; value; value >>= 1U)
{
result <<= 1U;
result |= value & 1U;
s--;
}
result <<= s; /* shift when v's highest bits are zero */
return(result);
}
#endif
/**
\brief Count leading zeros
\details Counts the number of leading zeros of a data value.
\param [in] value Value to count the leading zeros
\return number of leading zeros in value
*/
#define __CLZ __clz
#if ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \
(defined (__ARM_ARCH_7EM__) && (__ARM_ARCH_7EM__ == 1)) )
/**
\brief LDR Exclusive (8 bit)
\details Executes a exclusive LDR instruction for 8 bit value.
\param [in] ptr Pointer to data
\return value of type uint8_t at (*ptr)
*/
#if defined(__ARMCC_VERSION) && (__ARMCC_VERSION < 5060020)
#define __LDREXB(ptr) ((uint8_t ) __ldrex(ptr))
#else
#define __LDREXB(ptr) _Pragma("push") _Pragma("diag_suppress 3731") ((uint8_t ) __ldrex(ptr)) _Pragma("pop")
#endif
/**
\brief LDR Exclusive (16 bit)
\details Executes a exclusive LDR instruction for 16 bit values.
\param [in] ptr Pointer to data
\return value of type uint16_t at (*ptr)
*/
#if defined(__ARMCC_VERSION) && (__ARMCC_VERSION < 5060020)
#define __LDREXH(ptr) ((uint16_t) __ldrex(ptr))
#else
#define __LDREXH(ptr) _Pragma("push") _Pragma("diag_suppress 3731") ((uint16_t) __ldrex(ptr)) _Pragma("pop")
#endif
/**
\brief LDR Exclusive (32 bit)
\details Executes a exclusive LDR instruction for 32 bit values.
\param [in] ptr Pointer to data
\return value of type uint32_t at (*ptr)
*/
#if defined(__ARMCC_VERSION) && (__ARMCC_VERSION < 5060020)
#define __LDREXW(ptr) ((uint32_t ) __ldrex(ptr))
#else
#define __LDREXW(ptr) _Pragma("push") _Pragma("diag_suppress 3731") ((uint32_t ) __ldrex(ptr)) _Pragma("pop")
#endif
/**
\brief STR Exclusive (8 bit)
\details Executes a exclusive STR instruction for 8 bit values.
\param [in] value Value to store
\param [in] ptr Pointer to location
\return 0 Function succeeded
\return 1 Function failed
*/
#if defined(__ARMCC_VERSION) && (__ARMCC_VERSION < 5060020)
#define __STREXB(value, ptr) __strex(value, ptr)
#else
#define __STREXB(value, ptr) _Pragma("push") _Pragma("diag_suppress 3731") __strex(value, ptr) _Pragma("pop")
#endif
/**
\brief STR Exclusive (16 bit)
\details Executes a exclusive STR instruction for 16 bit values.
\param [in] value Value to store
\param [in] ptr Pointer to location
\return 0 Function succeeded
\return 1 Function failed
*/
#if defined(__ARMCC_VERSION) && (__ARMCC_VERSION < 5060020)
#define __STREXH(value, ptr) __strex(value, ptr)
#else
#define __STREXH(value, ptr) _Pragma("push") _Pragma("diag_suppress 3731") __strex(value, ptr) _Pragma("pop")
#endif
/**
\brief STR Exclusive (32 bit)
\details Executes a exclusive STR instruction for 32 bit values.
\param [in] value Value to store
\param [in] ptr Pointer to location
\return 0 Function succeeded
\return 1 Function failed
*/
#if defined(__ARMCC_VERSION) && (__ARMCC_VERSION < 5060020)
#define __STREXW(value, ptr) __strex(value, ptr)
#else
#define __STREXW(value, ptr) _Pragma("push") _Pragma("diag_suppress 3731") __strex(value, ptr) _Pragma("pop")
#endif
/**
\brief Remove the exclusive lock
\details Removes the exclusive lock which is created by LDREX.
*/
#define __CLREX __clrex
/**
\brief Signed Saturate
\details Saturates a signed value.
\param [in] value Value to be saturated
\param [in] sat Bit position to saturate to (1..32)
\return Saturated value
*/
#define __SSAT __ssat
/**
\brief Unsigned Saturate
\details Saturates an unsigned value.
\param [in] value Value to be saturated
\param [in] sat Bit position to saturate to (0..31)
\return Saturated value
*/
#define __USAT __usat
/**
\brief Rotate Right with Extend (32 bit)
\details Moves each bit of a bitstring right by one bit.
The carry input is shifted in at the left end of the bitstring.
\param [in] value Value to rotate
\return Rotated value
*/
#ifndef __NO_EMBEDDED_ASM
__attribute__((section(".rrx_text"))) __STATIC_INLINE __ASM uint32_t __RRX(uint32_t value)
{
rrx r0, r0
bx lr
}
#endif
/**
\brief LDRT Unprivileged (8 bit)
\details Executes a Unprivileged LDRT instruction for 8 bit value.
\param [in] ptr Pointer to data
\return value of type uint8_t at (*ptr)
*/
#define __LDRBT(ptr) ((uint8_t ) __ldrt(ptr))
/**
\brief LDRT Unprivileged (16 bit)
\details Executes a Unprivileged LDRT instruction for 16 bit values.
\param [in] ptr Pointer to data
\return value of type uint16_t at (*ptr)
*/
#define __LDRHT(ptr) ((uint16_t) __ldrt(ptr))
/**
\brief LDRT Unprivileged (32 bit)
\details Executes a Unprivileged LDRT instruction for 32 bit values.
\param [in] ptr Pointer to data
\return value of type uint32_t at (*ptr)
*/
#define __LDRT(ptr) ((uint32_t ) __ldrt(ptr))
/**
\brief STRT Unprivileged (8 bit)
\details Executes a Unprivileged STRT instruction for 8 bit values.
\param [in] value Value to store
\param [in] ptr Pointer to location
*/
#define __STRBT(value, ptr) __strt(value, ptr)
/**
\brief STRT Unprivileged (16 bit)
\details Executes a Unprivileged STRT instruction for 16 bit values.
\param [in] value Value to store
\param [in] ptr Pointer to location
*/
#define __STRHT(value, ptr) __strt(value, ptr)
/**
\brief STRT Unprivileged (32 bit)
\details Executes a Unprivileged STRT instruction for 32 bit values.
\param [in] value Value to store
\param [in] ptr Pointer to location
*/
#define __STRT(value, ptr) __strt(value, ptr)
#endif /* ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \
(defined (__ARM_ARCH_7EM__) && (__ARM_ARCH_7EM__ == 1)) ) */
/*@}*/ /* end of group CMSIS_Core_InstructionInterface */
/* ################### Compiler specific Intrinsics ########################### */
/** \defgroup CMSIS_SIMD_intrinsics CMSIS SIMD Intrinsics
Access to dedicated SIMD instructions
@{
*/
#if ((defined (__ARM_ARCH_7EM__) && (__ARM_ARCH_7EM__ == 1)) )
#define __SADD8 __sadd8
#define __QADD8 __qadd8
#define __SHADD8 __shadd8
#define __UADD8 __uadd8
#define __UQADD8 __uqadd8
#define __UHADD8 __uhadd8
#define __SSUB8 __ssub8
#define __QSUB8 __qsub8
#define __SHSUB8 __shsub8
#define __USUB8 __usub8
#define __UQSUB8 __uqsub8
#define __UHSUB8 __uhsub8
#define __SADD16 __sadd16
#define __QADD16 __qadd16
#define __SHADD16 __shadd16
#define __UADD16 __uadd16
#define __UQADD16 __uqadd16
#define __UHADD16 __uhadd16
#define __SSUB16 __ssub16
#define __QSUB16 __qsub16
#define __SHSUB16 __shsub16
#define __USUB16 __usub16
#define __UQSUB16 __uqsub16
#define __UHSUB16 __uhsub16
#define __SASX __sasx
#define __QASX __qasx
#define __SHASX __shasx
#define __UASX __uasx
#define __UQASX __uqasx
#define __UHASX __uhasx
#define __SSAX __ssax
#define __QSAX __qsax
#define __SHSAX __shsax
#define __USAX __usax
#define __UQSAX __uqsax
#define __UHSAX __uhsax
#define __USAD8 __usad8
#define __USADA8 __usada8
#define __SSAT16 __ssat16
#define __USAT16 __usat16
#define __UXTB16 __uxtb16
#define __UXTAB16 __uxtab16
#define __SXTB16 __sxtb16
#define __SXTAB16 __sxtab16
#define __SMUAD __smuad
#define __SMUADX __smuadx
#define __SMLAD __smlad
#define __SMLADX __smladx
#define __SMLALD __smlald
#define __SMLALDX __smlaldx
#define __SMUSD __smusd
#define __SMUSDX __smusdx
#define __SMLSD __smlsd
#define __SMLSDX __smlsdx
#define __SMLSLD __smlsld
#define __SMLSLDX __smlsldx
#define __SEL __sel
#define __QADD __qadd
#define __QSUB __qsub
#define __PKHBT(ARG1,ARG2,ARG3) ( ((((uint32_t)(ARG1)) ) & 0x0000FFFFUL) | \
((((uint32_t)(ARG2)) << (ARG3)) & 0xFFFF0000UL) )
#define __PKHTB(ARG1,ARG2,ARG3) ( ((((uint32_t)(ARG1)) ) & 0xFFFF0000UL) | \
((((uint32_t)(ARG2)) >> (ARG3)) & 0x0000FFFFUL) )
#define __SMMLA(ARG1,ARG2,ARG3) ( (int32_t)((((int64_t)(ARG1) * (ARG2)) + \
((int64_t)(ARG3) << 32U) ) >> 32U))
#endif /* ((defined (__ARM_ARCH_7EM__) && (__ARM_ARCH_7EM__ == 1)) ) */
/*@} end of group CMSIS_SIMD_intrinsics */
#endif /* __CMSIS_ARMCC_H */

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,287 @@
/**************************************************************************//**
* @file cmsis_compiler.h
* @brief CMSIS compiler generic header file
* @version V5.0.2
* @date 13. February 2017
******************************************************************************/
/*
* Copyright (c) 2009-2017 ARM Limited. All rights reserved.
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the License); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an AS IS BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef __CMSIS_COMPILER_H
#define __CMSIS_COMPILER_H
#include <stdint.h>
/*
* ARM Compiler 4/5
*/
#if defined ( __CC_ARM )
#include "cmsis_armcc.h"
/*
* ARM Compiler 6 (armclang)
*/
#elif defined (__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050)
#include "cmsis_armclang.h"
/*
* GNU Compiler
*/
#elif defined ( __GNUC__ )
#include "cmsis_gcc.h"
/*
* IAR Compiler
*/
#elif defined ( __ICCARM__ )
#ifndef __ASM
#define __ASM __asm
#endif
#ifndef __INLINE
#define __INLINE inline
#endif
#ifndef __STATIC_INLINE
#define __STATIC_INLINE static inline
#endif
#include <cmsis_iar.h>
#ifndef __NO_RETURN
#define __NO_RETURN __noreturn
#endif
#ifndef __USED
#define __USED __root
#endif
#ifndef __WEAK
#define __WEAK __weak
#endif
#ifndef __PACKED
#define __PACKED __packed
#endif
#ifndef __PACKED_STRUCT
#define __PACKED_STRUCT __packed struct
#endif
#ifndef __UNALIGNED_UINT32 /* deprecated */
__packed struct T_UINT32 { uint32_t v; };
#define __UNALIGNED_UINT32(x) (((struct T_UINT32 *)(x))->v)
#endif
#ifndef __UNALIGNED_UINT16_WRITE
__PACKED_STRUCT T_UINT16_WRITE { uint16_t v; };
#define __UNALIGNED_UINT16_WRITE(addr, val) (void)((((struct T_UINT16_WRITE *)(void *)(addr))->v) = (val))
#endif
#ifndef __UNALIGNED_UINT16_READ
__PACKED_STRUCT T_UINT16_READ { uint16_t v; };
#define __UNALIGNED_UINT16_READ(addr) (((const struct T_UINT16_READ *)(const void *)(addr))->v)
#endif
#ifndef __UNALIGNED_UINT32_WRITE
__PACKED_STRUCT T_UINT32_WRITE { uint32_t v; };
#define __UNALIGNED_UINT32_WRITE(addr, val) (void)((((struct T_UINT32_WRITE *)(void *)(addr))->v) = (val))
#endif
#ifndef __UNALIGNED_UINT32_READ
__PACKED_STRUCT T_UINT32_READ { uint32_t v; };
#define __UNALIGNED_UINT32_READ(addr) (((const struct T_UINT32_READ *)(const void *)(addr))->v)
#endif
#ifndef __ALIGNED
#warning No compiler specific solution for __ALIGNED. __ALIGNED is ignored.
#define __ALIGNED(x)
#endif
/*
* TI ARM Compiler
*/
#elif defined ( __TI_ARM__ )
#include <cmsis_ccs.h>
#ifndef __ASM
#define __ASM __asm
#endif
#ifndef __INLINE
#define __INLINE inline
#endif
#ifndef __STATIC_INLINE
#define __STATIC_INLINE static inline
#endif
#ifndef __NO_RETURN
#define __NO_RETURN __attribute__((noreturn))
#endif
#ifndef __USED
#define __USED __attribute__((used))
#endif
#ifndef __WEAK
#define __WEAK __attribute__((weak))
#endif
#ifndef __PACKED
#define __PACKED __attribute__((packed))
#endif
#ifndef __PACKED_STRUCT
#define __PACKED_STRUCT struct __attribute__((packed))
#endif
#ifndef __UNALIGNED_UINT32 /* deprecated */
struct __attribute__((packed)) T_UINT32 { uint32_t v; };
#define __UNALIGNED_UINT32(x) (((struct T_UINT32 *)(x))->v)
#endif
#ifndef __UNALIGNED_UINT16_WRITE
__PACKED_STRUCT T_UINT16_WRITE { uint16_t v; };
#define __UNALIGNED_UINT16_WRITE(addr, val) (void)((((struct T_UINT16_WRITE *)(void*)(addr))->v) = (val))
#endif
#ifndef __UNALIGNED_UINT16_READ
__PACKED_STRUCT T_UINT16_READ { uint16_t v; };
#define __UNALIGNED_UINT16_READ(addr) (((const struct T_UINT16_READ *)(const void *)(addr))->v)
#endif
#ifndef __UNALIGNED_UINT32_WRITE
__PACKED_STRUCT T_UINT32_WRITE { uint32_t v; };
#define __UNALIGNED_UINT32_WRITE(addr, val) (void)((((struct T_UINT32_WRITE *)(void *)(addr))->v) = (val))
#endif
#ifndef __UNALIGNED_UINT32_READ
__PACKED_STRUCT T_UINT32_READ { uint32_t v; };
#define __UNALIGNED_UINT32_READ(addr) (((const struct T_UINT32_READ *)(const void *)(addr))->v)
#endif
#ifndef __ALIGNED
#define __ALIGNED(x) __attribute__((aligned(x)))
#endif
/*
* TASKING Compiler
*/
#elif defined ( __TASKING__ )
/*
* The CMSIS functions have been implemented as intrinsics in the compiler.
* Please use "carm -?i" to get an up to date list of all intrinsics,
* Including the CMSIS ones.
*/
#ifndef __ASM
#define __ASM __asm
#endif
#ifndef __INLINE
#define __INLINE inline
#endif
#ifndef __STATIC_INLINE
#define __STATIC_INLINE static inline
#endif
#ifndef __NO_RETURN
#define __NO_RETURN __attribute__((noreturn))
#endif
#ifndef __USED
#define __USED __attribute__((used))
#endif
#ifndef __WEAK
#define __WEAK __attribute__((weak))
#endif
#ifndef __PACKED
#define __PACKED __packed__
#endif
#ifndef __PACKED_STRUCT
#define __PACKED_STRUCT struct __packed__
#endif
#ifndef __UNALIGNED_UINT32 /* deprecated */
struct __packed__ T_UINT32 { uint32_t v; };
#define __UNALIGNED_UINT32(x) (((struct T_UINT32 *)(x))->v)
#endif
#ifndef __UNALIGNED_UINT16_WRITE
__PACKED_STRUCT T_UINT16_WRITE { uint16_t v; };
#define __UNALIGNED_UINT16_WRITE(addr, val) (void)((((struct T_UINT16_WRITE *)(void *)(addr))->v) = (val))
#endif
#ifndef __UNALIGNED_UINT16_READ
__PACKED_STRUCT T_UINT16_READ { uint16_t v; };
#define __UNALIGNED_UINT16_READ(addr) (((const struct T_UINT16_READ *)(const void *)(addr))->v)
#endif
#ifndef __UNALIGNED_UINT32_WRITE
__PACKED_STRUCT T_UINT32_WRITE { uint32_t v; };
#define __UNALIGNED_UINT32_WRITE(addr, val) (void)((((struct T_UINT32_WRITE *)(void *)(addr))->v) = (val))
#endif
#ifndef __UNALIGNED_UINT32_READ
__PACKED_STRUCT T_UINT32_READ { uint32_t v; };
#define __UNALIGNED_UINT32_READ(addr) (((const struct T_UINT32_READ *)(const void *)(addr))->v)
#endif
#ifndef __ALIGNED
#define __ALIGNED(x) __align(x)
#endif
/*
* COSMIC Compiler
*/
#elif defined ( __CSMC__ )
#include <cmsis_csm.h>
#ifndef __ASM
#define __ASM _asm
#endif
#ifndef __INLINE
#define __INLINE inline
#endif
#ifndef __STATIC_INLINE
#define __STATIC_INLINE static inline
#endif
#ifndef __NO_RETURN
// NO RETURN is automatically detected hence no warning here
#define __NO_RETURN
#endif
#ifndef __USED
#warning No compiler specific solution for __USED. __USED is ignored.
#define __USED
#endif
#ifndef __WEAK
#define __WEAK __weak
#endif
#ifndef __PACKED
#define __PACKED @packed
#endif
#ifndef __PACKED_STRUCT
#define __PACKED_STRUCT @packed struct
#endif
#ifndef __UNALIGNED_UINT32 /* deprecated */
@packed struct T_UINT32 { uint32_t v; };
#define __UNALIGNED_UINT32(x) (((struct T_UINT32 *)(x))->v)
#endif
#ifndef __UNALIGNED_UINT16_WRITE
__PACKED_STRUCT T_UINT16_WRITE { uint16_t v; };
#define __UNALIGNED_UINT16_WRITE(addr, val) (void)((((struct T_UINT16_WRITE *)(void *)(addr))->v) = (val))
#endif
#ifndef __UNALIGNED_UINT16_READ
__PACKED_STRUCT T_UINT16_READ { uint16_t v; };
#define __UNALIGNED_UINT16_READ(addr) (((const struct T_UINT16_READ *)(const void *)(addr))->v)
#endif
#ifndef __UNALIGNED_UINT32_WRITE
__PACKED_STRUCT T_UINT32_WRITE { uint32_t v; };
#define __UNALIGNED_UINT32_WRITE(addr, val) (void)((((struct T_UINT32_WRITE *)(void *)(addr))->v) = (val))
#endif
#ifndef __UNALIGNED_UINT32_READ
__PACKED_STRUCT T_UINT32_READ { uint32_t v; };
#define __UNALIGNED_UINT32_READ(addr) (((const struct T_UINT32_READ *)(const void *)(addr))->v)
#endif
#ifndef __ALIGNED
#warning No compiler specific solution for __ALIGNED. __ALIGNED is ignored.
#define __ALIGNED(x)
#endif
#else
#error Unknown compiler.
#endif
#endif /* __CMSIS_COMPILER_H */

7226
cmsis/arm_math.h Normal file

File diff suppressed because it is too large Load Diff

1876
cmsis/core_armv8mbl.h Normal file

File diff suppressed because it is too large Load Diff

2900
cmsis/core_armv8mml.h Normal file

File diff suppressed because it is too large Load Diff

2016
cmsis/core_ca.h Normal file

File diff suppressed because it is too large Load Diff

886
cmsis/core_cm0.h Normal file
View File

@ -0,0 +1,886 @@
/**************************************************************************//**
* @file core_cm0.h
* @brief CMSIS Cortex-M0 Core Peripheral Access Layer Header File
* @version V5.0.2
* @date 13. February 2017
******************************************************************************/
/*
* Copyright (c) 2009-2017 ARM Limited. All rights reserved.
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the License); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an AS IS BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#if defined ( __ICCARM__ )
#pragma system_include /* treat file as system include file for MISRA check */
#elif defined (__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050)
#pragma clang system_header /* treat file as system include file */
#endif
#ifndef __CORE_CM0_H_GENERIC
#define __CORE_CM0_H_GENERIC
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
/**
\page CMSIS_MISRA_Exceptions MISRA-C:2004 Compliance Exceptions
CMSIS violates the following MISRA-C:2004 rules:
\li Required Rule 8.5, object/function definition in header file.<br>
Function definitions in header files are used to allow 'inlining'.
\li Required Rule 18.4, declaration of union type or object of union type: '{...}'.<br>
Unions are used for effective representation of core registers.
\li Advisory Rule 19.7, Function-like macro defined.<br>
Function-like macros are used to allow more efficient code.
*/
/*******************************************************************************
* CMSIS definitions
******************************************************************************/
/**
\ingroup Cortex_M0
@{
*/
/* CMSIS CM0 definitions */
#define __CM0_CMSIS_VERSION_MAIN ( 5U) /*!< [31:16] CMSIS HAL main version */
#define __CM0_CMSIS_VERSION_SUB ( 0U) /*!< [15:0] CMSIS HAL sub version */
#define __CM0_CMSIS_VERSION ((__CM0_CMSIS_VERSION_MAIN << 16U) | \
__CM0_CMSIS_VERSION_SUB ) /*!< CMSIS HAL version number */
#define __CORTEX_M (0U) /*!< Cortex-M Core */
/** __FPU_USED indicates whether an FPU is used or not.
This core does not support an FPU at all
*/
#define __FPU_USED 0U
#if defined ( __CC_ARM )
#if defined __TARGET_FPU_VFP
#error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)"
#endif
#elif defined (__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050)
#if defined __ARM_PCS_VFP
#error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)"
#endif
#elif defined ( __GNUC__ )
#if defined (__VFP_FP__) && !defined(__SOFTFP__)
#error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)"
#endif
#elif defined ( __ICCARM__ )
#if defined __ARMVFP__
#error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)"
#endif
#elif defined ( __TI_ARM__ )
#if defined __TI_VFP_SUPPORT__
#error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)"
#endif
#elif defined ( __TASKING__ )
#if defined __FPU_VFP__
#error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)"
#endif
#elif defined ( __CSMC__ )
#if ( __CSMC__ & 0x400U)
#error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)"
#endif
#endif
#include "cmsis_compiler.h" /* CMSIS compiler specific defines */
#ifdef __cplusplus
}
#endif
#endif /* __CORE_CM0_H_GENERIC */
#ifndef __CMSIS_GENERIC
#ifndef __CORE_CM0_H_DEPENDANT
#define __CORE_CM0_H_DEPENDANT
#ifdef __cplusplus
extern "C" {
#endif
/* check device defines and use defaults */
#if defined __CHECK_DEVICE_DEFINES
#ifndef __CM0_REV
#define __CM0_REV 0x0000U
#warning "__CM0_REV not defined in device header file; using default!"
#endif
#ifndef __NVIC_PRIO_BITS
#define __NVIC_PRIO_BITS 2U
#warning "__NVIC_PRIO_BITS not defined in device header file; using default!"
#endif
#ifndef __Vendor_SysTickConfig
#define __Vendor_SysTickConfig 0U
#warning "__Vendor_SysTickConfig not defined in device header file; using default!"
#endif
#endif
/* IO definitions (access restrictions to peripheral registers) */
/**
\defgroup CMSIS_glob_defs CMSIS Global Defines
<strong>IO Type Qualifiers</strong> are used
\li to specify the access to peripheral variables.
\li for automatic generation of peripheral register debug information.
*/
#ifdef __cplusplus
#define __I volatile /*!< Defines 'read only' permissions */
#else
#define __I volatile const /*!< Defines 'read only' permissions */
#endif
#define __O volatile /*!< Defines 'write only' permissions */
#define __IO volatile /*!< Defines 'read / write' permissions */
/* following defines should be used for structure members */
#define __IM volatile const /*! Defines 'read only' structure member permissions */
#define __OM volatile /*! Defines 'write only' structure member permissions */
#define __IOM volatile /*! Defines 'read / write' structure member permissions */
/*@} end of group Cortex_M0 */
/*******************************************************************************
* Register Abstraction
Core Register contain:
- Core Register
- Core NVIC Register
- Core SCB Register
- Core SysTick Register
******************************************************************************/
/**
\defgroup CMSIS_core_register Defines and Type Definitions
\brief Type definitions and defines for Cortex-M processor based devices.
*/
/**
\ingroup CMSIS_core_register
\defgroup CMSIS_CORE Status and Control Registers
\brief Core Register type definitions.
@{
*/
/**
\brief Union type to access the Application Program Status Register (APSR).
*/
typedef union
{
struct
{
uint32_t _reserved0:28; /*!< bit: 0..27 Reserved */
uint32_t V:1; /*!< bit: 28 Overflow condition code flag */
uint32_t C:1; /*!< bit: 29 Carry condition code flag */
uint32_t Z:1; /*!< bit: 30 Zero condition code flag */
uint32_t N:1; /*!< bit: 31 Negative condition code flag */
} b; /*!< Structure used for bit access */
uint32_t w; /*!< Type used for word access */
} APSR_Type;
/* APSR Register Definitions */
#define APSR_N_Pos 31U /*!< APSR: N Position */
#define APSR_N_Msk (1UL << APSR_N_Pos) /*!< APSR: N Mask */
#define APSR_Z_Pos 30U /*!< APSR: Z Position */
#define APSR_Z_Msk (1UL << APSR_Z_Pos) /*!< APSR: Z Mask */
#define APSR_C_Pos 29U /*!< APSR: C Position */
#define APSR_C_Msk (1UL << APSR_C_Pos) /*!< APSR: C Mask */
#define APSR_V_Pos 28U /*!< APSR: V Position */
#define APSR_V_Msk (1UL << APSR_V_Pos) /*!< APSR: V Mask */
/**
\brief Union type to access the Interrupt Program Status Register (IPSR).
*/
typedef union
{
struct
{
uint32_t ISR:9; /*!< bit: 0.. 8 Exception number */
uint32_t _reserved0:23; /*!< bit: 9..31 Reserved */
} b; /*!< Structure used for bit access */
uint32_t w; /*!< Type used for word access */
} IPSR_Type;
/* IPSR Register Definitions */
#define IPSR_ISR_Pos 0U /*!< IPSR: ISR Position */
#define IPSR_ISR_Msk (0x1FFUL /*<< IPSR_ISR_Pos*/) /*!< IPSR: ISR Mask */
/**
\brief Union type to access the Special-Purpose Program Status Registers (xPSR).
*/
typedef union
{
struct
{
uint32_t ISR:9; /*!< bit: 0.. 8 Exception number */
uint32_t _reserved0:15; /*!< bit: 9..23 Reserved */
uint32_t T:1; /*!< bit: 24 Thumb bit (read 0) */
uint32_t _reserved1:3; /*!< bit: 25..27 Reserved */
uint32_t V:1; /*!< bit: 28 Overflow condition code flag */
uint32_t C:1; /*!< bit: 29 Carry condition code flag */
uint32_t Z:1; /*!< bit: 30 Zero condition code flag */
uint32_t N:1; /*!< bit: 31 Negative condition code flag */
} b; /*!< Structure used for bit access */
uint32_t w; /*!< Type used for word access */
} xPSR_Type;
/* xPSR Register Definitions */
#define xPSR_N_Pos 31U /*!< xPSR: N Position */
#define xPSR_N_Msk (1UL << xPSR_N_Pos) /*!< xPSR: N Mask */
#define xPSR_Z_Pos 30U /*!< xPSR: Z Position */
#define xPSR_Z_Msk (1UL << xPSR_Z_Pos) /*!< xPSR: Z Mask */
#define xPSR_C_Pos 29U /*!< xPSR: C Position */
#define xPSR_C_Msk (1UL << xPSR_C_Pos) /*!< xPSR: C Mask */
#define xPSR_V_Pos 28U /*!< xPSR: V Position */
#define xPSR_V_Msk (1UL << xPSR_V_Pos) /*!< xPSR: V Mask */
#define xPSR_T_Pos 24U /*!< xPSR: T Position */
#define xPSR_T_Msk (1UL << xPSR_T_Pos) /*!< xPSR: T Mask */
#define xPSR_ISR_Pos 0U /*!< xPSR: ISR Position */
#define xPSR_ISR_Msk (0x1FFUL /*<< xPSR_ISR_Pos*/) /*!< xPSR: ISR Mask */
/**
\brief Union type to access the Control Registers (CONTROL).
*/
typedef union
{
struct
{
uint32_t _reserved0:1; /*!< bit: 0 Reserved */
uint32_t SPSEL:1; /*!< bit: 1 Stack to be used */
uint32_t _reserved1:30; /*!< bit: 2..31 Reserved */
} b; /*!< Structure used for bit access */
uint32_t w; /*!< Type used for word access */
} CONTROL_Type;
/* CONTROL Register Definitions */
#define CONTROL_SPSEL_Pos 1U /*!< CONTROL: SPSEL Position */
#define CONTROL_SPSEL_Msk (1UL << CONTROL_SPSEL_Pos) /*!< CONTROL: SPSEL Mask */
/*@} end of group CMSIS_CORE */
/**
\ingroup CMSIS_core_register
\defgroup CMSIS_NVIC Nested Vectored Interrupt Controller (NVIC)
\brief Type definitions for the NVIC Registers
@{
*/
/**
\brief Structure type to access the Nested Vectored Interrupt Controller (NVIC).
*/
typedef struct
{
__IOM uint32_t ISER[1U]; /*!< Offset: 0x000 (R/W) Interrupt Set Enable Register */
uint32_t RESERVED0[31U];
__IOM uint32_t ICER[1U]; /*!< Offset: 0x080 (R/W) Interrupt Clear Enable Register */
uint32_t RSERVED1[31U];
__IOM uint32_t ISPR[1U]; /*!< Offset: 0x100 (R/W) Interrupt Set Pending Register */
uint32_t RESERVED2[31U];
__IOM uint32_t ICPR[1U]; /*!< Offset: 0x180 (R/W) Interrupt Clear Pending Register */
uint32_t RESERVED3[31U];
uint32_t RESERVED4[64U];
__IOM uint32_t IP[8U]; /*!< Offset: 0x300 (R/W) Interrupt Priority Register */
} NVIC_Type;
/*@} end of group CMSIS_NVIC */
/**
\ingroup CMSIS_core_register
\defgroup CMSIS_SCB System Control Block (SCB)
\brief Type definitions for the System Control Block Registers
@{
*/
/**
\brief Structure type to access the System Control Block (SCB).
*/
typedef struct
{
__IM uint32_t CPUID; /*!< Offset: 0x000 (R/ ) CPUID Base Register */
__IOM uint32_t ICSR; /*!< Offset: 0x004 (R/W) Interrupt Control and State Register */
uint32_t RESERVED0;
__IOM uint32_t AIRCR; /*!< Offset: 0x00C (R/W) Application Interrupt and Reset Control Register */
__IOM uint32_t SCR; /*!< Offset: 0x010 (R/W) System Control Register */
__IOM uint32_t CCR; /*!< Offset: 0x014 (R/W) Configuration Control Register */
uint32_t RESERVED1;
__IOM uint32_t SHP[2U]; /*!< Offset: 0x01C (R/W) System Handlers Priority Registers. [0] is RESERVED */
__IOM uint32_t SHCSR; /*!< Offset: 0x024 (R/W) System Handler Control and State Register */
} SCB_Type;
/* SCB CPUID Register Definitions */
#define SCB_CPUID_IMPLEMENTER_Pos 24U /*!< SCB CPUID: IMPLEMENTER Position */
#define SCB_CPUID_IMPLEMENTER_Msk (0xFFUL << SCB_CPUID_IMPLEMENTER_Pos) /*!< SCB CPUID: IMPLEMENTER Mask */
#define SCB_CPUID_VARIANT_Pos 20U /*!< SCB CPUID: VARIANT Position */
#define SCB_CPUID_VARIANT_Msk (0xFUL << SCB_CPUID_VARIANT_Pos) /*!< SCB CPUID: VARIANT Mask */
#define SCB_CPUID_ARCHITECTURE_Pos 16U /*!< SCB CPUID: ARCHITECTURE Position */
#define SCB_CPUID_ARCHITECTURE_Msk (0xFUL << SCB_CPUID_ARCHITECTURE_Pos) /*!< SCB CPUID: ARCHITECTURE Mask */
#define SCB_CPUID_PARTNO_Pos 4U /*!< SCB CPUID: PARTNO Position */
#define SCB_CPUID_PARTNO_Msk (0xFFFUL << SCB_CPUID_PARTNO_Pos) /*!< SCB CPUID: PARTNO Mask */
#define SCB_CPUID_REVISION_Pos 0U /*!< SCB CPUID: REVISION Position */
#define SCB_CPUID_REVISION_Msk (0xFUL /*<< SCB_CPUID_REVISION_Pos*/) /*!< SCB CPUID: REVISION Mask */
/* SCB Interrupt Control State Register Definitions */
#define SCB_ICSR_NMIPENDSET_Pos 31U /*!< SCB ICSR: NMIPENDSET Position */
#define SCB_ICSR_NMIPENDSET_Msk (1UL << SCB_ICSR_NMIPENDSET_Pos) /*!< SCB ICSR: NMIPENDSET Mask */
#define SCB_ICSR_PENDSVSET_Pos 28U /*!< SCB ICSR: PENDSVSET Position */
#define SCB_ICSR_PENDSVSET_Msk (1UL << SCB_ICSR_PENDSVSET_Pos) /*!< SCB ICSR: PENDSVSET Mask */
#define SCB_ICSR_PENDSVCLR_Pos 27U /*!< SCB ICSR: PENDSVCLR Position */
#define SCB_ICSR_PENDSVCLR_Msk (1UL << SCB_ICSR_PENDSVCLR_Pos) /*!< SCB ICSR: PENDSVCLR Mask */
#define SCB_ICSR_PENDSTSET_Pos 26U /*!< SCB ICSR: PENDSTSET Position */
#define SCB_ICSR_PENDSTSET_Msk (1UL << SCB_ICSR_PENDSTSET_Pos) /*!< SCB ICSR: PENDSTSET Mask */
#define SCB_ICSR_PENDSTCLR_Pos 25U /*!< SCB ICSR: PENDSTCLR Position */
#define SCB_ICSR_PENDSTCLR_Msk (1UL << SCB_ICSR_PENDSTCLR_Pos) /*!< SCB ICSR: PENDSTCLR Mask */
#define SCB_ICSR_ISRPREEMPT_Pos 23U /*!< SCB ICSR: ISRPREEMPT Position */
#define SCB_ICSR_ISRPREEMPT_Msk (1UL << SCB_ICSR_ISRPREEMPT_Pos) /*!< SCB ICSR: ISRPREEMPT Mask */
#define SCB_ICSR_ISRPENDING_Pos 22U /*!< SCB ICSR: ISRPENDING Position */
#define SCB_ICSR_ISRPENDING_Msk (1UL << SCB_ICSR_ISRPENDING_Pos) /*!< SCB ICSR: ISRPENDING Mask */
#define SCB_ICSR_VECTPENDING_Pos 12U /*!< SCB ICSR: VECTPENDING Position */
#define SCB_ICSR_VECTPENDING_Msk (0x1FFUL << SCB_ICSR_VECTPENDING_Pos) /*!< SCB ICSR: VECTPENDING Mask */
#define SCB_ICSR_VECTACTIVE_Pos 0U /*!< SCB ICSR: VECTACTIVE Position */
#define SCB_ICSR_VECTACTIVE_Msk (0x1FFUL /*<< SCB_ICSR_VECTACTIVE_Pos*/) /*!< SCB ICSR: VECTACTIVE Mask */
/* SCB Application Interrupt and Reset Control Register Definitions */
#define SCB_AIRCR_VECTKEY_Pos 16U /*!< SCB AIRCR: VECTKEY Position */
#define SCB_AIRCR_VECTKEY_Msk (0xFFFFUL << SCB_AIRCR_VECTKEY_Pos) /*!< SCB AIRCR: VECTKEY Mask */
#define SCB_AIRCR_VECTKEYSTAT_Pos 16U /*!< SCB AIRCR: VECTKEYSTAT Position */
#define SCB_AIRCR_VECTKEYSTAT_Msk (0xFFFFUL << SCB_AIRCR_VECTKEYSTAT_Pos) /*!< SCB AIRCR: VECTKEYSTAT Mask */
#define SCB_AIRCR_ENDIANESS_Pos 15U /*!< SCB AIRCR: ENDIANESS Position */
#define SCB_AIRCR_ENDIANESS_Msk (1UL << SCB_AIRCR_ENDIANESS_Pos) /*!< SCB AIRCR: ENDIANESS Mask */
#define SCB_AIRCR_SYSRESETREQ_Pos 2U /*!< SCB AIRCR: SYSRESETREQ Position */
#define SCB_AIRCR_SYSRESETREQ_Msk (1UL << SCB_AIRCR_SYSRESETREQ_Pos) /*!< SCB AIRCR: SYSRESETREQ Mask */
#define SCB_AIRCR_VECTCLRACTIVE_Pos 1U /*!< SCB AIRCR: VECTCLRACTIVE Position */
#define SCB_AIRCR_VECTCLRACTIVE_Msk (1UL << SCB_AIRCR_VECTCLRACTIVE_Pos) /*!< SCB AIRCR: VECTCLRACTIVE Mask */
/* SCB System Control Register Definitions */
#define SCB_SCR_SEVONPEND_Pos 4U /*!< SCB SCR: SEVONPEND Position */
#define SCB_SCR_SEVONPEND_Msk (1UL << SCB_SCR_SEVONPEND_Pos) /*!< SCB SCR: SEVONPEND Mask */
#define SCB_SCR_SLEEPDEEP_Pos 2U /*!< SCB SCR: SLEEPDEEP Position */
#define SCB_SCR_SLEEPDEEP_Msk (1UL << SCB_SCR_SLEEPDEEP_Pos) /*!< SCB SCR: SLEEPDEEP Mask */
#define SCB_SCR_SLEEPONEXIT_Pos 1U /*!< SCB SCR: SLEEPONEXIT Position */
#define SCB_SCR_SLEEPONEXIT_Msk (1UL << SCB_SCR_SLEEPONEXIT_Pos) /*!< SCB SCR: SLEEPONEXIT Mask */
/* SCB Configuration Control Register Definitions */
#define SCB_CCR_STKALIGN_Pos 9U /*!< SCB CCR: STKALIGN Position */
#define SCB_CCR_STKALIGN_Msk (1UL << SCB_CCR_STKALIGN_Pos) /*!< SCB CCR: STKALIGN Mask */
#define SCB_CCR_UNALIGN_TRP_Pos 3U /*!< SCB CCR: UNALIGN_TRP Position */
#define SCB_CCR_UNALIGN_TRP_Msk (1UL << SCB_CCR_UNALIGN_TRP_Pos) /*!< SCB CCR: UNALIGN_TRP Mask */
/* SCB System Handler Control and State Register Definitions */
#define SCB_SHCSR_SVCALLPENDED_Pos 15U /*!< SCB SHCSR: SVCALLPENDED Position */
#define SCB_SHCSR_SVCALLPENDED_Msk (1UL << SCB_SHCSR_SVCALLPENDED_Pos) /*!< SCB SHCSR: SVCALLPENDED Mask */
/*@} end of group CMSIS_SCB */
/**
\ingroup CMSIS_core_register
\defgroup CMSIS_SysTick System Tick Timer (SysTick)
\brief Type definitions for the System Timer Registers.
@{
*/
/**
\brief Structure type to access the System Timer (SysTick).
*/
typedef struct
{
__IOM uint32_t CTRL; /*!< Offset: 0x000 (R/W) SysTick Control and Status Register */
__IOM uint32_t LOAD; /*!< Offset: 0x004 (R/W) SysTick Reload Value Register */
__IOM uint32_t VAL; /*!< Offset: 0x008 (R/W) SysTick Current Value Register */
__IM uint32_t CALIB; /*!< Offset: 0x00C (R/ ) SysTick Calibration Register */
} SysTick_Type;
/* SysTick Control / Status Register Definitions */
#define SysTick_CTRL_COUNTFLAG_Pos 16U /*!< SysTick CTRL: COUNTFLAG Position */
#define SysTick_CTRL_COUNTFLAG_Msk (1UL << SysTick_CTRL_COUNTFLAG_Pos) /*!< SysTick CTRL: COUNTFLAG Mask */
#define SysTick_CTRL_CLKSOURCE_Pos 2U /*!< SysTick CTRL: CLKSOURCE Position */
#define SysTick_CTRL_CLKSOURCE_Msk (1UL << SysTick_CTRL_CLKSOURCE_Pos) /*!< SysTick CTRL: CLKSOURCE Mask */
#define SysTick_CTRL_TICKINT_Pos 1U /*!< SysTick CTRL: TICKINT Position */
#define SysTick_CTRL_TICKINT_Msk (1UL << SysTick_CTRL_TICKINT_Pos) /*!< SysTick CTRL: TICKINT Mask */
#define SysTick_CTRL_ENABLE_Pos 0U /*!< SysTick CTRL: ENABLE Position */
#define SysTick_CTRL_ENABLE_Msk (1UL /*<< SysTick_CTRL_ENABLE_Pos*/) /*!< SysTick CTRL: ENABLE Mask */
/* SysTick Reload Register Definitions */
#define SysTick_LOAD_RELOAD_Pos 0U /*!< SysTick LOAD: RELOAD Position */
#define SysTick_LOAD_RELOAD_Msk (0xFFFFFFUL /*<< SysTick_LOAD_RELOAD_Pos*/) /*!< SysTick LOAD: RELOAD Mask */
/* SysTick Current Register Definitions */
#define SysTick_VAL_CURRENT_Pos 0U /*!< SysTick VAL: CURRENT Position */
#define SysTick_VAL_CURRENT_Msk (0xFFFFFFUL /*<< SysTick_VAL_CURRENT_Pos*/) /*!< SysTick VAL: CURRENT Mask */
/* SysTick Calibration Register Definitions */
#define SysTick_CALIB_NOREF_Pos 31U /*!< SysTick CALIB: NOREF Position */
#define SysTick_CALIB_NOREF_Msk (1UL << SysTick_CALIB_NOREF_Pos) /*!< SysTick CALIB: NOREF Mask */
#define SysTick_CALIB_SKEW_Pos 30U /*!< SysTick CALIB: SKEW Position */
#define SysTick_CALIB_SKEW_Msk (1UL << SysTick_CALIB_SKEW_Pos) /*!< SysTick CALIB: SKEW Mask */
#define SysTick_CALIB_TENMS_Pos 0U /*!< SysTick CALIB: TENMS Position */
#define SysTick_CALIB_TENMS_Msk (0xFFFFFFUL /*<< SysTick_CALIB_TENMS_Pos*/) /*!< SysTick CALIB: TENMS Mask */
/*@} end of group CMSIS_SysTick */
/**
\ingroup CMSIS_core_register
\defgroup CMSIS_CoreDebug Core Debug Registers (CoreDebug)
\brief Cortex-M0 Core Debug Registers (DCB registers, SHCSR, and DFSR) are only accessible over DAP and not via processor.
Therefore they are not covered by the Cortex-M0 header file.
@{
*/
/*@} end of group CMSIS_CoreDebug */
/**
\ingroup CMSIS_core_register
\defgroup CMSIS_core_bitfield Core register bit field macros
\brief Macros for use with bit field definitions (xxx_Pos, xxx_Msk).
@{
*/
/**
\brief Mask and shift a bit field value for use in a register bit range.
\param[in] field Name of the register bit field.
\param[in] value Value of the bit field. This parameter is interpreted as an uint32_t type.
\return Masked and shifted value.
*/
#define _VAL2FLD(field, value) (((uint32_t)(value) << field ## _Pos) & field ## _Msk)
/**
\brief Mask and shift a register value to extract a bit filed value.
\param[in] field Name of the register bit field.
\param[in] value Value of register. This parameter is interpreted as an uint32_t type.
\return Masked and shifted bit field value.
*/
#define _FLD2VAL(field, value) (((uint32_t)(value) & field ## _Msk) >> field ## _Pos)
/*@} end of group CMSIS_core_bitfield */
/**
\ingroup CMSIS_core_register
\defgroup CMSIS_core_base Core Definitions
\brief Definitions for base addresses, unions, and structures.
@{
*/
/* Memory mapping of Core Hardware */
#define SCS_BASE (0xE000E000UL) /*!< System Control Space Base Address */
#define SysTick_BASE (SCS_BASE + 0x0010UL) /*!< SysTick Base Address */
#define NVIC_BASE (SCS_BASE + 0x0100UL) /*!< NVIC Base Address */
#define SCB_BASE (SCS_BASE + 0x0D00UL) /*!< System Control Block Base Address */
#define SCB ((SCB_Type *) SCB_BASE ) /*!< SCB configuration struct */
#define SysTick ((SysTick_Type *) SysTick_BASE ) /*!< SysTick configuration struct */
#define NVIC ((NVIC_Type *) NVIC_BASE ) /*!< NVIC configuration struct */
/*@} */
/*******************************************************************************
* Hardware Abstraction Layer
Core Function Interface contains:
- Core NVIC Functions
- Core SysTick Functions
- Core Register Access Functions
******************************************************************************/
/**
\defgroup CMSIS_Core_FunctionInterface Functions and Instructions Reference
*/
/* ########################## NVIC functions #################################### */
/**
\ingroup CMSIS_Core_FunctionInterface
\defgroup CMSIS_Core_NVICFunctions NVIC Functions
\brief Functions that manage interrupts and exceptions via the NVIC.
@{
*/
#ifdef CMSIS_NVIC_VIRTUAL
#ifndef CMSIS_NVIC_VIRTUAL_HEADER_FILE
#define CMSIS_NVIC_VIRTUAL_HEADER_FILE "cmsis_nvic_virtual.h"
#endif
#include CMSIS_NVIC_VIRTUAL_HEADER_FILE
#else
/*#define NVIC_SetPriorityGrouping __NVIC_SetPriorityGrouping not available for Cortex-M0 */
/*#define NVIC_GetPriorityGrouping __NVIC_GetPriorityGrouping not available for Cortex-M0 */
#define NVIC_EnableIRQ __NVIC_EnableIRQ
#define NVIC_GetEnableIRQ __NVIC_GetEnableIRQ
#define NVIC_DisableIRQ __NVIC_DisableIRQ
#define NVIC_GetPendingIRQ __NVIC_GetPendingIRQ
#define NVIC_SetPendingIRQ __NVIC_SetPendingIRQ
#define NVIC_ClearPendingIRQ __NVIC_ClearPendingIRQ
/*#define NVIC_GetActive __NVIC_GetActive not available for Cortex-M0 */
#define NVIC_SetPriority __NVIC_SetPriority
#define NVIC_GetPriority __NVIC_GetPriority
#define NVIC_SystemReset __NVIC_SystemReset
#endif /* CMSIS_NVIC_VIRTUAL */
#ifdef CMSIS_VECTAB_VIRTUAL
#ifndef CMSIS_VECTAB_VIRTUAL_HEADER_FILE
#define CMSIS_VECTAB_VIRTUAL_HEADER_FILE "cmsis_vectab_virtual.h"
#endif
#include CMSIS_VECTAB_VIRTUAL_HEADER_FILE
#else
#define NVIC_SetVector __NVIC_SetVector
#define NVIC_GetVector __NVIC_GetVector
#endif /* (CMSIS_VECTAB_VIRTUAL) */
#define NVIC_USER_IRQ_OFFSET 16
/* Interrupt Priorities are WORD accessible only under ARMv6M */
/* The following MACROS handle generation of the register offset and byte masks */
#define _BIT_SHIFT(IRQn) ( ((((uint32_t)(int32_t)(IRQn)) ) & 0x03UL) * 8UL)
#define _SHP_IDX(IRQn) ( (((((uint32_t)(int32_t)(IRQn)) & 0x0FUL)-8UL) >> 2UL) )
#define _IP_IDX(IRQn) ( (((uint32_t)(int32_t)(IRQn)) >> 2UL) )
/**
\brief Enable Interrupt
\details Enables a device specific interrupt in the NVIC interrupt controller.
\param [in] IRQn Device specific interrupt number.
\note IRQn must not be negative.
*/
__STATIC_INLINE void __NVIC_EnableIRQ(IRQn_Type IRQn)
{
if ((int32_t)(IRQn) >= 0)
{
NVIC->ISER[0U] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL));
}
}
/**
\brief Get Interrupt Enable status
\details Returns a device specific interrupt enable status from the NVIC interrupt controller.
\param [in] IRQn Device specific interrupt number.
\return 0 Interrupt is not enabled.
\return 1 Interrupt is enabled.
\note IRQn must not be negative.
*/
__STATIC_INLINE uint32_t __NVIC_GetEnableIRQ(IRQn_Type IRQn)
{
if ((int32_t)(IRQn) >= 0)
{
return((uint32_t)(((NVIC->ISER[0U] & (1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL));
}
else
{
return(0U);
}
}
/**
\brief Disable Interrupt
\details Disables a device specific interrupt in the NVIC interrupt controller.
\param [in] IRQn Device specific interrupt number.
\note IRQn must not be negative.
*/
__STATIC_INLINE void __NVIC_DisableIRQ(IRQn_Type IRQn)
{
if ((int32_t)(IRQn) >= 0)
{
NVIC->ICER[0U] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL));
__DSB();
__ISB();
}
}
/**
\brief Get Pending Interrupt
\details Reads the NVIC pending register and returns the pending bit for the specified device specific interrupt.
\param [in] IRQn Device specific interrupt number.
\return 0 Interrupt status is not pending.
\return 1 Interrupt status is pending.
\note IRQn must not be negative.
*/
__STATIC_INLINE uint32_t __NVIC_GetPendingIRQ(IRQn_Type IRQn)
{
if ((int32_t)(IRQn) >= 0)
{
return((uint32_t)(((NVIC->ISPR[0U] & (1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL));
}
else
{
return(0U);
}
}
/**
\brief Set Pending Interrupt
\details Sets the pending bit of a device specific interrupt in the NVIC pending register.
\param [in] IRQn Device specific interrupt number.
\note IRQn must not be negative.
*/
__STATIC_INLINE void __NVIC_SetPendingIRQ(IRQn_Type IRQn)
{
if ((int32_t)(IRQn) >= 0)
{
NVIC->ISPR[0U] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL));
}
}
/**
\brief Clear Pending Interrupt
\details Clears the pending bit of a device specific interrupt in the NVIC pending register.
\param [in] IRQn Device specific interrupt number.
\note IRQn must not be negative.
*/
__STATIC_INLINE void __NVIC_ClearPendingIRQ(IRQn_Type IRQn)
{
if ((int32_t)(IRQn) >= 0)
{
NVIC->ICPR[0U] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL));
}
}
/**
\brief Set Interrupt Priority
\details Sets the priority of a device specific interrupt or a processor exception.
The interrupt number can be positive to specify a device specific interrupt,
or negative to specify a processor exception.
\param [in] IRQn Interrupt number.
\param [in] priority Priority to set.
\note The priority cannot be set for every processor exception.
*/
__STATIC_INLINE void __NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority)
{
if ((int32_t)(IRQn) >= 0)
{
NVIC->IP[_IP_IDX(IRQn)] = ((uint32_t)(NVIC->IP[_IP_IDX(IRQn)] & ~(0xFFUL << _BIT_SHIFT(IRQn))) |
(((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL) << _BIT_SHIFT(IRQn)));
}
else
{
SCB->SHP[_SHP_IDX(IRQn)] = ((uint32_t)(SCB->SHP[_SHP_IDX(IRQn)] & ~(0xFFUL << _BIT_SHIFT(IRQn))) |
(((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL) << _BIT_SHIFT(IRQn)));
}
}
/**
\brief Get Interrupt Priority
\details Reads the priority of a device specific interrupt or a processor exception.
The interrupt number can be positive to specify a device specific interrupt,
or negative to specify a processor exception.
\param [in] IRQn Interrupt number.
\return Interrupt Priority.
Value is aligned automatically to the implemented priority bits of the microcontroller.
*/
__STATIC_INLINE uint32_t __NVIC_GetPriority(IRQn_Type IRQn)
{
if ((int32_t)(IRQn) >= 0)
{
return((uint32_t)(((NVIC->IP[ _IP_IDX(IRQn)] >> _BIT_SHIFT(IRQn) ) & (uint32_t)0xFFUL) >> (8U - __NVIC_PRIO_BITS)));
}
else
{
return((uint32_t)(((SCB->SHP[_SHP_IDX(IRQn)] >> _BIT_SHIFT(IRQn) ) & (uint32_t)0xFFUL) >> (8U - __NVIC_PRIO_BITS)));
}
}
/**
\brief Set Interrupt Vector
\details Sets an interrupt vector in SRAM based interrupt vector table.
The interrupt number can be positive to specify a device specific interrupt,
or negative to specify a processor exception.
Address 0 must be mapped to SRAM.
\param [in] IRQn Interrupt number
\param [in] vector Address of interrupt handler function
*/
__STATIC_INLINE void __NVIC_SetVector(IRQn_Type IRQn, uint32_t vector)
{
uint32_t *vectors = (uint32_t *)0x0U;
vectors[(int32_t)IRQn + NVIC_USER_IRQ_OFFSET] = vector;
}
/**
\brief Get Interrupt Vector
\details Reads an interrupt vector from interrupt vector table.
The interrupt number can be positive to specify a device specific interrupt,
or negative to specify a processor exception.
\param [in] IRQn Interrupt number.
\return Address of interrupt handler function
*/
__STATIC_INLINE uint32_t __NVIC_GetVector(IRQn_Type IRQn)
{
uint32_t *vectors = (uint32_t *)0x0U;
return vectors[(int32_t)IRQn + NVIC_USER_IRQ_OFFSET];
}
/**
\brief System Reset
\details Initiates a system reset request to reset the MCU.
*/
__STATIC_INLINE void __NVIC_SystemReset(void)
{
__DSB(); /* Ensure all outstanding memory accesses included
buffered write are completed before reset */
SCB->AIRCR = ((0x5FAUL << SCB_AIRCR_VECTKEY_Pos) |
SCB_AIRCR_SYSRESETREQ_Msk);
__DSB(); /* Ensure completion of memory access */
for(;;) /* wait until reset */
{
__NOP();
}
}
/*@} end of CMSIS_Core_NVICFunctions */
/* ########################## FPU functions #################################### */
/**
\ingroup CMSIS_Core_FunctionInterface
\defgroup CMSIS_Core_FpuFunctions FPU Functions
\brief Function that provides FPU type.
@{
*/
/**
\brief get FPU type
\details returns the FPU type
\returns
- \b 0: No FPU
- \b 1: Single precision FPU
- \b 2: Double + Single precision FPU
*/
__STATIC_INLINE uint32_t SCB_GetFPUType(void)
{
return 0U; /* No FPU */
}
/*@} end of CMSIS_Core_FpuFunctions */
/* ################################## SysTick function ############################################ */
/**
\ingroup CMSIS_Core_FunctionInterface
\defgroup CMSIS_Core_SysTickFunctions SysTick Functions
\brief Functions that configure the System.
@{
*/
#if defined (__Vendor_SysTickConfig) && (__Vendor_SysTickConfig == 0U)
/**
\brief System Tick Configuration
\details Initializes the System Timer and its interrupt, and starts the System Tick Timer.
Counter is in free running mode to generate periodic interrupts.
\param [in] ticks Number of ticks between two interrupts.
\return 0 Function succeeded.
\return 1 Function failed.
\note When the variable <b>__Vendor_SysTickConfig</b> is set to 1, then the
function <b>SysTick_Config</b> is not included. In this case, the file <b><i>device</i>.h</b>
must contain a vendor-specific implementation of this function.
*/
__STATIC_INLINE uint32_t SysTick_Config(uint32_t ticks)
{
if ((ticks - 1UL) > SysTick_LOAD_RELOAD_Msk)
{
return (1UL); /* Reload value impossible */
}
SysTick->LOAD = (uint32_t)(ticks - 1UL); /* set reload register */
NVIC_SetPriority (SysTick_IRQn, (1UL << __NVIC_PRIO_BITS) - 1UL); /* set Priority for Systick Interrupt */
SysTick->VAL = 0UL; /* Load the SysTick Counter Value */
SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk |
SysTick_CTRL_TICKINT_Msk |
SysTick_CTRL_ENABLE_Msk; /* Enable SysTick IRQ and SysTick Timer */
return (0UL); /* Function successful */
}
#endif
/*@} end of CMSIS_Core_SysTickFunctions */
#ifdef __cplusplus
}
#endif
#endif /* __CORE_CM0_H_DEPENDANT */
#endif /* __CMSIS_GENERIC */

1012
cmsis/core_cm0plus.h Normal file

File diff suppressed because it is too large Load Diff

1876
cmsis/core_cm23.h Normal file

File diff suppressed because it is too large Load Diff

1919
cmsis/core_cm3.h Normal file

File diff suppressed because it is too large Load Diff

2896
cmsis/core_cm33.h Normal file

File diff suppressed because it is too large Load Diff

2103
cmsis/core_cm4.h Normal file

File diff suppressed because it is too large Load Diff

2646
cmsis/core_cm7.h Normal file

File diff suppressed because it is too large Load Diff

1014
cmsis/core_sc000.h Normal file

File diff suppressed because it is too large Load Diff

1901
cmsis/core_sc300.h Normal file

File diff suppressed because it is too large Load Diff

69
cmsis/tz_context.h Normal file
View File

@ -0,0 +1,69 @@
/*
* Copyright (c) 2015-2016 ARM Limited. All rights reserved.
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the License); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an AS IS BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* ----------------------------------------------------------------------------
*
* $Date: 21. September 2016
* $Revision: V1.0
*
* Project: TrustZone for ARMv8-M
* Title: Context Management for ARMv8-M TrustZone
*
* Version 1.0
* Initial Release
*---------------------------------------------------------------------------*/
#ifndef TZ_CONTEXT_H
#define TZ_CONTEXT_H
#include <stdint.h>
#ifndef TZ_MODULEID_T
#define TZ_MODULEID_T
/// \details Data type that identifies secure software modules called by a process.
typedef uint32_t TZ_ModuleId_t;
#endif
/// \details TZ Memory ID identifies an allocated memory slot.
typedef uint32_t TZ_MemoryId_t;
/// Initialize secure context memory system
/// \return execution status (1: success, 0: error)
uint32_t TZ_InitContextSystem_S (void);
/// Allocate context memory for calling secure software modules in TrustZone
/// \param[in] module identifies software modules called from non-secure mode
/// \return value != 0 id TrustZone memory slot identifier
/// \return value 0 no memory available or internal error
TZ_MemoryId_t TZ_AllocModuleContext_S (TZ_ModuleId_t module);
/// Free context memory that was previously allocated with \ref TZ_AllocModuleContext_S
/// \param[in] id TrustZone memory slot identifier
/// \return execution status (1: success, 0: error)
uint32_t TZ_FreeModuleContext_S (TZ_MemoryId_t id);
/// Load secure context (called on RTOS thread context switch)
/// \param[in] id TrustZone memory slot identifier
/// \return execution status (1: success, 0: error)
uint32_t TZ_LoadContext_S (TZ_MemoryId_t id);
/// Store secure context (called on RTOS thread context switch)
/// \param[in] id TrustZone memory slot identifier
/// \return execution status (1: success, 0: error)
uint32_t TZ_StoreContext_S (TZ_MemoryId_t id);
#endif // TZ_CONTEXT_H

898
rtos/rtx/cmsis_os.h Normal file
View File

@ -0,0 +1,898 @@
/*
* Copyright (c) 2013-2017 ARM Limited. All rights reserved.
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the License); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an AS IS BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* ----------------------------------------------------------------------
*
* $Date: 10. January 2017
* $Revision: V2.1.0
*
* Project: CMSIS-RTOS API
* Title: cmsis_os.h RTX header file
*
* Version 0.02
* Initial Proposal Phase
* Version 0.03
* osKernelStart added, optional feature: main started as thread
* osSemaphores have standard behavior
* osTimerCreate does not start the timer, added osTimerStart
* osThreadPass is renamed to osThreadYield
* Version 1.01
* Support for C++ interface
* - const attribute removed from the osXxxxDef_t typedefs
* - const attribute added to the osXxxxDef macros
* Added: osTimerDelete, osMutexDelete, osSemaphoreDelete
* Added: osKernelInitialize
* Version 1.02
* Control functions for short timeouts in microsecond resolution:
* Added: osKernelSysTick, osKernelSysTickFrequency, osKernelSysTickMicroSec
* Removed: osSignalGet
* Version 2.0.0
* OS objects creation without macros (dynamic creation and resource allocation):
* - added: osXxxxNew functions which replace osXxxxCreate
* - added: osXxxxAttr_t structures
* - deprecated: osXxxxCreate functions, osXxxxDef_t structures
* - deprecated: osXxxxDef and osXxxx macros
* osStatus codes simplified and renamed to osStatus_t
* osEvent return structure deprecated
* Kernel:
* - added: osKernelInfo_t and osKernelGetInfo
* - added: osKernelState_t and osKernelGetState (replaces osKernelRunning)
* - added: osKernelLock, osKernelUnlock
* - added: osKernelSuspend, osKernelResume
* - added: osKernelGetTickCount, osKernelGetTickFreq
* - renamed osKernelSysTick to osKernelGetSysTimerCount
* - replaced osKernelSysTickFrequency with osKernelGetSysTimerFreq
* - deprecated osKernelSysTickMicroSec
* Thread:
* - extended number of thread priorities
* - renamed osPrioriry to osPrioriry_t
* - replaced osThreadCreate with osThreadNew
* - added: osThreadGetName
* - added: osThreadState_t and osThreadGetState
* - added: osThreadGetStackSize, osThreadGetStackSpace
* - added: osThreadSuspend, osThreadResume
* - added: osThreadJoin, osThreadDetach, osThreadExit
* - added: osThreadGetCount, osThreadEnumerate
* - added: Thread Flags (moved from Signals)
* Signals:
* - renamed osSignals to osThreadFlags (moved to Thread Flags)
* - changed return value of Set/Clear/Wait functions
* - Clear function limited to current running thread
* - extended Wait function (options)
* - added: osThreadFlagsGet
* Event Flags:
* - added new independent object for handling Event Flags
* Delay and Wait functions:
* - added: osDelayUntil
* - deprecated: osWait
* Timer:
* - replaced osTimerCreate with osTimerNew
* - added: osTimerGetName, osTimerIsRunning
* Mutex:
* - extended: attributes (Recursive, Priority Inherit, Robust)
* - replaced osMutexCreate with osMutexNew
* - renamed osMutexWait to osMutexAcquire
* - added: osMutexGetName, osMutexGetOwner
* Semaphore:
* - extended: maximum and initial token count
* - replaced osSemaphoreCreate with osSemaphoreNew
* - renamed osSemaphoreWait to osSemaphoreAcquire (changed return value)
* - added: osSemaphoreGetName, osSemaphoreGetCount
* Memory Pool:
* - using osMemoryPool prefix instead of osPool
* - replaced osPoolCreate with osMemoryPoolNew
* - extended osMemoryPoolAlloc (timeout)
* - added: osMemoryPoolGetName
* - added: osMemoryPoolGetCapacity, osMemoryPoolGetBlockSize
* - added: osMemoryPoolGetCount, osMemoryPoolGetSpace
* - added: osMemoryPoolDelete
* - deprecated: osPoolCAlloc
* Message Queue:
* - extended: fixed size message instead of a single 32-bit value
* - using osMessageQueue prefix instead of osMessage
* - replaced osMessageCreate with osMessageQueueNew
* - updated: osMessageQueuePut, osMessageQueueGet
* - added: osMessageQueueGetName
* - added: osMessageQueueGetCapacity, osMessageQueueGetMsgSize
* - added: osMessageQueueGetCount, osMessageQueueGetSpace
* - added: osMessageQueueReset, osMessageQueueDelete
* Mail Queue:
* - deprecated (superseded by extended Message Queue functionality)
* Version 2.1.0
* Support for critical and uncritical sections (nesting safe):
* - updated: osKernelLock, osKernelUnlock
* - added: osKernelRestoreLock
* Updated Thread and Event Flags:
* - changed flags parameter and return type from int32_t to uint32_t
*---------------------------------------------------------------------------*/
#ifndef CMSIS_OS_H_
#define CMSIS_OS_H_
#define osCMSIS 0x20001U ///< API version (main[31:16].sub[15:0])
#define osCMSIS_RTX 0x50001U ///< RTOS identification and version (main[31:16].sub[15:0])
#define osKernelSystemId "RTX V5.1" ///< RTOS identification string
#define osFeature_MainThread 0 ///< main thread 1=main can be thread, 0=not available
#define osFeature_Signals 31U ///< maximum number of Signal Flags available per thread
#define osFeature_Semaphore 65535U ///< maximum count for \ref osSemaphoreCreate function
#define osFeature_Wait 0 ///< osWait function: 1=available, 0=not available
#define osFeature_SysTick 1 ///< osKernelSysTick functions: 1=available, 0=not available
#define osFeature_Pool 1 ///< Memory Pools: 1=available, 0=not available
#define osFeature_MessageQ 1 ///< Message Queues: 1=available, 0=not available
#define osFeature_MailQ 1 ///< Mail Queues: 1=available, 0=not available
#if defined(__CC_ARM)
#define os_InRegs __value_in_regs
#elif defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050)
#define os_InRegs __attribute__((value_in_regs))
#else
#define os_InRegs
#endif
#if (osCMSIS >= 0x20000U)
#include "cmsis_os2.h"
#else
#include <stdint.h>
#include <stddef.h>
#endif
#include "rtx_os.h"
#ifdef __cplusplus
extern "C"
{
#endif
// ==== Enumerations, structures, defines ====
/// Priority values.
#if (osCMSIS < 0x20000U)
typedef enum {
osPriorityIdle = -3, ///< Priority: idle (lowest)
osPriorityLow = -2, ///< Priority: low
osPriorityBelowNormal = -1, ///< Priority: below normal
osPriorityNormal = 0, ///< Priority: normal (default)
osPriorityAboveNormal = +1, ///< Priority: above normal
osPriorityHigh = +2, ///< Priority: high
osPriorityRealtime = +3, ///< Priority: realtime (highest)
osPriorityError = 0x84, ///< System cannot determine priority or illegal priority.
osPriorityReserved = 0x7FFFFFFF ///< Prevents enum down-size compiler optimization.
} osPriority;
#else
#define osPriority osPriority_t
#endif
/// Entry point of a thread.
typedef void (*os_pthread) (void const *argument);
/// Entry point of a timer call back function.
typedef void (*os_ptimer) (void const *argument);
/// Timer type.
#if (osCMSIS < 0x20000U)
typedef enum {
osTimerOnce = 0, ///< One-shot timer.
osTimerPeriodic = 1 ///< Repeating timer.
} os_timer_type;
#else
#define os_timer_type osTimerType_t
#endif
/// Timeout value.
#define osWaitForever 0xFFFFFFFFU ///< Wait forever timeout value.
/// Status code values returned by CMSIS-RTOS functions.
#if (osCMSIS < 0x20000U)
typedef enum {
osOK = 0, ///< Function completed; no error or event occurred.
osEventSignal = 0x08, ///< Function completed; signal event occurred.
osEventMessage = 0x10, ///< Function completed; message event occurred.
osEventMail = 0x20, ///< Function completed; mail event occurred.
osEventTimeout = 0x40, ///< Function completed; timeout occurred.
osErrorParameter = 0x80, ///< Parameter error: a mandatory parameter was missing or specified an incorrect object.
osErrorResource = 0x81, ///< Resource not available: a specified resource was not available.
osErrorTimeoutResource = 0xC1, ///< Resource not available within given time: a specified resource was not available within the timeout period.
osErrorISR = 0x82, ///< Not allowed in ISR context: the function cannot be called from interrupt service routines.
osErrorISRRecursive = 0x83, ///< Function called multiple times from ISR with same object.
osErrorPriority = 0x84, ///< System cannot determine priority or thread has illegal priority.
osErrorNoMemory = 0x85, ///< System is out of memory: it was impossible to allocate or reserve memory for the operation.
osErrorValue = 0x86, ///< Value of a parameter is out of range.
osErrorOS = 0xFF, ///< Unspecified RTOS error: run-time error but no other error message fits.
osStatusReserved = 0x7FFFFFFF ///< Prevents enum down-size compiler optimization.
} osStatus;
#else
typedef int32_t osStatus;
#define osEventSignal (0x08)
#define osEventMessage (0x10)
#define osEventMail (0x20)
#define osEventTimeout (0x40)
#define osErrorOS osError
#define osErrorTimeoutResource osErrorTimeout
#define osErrorISRRecursive (-126)
#define osErrorValue (-127)
#define osErrorPriority (-128)
#endif
// >>> the following data type definitions may be adapted towards a specific RTOS
/// Thread ID identifies the thread.
#if (osCMSIS < 0x20000U)
typedef void *osThreadId;
#else
#define osThreadId osThreadId_t
#endif
/// Timer ID identifies the timer.
#if (osCMSIS < 0x20000U)
typedef void *osTimerId;
#else
#define osTimerId osTimerId_t
#endif
/// Mutex ID identifies the mutex.
#if (osCMSIS < 0x20000U)
typedef void *osMutexId;
#else
#define osMutexId osMutexId_t
#endif
/// Semaphore ID identifies the semaphore.
#if (osCMSIS < 0x20000U)
typedef void *osSemaphoreId;
#else
#define osSemaphoreId osSemaphoreId_t
#endif
/// Pool ID identifies the memory pool.
typedef void *osPoolId;
/// Message ID identifies the message queue.
typedef void *osMessageQId;
/// Mail ID identifies the mail queue.
typedef void *osMailQId;
/// Thread Definition structure contains startup information of a thread.
#if (osCMSIS < 0x20000U)
typedef struct os_thread_def {
os_pthread pthread; ///< start address of thread function
osPriority tpriority; ///< initial thread priority
uint32_t instances; ///< maximum number of instances of that thread function
uint32_t stacksize; ///< stack size requirements in bytes; 0 is default stack size
} osThreadDef_t;
#else
typedef struct os_thread_def {
os_pthread pthread; ///< start address of thread function
osThreadAttr_t attr; ///< thread attributes
} osThreadDef_t;
#endif
/// Timer Definition structure contains timer parameters.
#if (osCMSIS < 0x20000U)
typedef struct os_timer_def {
os_ptimer ptimer; ///< start address of a timer function
} osTimerDef_t;
#else
typedef struct os_timer_def {
os_ptimer ptimer; ///< start address of a timer function
osTimerAttr_t attr; ///< timer attributes
} osTimerDef_t;
#endif
/// Mutex Definition structure contains setup information for a mutex.
#if (osCMSIS < 0x20000U)
typedef struct os_mutex_def {
uint32_t dummy; ///< dummy value
} osMutexDef_t;
#else
#define osMutexDef_t osMutexAttr_t
#endif
/// Semaphore Definition structure contains setup information for a semaphore.
#if (osCMSIS < 0x20000U)
typedef struct os_semaphore_def {
uint32_t dummy; ///< dummy value
} osSemaphoreDef_t;
#else
#define osSemaphoreDef_t osSemaphoreAttr_t
#endif
/// Definition structure for memory block allocation.
#if (osCMSIS < 0x20000U)
typedef struct os_pool_def {
uint32_t pool_sz; ///< number of items (elements) in the pool
uint32_t item_sz; ///< size of an item
void *pool; ///< pointer to memory for pool
} osPoolDef_t;
#else
typedef struct os_pool_def {
uint32_t pool_sz; ///< number of items (elements) in the pool
uint32_t item_sz; ///< size of an item
osMemoryPoolAttr_t attr; ///< memory pool attributes
} osPoolDef_t;
#endif
/// Definition structure for message queue.
#if (osCMSIS < 0x20000U)
typedef struct os_messageQ_def {
uint32_t queue_sz; ///< number of elements in the queue
void *pool; ///< memory array for messages
} osMessageQDef_t;
#else
typedef struct os_messageQ_def {
uint32_t queue_sz; ///< number of elements in the queue
osMessageQueueAttr_t attr; ///< message queue attributes
} osMessageQDef_t;
#endif
/// Definition structure for mail queue.
#if (osCMSIS < 0x20000U)
typedef struct os_mailQ_def {
uint32_t queue_sz; ///< number of elements in the queue
uint32_t item_sz; ///< size of an item
void *pool; ///< memory array for mail
} osMailQDef_t;
#else
typedef struct os_mailQ_def {
uint32_t queue_sz; ///< number of elements in the queue
uint32_t item_sz; ///< size of an item
void *mail; ///< pointer to mail
osMemoryPoolAttr_t mp_attr; ///< memory pool attributes
osMessageQueueAttr_t mq_attr; ///< message queue attributes
} osMailQDef_t;
#endif
/// Event structure contains detailed information about an event.
typedef struct {
osStatus status; ///< status code: event or error information
union {
uint32_t v; ///< message as 32-bit value
void *p; ///< message or mail as void pointer
int32_t signals; ///< signal flags
} value; ///< event value
union {
osMailQId mail_id; ///< mail id obtained by \ref osMailCreate
osMessageQId message_id; ///< message id obtained by \ref osMessageCreate
} def; ///< event definition
} osEvent;
// ==== Kernel Management Functions ====
/// Initialize the RTOS Kernel for creating objects.
/// \return status code that indicates the execution status of the function.
#if (osCMSIS < 0x20000U)
osStatus osKernelInitialize (void);
#endif
/// Start the RTOS Kernel scheduler.
/// \return status code that indicates the execution status of the function.
#if (osCMSIS < 0x20000U)
osStatus osKernelStart (void);
#endif
/// Check if the RTOS kernel is already started.
/// \return 0 RTOS is not started, 1 RTOS is started.
#if (osCMSIS < 0x20000U)
int32_t osKernelRunning(void);
#endif
#if (defined(osFeature_SysTick) && (osFeature_SysTick != 0)) // System Timer available
/// Get the RTOS kernel system timer counter.
/// \return RTOS kernel system timer as 32-bit value
#if (osCMSIS < 0x20000U)
uint32_t osKernelSysTick (void);
#else
#define osKernelSysTick osKernelGetSysTimerCount
#endif
/// The RTOS kernel system timer frequency in Hz.
/// \note Reflects the system timer setting and is typically defined in a configuration file.
#if (osCMSIS < 0x20000U)
#define osKernelSysTickFrequency 100000000
#endif
/// 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
#if (osCMSIS < 0x20000U)
#define osKernelSysTickMicroSec(microsec) (((uint64_t)microsec * (osKernelSysTickFrequency)) / 1000000)
#else
#define osKernelSysTickMicroSec(microsec) (((uint64_t)microsec * osKernelGetSysTimerFreq()) / 1000000)
#endif
#endif // System Timer available
// ==== Thread Management Functions ====
/// Create a Thread Definition with function, priority, and stack requirements.
/// \param name name of the thread function.
/// \param priority initial priority of the thread function.
/// \param instances number of possible thread instances.
/// \param stacksz stack size (in bytes) requirements for the thread function.
#if defined (osObjectsExternal) // object is external
#define osThreadDef(name, priority, instances, stacksz) \
extern const osThreadDef_t os_thread_def_##name
#else // define the object
#if (osCMSIS < 0x20000U)
#define osThreadDef(name, priority, instances, stacksz) \
const osThreadDef_t os_thread_def_##name = \
{ (name), (priority), (instances), (stacksz) }
#else
#define osThreadDef(name, priority, instances, stacksz) \
static uint64_t os_thread_stack##name[(stacksz)?(((stacksz+7)/8)):1] __attribute__((section(".bss.os.thread.stack"))); \
static osRtxThread_t os_thread_cb_##name __attribute__((section(".bss.os.thread.cb"))); \
const osThreadDef_t os_thread_def_##name = \
{ (name), \
{ NULL, osThreadDetached, \
(instances == 1) ? (&os_thread_cb_##name) : NULL,\
(instances == 1) ? osRtxThreadCbSize : 0U, \
((stacksz) && (instances == 1)) ? (&os_thread_stack##name) : NULL, \
8*((stacksz+7)/8), \
(priority), 0U, 0U } }
#endif
#endif
/// Access a Thread definition.
/// \param name name of the thread definition object.
#define osThread(name) \
&os_thread_def_##name
/// Create a thread and add it to Active Threads and set it to state READY.
/// \param[in] thread_def thread definition referenced with \ref osThread.
/// \param[in] argument pointer that is passed to the thread function as start argument.
/// \return thread ID for reference by other functions or NULL in case of error.
osThreadId osThreadCreate (const osThreadDef_t *thread_def, void *argument);
/// Return the thread ID of the current running thread.
/// \return thread ID for reference by other functions or NULL in case of error.
#if (osCMSIS < 0x20000U)
osThreadId osThreadGetId (void);
#endif
/// Change priority of a thread.
/// \param[in] thread_id thread ID obtained by \ref osThreadCreate or \ref osThreadGetId.
/// \param[in] priority new priority value for the thread function.
/// \return status code that indicates the execution status of the function.
#if (osCMSIS < 0x20000U)
osStatus osThreadSetPriority (osThreadId thread_id, osPriority priority);
#endif
/// Get current priority of a thread.
/// \param[in] thread_id thread ID obtained by \ref osThreadCreate or \ref osThreadGetId.
/// \return current priority value of the specified thread.
#if (osCMSIS < 0x20000U)
osPriority osThreadGetPriority (osThreadId thread_id);
#endif
/// Pass control to next thread that is in state \b READY.
/// \return status code that indicates the execution status of the function.
#if (osCMSIS < 0x20000U)
osStatus osThreadYield (void);
#endif
/// Terminate execution of a thread.
/// \param[in] thread_id thread ID obtained by \ref osThreadCreate or \ref osThreadGetId.
/// \return status code that indicates the execution status of the function.
#if (osCMSIS < 0x20000U)
osStatus osThreadTerminate (osThreadId thread_id);
#endif
// ==== Signal Management ====
/// Set the specified Signal Flags of an active thread.
/// \param[in] thread_id thread ID obtained by \ref osThreadCreate or \ref osThreadGetId.
/// \param[in] signals specifies the signal flags of the thread that should be set.
/// \return previous signal flags of the specified thread or 0x80000000 in case of incorrect parameters.
int32_t osSignalSet (osThreadId thread_id, int32_t signals);
/// Clear the specified Signal Flags of an active thread.
/// \param[in] thread_id thread ID obtained by \ref osThreadCreate or \ref osThreadGetId.
/// \param[in] signals specifies the signal flags of the thread that shall be cleared.
/// \return previous signal flags of the specified thread or 0x80000000 in case of incorrect parameters or call from ISR.
int32_t osSignalClear (osThreadId thread_id, int32_t signals);
/// Wait for one or more Signal Flags to become signaled for the current \b RUNNING thread.
/// \param[in] signals wait until all specified signal flags set or 0 for any single signal flag.
/// \param[in] millisec \ref CMSIS_RTOS_TimeOutValue or 0 in case of no time-out.
/// \return event flag information or error code.
os_InRegs osEvent osSignalWait (int32_t signals, uint32_t millisec);
// ==== Generic Wait Functions ====
/// Wait for Timeout (Time Delay).
/// \param[in] millisec \ref CMSIS_RTOS_TimeOutValue "time delay" value
/// \return status code that indicates the execution status of the function.
#if (osCMSIS < 0x20000U)
osStatus osDelay (uint32_t millisec);
#endif
#if (defined (osFeature_Wait) && (osFeature_Wait != 0)) // Generic Wait available
/// Wait for Signal, Message, Mail, or Timeout.
/// \param[in] millisec \ref CMSIS_RTOS_TimeOutValue or 0 in case of no time-out
/// \return event that contains signal, message, or mail information or error code.
os_InRegs osEvent osWait (uint32_t millisec);
#endif // Generic Wait available
// ==== Timer Management Functions ====
/// Define a Timer object.
/// \param name name of the timer object.
/// \param function name of the timer call back function.
#if defined (osObjectsExternal) // object is external
#define osTimerDef(name, function) \
extern const osTimerDef_t os_timer_def_##name
#else // define the object
#if (osCMSIS < 0x20000U)
#define osTimerDef(name, function) \
const osTimerDef_t os_timer_def_##name = { (function) }
#else
#define osTimerDef(name, function) \
static osRtxTimer_t os_timer_cb_##name __attribute__((section(".bss.os.timer.cb"))); \
const osTimerDef_t os_timer_def_##name = \
{ (function), { NULL, 0U, (&os_timer_cb_##name), osRtxTimerCbSize } }
#endif
#endif
/// Access a Timer definition.
/// \param name name of the timer object.
#define osTimer(name) \
&os_timer_def_##name
/// Create and Initialize a timer.
/// \param[in] timer_def timer object referenced with \ref osTimer.
/// \param[in] type osTimerOnce for one-shot or osTimerPeriodic for periodic behavior.
/// \param[in] argument argument to the timer call back function.
/// \return timer ID for reference by other functions or NULL in case of error.
osTimerId osTimerCreate (const osTimerDef_t *timer_def, os_timer_type type, void *argument);
/// Start or restart a timer.
/// \param[in] timer_id timer ID obtained by \ref osTimerCreate.
/// \param[in] millisec \ref CMSIS_RTOS_TimeOutValue "time delay" value of the timer.
/// \return status code that indicates the execution status of the function.
#if (osCMSIS < 0x20000U)
osStatus osTimerStart (osTimerId timer_id, uint32_t millisec);
#endif
/// Stop a timer.
/// \param[in] timer_id timer ID obtained by \ref osTimerCreate.
/// \return status code that indicates the execution status of the function.
#if (osCMSIS < 0x20000U)
osStatus osTimerStop (osTimerId timer_id);
#endif
/// Delete a timer.
/// \param[in] timer_id timer ID obtained by \ref osTimerCreate.
/// \return status code that indicates the execution status of the function.
#if (osCMSIS < 0x20000U)
osStatus osTimerDelete (osTimerId timer_id);
#endif
// ==== Mutex Management Functions ====
/// Define a Mutex.
/// \param name name of the mutex object.
#if defined (osObjectsExternal) // object is external
#define osMutexDef(name) \
extern const osMutexDef_t os_mutex_def_##name
#else // define the object
#if (osCMSIS < 0x20000U)
#define osMutexDef(name) \
const osMutexDef_t os_mutex_def_##name = { 0 }
#else
#define osMutexDef(name) \
static osRtxMutex_t os_mutex_cb_##name __attribute__((section(".bss.os.mutex.cb"))); \
const osMutexDef_t os_mutex_def_##name = \
{ NULL, osMutexRecursive | osMutexPrioInherit | osMutexRobust, (&os_mutex_cb_##name), osRtxMutexCbSize }
#endif
#endif
/// Access a Mutex definition.
/// \param name name of the mutex object.
#define osMutex(name) \
&os_mutex_def_##name
/// Create and Initialize a Mutex object.
/// \param[in] mutex_def mutex definition referenced with \ref osMutex.
/// \return mutex ID for reference by other functions or NULL in case of error.
osMutexId osMutexCreate (const osMutexDef_t *mutex_def);
/// Wait until a Mutex becomes available.
/// \param[in] mutex_id mutex ID obtained by \ref osMutexCreate.
/// \param[in] millisec \ref CMSIS_RTOS_TimeOutValue or 0 in case of no time-out.
/// \return status code that indicates the execution status of the function.
#if (osCMSIS < 0x20000U)
osStatus osMutexWait (osMutexId mutex_id, uint32_t millisec);
#else
#define osMutexWait osMutexAcquire
#endif
/// Release a Mutex that was obtained by \ref osMutexWait.
/// \param[in] mutex_id mutex ID obtained by \ref osMutexCreate.
/// \return status code that indicates the execution status of the function.
#if (osCMSIS < 0x20000U)
osStatus osMutexRelease (osMutexId mutex_id);
#endif
/// Delete a Mutex object.
/// \param[in] mutex_id mutex ID obtained by \ref osMutexCreate.
/// \return status code that indicates the execution status of the function.
#if (osCMSIS < 0x20000U)
osStatus osMutexDelete (osMutexId mutex_id);
#endif
// ==== Semaphore Management Functions ====
#if (defined (osFeature_Semaphore) && (osFeature_Semaphore != 0U)) // Semaphore available
/// Define a Semaphore object.
/// \param name name of the semaphore object.
#if defined (osObjectsExternal) // object is external
#define osSemaphoreDef(name) \
extern const osSemaphoreDef_t os_semaphore_def_##name
#else // define the object
#if (osCMSIS < 0x20000U)
#define osSemaphoreDef(name) \
const osSemaphoreDef_t os_semaphore_def_##name = { 0 }
#else
#define osSemaphoreDef(name) \
static osRtxSemaphore_t os_semaphore_cb_##name __attribute__((section(".bss.os.semaphore.cb"))); \
const osSemaphoreDef_t os_semaphore_def_##name = \
{ NULL, 0U, (&os_semaphore_cb_##name), osRtxSemaphoreCbSize }
#endif
#endif
/// Access a Semaphore definition.
/// \param name name of the semaphore object.
#define osSemaphore(name) \
&os_semaphore_def_##name
/// Create and Initialize a Semaphore object.
/// \param[in] semaphore_def semaphore definition referenced with \ref osSemaphore.
/// \param[in] count maximum and initial number of available tokens.
/// \return semaphore ID for reference by other functions or NULL in case of error.
osSemaphoreId osSemaphoreCreate (const osSemaphoreDef_t *semaphore_def, int32_t count);
/// Wait until a Semaphore token becomes available.
/// \param[in] semaphore_id semaphore object referenced with \ref osSemaphoreCreate.
/// \param[in] millisec \ref CMSIS_RTOS_TimeOutValue or 0 in case of no time-out.
/// \return number of available tokens, or -1 in case of incorrect parameters.
int32_t osSemaphoreWait (osSemaphoreId semaphore_id, uint32_t millisec);
/// Release a Semaphore token.
/// \param[in] semaphore_id semaphore object referenced with \ref osSemaphoreCreate.
/// \return status code that indicates the execution status of the function.
#if (osCMSIS < 0x20000U)
osStatus osSemaphoreRelease (osSemaphoreId semaphore_id);
#endif
/// Delete a Semaphore object.
/// \param[in] semaphore_id semaphore object referenced with \ref osSemaphoreCreate.
/// \return status code that indicates the execution status of the function.
#if (osCMSIS < 0x20000U)
osStatus osSemaphoreDelete (osSemaphoreId semaphore_id);
#endif
#endif // Semaphore available
// ==== Memory Pool Management Functions ====
#if (defined(osFeature_Pool) && (osFeature_Pool != 0)) // Memory Pool available
/// \brief Define a Memory Pool.
/// \param name name of the memory pool.
/// \param no maximum number of blocks (objects) in the memory pool.
/// \param type data type of a single block (object).
#if defined (osObjectsExternal) // object is external
#define osPoolDef(name, no, type) \
extern const osPoolDef_t os_pool_def_##name
#else // define the object
#if (osCMSIS < 0x20000U)
#define osPoolDef(name, no, type) \
const osPoolDef_t os_pool_def_##name = \
{ (no), sizeof(type), NULL }
#else
#define osPoolDef(name, no, type) \
static osRtxMemoryPool_t os_mp_cb_##name __attribute__((section(".bss.os.mempool.cb"))); \
static uint32_t os_mp_data_##name[osRtxMemoryPoolMemSize((no),sizeof(type))/4] __attribute__((section(".bss.os.mempool.mem"))); \
const osPoolDef_t os_pool_def_##name = \
{ (no), sizeof(type), \
{ NULL, 0U, (&os_mp_cb_##name), osRtxMemoryPoolCbSize, \
(&os_mp_data_##name), sizeof(os_mp_data_##name) } }
#endif
#endif
/// \brief Access a Memory Pool definition.
/// \param name name of the memory pool
#define osPool(name) \
&os_pool_def_##name
/// Create and Initialize a Memory Pool object.
/// \param[in] pool_def memory pool definition referenced with \ref osPool.
/// \return memory pool ID for reference by other functions or NULL in case of error.
osPoolId osPoolCreate (const osPoolDef_t *pool_def);
/// Allocate a memory block from a Memory Pool.
/// \param[in] pool_id memory pool ID obtain referenced with \ref osPoolCreate.
/// \return address of the allocated memory block or NULL in case of no memory available.
void *osPoolAlloc (osPoolId pool_id);
/// Allocate a memory block from a Memory Pool and set memory block to zero.
/// \param[in] pool_id memory pool ID obtain referenced with \ref osPoolCreate.
/// \return address of the allocated memory block or NULL in case of no memory available.
void *osPoolCAlloc (osPoolId pool_id);
/// Return an allocated memory block back to a Memory Pool.
/// \param[in] pool_id memory pool ID obtain referenced with \ref osPoolCreate.
/// \param[in] block address of the allocated memory block to be returned to the memory pool.
/// \return status code that indicates the execution status of the function.
osStatus osPoolFree (osPoolId pool_id, void *block);
#endif // Memory Pool available
// ==== Message Queue Management Functions ====
#if (defined(osFeature_MessageQ) && (osFeature_MessageQ != 0)) // Message Queue available
/// \brief Create a Message Queue Definition.
/// \param name name of the queue.
/// \param queue_sz maximum number of messages in the queue.
/// \param type data type of a single message element (for debugger).
#if defined (osObjectsExternal) // object is external
#define osMessageQDef(name, queue_sz, type) \
extern const osMessageQDef_t os_messageQ_def_##name
#else // define the object
#if (osCMSIS < 0x20000U)
#define osMessageQDef(name, queue_sz, type) \
const osMessageQDef_t os_messageQ_def_##name = \
{ (queue_sz), NULL }
#else
#define osMessageQDef(name, queue_sz, type) \
static osRtxMessageQueue_t os_mq_cb_##name __attribute__((section(".bss.os.msgqueue.cb"))); \
static uint32_t os_mq_data_##name[osRtxMessageQueueMemSize((queue_sz),sizeof(uint32_t))/4] __attribute__((section(".bss.os.msgqueue.mem"))); \
const osMessageQDef_t os_messageQ_def_##name = \
{ (queue_sz), \
{ NULL, 0U, (&os_mq_cb_##name), osRtxMessageQueueCbSize, \
(&os_mq_data_##name), sizeof(os_mq_data_##name) } }
#endif
#endif
/// \brief Access a Message Queue Definition.
/// \param name name of the queue
#define osMessageQ(name) \
&os_messageQ_def_##name
/// Create and Initialize a Message Queue object.
/// \param[in] queue_def message queue definition referenced with \ref osMessageQ.
/// \param[in] thread_id thread ID (obtained by \ref osThreadCreate or \ref osThreadGetId) or NULL.
/// \return message queue ID for reference by other functions or NULL in case of error.
osMessageQId osMessageCreate (const osMessageQDef_t *queue_def, osThreadId thread_id);
/// Put a Message to a Queue.
/// \param[in] queue_id message queue ID obtained with \ref osMessageCreate.
/// \param[in] info message information.
/// \param[in] millisec \ref CMSIS_RTOS_TimeOutValue or 0 in case of no time-out.
/// \return status code that indicates the execution status of the function.
osStatus osMessagePut (osMessageQId queue_id, uint32_t info, uint32_t millisec);
/// Get a Message from a Queue or timeout if Queue is empty.
/// \param[in] queue_id message queue ID obtained with \ref osMessageCreate.
/// \param[in] millisec \ref CMSIS_RTOS_TimeOutValue or 0 in case of no time-out.
/// \return event information that includes status code.
os_InRegs osEvent osMessageGet (osMessageQId queue_id, uint32_t millisec);
#endif // Message Queue available
// ==== Mail Queue Management Functions ====
#if (defined(osFeature_MailQ) && (osFeature_MailQ != 0)) // Mail Queue available
/// \brief Create a Mail Queue Definition.
/// \param name name of the queue.
/// \param queue_sz maximum number of mails in the queue.
/// \param type data type of a single mail element.
#if defined (osObjectsExternal) // object is external
#define osMailQDef(name, queue_sz, type) \
extern const osMailQDef_t os_mailQ_def_##name
#else // define the object
#if (osCMSIS < 0x20000U)
#define osMailQDef(name, queue_sz, type) \
const osMailQDef_t os_mailQ_def_##name = \
{ (queue_sz), sizeof(type), NULL }
#else
#define osMailQDef(name, queue_sz, type) \
static void *os_mail_p_##name[2] __attribute__((section(".bss.os"))); \
static osRtxMemoryPool_t os_mail_mp_cb_##name __attribute__((section(".bss.os.mempool.cb"))); \
static osRtxMessageQueue_t os_mail_mq_cb_##name __attribute__((section(".bss.os.msgqueue.cb"))); \
static uint32_t os_mail_mp_data_##name[osRtxMemoryPoolMemSize ((queue_sz),sizeof(type) )/4] __attribute__((section(".bss.os.mempool.mem"))); \
static uint32_t os_mail_mq_data_##name[osRtxMessageQueueMemSize((queue_sz),sizeof(void*))/4] __attribute__((section(".bss.os.msgqueue.mem"))); \
const osMailQDef_t os_mailQ_def_##name = \
{ (queue_sz), sizeof(type), (&os_mail_p_##name), \
{ NULL, 0U, (&os_mail_mp_cb_##name), osRtxMemoryPoolCbSize, \
(&os_mail_mp_data_##name), sizeof(os_mail_mp_data_##name) }, \
{ NULL, 0U, (&os_mail_mq_cb_##name), osRtxMessageQueueCbSize, \
(&os_mail_mq_data_##name), sizeof(os_mail_mq_data_##name) } }
#endif
#endif
/// \brief Access a Mail Queue Definition.
/// \param name name of the queue
#define osMailQ(name) \
&os_mailQ_def_##name
/// Create and Initialize a Mail Queue object.
/// \param[in] queue_def mail queue definition referenced with \ref osMailQ.
/// \param[in] thread_id thread ID (obtained by \ref osThreadCreate or \ref osThreadGetId) or NULL.
/// \return mail queue ID for reference by other functions or NULL in case of error.
osMailQId osMailCreate (const osMailQDef_t *queue_def, osThreadId thread_id);
/// Allocate a memory block for mail from a mail memory pool.
/// \param[in] queue_id mail queue ID obtained with \ref osMailCreate.
/// \param[in] millisec \ref CMSIS_RTOS_TimeOutValue or 0 in case of no time-out
/// \return pointer to memory block that can be filled with mail or NULL in case of error.
void *osMailAlloc (osMailQId queue_id, uint32_t millisec);
/// Allocate a memory block for mail from a mail memory pool and set memory block to zero.
/// \param[in] queue_id mail queue ID obtained with \ref osMailCreate.
/// \param[in] millisec \ref CMSIS_RTOS_TimeOutValue or 0 in case of no time-out
/// \return pointer to memory block that can be filled with mail or NULL in case of error.
void *osMailCAlloc (osMailQId queue_id, uint32_t millisec);
/// Put a Mail into a Queue.
/// \param[in] queue_id mail queue ID obtained with \ref osMailCreate.
/// \param[in] mail pointer to memory with mail to put into a queue.
/// \return status code that indicates the execution status of the function.
osStatus osMailPut (osMailQId queue_id, const void *mail);
/// Get a Mail from a Queue or timeout if Queue is empty.
/// \param[in] queue_id mail queue ID obtained with \ref osMailCreate.
/// \param[in] millisec \ref CMSIS_RTOS_TimeOutValue or 0 in case of no time-out.
/// \return event information that includes status code.
os_InRegs osEvent osMailGet (osMailQId queue_id, uint32_t millisec);
/// Free a memory block by returning it to a mail memory pool.
/// \param[in] queue_id mail queue ID obtained with \ref osMailCreate.
/// \param[in] mail pointer to memory block that was obtained with \ref osMailGet.
/// \return status code that indicates the execution status of the function.
osStatus osMailFree (osMailQId queue_id, void *mail);
#endif // Mail Queue available
#ifdef __cplusplus
}
#endif
#endif // CMSIS_OS_H_

371
rtos/rtx/cmsis_os1.c Normal file
View File

@ -0,0 +1,371 @@
/*
* Copyright (c) 2013-2017 ARM Limited. All rights reserved.
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the License); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an AS IS BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* ----------------------------------------------------------------------
*
* $Date: 10. January 2017
* $Revision: V1.2
*
* Project: CMSIS-RTOS API V1
* Title: cmsis_os_v1.c V1 module file
*---------------------------------------------------------------------------*/
#include <string.h>
#include "cmsis_os.h"
#if (osCMSIS >= 0x20000U) && !defined(os1_Disable)
// Thread
#if !defined(os1_Disable_Thread)
osThreadId osThreadCreate (const osThreadDef_t *thread_def, void *argument) {
if (thread_def == NULL) {
return NULL;
}
return osThreadNew((osThreadFunc_t)thread_def->pthread, argument, &thread_def->attr);
}
#endif
// Signals
#if !defined(os1_Disable_Signal)
#define SignalMask ((1U<<osFeature_Signals)-1U)
int32_t osSignalSet (osThreadId thread_id, int32_t signals) {
uint32_t flags;
flags = osThreadFlagsSet(thread_id, (uint32_t)signals);
if ((flags & 0x80000000U) != 0U) {
return ((int32_t)0x80000000U);
}
return ((int32_t)(flags & ~((uint32_t)signals)));
}
int32_t osSignalClear (osThreadId thread_id, int32_t signals) {
uint32_t flags;
if (thread_id != osThreadGetId()) {
return ((int32_t)0x80000000U);
}
flags = osThreadFlagsClear((uint32_t)signals);
if ((flags & 0x80000000U) != 0U) {
return ((int32_t)0x80000000U);
}
return ((int32_t)flags);
}
os_InRegs osEvent osSignalWait (int32_t signals, uint32_t millisec) {
osEvent event;
uint32_t flags;
if (signals != 0) {
flags = osThreadFlagsWait((uint32_t)signals, osFlagsWaitAll, millisec);
} else {
flags = osThreadFlagsWait(SignalMask, osFlagsWaitAny, millisec);
}
if ((flags > 0U) && (flags < 0x80000000U)) {
event.status = osEventSignal;
event.value.signals = (int32_t)flags;
} else {
switch ((int32_t)flags) {
case osErrorResource:
event.status = osOK;
break;
case osErrorTimeout:
event.status = osEventTimeout;
break;
case osErrorParameter:
event.status = osErrorValue;
break;
default:
event.status = (osStatus)flags;
break;
}
}
return event;
}
#endif // Signal
// Timer
#if !defined(os1_Disable_Timer)
osTimerId osTimerCreate (const osTimerDef_t *timer_def, os_timer_type type, void *argument) {
if (timer_def == NULL) {
return NULL;
}
return osTimerNew((osTimerFunc_t)timer_def->ptimer, type, argument, &timer_def->attr);
}
#endif
// Mutex
#if !defined(os1_Disable_Mutex)
osMutexId osMutexCreate (const osMutexDef_t *mutex_def) {
if (mutex_def == NULL) {
return NULL;
}
return osMutexNew(mutex_def);
}
#endif
// Semaphore
#if (defined (osFeature_Semaphore) && (osFeature_Semaphore != 0U)) && !defined(os1_Disable_Semaphore)
osSemaphoreId osSemaphoreCreate (const osSemaphoreDef_t *semaphore_def, int32_t count) {
if (semaphore_def == NULL) {
return NULL;
}
return osSemaphoreNew((uint32_t)count, (uint32_t)count, semaphore_def);
}
int32_t osSemaphoreWait (osSemaphoreId semaphore_id, uint32_t millisec) {
osStatus_t status;
uint32_t count;
status = osSemaphoreAcquire(semaphore_id, millisec);
switch (status) {
case osOK:
count = osSemaphoreGetCount(semaphore_id);
return ((int32_t)count + 1);
case osErrorResource:
case osErrorTimeout:
return 0;
default:
break;
}
return -1;
}
#endif // Semaphore
// Memory Pool
#if (defined(osFeature_Pool) && (osFeature_Pool != 0))&& !defined(os1_Disable_Pool)
osPoolId osPoolCreate (const osPoolDef_t *pool_def) {
if (pool_def == NULL) {
return NULL;
}
return osMemoryPoolNew(pool_def->pool_sz, pool_def->item_sz, &pool_def->attr);
}
void *osPoolAlloc (osPoolId pool_id) {
return osMemoryPoolAlloc(pool_id, 0U);
}
void *osPoolCAlloc (osPoolId pool_id) {
void *block;
uint32_t block_size;
block_size = osMemoryPoolGetBlockSize((osMemoryPoolId_t)pool_id);
if (block_size == 0U) {
return NULL;
}
block = osMemoryPoolAlloc(pool_id, 0U);
if (block != NULL) {
memset(block, 0, block_size);
}
return block;
}
osStatus osPoolFree (osPoolId pool_id, void *block) {
return osMemoryPoolFree(pool_id, block);
}
#endif // Memory Pool
// Message Queue
#if (defined(osFeature_MessageQ) && (osFeature_MessageQ != 0)) && !defined(os1_Disable_MessageQ)
osMessageQId osMessageCreate (const osMessageQDef_t *queue_def, osThreadId thread_id) {
(void)thread_id;
if (queue_def == NULL) {
return NULL;
}
return osMessageQueueNew(queue_def->queue_sz, sizeof(uint32_t), &queue_def->attr);
}
osStatus osMessagePut (osMessageQId queue_id, uint32_t info, uint32_t millisec) {
return osMessageQueuePut(queue_id, &info, 0U, millisec);
}
os_InRegs osEvent osMessageGet (osMessageQId queue_id, uint32_t millisec) {
osStatus_t status;
osEvent event;
uint32_t message;
status = osMessageQueueGet(queue_id, &message, NULL, millisec);
switch (status) {
case osOK:
event.status = osEventMessage;
event.value.v = message;
break;
case osErrorResource:
event.status = osOK;
break;
case osErrorTimeout:
event.status = osEventTimeout;
break;
default:
event.status = status;
break;
}
return event;
}
#endif // Message Queue
// Mail Queue
#if (defined(osFeature_MailQ) && (osFeature_MailQ != 0)) && !defined(os1_Disable_MailQ)
typedef struct os_mail_queue_s {
osMemoryPoolId_t mp_id;
osMessageQueueId_t mq_id;
} os_mail_queue_t;
osMailQId osMailCreate (const osMailQDef_t *queue_def, osThreadId thread_id) {
os_mail_queue_t *ptr;
(void)thread_id;
if (queue_def == NULL) {
return NULL;
}
ptr = queue_def->mail;
if (ptr == NULL) {
return NULL;
}
ptr->mp_id = osMemoryPoolNew (queue_def->queue_sz, queue_def->item_sz, &queue_def->mp_attr);
ptr->mq_id = osMessageQueueNew(queue_def->queue_sz, sizeof(void *), &queue_def->mq_attr);
if ((ptr->mp_id == NULL) || (ptr->mq_id == NULL)) {
if (ptr->mp_id != NULL) {
osMemoryPoolDelete(ptr->mp_id);
}
if (ptr->mq_id != NULL) {
osMessageQueueDelete(ptr->mq_id);
}
return NULL;
}
return ptr;
}
void *osMailAlloc (osMailQId queue_id, uint32_t millisec) {
os_mail_queue_t *ptr = (os_mail_queue_t *)queue_id;
if (ptr == NULL) {
return NULL;
}
return osMemoryPoolAlloc(ptr->mp_id, millisec);
}
void *osMailCAlloc (osMailQId queue_id, uint32_t millisec) {
os_mail_queue_t *ptr = (os_mail_queue_t *)queue_id;
void *block;
uint32_t block_size;
if (ptr == NULL) {
return NULL;
}
block_size = osMemoryPoolGetBlockSize(ptr->mp_id);
if (block_size == 0U) {
return NULL;
}
block = osMemoryPoolAlloc(ptr->mp_id, millisec);
if (block != NULL) {
memset(block, 0, block_size);
}
return block;
}
osStatus osMailPut (osMailQId queue_id, const void *mail) {
os_mail_queue_t *ptr = (os_mail_queue_t *)queue_id;
if (ptr == NULL) {
return osErrorParameter;
}
if (mail == NULL) {
return osErrorValue;
}
return osMessageQueuePut(ptr->mq_id, &mail, 0U, 0U);
}
os_InRegs osEvent osMailGet (osMailQId queue_id, uint32_t millisec) {
os_mail_queue_t *ptr = (os_mail_queue_t *)queue_id;
osStatus_t status;
osEvent event;
void *mail;
if (ptr == NULL) {
event.status = osErrorParameter;
return event;
}
status = osMessageQueueGet(ptr->mq_id, &mail, NULL, millisec);
switch (status) {
case osOK:
event.status = osEventMail;
event.value.p = mail;
break;
case osErrorResource:
event.status = osOK;
break;
case osErrorTimeout:
event.status = osEventTimeout;
break;
default:
event.status = status;
break;
}
return event;
}
osStatus osMailFree (osMailQId queue_id, void *mail) {
os_mail_queue_t *ptr = (os_mail_queue_t *)queue_id;
if (ptr == NULL) {
return osErrorParameter;
}
if (mail == NULL) {
return osErrorValue;
}
return osMemoryPoolFree(ptr->mp_id, mail);
}
#endif // Mail Queue
#endif // osCMSIS

View File

@ -0,0 +1,63 @@
/*
* Copyright (c) 2013-2017 ARM Limited. All rights reserved.
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the License); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an AS IS BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* -----------------------------------------------------------------------------
*
* $Revision: V5.1.0
*
* Project: CMSIS-RTOS RTX
* Title: RTX Configuration
*
* -----------------------------------------------------------------------------
*/
#include "cmsis_compiler.h"
#include "rtx_os.h"
// OS Idle Thread
__WEAK __NO_RETURN void osRtxIdleThread (void *argument) {
(void)argument;
for (;;) {}
}
// OS Error Callback function
__WEAK uint32_t osRtxErrorNotify (uint32_t code, void *object_id) {
(void)object_id;
switch (code) {
case osRtxErrorStackUnderflow:
// Stack underflow detected for thread (thread_id=object_id)
break;
case osRtxErrorISRQueueOverflow:
// ISR Queue overflow detected when inserting object (object_id)
break;
case osRtxErrorTimerQueueOverflow:
// User Timer Callback Queue overflow detected for timer (timer_id=object_id)
break;
case osRtxErrorClibSpace:
// Standard C/C++ library libspace not available: increase OS_THREAD_LIBSPACE_NUM
break;
case osRtxErrorClibMutex:
// Standard C/C++ library mutex initialization failed
break;
default:
break;
}
for (;;) {}
//return 0U;
}

View File

@ -0,0 +1,379 @@
/*
* Copyright (c) 2013-2017 ARM Limited. All rights reserved.
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the License); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an AS IS BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* -----------------------------------------------------------------------------
*
* $Revision: V5.1.0
*
* Project: CMSIS-RTOS RTX
* Title: RTX Configuration definitions
*
* -----------------------------------------------------------------------------
*/
#ifndef RTX_CONFIG_H_
#define RTX_CONFIG_H_
//-------- <<< Use Configuration Wizard in Context Menu >>> --------------------
// <h>System Configuration
// =======================
// <o>Global Dynamic Memory size [bytes] <0-1073741824:8>
// <i> Defines the combined global dynamic memory size.
// <i> Default: 4096
#ifndef OS_DYNAMIC_MEM_SIZE
#define OS_DYNAMIC_MEM_SIZE 4096
#endif
// <o>Kernel Tick Frequency [Hz] <1-1000000>
// <i> Defines base time unit for delays and timeouts.
// <i> Default: 1000 (1ms tick)
#ifndef OS_TICK_FREQ
#define OS_TICK_FREQ 1000
#endif
// <e>Round-Robin Thread switching
// <i> Enables Round-Robin Thread switching.
#ifndef OS_ROBIN_ENABLE
#define OS_ROBIN_ENABLE 1
#endif
// <o>Round-Robin Timeout <1-1000>
// <i> Defines how many ticks a thread will execute before a thread switch.
// <i> Default: 5
#ifndef OS_ROBIN_TIMEOUT
#define OS_ROBIN_TIMEOUT 5
#endif
// </e>
// <h>Event Recording
// <q>Memory Management
// <i> Enables Memory Management events recording.
#ifndef OS_EVR_MEMORY
#define OS_EVR_MEMORY 1
#endif
// <q>Kernel
// <i> Enables Kernel events recording.
#ifndef OS_EVR_KERNEL
#define OS_EVR_KERNEL 1
#endif
// <q>Thread
// <i> Enables Thread events recording.
#ifndef OS_EVR_THREAD
#define OS_EVR_THREAD 1
#endif
// <q>Timer
// <i> Enables Timer events recording.
#ifndef OS_EVR_TIMER
#define OS_EVR_TIMER 1
#endif
// <q>Event Flags
// <i> Enables Event Flags events recording.
#ifndef OS_EVR_EVFLAGS
#define OS_EVR_EVFLAGS 1
#endif
// <q>Mutex
// <i> Enables Mutex events recording.
#ifndef OS_EVR_MUTEX
#define OS_EVR_MUTEX 1
#endif
// <q>Semaphore
// <i> Enables Semaphore events recording.
#ifndef OS_EVR_SEMAPHORE
#define OS_EVR_SEMAPHORE 1
#endif
// <q>Memory Pool
// <i> Enables Memory Pool events recording.
#ifndef OS_EVR_MEMPOOL
#define OS_EVR_MEMPOOL 1
#endif
// <q>Message Queue
// <i> Enables Message Queue events recording.
#ifndef OS_EVR_MSGQUEUE
#define OS_EVR_MSGQUEUE 1
#endif
// </h>
// <o>ISR FIFO Queue
// <4=> 4 entries <8=> 8 entries <12=> 12 entries <16=> 16 entries
// <24=> 24 entries <32=> 32 entries <48=> 48 entries <64=> 64 entries
// <96=> 96 entries <128=> 128 entries <196=> 196 entries <256=> 256 entries
// <i> RTOS Functions called from ISR store requests to this buffer.
// <i> Default: 16 entries
#ifndef OS_ISR_FIFO_QUEUE
#define OS_ISR_FIFO_QUEUE 16
#endif
// </h>
// <h>Thread Configuration
// =======================
// <e>Object specific Memory allocation
// <i> Enables object specific memory allocation.
#ifndef OS_THREAD_OBJ_MEM
#define OS_THREAD_OBJ_MEM 0
#endif
// <o>Number of user Threads <1-1000>
// <i> Defines maximum number of user threads that can be active at the same time.
// <i> Applies to user threads with system provided memory for control blocks.
#ifndef OS_THREAD_NUM
#define OS_THREAD_NUM 1
#endif
// <o>Number of user Threads with default Stack size <0-1000>
// <i> Defines maximum number of user threads with default stack size.
// <i> Applies to user threads with zero stack size specified.
#ifndef OS_THREAD_DEF_STACK_NUM
#define OS_THREAD_DEF_STACK_NUM 0
#endif
// <o>Total Stack size [bytes] for user Threads with user-provided Stack size <0-1073741824:8>
// <i> Defines the combined stack size for user threads with user-provided stack size.
// <i> Applies to user threads with user-provided stack size and system provided memory for stack.
// <i> Default: 0
#ifndef OS_THREAD_USER_STACK_SIZE
#define OS_THREAD_USER_STACK_SIZE 0
#endif
// </e>
// <o>Default Thread Stack size [bytes] <96-1073741824:8>
// <i> Defines stack size for threads with zero stack size specified.
// <i> Default: 200
#ifndef OS_STACK_SIZE
#define OS_STACK_SIZE 200
#endif
// <o>Idle Thread Stack size [bytes] <72-1073741824:8>
// <i> Defines stack size for Idle thread.
// <i> Default: 200
#ifndef OS_IDLE_THREAD_STACK_SIZE
#define OS_IDLE_THREAD_STACK_SIZE 200
#endif
// <q>Stack overrun checking
// <i> Enable stack overrun checks at thread switch.
// <i> Enabling this option increases slightly the execution time of a thread switch.
#ifndef OS_STACK_CHECK
#define OS_STACK_CHECK 1
#endif
// <q>Stack usage watermark
// <i> Initialize thread stack with watermark pattern for analyzing stack usage.
// <i> Enabling this option increases significantly the execution time of thread creation.
#ifndef OS_STACK_WATERMARK
#define OS_STACK_WATERMARK 0
#endif
// <o>Processor mode for Thread execution
// <0=> Unprivileged mode
// <1=> Privileged mode
// <i> Default: Privileged mode
#ifndef OS_PRIVILEGE_MODE
#define OS_PRIVILEGE_MODE 1
#endif
// </h>
// <h>Timer Configuration
// ======================
// <e>Object specific Memory allocation
// <i> Enables object specific memory allocation.
#ifndef OS_TIMER_OBJ_MEM
#define OS_TIMER_OBJ_MEM 0
#endif
// <o>Number of Timer objects <1-1000>
// <i> Defines maximum number of objects that can be active at the same time.
// <i> Applies to objects with system provided memory for control blocks.
#ifndef OS_TIMER_NUM
#define OS_TIMER_NUM 1
#endif
// </e>
// <o>Timer Thread Priority
// <8=> Low
// <16=> Below Normal <24=> Normal <32=> Above Normal
// <40=> High
// <48=> Realtime
// <i> Defines priority for timer thread
// <i> Default: High
#ifndef OS_TIMER_THREAD_PRIO
#define OS_TIMER_THREAD_PRIO 40
#endif
// <o>Timer Thread Stack size [bytes] <0-1073741824:8>
// <i> Defines stack size for Timer thread.
// <i> May be set to 0 when timers are not used.
// <i> Default: 200
#ifndef OS_TIMER_THREAD_STACK_SIZE
#define OS_TIMER_THREAD_STACK_SIZE 200
#endif
// <o>Timer Callback Queue entries <0-256>
// <i> Number of concurrent active timer callback functions.
// <i> May be set to 0 when timers are not used.
// <i> Default: 4
#ifndef OS_TIMER_CB_QUEUE
#define OS_TIMER_CB_QUEUE 4
#endif
// </h>
// <h>Event Flags Configuration
// ============================
// <e>Object specific Memory allocation
// <i> Enables object specific memory allocation.
#ifndef OS_EVFLAGS_OBJ_MEM
#define OS_EVFLAGS_OBJ_MEM 0
#endif
// <o>Number of Event Flags objects <1-1000>
// <i> Defines maximum number of objects that can be active at the same time.
// <i> Applies to objects with system provided memory for control blocks.
#ifndef OS_EVFLAGS_NUM
#define OS_EVFLAGS_NUM 1
#endif
// </e>
// </h>
// <h>Mutex Configuration
// ======================
// <e>Object specific Memory allocation
// <i> Enables object specific memory allocation.
#ifndef OS_MUTEX_OBJ_MEM
#define OS_MUTEX_OBJ_MEM 0
#endif
// <o>Number of Mutex objects <1-1000>
// <i> Defines maximum number of objects that can be active at the same time.
// <i> Applies to objects with system provided memory for control blocks.
#ifndef OS_MUTEX_NUM
#define OS_MUTEX_NUM 1
#endif
// </e>
// </h>
// <h>Semaphore Configuration
// ==========================
// <e>Object specific Memory allocation
// <i> Enables object specific memory allocation.
#ifndef OS_SEMAPHORE_OBJ_MEM
#define OS_SEMAPHORE_OBJ_MEM 0
#endif
// <o>Number of Semaphore objects <1-1000>
// <i> Defines maximum number of objects that can be active at the same time.
// <i> Applies to objects with system provided memory for control blocks.
#ifndef OS_SEMAPHORE_NUM
#define OS_SEMAPHORE_NUM 1
#endif
// </e>
// </h>
// <h>Memory Pool Configuration
// ============================
// <e>Object specific Memory allocation
// <i> Enables object specific memory allocation.
#ifndef OS_MEMPOOL_OBJ_MEM
#define OS_MEMPOOL_OBJ_MEM 0
#endif
// <o>Number of Memory Pool objects <1-1000>
// <i> Defines maximum number of objects that can be active at the same time.
// <i> Applies to objects with system provided memory for control blocks.
#ifndef OS_MEMPOOL_NUM
#define OS_MEMPOOL_NUM 1
#endif
// <o>Data Storage Memory size [bytes] <0-1073741824:8>
// <i> Defines the combined data storage memory size.
// <i> Applies to objects with system provided memory for data storage.
// <i> Default: 0
#ifndef OS_MEMPOOL_DATA_SIZE
#define OS_MEMPOOL_DATA_SIZE 0
#endif
// </e>
// </h>
// <h>Message Queue Configuration
// ==============================
// <e>Object specific Memory allocation
// <i> Enables object specific memory allocation.
#ifndef OS_MSGQUEUE_OBJ_MEM
#define OS_MSGQUEUE_OBJ_MEM 0
#endif
// <o>Number of Message Queue objects <1-1000>
// <i> Defines maximum number of objects that can be active at the same time.
// <i> Applies to objects with system provided memory for control blocks.
#ifndef OS_MSGQUEUE_NUM
#define OS_MSGQUEUE_NUM 1
#endif
// <o>Data Storage Memory size [bytes] <0-1073741824:8>
// <i> Defines the combined data storage memory size.
// <i> Applies to objects with system provided memory for data storage.
// <i> Default: 0
#ifndef OS_MSGQUEUE_DATA_SIZE
#define OS_MSGQUEUE_DATA_SIZE 0
#endif
// </e>
// </h>
// Number of Threads which use standard C/C++ library libspace
// (when thread specific memory allocation is not used).
#if (OS_THREAD_OBJ_MEM == 0)
#define OS_THREAD_LIBSPACE_NUM 4
#else
#define OS_THREAD_LIBSPACE_NUM OS_THREAD_NUM
#endif
//------------- <<< end of configuration section >>> ---------------------------
#endif // RTX_CONFIG_H_

View File

@ -0,0 +1,155 @@
;/*
; * Copyright (c) 2013-2017 ARM Limited. All rights reserved.
; *
; * SPDX-License-Identifier: Apache-2.0
; *
; * Licensed under the Apache License, Version 2.0 (the License); you may
; * not use this file except in compliance with the License.
; * You may obtain a copy of the License at
; *
; * www.apache.org/licenses/LICENSE-2.0
; *
; * Unless required by applicable law or agreed to in writing, software
; * distributed under the License is distributed on an AS IS BASIS, WITHOUT
; * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
; * See the License for the specific language governing permissions and
; * limitations under the License.
; *
; * -----------------------------------------------------------------------------
; *
; * Project: CMSIS-RTOS RTX
; * Title: Cortex-M0 Exception handlers
; *
; * -----------------------------------------------------------------------------
; */
I_T_RUN_OFS EQU 28 ; osRtxInfo.thread.run offset
TCB_SP_OFS EQU 56 ; TCB.SP offset
PRESERVE8
THUMB
AREA |.constdata|, DATA, READONLY
EXPORT irqRtxLib
irqRtxLib DCB 0 ; Non weak library reference
AREA |.text|, CODE, READONLY
SVC_Handler PROC
EXPORT SVC_Handler
IMPORT osRtxUserSVC
IMPORT osRtxInfo
MRS R0,PSP ; Get PSP
LDR R1,[R0,#24] ; Load saved PC from stack
SUBS R1,R1,#2 ; Point to SVC instruction
LDRB R1,[R1] ; Load SVC number
CMP R1,#0
BNE SVC_User ; Branch if not SVC 0
PUSH {R0,LR} ; Save PSP and EXC_RETURN
LDMIA R0,{R0-R3} ; Load function parameters from stack
BLX R7 ; Call service function
POP {R2,R3} ; Restore PSP and EXC_RETURN
STMIA R2!,{R0-R1} ; Store function return values
MOV LR,R3 ; Set EXC_RETURN
SVC_Context
LDR R3,=osRtxInfo+I_T_RUN_OFS; Load address of osRtxInfo.run
LDMIA R3!,{R1,R2} ; Load osRtxInfo.thread.run: curr & next
CMP R1,R2 ; Check if thread switch is required
BEQ SVC_Exit ; Branch when threads are the same
CMP R1,#0
BEQ SVC_ContextSwitch ; Branch if running thread is deleted
SVC_ContextSave
MRS R0,PSP ; Get PSP
SUBS R0,R0,#32 ; Adjust address
STR R0,[R1,#TCB_SP_OFS] ; Store SP
STMIA R0!,{R4-R7} ; Save R4..R7
MOV R4,R8
MOV R5,R9
MOV R6,R10
MOV R7,R11
STMIA R0!,{R4-R7} ; Save R8..R11
SVC_ContextSwitch
SUBS R3,R3,#8
STR R2,[R3] ; osRtxInfo.thread.run: curr = next
SVC_ContextRestore
LDR R0,[R2,#TCB_SP_OFS] ; Load SP
ADDS R0,R0,#16 ; Adjust address
LDMIA R0!,{R4-R7} ; Restore R8..R11
MOV R8,R4
MOV R9,R5
MOV R10,R6
MOV R11,R7
MSR PSP,R0 ; Set PSP
SUBS R0,R0,#32 ; Adjust address
LDMIA R0!,{R4-R7} ; Restore R4..R7
MOVS R0,#~0xFFFFFFFD
MVNS R0,R0 ; Set EXC_RETURN value
BX R0 ; Exit from handler
SVC_Exit
BX LR ; Exit from handler
SVC_User
PUSH {R4,LR} ; Save registers
LDR R2,=osRtxUserSVC ; Load address of SVC table
LDR R3,[R2] ; Load SVC maximum number
CMP R1,R3 ; Check SVC number range
BHI SVC_Done ; Branch if out of range
LSLS R1,R1,#2
LDR R4,[R2,R1] ; Load address of SVC function
LDMIA R0,{R0-R3} ; Load function parameters from stack
BLX R4 ; Call service function
MRS R4,PSP ; Get PSP
STMIA R4!,{R0-R3} ; Store function return values
SVC_Done
POP {R4,PC} ; Return from handler
ALIGN
ENDP
PendSV_Handler PROC
EXPORT PendSV_Handler
IMPORT osRtxPendSV_Handler
PUSH {R0,LR} ; Save EXC_RETURN
BL osRtxPendSV_Handler ; Call osRtxPendSV_Handler
POP {R0,R1} ; Restore EXC_RETURN
MOV LR,R1 ; Set EXC_RETURN
B SVC_Context
ALIGN
ENDP
SysTick_Handler PROC
EXPORT SysTick_Handler
IMPORT osRtxTick_Handler
PUSH {R0,LR} ; Save EXC_RETURN
BL osRtxTick_Handler ; Call osRtxTick_Handler
POP {R0,R1} ; Restore EXC_RETURN
MOV LR,R1 ; Set EXC_RETURN
B SVC_Context
ALIGN
ENDP
END

View File

@ -0,0 +1,164 @@
/*
* Copyright (c) 2013-2017 ARM Limited. All rights reserved.
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the License); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an AS IS BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* -----------------------------------------------------------------------------
*
* Project: CMSIS-RTOS RTX
* Title: Cortex-M0 Exception handlers
*
* -----------------------------------------------------------------------------
*/
.file "irq_cm0.S"
.syntax unified
.equ I_T_RUN_OFS, 28 // osRtxInfo.thread.run offset
.equ TCB_SP_OFS, 56 // TCB.SP offset
.section ".rodata"
.global irqRtxLib // Non weak library reference
irqRtxLib:
.byte 0
.thumb
.section ".text"
.align 2
.thumb_func
.type SVC_Handler, %function
.global SVC_Handler
.fnstart
.cantunwind
SVC_Handler:
MRS R0,PSP // Get PSP
LDR R1,[R0,#24] // Load saved PC from stack
SUBS R1,R1,#2 // Point to SVC instruction
LDRB R1,[R1] // Load SVC number
CMP R1,#0
BNE SVC_User // Branch if not SVC 0
PUSH {R0,LR} // Save PSP and EXC_RETURN
LDMIA R0,{R0-R3} // Load function parameters from stack
BLX R7 // Call service function
POP {R2,R3} // Restore PSP and EXC_RETURN
STMIA R2!,{R0-R1} // Store function return values
MOV LR,R3 // Set EXC_RETURN
SVC_Context:
LDR R3,=osRtxInfo+I_T_RUN_OFS // Load address of osRtxInfo.run
LDMIA R3!,{R1,R2} // Load osRtxInfo.thread.run: curr & next
CMP R1,R2 // Check if thread switch is required
BEQ SVC_Exit // Branch when threads are the same
CMP R1,#0
BEQ SVC_ContextSwitch // Branch if running thread is deleted
SVC_ContextSave:
MRS R0,PSP // Get PSP
SUBS R0,R0,#32 // Adjust address
STR R0,[R1,#TCB_SP_OFS]; // Store SP
STMIA R0!,{R4-R7} // Save R4..R7
MOV R4,R8
MOV R5,R9
MOV R6,R10
MOV R7,R11
STMIA R0!,{R4-R7} // Save R8..R11
SVC_ContextSwitch:
SUBS R3,R3,#8
STR R2,[R3] // osRtxInfo.thread.run: curr = next
SVC_ContextRestore:
LDR R0,[R2,#TCB_SP_OFS] // Load SP
ADDS R0,R0,#16 // Adjust address
LDMIA R0!,{R4-R7} // Restore R8..R11
MOV R8,R4
MOV R9,R5
MOV R10,R6
MOV R11,R7
MSR PSP,R0 // Set PSP
SUBS R0,R0,#32 // Adjust address
LDMIA R0!,{R4-R7} // Restore R4..R7
MOVS R0,#~0xFFFFFFFD
MVNS R0,R0 // Set EXC_RETURN value
BX R0 // Exit from handler
SVC_Exit:
BX LR // Exit from handler
SVC_User:
PUSH {R4,LR} // Save registers
LDR R2,=osRtxUserSVC // Load address of SVC table
LDR R3,[R2] // Load SVC maximum number
CMP R1,R3 // Check SVC number range
BHI SVC_Done // Branch if out of range
LSLS R1,R1,#2
LDR R4,[R2,R1] // Load address of SVC function
LDMIA R0,{R0-R3} // Load function parameters from stack
BLX R4 // Call service function
MRS R4,PSP // Get PSP
STMIA R4!,{R0-R3} // Store function return values
SVC_Done:
POP {R4,PC} // Return from handler
.fnend
.size SVC_Handler, .-SVC_Handler
.thumb_func
.type PendSV_Handler, %function
.global PendSV_Handler
.fnstart
.cantunwind
PendSV_Handler:
PUSH {R0,LR} // Save EXC_RETURN
BL osRtxPendSV_Handler // Call osRtxPendSV_Handler
POP {R0,R1} // Restore EXC_RETURN
MOV LR,R1 // Set EXC_RETURN
B SVC_Context
.fnend
.size PendSV_Handler, .-PendSV_Handler
.thumb_func
.type SysTick_Handler, %function
.global SysTick_Handler
.fnstart
.cantunwind
SysTick_Handler:
PUSH {R0,LR} // Save EXC_RETURN
BL osRtxTick_Handler // Call osRtxTick_Handler
POP {R0,R1} // Restore EXC_RETURN
MOV LR,R1 // Set EXC_RETURN
B SVC_Context
.fnend
.size SysTick_Handler, .-SysTick_Handler
.end

View File

@ -0,0 +1,149 @@
;/*
; * Copyright (c) 2013-2017 ARM Limited. All rights reserved.
; *
; * SPDX-License-Identifier: Apache-2.0
; *
; * Licensed under the Apache License, Version 2.0 (the License); you may
; * not use this file except in compliance with the License.
; * You may obtain a copy of the License at
; *
; * www.apache.org/licenses/LICENSE-2.0
; *
; * Unless required by applicable law or agreed to in writing, software
; * distributed under the License is distributed on an AS IS BASIS, WITHOUT
; * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
; * See the License for the specific language governing permissions and
; * limitations under the License.
; *
; * -----------------------------------------------------------------------------
; *
; * Project: CMSIS-RTOS RTX
; * Title: Cortex-M0 Exception handlers
; *
; * -----------------------------------------------------------------------------
; */
NAME irq_cm0.s
I_T_RUN_OFS EQU 28 ; osRtxInfo.thread.run offset
TCB_SP_OFS EQU 56 ; TCB.SP offset
PRESERVE8
SECTION .rodata:DATA:NOROOT(2)
EXPORT irqRtxLib
irqRtxLib DCB 0 ; Non weak library reference
THUMB
SECTION .text:CODE:NOROOT(2)
SVC_Handler
EXPORT SVC_Handler
IMPORT osRtxUserSVC
IMPORT osRtxInfo
MRS R0,PSP ; Get PSP
LDR R1,[R0,#24] ; Load saved PC from stack
SUBS R1,R1,#2 ; Point to SVC instruction
LDRB R1,[R1] ; Load SVC number
CMP R1,#0
BNE SVC_User ; Branch if not SVC 0
PUSH {R0,LR} ; Save PSP and EXC_RETURN
LDMIA R0,{R0-R3} ; Load function parameters from stack
BLX R7 ; Call service function
POP {R2,R3} ; Restore PSP and EXC_RETURN
STMIA R2!,{R0-R1} ; Store function return values
MOV LR,R3 ; Set EXC_RETURN
SVC_Context
LDR R3,=osRtxInfo+I_T_RUN_OFS; Load address of osRtxInfo.run
LDMIA R3!,{R1,R2} ; Load osRtxInfo.thread.run: curr & next
CMP R1,R2 ; Check if thread switch is required
BEQ SVC_Exit ; Branch when threads are the same
CMP R1,#0
BEQ SVC_ContextSwitch ; Branch if running thread is deleted
SVC_ContextSave
MRS R0,PSP ; Get PSP
SUBS R0,R0,#32 ; Adjust address
STR R0,[R1,#TCB_SP_OFS] ; Store SP
STMIA R0!,{R4-R7} ; Save R4..R7
MOV R4,R8
MOV R5,R9
MOV R6,R10
MOV R7,R11
STMIA R0!,{R4-R7} ; Save R8..R11
SVC_ContextSwitch
SUBS R3,R3,#8
STR R2,[R3] ; osRtxInfo.thread.run: curr = next
SVC_ContextRestore
LDR R0,[R2,#TCB_SP_OFS] ; Load SP
ADDS R0,R0,#16 ; Adjust address
LDMIA R0!,{R4-R7} ; Restore R8..R11
MOV R8,R4
MOV R9,R5
MOV R10,R6
MOV R11,R7
MSR PSP,R0 ; Set PSP
SUBS R0,R0,#32 ; Adjust address
LDMIA R0!,{R4-R7} ; Restore R4..R7
MOVS R0,#~0xFFFFFFFD
MVNS R0,R0 ; Set EXC_RETURN value
BX R0 ; Exit from handler
SVC_Exit
BX LR ; Exit from handler
SVC_User
PUSH {R4,LR} ; Save registers
LDR R2,=osRtxUserSVC ; Load address of SVC table
LDR R3,[R2] ; Load SVC maximum number
CMP R1,R3 ; Check SVC number range
BHI SVC_Done ; Branch if out of range
LSLS R1,R1,#2
LDR R4,[R2,R1] ; Load address of SVC function
LDMIA R0,{R0-R3} ; Load function parameters from stack
BLX R4 ; Call service function
MRS R4,PSP ; Get PSP
STMIA R4!,{R0-R3} ; Store function return values
SVC_Done
POP {R4,PC} ; Return from handler
PendSV_Handler
EXPORT PendSV_Handler
IMPORT osRtxPendSV_Handler
PUSH {R0,LR} ; Save EXC_RETURN
BL osRtxPendSV_Handler ; Call osRtxPendSV_Handler
POP {R0,R1} ; Restore EXC_RETURN
MOV LR,R1 ; Set EXC_RETURN
B SVC_Context
SysTick_Handler
EXPORT SysTick_Handler
IMPORT osRtxTick_Handler
PUSH {R0,LR} ; Save EXC_RETURN
BL osRtxTick_Handler ; Call osRtxTick_Handler
POP {R0,R1} ; Restore EXC_RETURN
MOV LR,R1 ; Set EXC_RETURN
B SVC_Context
END

View File

@ -0,0 +1,155 @@
;/*
; * Copyright (c) 2013-2017 ARM Limited. All rights reserved.
; *
; * SPDX-License-Identifier: Apache-2.0
; *
; * Licensed under the Apache License, Version 2.0 (the License); you may
; * not use this file except in compliance with the License.
; * You may obtain a copy of the License at
; *
; * www.apache.org/licenses/LICENSE-2.0
; *
; * Unless required by applicable law or agreed to in writing, software
; * distributed under the License is distributed on an AS IS BASIS, WITHOUT
; * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
; * See the License for the specific language governing permissions and
; * limitations under the License.
; *
; * -----------------------------------------------------------------------------
; *
; * Project: CMSIS-RTOS RTX
; * Title: Cortex-M0 Exception handlers
; *
; * -----------------------------------------------------------------------------
; */
I_T_RUN_OFS EQU 28 ; osRtxInfo.thread.run offset
TCB_SP_OFS EQU 56 ; TCB.SP offset
PRESERVE8
THUMB
AREA |.constdata|, DATA, READONLY
EXPORT irqRtxLib
irqRtxLib DCB 0 ; Non weak library reference
AREA |.text|, CODE, READONLY
SVC_Handler PROC
EXPORT SVC_Handler
IMPORT osRtxUserSVC
IMPORT osRtxInfo
MRS R0,PSP ; Get PSP
LDR R1,[R0,#24] ; Load saved PC from stack
SUBS R1,R1,#2 ; Point to SVC instruction
LDRB R1,[R1] ; Load SVC number
CMP R1,#0
BNE SVC_User ; Branch if not SVC 0
PUSH {R0,LR} ; Save PSP and EXC_RETURN
LDMIA R0,{R0-R3} ; Load function parameters from stack
BLX R7 ; Call service function
POP {R2,R3} ; Restore PSP and EXC_RETURN
STMIA R2!,{R0-R1} ; Store function return values
MOV LR,R3 ; Set EXC_RETURN
SVC_Context
LDR R3,=osRtxInfo+I_T_RUN_OFS; Load address of osRtxInfo.run
LDMIA R3!,{R1,R2} ; Load osRtxInfo.thread.run: curr & next
CMP R1,R2 ; Check if thread switch is required
BEQ SVC_Exit ; Branch when threads are the same
CMP R1,#0
BEQ SVC_ContextSwitch ; Branch if running thread is deleted
SVC_ContextSave
MRS R0,PSP ; Get PSP
SUBS R0,R0,#32 ; Adjust address
STR R0,[R1,#TCB_SP_OFS] ; Store SP
STMIA R0!,{R4-R7} ; Save R4..R7
MOV R4,R8
MOV R5,R9
MOV R6,R10
MOV R7,R11
STMIA R0!,{R4-R7} ; Save R8..R11
SVC_ContextSwitch
SUBS R3,R3,#8
STR R2,[R3] ; osRtxInfo.thread.run: curr = next
SVC_ContextRestore
LDR R0,[R2,#TCB_SP_OFS] ; Load SP
ADDS R0,R0,#16 ; Adjust address
LDMIA R0!,{R4-R7} ; Restore R8..R11
MOV R8,R4
MOV R9,R5
MOV R10,R6
MOV R11,R7
MSR PSP,R0 ; Set PSP
SUBS R0,R0,#32 ; Adjust address
LDMIA R0!,{R4-R7} ; Restore R4..R7
MOVS R0,#~0xFFFFFFFD
MVNS R0,R0 ; Set EXC_RETURN value
BX R0 ; Exit from handler
SVC_Exit
BX LR ; Exit from handler
SVC_User
PUSH {R4,LR} ; Save registers
LDR R2,=osRtxUserSVC ; Load address of SVC table
LDR R3,[R2] ; Load SVC maximum number
CMP R1,R3 ; Check SVC number range
BHI SVC_Done ; Branch if out of range
LSLS R1,R1,#2
LDR R4,[R2,R1] ; Load address of SVC function
LDMIA R0,{R0-R3} ; Load function parameters from stack
BLX R4 ; Call service function
MRS R4,PSP ; Get PSP
STMIA R4!,{R0-R3} ; Store function return values
SVC_Done
POP {R4,PC} ; Return from handler
ALIGN
ENDP
PendSV_Handler PROC
EXPORT PendSV_Handler
IMPORT osRtxPendSV_Handler
PUSH {R0,LR} ; Save EXC_RETURN
BL osRtxPendSV_Handler ; Call osRtxPendSV_Handler
POP {R0,R1} ; Restore EXC_RETURN
MOV LR,R1 ; Set EXC_RETURN
B SVC_Context
ALIGN
ENDP
SysTick_Handler PROC
EXPORT SysTick_Handler
IMPORT osRtxTick_Handler
PUSH {R0,LR} ; Save EXC_RETURN
BL osRtxTick_Handler ; Call osRtxTick_Handler
POP {R0,R1} ; Restore EXC_RETURN
MOV LR,R1 ; Set EXC_RETURN
B SVC_Context
ALIGN
ENDP
END

View File

@ -0,0 +1,164 @@
/*
* Copyright (c) 2013-2017 ARM Limited. All rights reserved.
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the License); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an AS IS BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* -----------------------------------------------------------------------------
*
* Project: CMSIS-RTOS RTX
* Title: Cortex-M0 Exception handlers
*
* -----------------------------------------------------------------------------
*/
.file "irq_cm0.S"
.syntax unified
.equ I_T_RUN_OFS, 28 // osRtxInfo.thread.run offset
.equ TCB_SP_OFS, 56 // TCB.SP offset
.section ".rodata"
.global irqRtxLib // Non weak library reference
irqRtxLib:
.byte 0
.thumb
.section ".text"
.align 2
.thumb_func
.type SVC_Handler, %function
.global SVC_Handler
.fnstart
.cantunwind
SVC_Handler:
MRS R0,PSP // Get PSP
LDR R1,[R0,#24] // Load saved PC from stack
SUBS R1,R1,#2 // Point to SVC instruction
LDRB R1,[R1] // Load SVC number
CMP R1,#0
BNE SVC_User // Branch if not SVC 0
PUSH {R0,LR} // Save PSP and EXC_RETURN
LDMIA R0,{R0-R3} // Load function parameters from stack
BLX R7 // Call service function
POP {R2,R3} // Restore PSP and EXC_RETURN
STMIA R2!,{R0-R1} // Store function return values
MOV LR,R3 // Set EXC_RETURN
SVC_Context:
LDR R3,=osRtxInfo+I_T_RUN_OFS // Load address of osRtxInfo.run
LDMIA R3!,{R1,R2} // Load osRtxInfo.thread.run: curr & next
CMP R1,R2 // Check if thread switch is required
BEQ SVC_Exit // Branch when threads are the same
CMP R1,#0
BEQ SVC_ContextSwitch // Branch if running thread is deleted
SVC_ContextSave:
MRS R0,PSP // Get PSP
SUBS R0,R0,#32 // Adjust address
STR R0,[R1,#TCB_SP_OFS]; // Store SP
STMIA R0!,{R4-R7} // Save R4..R7
MOV R4,R8
MOV R5,R9
MOV R6,R10
MOV R7,R11
STMIA R0!,{R4-R7} // Save R8..R11
SVC_ContextSwitch:
SUBS R3,R3,#8
STR R2,[R3] // osRtxInfo.thread.run: curr = next
SVC_ContextRestore:
LDR R0,[R2,#TCB_SP_OFS] // Load SP
ADDS R0,R0,#16 // Adjust address
LDMIA R0!,{R4-R7} // Restore R8..R11
MOV R8,R4
MOV R9,R5
MOV R10,R6
MOV R11,R7
MSR PSP,R0 // Set PSP
SUBS R0,R0,#32 // Adjust address
LDMIA R0!,{R4-R7} // Restore R4..R7
MOVS R0,#~0xFFFFFFFD
MVNS R0,R0 // Set EXC_RETURN value
BX R0 // Exit from handler
SVC_Exit:
BX LR // Exit from handler
SVC_User:
PUSH {R4,LR} // Save registers
LDR R2,=osRtxUserSVC // Load address of SVC table
LDR R3,[R2] // Load SVC maximum number
CMP R1,R3 // Check SVC number range
BHI SVC_Done // Branch if out of range
LSLS R1,R1,#2
LDR R4,[R2,R1] // Load address of SVC function
LDMIA R0,{R0-R3} // Load function parameters from stack
BLX R4 // Call service function
MRS R4,PSP // Get PSP
STMIA R4!,{R0-R3} // Store function return values
SVC_Done:
POP {R4,PC} // Return from handler
.fnend
.size SVC_Handler, .-SVC_Handler
.thumb_func
.type PendSV_Handler, %function
.global PendSV_Handler
.fnstart
.cantunwind
PendSV_Handler:
PUSH {R0,LR} // Save EXC_RETURN
BL osRtxPendSV_Handler // Call osRtxPendSV_Handler
POP {R0,R1} // Restore EXC_RETURN
MOV LR,R1 // Set EXC_RETURN
B SVC_Context
.fnend
.size PendSV_Handler, .-PendSV_Handler
.thumb_func
.type SysTick_Handler, %function
.global SysTick_Handler
.fnstart
.cantunwind
SysTick_Handler:
PUSH {R0,LR} // Save EXC_RETURN
BL osRtxTick_Handler // Call osRtxTick_Handler
POP {R0,R1} // Restore EXC_RETURN
MOV LR,R1 // Set EXC_RETURN
B SVC_Context
.fnend
.size SysTick_Handler, .-SysTick_Handler
.end

View File

@ -0,0 +1,149 @@
;/*
; * Copyright (c) 2013-2017 ARM Limited. All rights reserved.
; *
; * SPDX-License-Identifier: Apache-2.0
; *
; * Licensed under the Apache License, Version 2.0 (the License); you may
; * not use this file except in compliance with the License.
; * You may obtain a copy of the License at
; *
; * www.apache.org/licenses/LICENSE-2.0
; *
; * Unless required by applicable law or agreed to in writing, software
; * distributed under the License is distributed on an AS IS BASIS, WITHOUT
; * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
; * See the License for the specific language governing permissions and
; * limitations under the License.
; *
; * -----------------------------------------------------------------------------
; *
; * Project: CMSIS-RTOS RTX
; * Title: Cortex-M0 Exception handlers
; *
; * -----------------------------------------------------------------------------
; */
NAME irq_cm0.s
I_T_RUN_OFS EQU 28 ; osRtxInfo.thread.run offset
TCB_SP_OFS EQU 56 ; TCB.SP offset
PRESERVE8
SECTION .rodata:DATA:NOROOT(2)
EXPORT irqRtxLib
irqRtxLib DCB 0 ; Non weak library reference
THUMB
SECTION .text:CODE:NOROOT(2)
SVC_Handler
EXPORT SVC_Handler
IMPORT osRtxUserSVC
IMPORT osRtxInfo
MRS R0,PSP ; Get PSP
LDR R1,[R0,#24] ; Load saved PC from stack
SUBS R1,R1,#2 ; Point to SVC instruction
LDRB R1,[R1] ; Load SVC number
CMP R1,#0
BNE SVC_User ; Branch if not SVC 0
PUSH {R0,LR} ; Save PSP and EXC_RETURN
LDMIA R0,{R0-R3} ; Load function parameters from stack
BLX R7 ; Call service function
POP {R2,R3} ; Restore PSP and EXC_RETURN
STMIA R2!,{R0-R1} ; Store function return values
MOV LR,R3 ; Set EXC_RETURN
SVC_Context
LDR R3,=osRtxInfo+I_T_RUN_OFS; Load address of osRtxInfo.run
LDMIA R3!,{R1,R2} ; Load osRtxInfo.thread.run: curr & next
CMP R1,R2 ; Check if thread switch is required
BEQ SVC_Exit ; Branch when threads are the same
CMP R1,#0
BEQ SVC_ContextSwitch ; Branch if running thread is deleted
SVC_ContextSave
MRS R0,PSP ; Get PSP
SUBS R0,R0,#32 ; Adjust address
STR R0,[R1,#TCB_SP_OFS] ; Store SP
STMIA R0!,{R4-R7} ; Save R4..R7
MOV R4,R8
MOV R5,R9
MOV R6,R10
MOV R7,R11
STMIA R0!,{R4-R7} ; Save R8..R11
SVC_ContextSwitch
SUBS R3,R3,#8
STR R2,[R3] ; osRtxInfo.thread.run: curr = next
SVC_ContextRestore
LDR R0,[R2,#TCB_SP_OFS] ; Load SP
ADDS R0,R0,#16 ; Adjust address
LDMIA R0!,{R4-R7} ; Restore R8..R11
MOV R8,R4
MOV R9,R5
MOV R10,R6
MOV R11,R7
MSR PSP,R0 ; Set PSP
SUBS R0,R0,#32 ; Adjust address
LDMIA R0!,{R4-R7} ; Restore R4..R7
MOVS R0,#~0xFFFFFFFD
MVNS R0,R0 ; Set EXC_RETURN value
BX R0 ; Exit from handler
SVC_Exit
BX LR ; Exit from handler
SVC_User
PUSH {R4,LR} ; Save registers
LDR R2,=osRtxUserSVC ; Load address of SVC table
LDR R3,[R2] ; Load SVC maximum number
CMP R1,R3 ; Check SVC number range
BHI SVC_Done ; Branch if out of range
LSLS R1,R1,#2
LDR R4,[R2,R1] ; Load address of SVC function
LDMIA R0,{R0-R3} ; Load function parameters from stack
BLX R4 ; Call service function
MRS R4,PSP ; Get PSP
STMIA R4!,{R0-R3} ; Store function return values
SVC_Done
POP {R4,PC} ; Return from handler
PendSV_Handler
EXPORT PendSV_Handler
IMPORT osRtxPendSV_Handler
PUSH {R0,LR} ; Save EXC_RETURN
BL osRtxPendSV_Handler ; Call osRtxPendSV_Handler
POP {R0,R1} ; Restore EXC_RETURN
MOV LR,R1 ; Set EXC_RETURN
B SVC_Context
SysTick_Handler
EXPORT SysTick_Handler
IMPORT osRtxTick_Handler
PUSH {R0,LR} ; Save EXC_RETURN
BL osRtxTick_Handler ; Call osRtxTick_Handler
POP {R0,R1} ; Restore EXC_RETURN
MOV LR,R1 ; Set EXC_RETURN
B SVC_Context
END

View File

@ -0,0 +1,133 @@
;/*
; * Copyright (c) 2013-2017 ARM Limited. All rights reserved.
; *
; * SPDX-License-Identifier: Apache-2.0
; *
; * Licensed under the Apache License, Version 2.0 (the License); you may
; * not use this file except in compliance with the License.
; * You may obtain a copy of the License at
; *
; * www.apache.org/licenses/LICENSE-2.0
; *
; * Unless required by applicable law or agreed to in writing, software
; * distributed under the License is distributed on an AS IS BASIS, WITHOUT
; * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
; * See the License for the specific language governing permissions and
; * limitations under the License.
; *
; * -----------------------------------------------------------------------------
; *
; * Project: CMSIS-RTOS RTX
; * Title: Cortex-M3 Exception handlers
; *
; * -----------------------------------------------------------------------------
; */
I_T_RUN_OFS EQU 28 ; osRtxInfo.thread.run offset
TCB_SP_OFS EQU 56 ; TCB.SP offset
PRESERVE8
THUMB
AREA |.constdata|, DATA, READONLY
EXPORT irqRtxLib
irqRtxLib DCB 0 ; Non weak library reference
AREA |.text|, CODE, READONLY
SVC_Handler PROC
EXPORT SVC_Handler
IMPORT osRtxUserSVC
IMPORT osRtxInfo
MRS R0,PSP ; Get PSP
LDR R1,[R0,#24] ; Load saved PC from stack
LDRB R1,[R1,#-2] ; Load SVC number
CBNZ R1,SVC_User ; Branch if not SVC 0
PUSH {R0,LR} ; Save PSP and EXC_RETURN
LDM R0,{R0-R3,R12} ; Load function parameters and address from stack
BLX R12 ; Call service function
POP {R12,LR} ; Restore PSP and EXC_RETURN
STM R12,{R0-R1} ; Store function return values
SVC_Context
LDR R3,=osRtxInfo+I_T_RUN_OFS; Load address of osRtxInfo.run
LDM R3,{R1,R2} ; Load osRtxInfo.thread.run: curr & next
CMP R1,R2 ; Check if thread switch is required
BXEQ LR ; Exit when threads are the same
CBZ R1,SVC_ContextSwitch ; Branch if running thread is deleted
SVC_ContextSave
STMDB R12!,{R4-R11} ; Save R4..R11
STR R12,[R1,#TCB_SP_OFS] ; Store SP
SVC_ContextSwitch
STR R2,[R3] ; osRtxInfo.thread.run: curr = next
SVC_ContextRestore
LDR R0,[R2,#TCB_SP_OFS] ; Load SP
LDMIA R0!,{R4-R11} ; Restore R4..R11
MSR PSP,R0 ; Set PSP
MVN LR,#~0xFFFFFFFD ; Set EXC_RETURN value
SVC_Exit
BX LR ; Exit from handler
SVC_User
PUSH {R4,LR} ; Save registers
LDR R2,=osRtxUserSVC ; Load address of SVC table
LDR R3,[R2] ; Load SVC maximum number
CMP R1,R3 ; Check SVC number range
BHI SVC_Done ; Branch if out of range
LDR R4,[R2,R1,LSL #2] ; Load address of SVC function
LDM R0,{R0-R3} ; Load function parameters from stack
BLX R4 ; Call service function
MRS R4,PSP ; Get PSP
STR R0,[R4] ; Store function return value
SVC_Done
POP {R4,PC} ; Return from handler
ALIGN
ENDP
PendSV_Handler PROC
EXPORT PendSV_Handler
IMPORT osRtxPendSV_Handler
PUSH {R4,LR} ; Save EXC_RETURN
BL osRtxPendSV_Handler ; Call osRtxPendSV_Handler
POP {R4,LR} ; Restore EXC_RETURN
MRS R12,PSP
B SVC_Context
ALIGN
ENDP
SysTick_Handler PROC
EXPORT SysTick_Handler
IMPORT osRtxTick_Handler
PUSH {R4,LR} ; Save EXC_RETURN
BL osRtxTick_Handler ; Call osRtxTick_Handler
POP {R4,LR} ; Restore EXC_RETURN
MRS R12,PSP
B SVC_Context
ALIGN
ENDP
END

View File

@ -0,0 +1,142 @@
/*
* Copyright (c) 2013-2017 ARM Limited. All rights reserved.
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the License); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an AS IS BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* -----------------------------------------------------------------------------
*
* Project: CMSIS-RTOS RTX
* Title: Cortex-M3 Exception handlers
*
* -----------------------------------------------------------------------------
*/
.file "irq_cm3.S"
.syntax unified
.equ I_T_RUN_OFS, 28 // osRtxInfo.thread.run offset
.equ TCB_SP_OFS, 56 // TCB.SP offset
.section ".rodata"
.global irqRtxLib // Non weak library reference
irqRtxLib:
.byte 0
.thumb
.section ".text"
.align 2
.thumb_func
.type SVC_Handler, %function
.global SVC_Handler
.fnstart
.cantunwind
SVC_Handler:
MRS R0,PSP // Get PSP
LDR R1,[R0,#24] // Load saved PC from stack
LDRB R1,[R1,#-2] // Load SVC number
CBNZ R1,SVC_User // Branch if not SVC 0
PUSH {R0,LR} // Save PSP and EXC_RETURN
LDM R0,{R0-R3,R12} // Load function parameters and address from stack
BLX R12 // Call service function
POP {R12,LR} // Restore PSP and EXC_RETURN
STM R12,{R0-R1} // Store function return values
SVC_Context:
LDR R3,=osRtxInfo+I_T_RUN_OFS // Load address of osRtxInfo.run
LDM R3,{R1,R2} // Load osRtxInfo.thread.run: curr & next
CMP R1,R2 // Check if thread switch is required
IT EQ
BXEQ LR // Exit when threads are the same
CBZ R1,SVC_ContextSwitch // Branch if running thread is deleted
SVC_ContextSave:
STMDB R12!,{R4-R11} // Save R4..R11
STR R12,[R1,#TCB_SP_OFS] // Store SP
SVC_ContextSwitch:
STR R2,[R3] // osRtxInfo.thread.run: curr = next
SVC_ContextRestore:
LDR R0,[R2,#TCB_SP_OFS] // Load SP
LDMIA R0!,{R4-R11} // Restore R4..R11
MSR PSP,R0 // Set PSP
MVN LR,#~0xFFFFFFFD // Set EXC_RETURN value
SVC_Exit:
BX LR // Exit from handler
SVC_User:
PUSH {R4,LR} // Save registers
LDR R2,=osRtxUserSVC // Load address of SVC table
LDR R3,[R2] // Load SVC maximum number
CMP R1,R3 // Check SVC number range
BHI SVC_Done // Branch if out of range
LDR R4,[R2,R1,LSL #2] // Load address of SVC function
LDM R0,{R0-R3} // Load function parameters from stack
BLX R4 // Call service function
MRS R4,PSP // Get PSP
STR R0,[R4] // Store function return value
SVC_Done:
POP {R4,PC} // Return from handler
.fnend
.size SVC_Handler, .-SVC_Handler
.thumb_func
.type PendSV_Handler, %function
.global PendSV_Handler
.fnstart
.cantunwind
PendSV_Handler:
PUSH {R4,LR} // Save EXC_RETURN
BL osRtxPendSV_Handler // Call osRtxPendSV_Handler
POP {R4,LR} // Restore EXC_RETURN
MRS R12,PSP
B SVC_Context
.fnend
.size PendSV_Handler, .-PendSV_Handler
.thumb_func
.type SysTick_Handler, %function
.global SysTick_Handler
.fnstart
.cantunwind
SysTick_Handler:
PUSH {R4,LR} // Save EXC_RETURN
BL osRtxTick_Handler // Call osRtxTick_Handler
POP {R4,LR} // Restore EXC_RETURN
MRS R12,PSP
B SVC_Context
.fnend
.size SysTick_Handler, .-SysTick_Handler
.end

View File

@ -0,0 +1,128 @@
;/*
; * Copyright (c) 2013-2017 ARM Limited. All rights reserved.
; *
; * SPDX-License-Identifier: Apache-2.0
; *
; * Licensed under the Apache License, Version 2.0 (the License); you may
; * not use this file except in compliance with the License.
; * You may obtain a copy of the License at
; *
; * www.apache.org/licenses/LICENSE-2.0
; *
; * Unless required by applicable law or agreed to in writing, software
; * distributed under the License is distributed on an AS IS BASIS, WITHOUT
; * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
; * See the License for the specific language governing permissions and
; * limitations under the License.
; *
; * -----------------------------------------------------------------------------
; *
; * Project: CMSIS-RTOS RTX
; * Title: Cortex-M3 Exception handlers
; *
; * -----------------------------------------------------------------------------
; */
NAME irq_cm3.s
I_T_RUN_OFS EQU 28 ; osRtxInfo.thread.run offset
TCB_SP_OFS EQU 56 ; TCB.SP offset
PRESERVE8
SECTION .rodata:DATA:NOROOT(2)
EXPORT irqRtxLib
irqRtxLib DCB 0 ; Non weak library reference
THUMB
SECTION .text:CODE:NOROOT(2)
SVC_Handler
EXPORT SVC_Handler
IMPORT osRtxUserSVC
IMPORT osRtxInfo
MRS R0,PSP ; Get PSP
LDR R1,[R0,#24] ; Load saved PC from stack
LDRB R1,[R1,#-2] ; Load SVC number
CBNZ R1,SVC_User ; Branch if not SVC 0
PUSH {R0,LR} ; Save PSP and EXC_RETURN
LDM R0,{R0-R3,R12} ; Load function parameters and address from stack
BLX R12 ; Call service function
POP {R12,LR} ; Restore PSP and EXC_RETURN
STM R12,{R0-R1} ; Store function return values
SVC_Context
LDR R3,=osRtxInfo+I_T_RUN_OFS; Load address of osRtxInfo.run
LDM R3,{R1,R2} ; Load osRtxInfo.thread.run: curr & next
CMP R1,R2 ; Check if thread switch is required
IT EQ
BXEQ LR ; Exit when threads are the same
CBZ R1,SVC_ContextSwitch ; Branch if running thread is deleted
SVC_ContextSave
STMDB R12!,{R4-R11} ; Save R4..R11
STR R12,[R1,#TCB_SP_OFS] ; Store SP
SVC_ContextSwitch
STR R2,[R3] ; osRtxInfo.thread.run: curr = next
SVC_ContextRestore
LDR R0,[R2,#TCB_SP_OFS] ; Load SP
LDMIA R0!,{R4-R11} ; Restore R4..R11
MSR PSP,R0 ; Set PSP
MVN LR,#~0xFFFFFFFD ; Set EXC_RETURN value
SVC_Exit
BX LR ; Exit from handler
SVC_User
PUSH {R4,LR} ; Save registers
LDR R2,=osRtxUserSVC ; Load address of SVC table
LDR R3,[R2] ; Load SVC maximum number
CMP R1,R3 ; Check SVC number range
BHI SVC_Done ; Branch if out of range
LDR R4,[R2,R1,LSL #2] ; Load address of SVC function
LDM R0,{R0-R3} ; Load function parameters from stack
BLX R4 ; Call service function
MRS R4,PSP ; Get PSP
STR R0,[R4] ; Store function return value
SVC_Done
POP {R4,PC} ; Return from handler
PendSV_Handler
EXPORT PendSV_Handler
IMPORT osRtxPendSV_Handler
PUSH {R4,LR} ; Save EXC_RETURN
BL osRtxPendSV_Handler ; Call osRtxPendSV_Handler
POP {R4,LR} ; Restore EXC_RETURN
MRS R12,PSP
B SVC_Context
SysTick_Handler
EXPORT SysTick_Handler
IMPORT osRtxTick_Handler
PUSH {R4,LR} ; Save EXC_RETURN
BL osRtxTick_Handler ; Call osRtxTick_Handler
POP {R4,LR} ; Restore EXC_RETURN
MRS R12,PSP
B SVC_Context
END

View File

@ -0,0 +1,148 @@
;/*
; * Copyright (c) 2013-2017 ARM Limited. All rights reserved.
; *
; * SPDX-License-Identifier: Apache-2.0
; *
; * Licensed under the Apache License, Version 2.0 (the License); you may
; * not use this file except in compliance with the License.
; * You may obtain a copy of the License at
; *
; * www.apache.org/licenses/LICENSE-2.0
; *
; * Unless required by applicable law or agreed to in writing, software
; * distributed under the License is distributed on an AS IS BASIS, WITHOUT
; * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
; * See the License for the specific language governing permissions and
; * limitations under the License.
; *
; * -----------------------------------------------------------------------------
; *
; * Project: CMSIS-RTOS RTX
; * Title: Cortex-M4F Exception handlers
; *
; * -----------------------------------------------------------------------------
; */
I_T_RUN_OFS EQU 28 ; osRtxInfo.thread.run offset
TCB_SP_OFS EQU 56 ; TCB.SP offset
TCB_SF_OFS EQU 34 ; TCB.stack_frame offset
PRESERVE8
THUMB
AREA |.constdata|, DATA, READONLY
EXPORT irqRtxLib
irqRtxLib DCB 0 ; Non weak library reference
AREA |.text|, CODE, READONLY
SVC_Handler PROC
EXPORT SVC_Handler
IMPORT osRtxUserSVC
IMPORT osRtxInfo
MRS R0,PSP ; Get PSP
LDR R1,[R0,#24] ; Load saved PC from stack
LDRB R1,[R1,#-2] ; Load SVC number
CBNZ R1,SVC_User ; Branch if not SVC 0
PUSH {R0,LR} ; Save PSP and EXC_RETURN
LDM R0,{R0-R3,R12} ; Load function parameters and address from stack
BLX R12 ; Call service function
POP {R12,LR} ; Restore PSP and EXC_RETURN
STM R12,{R0-R1} ; Store function return values
SVC_Context
LDR R3,=osRtxInfo+I_T_RUN_OFS; Load address of osRtxInfo.run
LDM R3,{R1,R2} ; Load osRtxInfo.thread.run: curr & next
CMP R1,R2 ; Check if thread switch is required
BXEQ LR ; Exit when threads are the same
CBNZ R1,SVC_ContextSave ; Branch if running thread is not deleted
TST LR,#0x10 ; Check if extended stack frame
BNE SVC_ContextSwitch
LDR R1,=0xE000EF34 ; FPCCR Address
LDR R0,[R1] ; Load FPCCR
BIC R0,#1 ; Clear LSPACT (Lazy state)
STR R0,[R1] ; Store FPCCR
B SVC_ContextSwitch
SVC_ContextSave
STMDB R12!,{R4-R11} ; Save R4..R11
TST LR,#0x10 ; Check if extended stack frame
VSTMDBEQ R12!,{S16-S31} ; Save VFP S16.S31
STR R12,[R1,#TCB_SP_OFS] ; Store SP
STRB LR, [R1,#TCB_SF_OFS] ; Store stack frame information
SVC_ContextSwitch
STR R2,[R3] ; osRtxInfo.thread.run: curr = next
SVC_ContextRestore
LDRB R1,[R2,#TCB_SF_OFS] ; Load stack frame information
LDR R0,[R2,#TCB_SP_OFS] ; Load SP
ORR LR,R1,#0xFFFFFF00 ; Set EXC_RETURN
TST LR,#0x10 ; Check if extended stack frame
VLDMIAEQ R0!,{S16-S31} ; Restore VFP S16..S31
LDMIA R0!,{R4-R11} ; Restore R4..R11
MSR PSP,R0 ; Set PSP
SVC_Exit
BX LR ; Exit from handler
SVC_User
PUSH {R4,LR} ; Save registers
LDR R2,=osRtxUserSVC ; Load address of SVC table
LDR R3,[R2] ; Load SVC maximum number
CMP R1,R3 ; Check SVC number range
BHI SVC_Done ; Branch if out of range
LDR R4,[R2,R1,LSL #2] ; Load address of SVC function
LDM R0,{R0-R3} ; Load function parameters from stack
BLX R4 ; Call service function
MRS R4,PSP ; Get PSP
STR R0,[R4] ; Store function return value
SVC_Done
POP {R4,PC} ; Return from handler
ALIGN
ENDP
PendSV_Handler PROC
EXPORT PendSV_Handler
IMPORT osRtxPendSV_Handler
PUSH {R4,LR} ; Save EXC_RETURN
BL osRtxPendSV_Handler ; Call osRtxPendSV_Handler
POP {R4,LR} ; Restore EXC_RETURN
MRS R12,PSP
B SVC_Context
ALIGN
ENDP
SysTick_Handler PROC
EXPORT SysTick_Handler
IMPORT osRtxTick_Handler
PUSH {R4,LR} ; Save EXC_RETURN
BL osRtxTick_Handler ; Call osRtxTick_Handler
POP {R4,LR} ; Restore EXC_RETURN
MRS R12,PSP
B SVC_Context
ALIGN
ENDP
END

View File

@ -0,0 +1,160 @@
/*
* Copyright (c) 2013-2017 ARM Limited. All rights reserved.
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the License); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an AS IS BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* -----------------------------------------------------------------------------
*
* Project: CMSIS-RTOS RTX
* Title: Cortex-M4F Exception handlers
*
* -----------------------------------------------------------------------------
*/
.file "irq_cm4f.S"
.syntax unified
.equ I_T_RUN_OFS, 28 // osRtxInfo.thread.run offset
.equ TCB_SP_OFS, 56 // TCB.SP offset
.equ TCB_SF_OFS, 34 // TCB.stack_frame offset
.section ".rodata"
.global irqRtxLib // Non weak library reference
irqRtxLib:
.byte 0
.thumb
.section ".text"
.align 2
.thumb_func
.type SVC_Handler, %function
.global SVC_Handler
.fnstart
.cantunwind
SVC_Handler:
MRS R0,PSP // Get PSP
LDR R1,[R0,#24] // Load saved PC from stack
LDRB R1,[R1,#-2] // Load SVC number
CBNZ R1,SVC_User // Branch if not SVC 0
PUSH {R0,LR} // Save PSP and EXC_RETURN
LDM R0,{R0-R3,R12} // Load function parameters and address from stack
BLX R12 // Call service function
POP {R12,LR} // Restore PSP and EXC_RETURN
STM R12,{R0-R1} // Store function return values
SVC_Context:
LDR R3,=osRtxInfo+I_T_RUN_OFS // Load address of osRtxInfo.run
LDM R3,{R1,R2} // Load osRtxInfo.thread.run: curr & next
CMP R1,R2 // Check if thread switch is required
IT EQ
BXEQ LR // Exit when threads are the same
CBNZ R1,SVC_ContextSave // Branch if running thread is not deleted
TST LR,#0x10 // Check if extended stack frame
BNE SVC_ContextSwitch
LDR R1,=0xE000EF34 // FPCCR Address
LDR R0,[R1] // Load FPCCR
BIC R0,#1 // Clear LSPACT (Lazy state)
STR R0,[R1] // Store FPCCR
B SVC_ContextSwitch
SVC_ContextSave:
STMDB R12!,{R4-R11} // Save R4..R11
TST LR,#0x10 // Check if extended stack frame
IT EQ
VSTMDBEQ R12!,{S16-S31} // Save VFP S16.S31
STR R12,[R1,#TCB_SP_OFS] // Store SP
STRB LR, [R1,#TCB_SF_OFS] // Store stack frame information
SVC_ContextSwitch:
STR R2,[R3] // osRtxInfo.thread.run: curr = next
SVC_ContextRestore:
LDRB R1,[R2,#TCB_SF_OFS] // Load stack frame information
LDR R0,[R2,#TCB_SP_OFS] // Load SP
ORR LR,R1,#0xFFFFFF00 // Set EXC_RETURN
TST LR,#0x10 // Check if extended stack frame
IT EQ
VLDMIAEQ R0!,{S16-S31} // Restore VFP S16..S31
LDMIA R0!,{R4-R11} // Restore R4..R11
MSR PSP,R0 // Set PSP
SVC_Exit:
BX LR // Exit from handler
SVC_User:
PUSH {R4,LR} // Save registers
LDR R2,=osRtxUserSVC // Load address of SVC table
LDR R3,[R2] // Load SVC maximum number
CMP R1,R3 // Check SVC number range
BHI SVC_Done // Branch if out of range
LDR R4,[R2,R1,LSL #2] // Load address of SVC function
LDM R0,{R0-R3} // Load function parameters from stack
BLX R4 // Call service function
MRS R4,PSP // Get PSP
STR R0,[R4] // Store function return value
SVC_Done:
POP {R4,PC} // Return from handler
.fnend
.size SVC_Handler, .-SVC_Handler
.thumb_func
.type PendSV_Handler, %function
.global PendSV_Handler
.fnstart
.cantunwind
PendSV_Handler:
PUSH {R4,LR} // Save EXC_RETURN
BL osRtxPendSV_Handler // Call osRtxPendSV_Handler
POP {R4,LR} // Restore EXC_RETURN
MRS R12,PSP
B SVC_Context
.fnend
.size PendSV_Handler, .-PendSV_Handler
.thumb_func
.type SysTick_Handler, %function
.global SysTick_Handler
.fnstart
.cantunwind
SysTick_Handler:
PUSH {R4,LR} // Save EXC_RETURN
BL osRtxTick_Handler // Call osRtxTick_Handler
POP {R4,LR} // Restore EXC_RETURN
MRS R12,PSP
B SVC_Context
.fnend
.size SysTick_Handler, .-SysTick_Handler
.end

View File

@ -0,0 +1,144 @@
;/*
; * Copyright (c) 2013-2017 ARM Limited. All rights reserved.
; *
; * SPDX-License-Identifier: Apache-2.0
; *
; * Licensed under the Apache License, Version 2.0 (the License); you may
; * not use this file except in compliance with the License.
; * You may obtain a copy of the License at
; *
; * www.apache.org/licenses/LICENSE-2.0
; *
; * Unless required by applicable law or agreed to in writing, software
; * distributed under the License is distributed on an AS IS BASIS, WITHOUT
; * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
; * See the License for the specific language governing permissions and
; * limitations under the License.
; *
; * -----------------------------------------------------------------------------
; *
; * Project: CMSIS-RTOS RTX
; * Title: Cortex-M4F Exception handlers
; *
; * -----------------------------------------------------------------------------
; */
NAME irq_cm4f.s
I_T_RUN_OFS EQU 28 ; osRtxInfo.thread.run offset
TCB_SP_OFS EQU 56 ; TCB.SP offset
TCB_SF_OFS EQU 34 ; TCB.stack_frame offset
PRESERVE8
SECTION .rodata:DATA:NOROOT(2)
EXPORT irqRtxLib
irqRtxLib DCB 0 ; Non weak library reference
THUMB
SECTION .text:CODE:NOROOT(2)
SVC_Handler
EXPORT SVC_Handler
IMPORT osRtxUserSVC
IMPORT osRtxInfo
MRS R0,PSP ; Get PSP
LDR R1,[R0,#24] ; Load saved PC from stack
LDRB R1,[R1,#-2] ; Load SVC number
CBNZ R1,SVC_User ; Branch if not SVC 0
PUSH {R0,LR} ; Save PSP and EXC_RETURN
LDM R0,{R0-R3,R12} ; Load function parameters and address from stack
BLX R12 ; Call service function
POP {R12,LR} ; Restore PSP and EXC_RETURN
STM R12,{R0-R1} ; Store function return values
SVC_Context
LDR R3,=osRtxInfo+I_T_RUN_OFS; Load address of osRtxInfo.run
LDM R3,{R1,R2} ; Load osRtxInfo.thread.run: curr & next
CMP R1,R2 ; Check if thread switch is required
IT EQ
BXEQ LR ; Exit when threads are the same
CBNZ R1,SVC_ContextSave ; Branch if running thread is not deleted
TST LR,#0x10 ; Check if extended stack frame
BNE SVC_ContextSwitch
LDR R1,=0xE000EF34 ; FPCCR Address
LDR R0,[R1] ; Load FPCCR
BIC R0,R0,#1 ; Clear LSPACT (Lazy state)
STR R0,[R1] ; Store FPCCR
B SVC_ContextSwitch
SVC_ContextSave
STMDB R12!,{R4-R11} ; Save R4..R11
TST LR,#0x10 ; Check if extended stack frame
IT EQ
VSTMDBEQ R12!,{S16-S31} ; Save VFP S16.S31
STR R12,[R1,#TCB_SP_OFS] ; Store SP
STRB LR, [R1,#TCB_SF_OFS] ; Store stack frame information
SVC_ContextSwitch
STR R2,[R3] ; osRtxInfo.thread.run: curr = next
SVC_ContextRestore
LDRB R1,[R2,#TCB_SF_OFS] ; Load stack frame information
LDR R0,[R2,#TCB_SP_OFS] ; Load SP
ORR LR,R1,#0xFFFFFF00 ; Set EXC_RETURN
TST LR,#0x10 ; Check if extended stack frame
IT EQ
VLDMIAEQ R0!,{S16-S31} ; Restore VFP S16..S31
LDMIA R0!,{R4-R11} ; Restore R4..R11
MSR PSP,R0 ; Set PSP
SVC_Exit
BX LR ; Exit from handler
SVC_User
PUSH {R4,LR} ; Save registers
LDR R2,=osRtxUserSVC ; Load address of SVC table
LDR R3,[R2] ; Load SVC maximum number
CMP R1,R3 ; Check SVC number range
BHI SVC_Done ; Branch if out of range
LDR R4,[R2,R1,LSL #2] ; Load address of SVC function
LDM R0,{R0-R3} ; Load function parameters from stack
BLX R4 ; Call service function
MRS R4,PSP ; Get PSP
STR R0,[R4] ; Store function return value
SVC_Done
POP {R4,PC} ; Return from handler
PendSV_Handler
EXPORT PendSV_Handler
IMPORT osRtxPendSV_Handler
PUSH {R4,LR} ; Save EXC_RETURN
BL osRtxPendSV_Handler ; Call osRtxPendSV_Handler
POP {R4,LR} ; Restore EXC_RETURN
MRS R12,PSP
B SVC_Context
SysTick_Handler
EXPORT SysTick_Handler
IMPORT osRtxTick_Handler
PUSH {R4,LR} ; Save EXC_RETURN
BL osRtxTick_Handler ; Call osRtxTick_Handler
POP {R4,LR} ; Restore EXC_RETURN
MRS R12,PSP
B SVC_Context
END

View File

@ -0,0 +1,745 @@
/*
* Copyright (c) 2013-2017 ARM Limited. All rights reserved.
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the License); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an AS IS BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* ----------------------------------------------------------------------
*
* $Date: 10. January 2017
* $Revision: V2.1.0
*
* Project: CMSIS-RTOS2 API
* Title: cmsis_os2.h header file
*
* Version 2.1.0
* Support for critical and uncritical sections (nesting safe):
* - updated: osKernelLock, osKernelUnlock
* - added: osKernelRestoreLock
* Updated Thread and Event Flags:
* - changed flags parameter and return type from int32_t to uint32_t
* Version 2.0.0
* Initial Release
*---------------------------------------------------------------------------*/
#ifndef CMSIS_OS2_H_
#define CMSIS_OS2_H_
#ifndef __NO_RETURN
#if defined(__CC_ARM)
#define __NO_RETURN __declspec(noreturn)
#elif defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050)
#define __NO_RETURN __attribute__((noreturn))
#elif defined(__GNUC__)
#define __NO_RETURN __attribute__((noreturn))
#elif defined(__ICCARM__)
#define __NO_RETURN __noreturn
#else
#define __NO_RETURN
#endif
#endif
#include <stdint.h>
#include <stddef.h>
#ifdef __cplusplus
extern "C"
{
#endif
// ==== Enumerations, structures, defines ====
/// Version information.
typedef struct {
uint32_t api; ///< API version (major.minor.rev: mmnnnrrrr dec).
uint32_t kernel; ///< Kernel version (major.minor.rev: mmnnnrrrr dec).
} osVersion_t;
/// Kernel state.
typedef enum {
osKernelInactive = 0, ///< Inactive.
osKernelReady = 1, ///< Ready.
osKernelRunning = 2, ///< Running.
osKernelLocked = 3, ///< Locked.
osKernelSuspended = 4, ///< Suspended.
osKernelError = -1, ///< Error.
osKernelReserved = 0x7FFFFFFFU ///< Prevents enum down-size compiler optimization.
} osKernelState_t;
/// Thread state.
typedef enum {
osThreadInactive = 0, ///< Inactive.
osThreadReady = 1, ///< Ready.
osThreadRunning = 2, ///< Running.
osThreadBlocked = 3, ///< Blocked.
osThreadTerminated = 4, ///< Terminated.
osThreadError = -1, ///< Error.
osThreadReserved = 0x7FFFFFFF ///< Prevents enum down-size compiler optimization.
} osThreadState_t;
/// Priority values.
typedef enum {
osPriorityNone = 0, ///< No priority (not initialized).
osPriorityIdle = 1, ///< Reserved for Idle thread.
osPriorityLow = 8, ///< Priority: low
osPriorityLow1 = 8+1, ///< Priority: low + 1
osPriorityLow2 = 8+2, ///< Priority: low + 2
osPriorityLow3 = 8+3, ///< Priority: low + 3
osPriorityLow4 = 8+4, ///< Priority: low + 4
osPriorityLow5 = 8+5, ///< Priority: low + 5
osPriorityLow6 = 8+6, ///< Priority: low + 6
osPriorityLow7 = 8+7, ///< Priority: low + 7
osPriorityBelowNormal = 16, ///< Priority: below normal
osPriorityBelowNormal1 = 16+1, ///< Priority: below normal + 1
osPriorityBelowNormal2 = 16+2, ///< Priority: below normal + 2
osPriorityBelowNormal3 = 16+3, ///< Priority: below normal + 3
osPriorityBelowNormal4 = 16+4, ///< Priority: below normal + 4
osPriorityBelowNormal5 = 16+5, ///< Priority: below normal + 5
osPriorityBelowNormal6 = 16+6, ///< Priority: below normal + 6
osPriorityBelowNormal7 = 16+7, ///< Priority: below normal + 7
osPriorityNormal = 24, ///< Priority: normal
osPriorityNormal1 = 24+1, ///< Priority: normal + 1
osPriorityNormal2 = 24+2, ///< Priority: normal + 2
osPriorityNormal3 = 24+3, ///< Priority: normal + 3
osPriorityNormal4 = 24+4, ///< Priority: normal + 4
osPriorityNormal5 = 24+5, ///< Priority: normal + 5
osPriorityNormal6 = 24+6, ///< Priority: normal + 6
osPriorityNormal7 = 24+7, ///< Priority: normal + 7
osPriorityAboveNormal = 32, ///< Priority: above normal
osPriorityAboveNormal1 = 32+1, ///< Priority: above normal + 1
osPriorityAboveNormal2 = 32+2, ///< Priority: above normal + 2
osPriorityAboveNormal3 = 32+3, ///< Priority: above normal + 3
osPriorityAboveNormal4 = 32+4, ///< Priority: above normal + 4
osPriorityAboveNormal5 = 32+5, ///< Priority: above normal + 5
osPriorityAboveNormal6 = 32+6, ///< Priority: above normal + 6
osPriorityAboveNormal7 = 32+7, ///< Priority: above normal + 7
osPriorityHigh = 40, ///< Priority: high
osPriorityHigh1 = 40+1, ///< Priority: high + 1
osPriorityHigh2 = 40+2, ///< Priority: high + 2
osPriorityHigh3 = 40+3, ///< Priority: high + 3
osPriorityHigh4 = 40+4, ///< Priority: high + 4
osPriorityHigh5 = 40+5, ///< Priority: high + 5
osPriorityHigh6 = 40+6, ///< Priority: high + 6
osPriorityHigh7 = 40+7, ///< Priority: high + 7
osPriorityRealtime = 48, ///< Priority: realtime
osPriorityRealtime1 = 48+1, ///< Priority: realtime + 1
osPriorityRealtime2 = 48+2, ///< Priority: realtime + 2
osPriorityRealtime3 = 48+3, ///< Priority: realtime + 3
osPriorityRealtime4 = 48+4, ///< Priority: realtime + 4
osPriorityRealtime5 = 48+5, ///< Priority: realtime + 5
osPriorityRealtime6 = 48+6, ///< Priority: realtime + 6
osPriorityRealtime7 = 48+7, ///< Priority: realtime + 7
osPriorityISR = 56, ///< Reserved for ISR deferred thread.
osPriorityError = -1, ///< System cannot determine priority or illegal priority.
osPriorityReserved = 0x7FFFFFFF ///< Prevents enum down-size compiler optimization.
} osPriority_t;
/// Entry point of a thread.
typedef void (*osThreadFunc_t) (void *argument);
/// Entry point of a timer call back function.
typedef void (*osTimerFunc_t) (void *argument);
/// Timer type.
typedef enum {
osTimerOnce = 0, ///< One-shot timer.
osTimerPeriodic = 1 ///< Repeating timer.
} osTimerType_t;
/// Timeout value.
#define osWaitForever 0xFFFFFFFFU ///< Wait forever timeout value.
/// Flags options (\ref osThreadFlagsWait and \ref osEventFlagsWait).
#define osFlagsWaitAny 0x00000000U ///< Wait for any flag (default).
#define osFlagsWaitAll 0x00000001U ///< Wait for all flags.
#define osFlagsNoClear 0x00000002U ///< Do not clear flags which have been specified to wait for.
/// Flags errors (returned by osThreadFlagsXxxx and osEventFlagsXxxx).
#define osFlagsError 0x80000000U ///< Error indicator.
#define osFlagsErrorUnknown 0xFFFFFFFFU ///< osError (-1).
#define osFlagsErrorTimeout 0xFFFFFFFEU ///< osErrorTimeout (-2).
#define osFlagsErrorResource 0xFFFFFFFDU ///< osErrorResource (-3).
#define osFlagsErrorParameter 0xFFFFFFFCU ///< osErrorParameter (-4).
#define osFlagsErrorISR 0xFFFFFFFAU ///< osErrorISR (-6).
/// Thread attributes (attr_bits in \ref osThreadAttr_t).
#define osThreadDetached 0x00000000U ///< Thread created in detached state (default)
#define osThreadJoinable 0x00000001U ///< Thread created in joinable state
/// Mutex attributes (attr_bits in \ref osMutexAttr_t).
#define osMutexRecursive 0x00000001U ///< Recursive mutex.
#define osMutexPrioInherit 0x00000002U ///< Priority inherit protocol.
#define osMutexRobust 0x00000008U ///< Robust mutex.
/// Status code values returned by CMSIS-RTOS functions.
typedef enum {
osOK = 0, ///< Operation completed successfully.
osError = -1, ///< Unspecified RTOS error: run-time error but no other error message fits.
osErrorTimeout = -2, ///< Operation not completed within the timeout period.
osErrorResource = -3, ///< Resource not available.
osErrorParameter = -4, ///< Parameter error.
osErrorNoMemory = -5, ///< System is out of memory: it was impossible to allocate or reserve memory for the operation.
osErrorISR = -6, ///< Not allowed in ISR context: the function cannot be called from interrupt service routines.
osStatusReserved = 0x7FFFFFFF ///< Prevents enum down-size compiler optimization.
} osStatus_t;
/// \details Thread ID identifies the thread.
typedef void *osThreadId_t;
/// \details Timer ID identifies the timer.
typedef void *osTimerId_t;
/// \details Event Flags ID identifies the event flags.
typedef void *osEventFlagsId_t;
/// \details Mutex ID identifies the mutex.
typedef void *osMutexId_t;
/// \details Semaphore ID identifies the semaphore.
typedef void *osSemaphoreId_t;
/// \details Memory Pool ID identifies the memory pool.
typedef void *osMemoryPoolId_t;
/// \details Message Queue ID identifies the message queue.
typedef void *osMessageQueueId_t;
#ifndef TZ_MODULEID_T
#define TZ_MODULEID_T
/// \details Data type that identifies secure software modules called by a process.
typedef uint32_t TZ_ModuleId_t;
#endif
/// Attributes structure for thread.
typedef struct {
const char *name; ///< name of the thread
uint32_t attr_bits; ///< attribute bits
void *cb_mem; ///< memory for control block
uint32_t cb_size; ///< size of provided memory for control block
void *stack_mem; ///< memory for stack
uint32_t stack_size; ///< size of stack
osPriority_t priority; ///< initial thread priority (default: osPriorityNormal)
TZ_ModuleId_t tz_module; ///< TrustZone module identifier
uint32_t reserved; ///< reserved (must be 0)
} osThreadAttr_t;
/// Attributes structure for timer.
typedef struct {
const char *name; ///< name of the timer
uint32_t attr_bits; ///< attribute bits
void *cb_mem; ///< memory for control block
uint32_t cb_size; ///< size of provided memory for control block
} osTimerAttr_t;
/// Attributes structure for event flags.
typedef struct {
const char *name; ///< name of the event flags
uint32_t attr_bits; ///< attribute bits
void *cb_mem; ///< memory for control block
uint32_t cb_size; ///< size of provided memory for control block
} osEventFlagsAttr_t;
/// Attributes structure for mutex.
typedef struct {
const char *name; ///< name of the mutex
uint32_t attr_bits; ///< attribute bits
void *cb_mem; ///< memory for control block
uint32_t cb_size; ///< size of provided memory for control block
} osMutexAttr_t;
/// Attributes structure for semaphore.
typedef struct {
const char *name; ///< name of the semaphore
uint32_t attr_bits; ///< attribute bits
void *cb_mem; ///< memory for control block
uint32_t cb_size; ///< size of provided memory for control block
} osSemaphoreAttr_t;
/// Attributes structure for memory pool.
typedef struct {
const char *name; ///< name of the memory pool
uint32_t attr_bits; ///< attribute bits
void *cb_mem; ///< memory for control block
uint32_t cb_size; ///< size of provided memory for control block
void *mp_mem; ///< memory for data storage
uint32_t mp_size; ///< size of provided memory for data storage
} osMemoryPoolAttr_t;
/// Attributes structure for message queue.
typedef struct {
const char *name; ///< name of the message queue
uint32_t attr_bits; ///< attribute bits
void *cb_mem; ///< memory for control block
uint32_t cb_size; ///< size of provided memory for control block
void *mq_mem; ///< memory for data storage
uint32_t mq_size; ///< size of provided memory for data storage
} osMessageQueueAttr_t;
// ==== Kernel Management Functions ====
/// Initialize the RTOS Kernel.
/// \return status code that indicates the execution status of the function.
osStatus_t osKernelInitialize (void);
/// Get RTOS Kernel Information.
/// \param[out] version pointer to buffer for retrieving version information.
/// \param[out] id_buf pointer to buffer for retrieving kernel identification string.
/// \param[in] id_size size of buffer for kernel identification string.
/// \return status code that indicates the execution status of the function.
osStatus_t osKernelGetInfo (osVersion_t *version, char *id_buf, uint32_t id_size);
/// Get the current RTOS Kernel state.
/// \return current RTOS Kernel state.
osKernelState_t osKernelGetState (void);
/// Start the RTOS Kernel scheduler.
/// \return status code that indicates the execution status of the function.
osStatus_t osKernelStart (void);
/// Lock the RTOS Kernel scheduler.
/// \return previous lock state (1 - locked, 0 - not locked, error code if negative).
int32_t osKernelLock (void);
/// Unlock the RTOS Kernel scheduler.
/// \return previous lock state (1 - locked, 0 - not locked, error code if negative).
int32_t osKernelUnlock (void);
/// Restore the RTOS Kernel scheduler lock state.
/// \param[in] lock lock state obtained by \ref osKernelLock or \ref osKernelUnlock.
/// \return new lock state (1 - locked, 0 - not locked, error code if negative).
int32_t osKernelRestoreLock (int32_t lock);
/// Suspend the RTOS Kernel scheduler.
/// \return time in ticks, for how long the system can sleep or power-down.
uint32_t osKernelSuspend (void);
/// Resume the RTOS Kernel scheduler.
/// \param[in] sleep_ticks time in ticks for how long the system was in sleep or power-down mode.
void osKernelResume (uint32_t sleep_ticks);
/// Get the RTOS kernel tick count.
/// \return RTOS kernel current tick count.
uint64_t osKernelGetTickCount (void);
/// Get the RTOS kernel tick frequency.
/// \return frequency of the kernel tick.
uint32_t osKernelGetTickFreq (void);
/// Get the RTOS kernel system timer count.
/// \return RTOS kernel current system timer count as 32-bit value.
uint32_t osKernelGetSysTimerCount (void);
/// Get the RTOS kernel system timer frequency.
/// \return frequency of the system timer.
uint32_t osKernelGetSysTimerFreq (void);
// ==== Thread Management Functions ====
/// Create a thread and add it to Active Threads.
/// \param[in] func thread function.
/// \param[in] argument pointer that is passed to the thread function as start argument.
/// \param[in] attr thread attributes; NULL: default values.
/// \return thread ID for reference by other functions or NULL in case of error.
osThreadId_t osThreadNew (osThreadFunc_t func, void *argument, const osThreadAttr_t *attr);
/// Get name of a thread.
/// \param[in] thread_id thread ID obtained by \ref osThreadNew or \ref osThreadGetId.
/// \return name as NULL terminated string.
const char *osThreadGetName (osThreadId_t thread_id);
/// Return the thread ID of the current running thread.
/// \return thread ID for reference by other functions or NULL in case of error.
osThreadId_t osThreadGetId (void);
/// Get current thread state of a thread.
/// \param[in] thread_id thread ID obtained by \ref osThreadNew or \ref osThreadGetId.
/// \return current thread state of the specified thread.
osThreadState_t osThreadGetState (osThreadId_t thread_id);
/// Get stack size of a thread.
/// \param[in] thread_id thread ID obtained by \ref osThreadNew or \ref osThreadGetId.
/// \return stack size in bytes.
uint32_t osThreadGetStackSize (osThreadId_t thread_id);
/// Get available stack space of a thread based on stack watermark recording during execution.
/// \param[in] thread_id thread ID obtained by \ref osThreadNew or \ref osThreadGetId.
/// \return remaining stack space in bytes.
uint32_t osThreadGetStackSpace (osThreadId_t thread_id);
/// Change priority of a thread.
/// \param[in] thread_id thread ID obtained by \ref osThreadNew or \ref osThreadGetId.
/// \param[in] priority new priority value for the thread function.
/// \return status code that indicates the execution status of the function.
osStatus_t osThreadSetPriority (osThreadId_t thread_id, osPriority_t priority);
/// Get current priority of a thread.
/// \param[in] thread_id thread ID obtained by \ref osThreadNew or \ref osThreadGetId.
/// \return current priority value of the specified thread.
osPriority_t osThreadGetPriority (osThreadId_t thread_id);
/// Pass control to next thread that is in state \b READY.
/// \return status code that indicates the execution status of the function.
osStatus_t osThreadYield (void);
/// Suspend execution of a thread.
/// \param[in] thread_id thread ID obtained by \ref osThreadNew or \ref osThreadGetId.
/// \return status code that indicates the execution status of the function.
osStatus_t osThreadSuspend (osThreadId_t thread_id);
/// Resume execution of a thread.
/// \param[in] thread_id thread ID obtained by \ref osThreadNew or \ref osThreadGetId.
/// \return status code that indicates the execution status of the function.
osStatus_t osThreadResume (osThreadId_t thread_id);
/// Detach a thread (thread storage can be reclaimed when thread terminates).
/// \param[in] thread_id thread ID obtained by \ref osThreadNew or \ref osThreadGetId.
/// \return status code that indicates the execution status of the function.
osStatus_t osThreadDetach (osThreadId_t thread_id);
/// Wait for specified thread to terminate.
/// \param[in] thread_id thread ID obtained by \ref osThreadNew or \ref osThreadGetId.
/// \return status code that indicates the execution status of the function.
osStatus_t osThreadJoin (osThreadId_t thread_id);
/// Terminate execution of current running thread.
__NO_RETURN void osThreadExit (void);
/// Terminate execution of a thread.
/// \param[in] thread_id thread ID obtained by \ref osThreadNew or \ref osThreadGetId.
/// \return status code that indicates the execution status of the function.
osStatus_t osThreadTerminate (osThreadId_t thread_id);
/// Get number of active threads.
/// \return number of active threads.
uint32_t osThreadGetCount (void);
/// Enumerate active threads.
/// \param[out] thread_array pointer to array for retrieving thread IDs.
/// \param[in] array_items maximum number of items in array for retrieving thread IDs.
/// \return number of enumerated threads.
uint32_t osThreadEnumerate (osThreadId_t *thread_array, uint32_t array_items);
// ==== Thread Flags Functions ====
/// Set the specified Thread Flags of a thread.
/// \param[in] thread_id thread ID obtained by \ref osThreadNew or \ref osThreadGetId.
/// \param[in] flags specifies the flags of the thread that shall be set.
/// \return thread flags after setting or error code if highest bit set.
uint32_t osThreadFlagsSet (osThreadId_t thread_id, uint32_t flags);
/// Clear the specified Thread Flags of current running thread.
/// \param[in] flags specifies the flags of the thread that shall be cleared.
/// \return thread flags before clearing or error code if highest bit set.
uint32_t osThreadFlagsClear (uint32_t flags);
/// Get the current Thread Flags of current running thread.
/// \return current thread flags.
uint32_t osThreadFlagsGet (void);
/// Wait for one or more Thread Flags of the current running thread to become signaled.
/// \param[in] flags specifies the flags to wait for.
/// \param[in] options specifies flags options (osFlagsXxxx).
/// \param[in] timeout \ref CMSIS_RTOS_TimeOutValue or 0 in case of no time-out.
/// \return thread flags before clearing or error code if highest bit set.
uint32_t osThreadFlagsWait (uint32_t flags, uint32_t options, uint32_t timeout);
// ==== Generic Wait Functions ====
/// Wait for Timeout (Time Delay).
/// \param[in] ticks \ref CMSIS_RTOS_TimeOutValue "time ticks" value
/// \return status code that indicates the execution status of the function.
osStatus_t osDelay (uint32_t ticks);
/// Wait until specified time.
/// \param[in] ticks absolute time in ticks
/// \return status code that indicates the execution status of the function.
osStatus_t osDelayUntil (uint64_t ticks);
// ==== Timer Management Functions ====
/// Create and Initialize a timer.
/// \param[in] func start address of a timer call back function.
/// \param[in] type osTimerOnce for one-shot or osTimerPeriodic for periodic behavior.
/// \param[in] argument argument to the timer call back function.
/// \param[in] attr timer attributes; NULL: default values.
/// \return timer ID for reference by other functions or NULL in case of error.
osTimerId_t osTimerNew (osTimerFunc_t func, osTimerType_t type, void *argument, const osTimerAttr_t *attr);
/// Get name of a timer.
/// \param[in] timer_id timer ID obtained by \ref osTimerNew.
/// \return name as NULL terminated string.
const char *osTimerGetName (osTimerId_t timer_id);
/// Start or restart a timer.
/// \param[in] timer_id timer ID obtained by \ref osTimerNew.
/// \param[in] ticks \ref CMSIS_RTOS_TimeOutValue "time ticks" value of the timer.
/// \return status code that indicates the execution status of the function.
osStatus_t osTimerStart (osTimerId_t timer_id, uint32_t ticks);
/// Stop a timer.
/// \param[in] timer_id timer ID obtained by \ref osTimerNew.
/// \return status code that indicates the execution status of the function.
osStatus_t osTimerStop (osTimerId_t timer_id);
/// Check if a timer is running.
/// \param[in] timer_id timer ID obtained by \ref osTimerNew.
/// \return 0 not running, 1 running.
uint32_t osTimerIsRunning (osTimerId_t timer_id);
/// Delete a timer.
/// \param[in] timer_id timer ID obtained by \ref osTimerNew.
/// \return status code that indicates the execution status of the function.
osStatus_t osTimerDelete (osTimerId_t timer_id);
// ==== Event Flags Management Functions ====
/// Create and Initialize an Event Flags object.
/// \param[in] attr event flags attributes; NULL: default values.
/// \return event flags ID for reference by other functions or NULL in case of error.
osEventFlagsId_t osEventFlagsNew (const osEventFlagsAttr_t *attr);
/// Get name of an Event Flags object.
/// \param[in] ef_id event flags ID obtained by \ref osEventFlagsNew.
/// \return name as NULL terminated string.
const char *osEventFlagsGetName (osEventFlagsId_t ef_id);
/// Set the specified Event Flags.
/// \param[in] ef_id event flags ID obtained by \ref osEventFlagsNew.
/// \param[in] flags specifies the flags that shall be set.
/// \return event flags after setting or error code if highest bit set.
uint32_t osEventFlagsSet (osEventFlagsId_t ef_id, uint32_t flags);
/// Clear the specified Event Flags.
/// \param[in] ef_id event flags ID obtained by \ref osEventFlagsNew.
/// \param[in] flags specifies the flags that shall be cleared.
/// \return event flags before clearing or error code if highest bit set.
uint32_t osEventFlagsClear (osEventFlagsId_t ef_id, uint32_t flags);
/// Get the current Event Flags.
/// \param[in] ef_id event flags ID obtained by \ref osEventFlagsNew.
/// \return current event flags.
uint32_t osEventFlagsGet (osEventFlagsId_t ef_id);
/// Wait for one or more Event Flags to become signaled.
/// \param[in] ef_id event flags ID obtained by \ref osEventFlagsNew.
/// \param[in] flags specifies the flags to wait for.
/// \param[in] options specifies flags options (osFlagsXxxx).
/// \param[in] timeout \ref CMSIS_RTOS_TimeOutValue or 0 in case of no time-out.
/// \return event flags before clearing or error code if highest bit set.
uint32_t osEventFlagsWait (osEventFlagsId_t ef_id, uint32_t flags, uint32_t options, uint32_t timeout);
/// Delete an Event Flags object.
/// \param[in] ef_id event flags ID obtained by \ref osEventFlagsNew.
/// \return status code that indicates the execution status of the function.
osStatus_t osEventFlagsDelete (osEventFlagsId_t ef_id);
// ==== Mutex Management Functions ====
/// Create and Initialize a Mutex object.
/// \param[in] attr mutex attributes; NULL: default values.
/// \return mutex ID for reference by other functions or NULL in case of error.
osMutexId_t osMutexNew (const osMutexAttr_t *attr);
/// Get name of a Mutex object.
/// \param[in] mutex_id mutex ID obtained by \ref osMutexNew.
/// \return name as NULL terminated string.
const char *osMutexGetName (osMutexId_t mutex_id);
/// Acquire a Mutex or timeout if it is locked.
/// \param[in] mutex_id mutex ID obtained by \ref osMutexNew.
/// \param[in] timeout \ref CMSIS_RTOS_TimeOutValue or 0 in case of no time-out.
/// \return status code that indicates the execution status of the function.
osStatus_t osMutexAcquire (osMutexId_t mutex_id, uint32_t timeout);
/// Release a Mutex that was acquired by \ref osMutexAcquire.
/// \param[in] mutex_id mutex ID obtained by \ref osMutexNew.
/// \return status code that indicates the execution status of the function.
osStatus_t osMutexRelease (osMutexId_t mutex_id);
/// Get Thread which owns a Mutex object.
/// \param[in] mutex_id mutex ID obtained by \ref osMutexNew.
/// \return thread ID of owner thread or NULL when mutex was not acquired.
osThreadId_t osMutexGetOwner (osMutexId_t mutex_id);
/// Delete a Mutex object.
/// \param[in] mutex_id mutex ID obtained by \ref osMutexNew.
/// \return status code that indicates the execution status of the function.
osStatus_t osMutexDelete (osMutexId_t mutex_id);
// ==== Semaphore Management Functions ====
/// Create and Initialize a Semaphore object.
/// \param[in] max_count maximum number of available tokens.
/// \param[in] initial_count initial number of available tokens.
/// \param[in] attr semaphore attributes; NULL: default values.
/// \return semaphore ID for reference by other functions or NULL in case of error.
osSemaphoreId_t osSemaphoreNew (uint32_t max_count, uint32_t initial_count, const osSemaphoreAttr_t *attr);
/// Get name of a Semaphore object.
/// \param[in] semaphore_id semaphore ID obtained by \ref osSemaphoreNew.
/// \return name as NULL terminated string.
const char *osSemaphoreGetName (osSemaphoreId_t semaphore_id);
/// Acquire a Semaphore token or timeout if no tokens are available.
/// \param[in] semaphore_id semaphore ID obtained by \ref osSemaphoreNew.
/// \param[in] timeout \ref CMSIS_RTOS_TimeOutValue or 0 in case of no time-out.
/// \return status code that indicates the execution status of the function.
osStatus_t osSemaphoreAcquire (osSemaphoreId_t semaphore_id, uint32_t timeout);
/// Release a Semaphore token that was acquired by \ref osSemaphoreAcquire.
/// \param[in] semaphore_id semaphore ID obtained by \ref osSemaphoreNew.
/// \return status code that indicates the execution status of the function.
osStatus_t osSemaphoreRelease (osSemaphoreId_t semaphore_id);
/// Get current Semaphore token count.
/// \param[in] semaphore_id semaphore ID obtained by \ref osSemaphoreNew.
/// \return number of tokens available.
uint32_t osSemaphoreGetCount (osSemaphoreId_t semaphore_id);
/// Delete a Semaphore object.
/// \param[in] semaphore_id semaphore ID obtained by \ref osSemaphoreNew.
/// \return status code that indicates the execution status of the function.
osStatus_t osSemaphoreDelete (osSemaphoreId_t semaphore_id);
// ==== Memory Pool Management Functions ====
/// Create and Initialize a Memory Pool object.
/// \param[in] block_count maximum number of memory blocks in memory pool.
/// \param[in] block_size memory block size in bytes.
/// \param[in] attr memory pool attributes; NULL: default values.
/// \return memory pool ID for reference by other functions or NULL in case of error.
osMemoryPoolId_t osMemoryPoolNew (uint32_t block_count, uint32_t block_size, const osMemoryPoolAttr_t *attr);
/// Get name of a Memory Pool object.
/// \param[in] mp_id memory pool ID obtained by \ref osMemoryPoolNew.
/// \return name as NULL terminated string.
const char *osMemoryPoolGetName (osMemoryPoolId_t mp_id);
/// Allocate a memory block from a Memory Pool.
/// \param[in] mp_id memory pool ID obtained by \ref osMemoryPoolNew.
/// \param[in] timeout \ref CMSIS_RTOS_TimeOutValue or 0 in case of no time-out.
/// \return address of the allocated memory block or NULL in case of no memory is available.
void *osMemoryPoolAlloc (osMemoryPoolId_t mp_id, uint32_t timeout);
/// Return an allocated memory block back to a Memory Pool.
/// \param[in] mp_id memory pool ID obtained by \ref osMemoryPoolNew.
/// \param[in] block address of the allocated memory block to be returned to the memory pool.
/// \return status code that indicates the execution status of the function.
osStatus_t osMemoryPoolFree (osMemoryPoolId_t mp_id, void *block);
/// Get maximum number of memory blocks in a Memory Pool.
/// \param[in] mp_id memory pool ID obtained by \ref osMemoryPoolNew.
/// \return maximum number of memory blocks.
uint32_t osMemoryPoolGetCapacity (osMemoryPoolId_t mp_id);
/// Get memory block size in a Memory Pool.
/// \param[in] mp_id memory pool ID obtained by \ref osMemoryPoolNew.
/// \return memory block size in bytes.
uint32_t osMemoryPoolGetBlockSize (osMemoryPoolId_t mp_id);
/// Get number of memory blocks used in a Memory Pool.
/// \param[in] mp_id memory pool ID obtained by \ref osMemoryPoolNew.
/// \return number of memory blocks used.
uint32_t osMemoryPoolGetCount (osMemoryPoolId_t mp_id);
/// Get number of memory blocks available in a Memory Pool.
/// \param[in] mp_id memory pool ID obtained by \ref osMemoryPoolNew.
/// \return number of memory blocks available.
uint32_t osMemoryPoolGetSpace (osMemoryPoolId_t mp_id);
/// Delete a Memory Pool object.
/// \param[in] mp_id memory pool ID obtained by \ref osMemoryPoolNew.
/// \return status code that indicates the execution status of the function.
osStatus_t osMemoryPoolDelete (osMemoryPoolId_t mp_id);
// ==== Message Queue Management Functions ====
/// Create and Initialize a Message Queue object.
/// \param[in] msg_count maximum number of messages in queue.
/// \param[in] msg_size maximum message size in bytes.
/// \param[in] attr message queue attributes; NULL: default values.
/// \return message queue ID for reference by other functions or NULL in case of error.
osMessageQueueId_t osMessageQueueNew (uint32_t msg_count, uint32_t msg_size, const osMessageQueueAttr_t *attr);
/// Get name of a Message Queue object.
/// \param[in] mq_id message queue ID obtained by \ref osMessageQueueNew.
/// \return name as NULL terminated string.
const char *osMessageQueueGetName (osMessageQueueId_t mq_id);
/// Put a Message into a Queue or timeout if Queue is full.
/// \param[in] mq_id message queue ID obtained by \ref osMessageQueueNew.
/// \param[in] msg_ptr pointer to buffer with message to put into a queue.
/// \param[in] msg_prio message priority.
/// \param[in] timeout \ref CMSIS_RTOS_TimeOutValue or 0 in case of no time-out.
/// \return status code that indicates the execution status of the function.
osStatus_t osMessageQueuePut (osMessageQueueId_t mq_id, const void *msg_ptr, uint8_t msg_prio, uint32_t timeout);
/// Get a Message from a Queue or timeout if Queue is empty.
/// \param[in] mq_id message queue ID obtained by \ref osMessageQueueNew.
/// \param[out] msg_ptr pointer to buffer for message to get from a queue.
/// \param[out] msg_prio pointer to buffer for message priority or NULL.
/// \param[in] timeout \ref CMSIS_RTOS_TimeOutValue or 0 in case of no time-out.
/// \return status code that indicates the execution status of the function.
osStatus_t osMessageQueueGet (osMessageQueueId_t mq_id, void *msg_ptr, uint8_t *msg_prio, uint32_t timeout);
/// Get maximum number of messages in a Message Queue.
/// \param[in] mq_id message queue ID obtained by \ref osMessageQueueNew.
/// \return maximum number of messages.
uint32_t osMessageQueueGetCapacity (osMessageQueueId_t mq_id);
/// Get maximum message size in a Memory Pool.
/// \param[in] mq_id message queue ID obtained by \ref osMessageQueueNew.
/// \return maximum message size in bytes.
uint32_t osMessageQueueGetMsgSize (osMessageQueueId_t mq_id);
/// Get number of queued messages in a Message Queue.
/// \param[in] mq_id message queue ID obtained by \ref osMessageQueueNew.
/// \return number of queued messages.
uint32_t osMessageQueueGetCount (osMessageQueueId_t mq_id);
/// Get number of available slots for messages in a Message Queue.
/// \param[in] mq_id message queue ID obtained by \ref osMessageQueueNew.
/// \return number of available slots for messages.
uint32_t osMessageQueueGetSpace (osMessageQueueId_t mq_id);
/// Reset a Message Queue to initial empty state.
/// \param[in] mq_id message queue ID obtained by \ref osMessageQueueNew.
/// \return status code that indicates the execution status of the function.
osStatus_t osMessageQueueReset (osMessageQueueId_t mq_id);
/// Delete a Message Queue object.
/// \param[in] mq_id message queue ID obtained by \ref osMessageQueueNew.
/// \return status code that indicates the execution status of the function.
osStatus_t osMessageQueueDelete (osMessageQueueId_t mq_id);
#ifdef __cplusplus
}
#endif
#endif // CMSIS_OS2_H_

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,88 @@
/*
* Copyright (c) 2013-2017 ARM Limited. All rights reserved.
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the License); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an AS IS BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* -----------------------------------------------------------------------------
*
* Project: CMSIS-RTOS RTX
* Title: Delay functions
*
* -----------------------------------------------------------------------------
*/
#include "rtx_lib.h"
// ==== Service Calls ====
// Service Calls definitions
SVC0_1(Delay, osStatus_t, uint32_t)
SVC0_2(DelayUntil, osStatus_t, uint32_t, uint32_t)
/// Wait for Timeout (Time Delay).
/// \note API identical to osDelay
osStatus_t svcRtxDelay (uint32_t ticks) {
if (ticks == 0U) {
return osOK;
}
osRtxThreadWaitEnter(osRtxThreadWaitingDelay, ticks);
return osOK;
}
/// Wait until specified time.
/// \note API identical to osDelayUntil
osStatus_t svcRtxDelayUntil (uint32_t ticks_l, uint32_t ticks_h) {
uint64_t ticks = ((uint64_t)ticks_l) | ((uint64_t)ticks_h << 32);
ticks -= osRtxInfo.kernel.tick;
if (ticks >= 0xFFFFFFFFU) {
EvrRtxThreadError(NULL, osErrorParameter);
return osErrorParameter;
}
if (ticks == 0U) {
return osOK;
}
osRtxThreadWaitEnter(osRtxThreadWaitingDelay, (uint32_t)ticks);
return osOK;
}
// ==== Public API ====
/// Wait for Timeout (Time Delay).
osStatus_t osDelay (uint32_t ticks) {
EvrRtxThreadDelay(ticks);
if (IS_IRQ_MODE() || IS_IRQ_MASKED()) {
EvrRtxThreadError(NULL, osErrorISR);
return osErrorISR;
}
return __svcDelay(ticks);
}
/// Wait until specified time.
osStatus_t osDelayUntil (uint64_t ticks) {
EvrRtxThreadDelayUntil(ticks);
if (IS_IRQ_MODE() || IS_IRQ_MASKED()) {
EvrRtxThreadError(NULL, osErrorISR);
return osErrorISR;
}
return __svcDelayUntil((uint32_t)ticks, (uint32_t)(ticks >> 32));
}

View File

@ -0,0 +1,576 @@
/*
* Copyright (c) 2013-2017 ARM Limited. All rights reserved.
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the License); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an AS IS BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* -----------------------------------------------------------------------------
*
* Project: CMSIS-RTOS RTX
* Title: Event Flags functions
*
* -----------------------------------------------------------------------------
*/
#include "rtx_lib.h"
// ==== Helper functions ====
/// Set Event Flags.
/// \param[in] ef event flags object.
/// \param[in] flags specifies the flags to set.
/// \return event flags after setting.
static uint32_t EventFlagsSet (os_event_flags_t *ef, uint32_t flags) {
#if (__EXCLUSIVE_ACCESS == 0U)
uint32_t primask = __get_PRIMASK();
#endif
uint32_t event_flags;
#if (__EXCLUSIVE_ACCESS == 0U)
__disable_irq();
ef->event_flags |= flags;
event_flags = ef->event_flags;
if (primask == 0U) {
__enable_irq();
}
#else
event_flags = atomic_set32(&ef->event_flags, flags);
#endif
return event_flags;
}
/// Clear Event Flags.
/// \param[in] ef event flags object.
/// \param[in] flags specifies the flags to clear.
/// \return event flags before clearing.
static uint32_t EventFlagsClear (os_event_flags_t *ef, uint32_t flags) {
#if (__EXCLUSIVE_ACCESS == 0U)
uint32_t primask = __get_PRIMASK();
#endif
uint32_t event_flags;
#if (__EXCLUSIVE_ACCESS == 0U)
__disable_irq();
event_flags = ef->event_flags;
ef->event_flags &= ~flags;
if (primask == 0U) {
__enable_irq();
}
#else
event_flags = atomic_clr32(&ef->event_flags, flags);
#endif
return event_flags;
}
/// Check Event Flags.
/// \param[in] ef event flags object.
/// \param[in] flags specifies the flags to check.
/// \param[in] options specifies flags options (osFlagsXxxx).
/// \return event flags before clearing or 0 if specified flags have not been set.
static uint32_t EventFlagsCheck (os_event_flags_t *ef, uint32_t flags, uint32_t options) {
#if (__EXCLUSIVE_ACCESS == 0U)
uint32_t primask;
#endif
uint32_t event_flags;
if ((options & osFlagsNoClear) == 0U) {
#if (__EXCLUSIVE_ACCESS == 0U)
primask = __get_PRIMASK();
__disable_irq();
event_flags = ef->event_flags;
if ((((options & osFlagsWaitAll) != 0U) && ((event_flags & flags) != flags)) ||
(((options & osFlagsWaitAll) == 0U) && ((event_flags & flags) == 0U))) {
event_flags = 0U;
} else {
ef->event_flags &= ~flags;
}
if (primask == 0U) {
__enable_irq();
}
#else
if ((options & osFlagsWaitAll) != 0U) {
event_flags = atomic_chk32_all(&ef->event_flags, flags);
} else {
event_flags = atomic_chk32_any(&ef->event_flags, flags);
}
#endif
} else {
event_flags = ef->event_flags;
if ((((options & osFlagsWaitAll) != 0U) && ((event_flags & flags) != flags)) ||
(((options & osFlagsWaitAll) == 0U) && ((event_flags & flags) == 0U))) {
event_flags = 0U;
}
}
return event_flags;
}
// ==== Library functions ====
/// Event Flags post ISR processing.
/// \param[in] ef event flags object.
void osRtxEventFlagsPostProcess (os_event_flags_t *ef) {
os_thread_t *thread;
os_thread_t *thread_next;
uint32_t event_flags;
if (ef->state == osRtxObjectInactive) {
return;
}
// Check if Threads are waiting for Event Flags
thread = ef->thread_list;
while (thread != NULL) {
thread_next = thread->thread_next;
event_flags = EventFlagsCheck(ef, thread->wait_flags, thread->flags_options);
if (event_flags != 0U) {
osRtxThreadListRemove(thread);
osRtxThreadWaitExit(thread, event_flags, false);
EvrRtxEventFlagsWaitCompleted(ef, thread->wait_flags, thread->flags_options, event_flags);
}
thread = thread_next;
}
}
// ==== Service Calls ====
// Service Calls definitions
SVC0_1M(EventFlagsNew, osEventFlagsId_t, const osEventFlagsAttr_t *)
SVC0_1 (EventFlagsGetName, const char *, osEventFlagsId_t)
SVC0_2 (EventFlagsSet, uint32_t, osEventFlagsId_t, uint32_t)
SVC0_2 (EventFlagsClear, uint32_t, osEventFlagsId_t, uint32_t)
SVC0_1 (EventFlagsGet, uint32_t, osEventFlagsId_t)
SVC0_4 (EventFlagsWait, uint32_t, osEventFlagsId_t, uint32_t, uint32_t, uint32_t)
SVC0_1 (EventFlagsDelete, osStatus_t, osEventFlagsId_t)
/// Create and Initialize an Event Flags object.
/// \note API identical to osEventFlagsNew
osEventFlagsId_t svcRtxEventFlagsNew (const osEventFlagsAttr_t *attr) {
os_event_flags_t *ef;
uint8_t flags;
const char *name;
// Process attributes
if (attr != NULL) {
name = attr->name;
ef = attr->cb_mem;
if (ef != NULL) {
if (((uint32_t)ef & 3U) || (attr->cb_size < sizeof(os_event_flags_t))) {
EvrRtxEventFlagsError(NULL, osRtxErrorInvalidControlBlock);
return NULL;
}
} else {
if (attr->cb_size != 0U) {
EvrRtxEventFlagsError(NULL, osRtxErrorInvalidControlBlock);
return NULL;
}
}
} else {
name = NULL;
ef = NULL;
}
// Allocate object memory if not provided
if (ef == NULL) {
if (osRtxInfo.mpi.event_flags != NULL) {
ef = osRtxMemoryPoolAlloc(osRtxInfo.mpi.event_flags);
} else {
ef = osRtxMemoryAlloc(osRtxInfo.mem.common, sizeof(os_event_flags_t), 1U);
}
if (ef == NULL) {
EvrRtxEventFlagsError(NULL, osErrorNoMemory);
return NULL;
}
flags = osRtxFlagSystemObject;
} else {
flags = 0U;
}
// Initialize control block
ef->id = osRtxIdEventFlags;
ef->state = osRtxObjectActive;
ef->flags = flags;
ef->name = name;
ef->thread_list = NULL;
ef->event_flags = 0U;
// Register post ISR processing function
osRtxInfo.post_process.event_flags = osRtxEventFlagsPostProcess;
EvrRtxEventFlagsCreated(ef);
return ef;
}
/// Get name of an Event Flags object.
/// \note API identical to osEventFlagsGetName
const char *svcRtxEventFlagsGetName (osEventFlagsId_t ef_id) {
os_event_flags_t *ef = (os_event_flags_t *)ef_id;
// Check parameters
if ((ef == NULL) || (ef->id != osRtxIdEventFlags)) {
EvrRtxEventFlagsGetName(ef, NULL);
return NULL;
}
// Check object state
if (ef->state == osRtxObjectInactive) {
EvrRtxEventFlagsGetName(ef, NULL);
return NULL;
}
EvrRtxEventFlagsGetName(ef, ef->name);
return ef->name;
}
/// Set the specified Event Flags.
/// \note API identical to osEventFlagsSet
uint32_t svcRtxEventFlagsSet (osEventFlagsId_t ef_id, uint32_t flags) {
os_event_flags_t *ef = (os_event_flags_t *)ef_id;
os_thread_t *thread;
os_thread_t *thread_next;
uint32_t event_flags;
uint32_t event_flags0;
// Check parameters
if ((ef == NULL) || (ef->id != osRtxIdEventFlags) ||
(flags & ~((1U << osRtxEventFlagsLimit) - 1U))) {
EvrRtxEventFlagsError(ef, osErrorParameter);
return ((uint32_t)osErrorParameter);
}
// Check object state
if (ef->state == osRtxObjectInactive) {
EvrRtxEventFlagsError(ef, osErrorResource);
return ((uint32_t)osErrorResource);
}
// Set Event Flags
event_flags = EventFlagsSet(ef, flags);
// Check if Threads are waiting for Event Flags
thread = ef->thread_list;
while (thread != NULL) {
thread_next = thread->thread_next;
event_flags0 = EventFlagsCheck(ef, thread->wait_flags, thread->flags_options);
if (event_flags0 != 0U) {
if ((thread->flags_options & osFlagsNoClear) == 0U) {
event_flags = event_flags0 & ~thread->wait_flags;
} else {
event_flags = event_flags0;
}
osRtxThreadListRemove(thread);
osRtxThreadWaitExit(thread, event_flags0, false);
EvrRtxEventFlagsWaitCompleted(ef, thread->wait_flags, thread->flags_options, event_flags0);
}
thread = thread_next;
}
osRtxThreadDispatch(NULL);
EvrRtxEventFlagsSetDone(ef, event_flags);
return event_flags;
}
/// Clear the specified Event Flags.
/// \note API identical to osEventFlagsClear
uint32_t svcRtxEventFlagsClear (osEventFlagsId_t ef_id, uint32_t flags) {
os_event_flags_t *ef = (os_event_flags_t *)ef_id;
uint32_t event_flags;
// Check parameters
if ((ef == NULL) || (ef->id != osRtxIdEventFlags) ||
(flags & ~((1U << osRtxEventFlagsLimit) - 1U))) {
EvrRtxEventFlagsError(ef, osErrorParameter);
return ((uint32_t)osErrorParameter);
}
// Check object state
if (ef->state == osRtxObjectInactive) {
EvrRtxEventFlagsError(ef, osErrorResource);
return ((uint32_t)osErrorResource);
}
// Clear Event Flags
event_flags = EventFlagsClear(ef, flags);
EvrRtxEventFlagsClearDone(ef, event_flags);
return event_flags;
}
/// Get the current Event Flags.
/// \note API identical to osEventFlagsGet
uint32_t svcRtxEventFlagsGet (osEventFlagsId_t ef_id) {
os_event_flags_t *ef = (os_event_flags_t *)ef_id;
// Check parameters
if ((ef == NULL) || (ef->id != osRtxIdEventFlags)) {
EvrRtxEventFlagsGet(ef, 0U);
return 0U;
}
// Check object state
if (ef->state == osRtxObjectInactive) {
EvrRtxEventFlagsGet(ef, 0U);
return 0U;
}
EvrRtxEventFlagsGet(ef, ef->event_flags);
return ef->event_flags;
}
/// Wait for one or more Event Flags to become signaled.
/// \note API identical to osEventFlagsWait
uint32_t svcRtxEventFlagsWait (osEventFlagsId_t ef_id, uint32_t flags, uint32_t options, uint32_t timeout) {
os_event_flags_t *ef = (os_event_flags_t *)ef_id;
os_thread_t *running_thread;
uint32_t event_flags;
running_thread = osRtxThreadGetRunning();
if (running_thread == NULL) {
EvrRtxEventFlagsError(ef, osRtxErrorKernelNotRunning);
return ((uint32_t)osError);
}
// Check parameters
if ((ef == NULL) || (ef->id != osRtxIdEventFlags) ||
(flags & ~((1U << osRtxEventFlagsLimit) - 1U))) {
EvrRtxEventFlagsError(ef, osErrorParameter);
return ((uint32_t)osErrorParameter);
}
// Check object state
if (ef->state == osRtxObjectInactive) {
EvrRtxEventFlagsError(ef, osErrorResource);
return ((uint32_t)osErrorResource);
}
// Check Event Flags
event_flags = EventFlagsCheck(ef, flags, options);
if (event_flags != 0U) {
EvrRtxEventFlagsWaitCompleted(ef, flags, options, event_flags);
return event_flags;
}
// Check if timeout is specified
if (timeout != 0U) {
EvrRtxEventFlagsWaitPending(ef, flags, options, timeout);
// Store waiting flags and options
running_thread->wait_flags = flags;
running_thread->flags_options = (uint8_t)options;
// Suspend current Thread
osRtxThreadListPut((os_object_t*)ef, running_thread);
osRtxThreadWaitEnter(osRtxThreadWaitingEventFlags, timeout);
return ((uint32_t)osErrorTimeout);
}
EvrRtxEventFlagsWaitNotCompleted(ef, flags, options);
return ((uint32_t)osErrorResource);
}
/// Delete an Event Flags object.
/// \note API identical to osEventFlagsDelete
osStatus_t svcRtxEventFlagsDelete (osEventFlagsId_t ef_id) {
os_event_flags_t *ef = (os_event_flags_t *)ef_id;
os_thread_t *thread;
// Check parameters
if ((ef == NULL) || (ef->id != osRtxIdEventFlags)) {
EvrRtxEventFlagsError(ef, osErrorParameter);
return osErrorParameter;
}
// Check object state
if (ef->state == osRtxObjectInactive) {
EvrRtxEventFlagsError(ef, osErrorResource);
return osErrorResource;
}
// Mark object as inactive
ef->state = osRtxObjectInactive;
// Unblock waiting threads
if (ef->thread_list != NULL) {
do {
thread = osRtxThreadListGet((os_object_t*)ef);
osRtxThreadWaitExit(thread, (uint32_t)osErrorResource, false);
} while (ef->thread_list != NULL);
osRtxThreadDispatch(NULL);
}
// Free object memory
if (ef->flags & osRtxFlagSystemObject) {
if (osRtxInfo.mpi.event_flags != NULL) {
osRtxMemoryPoolFree(osRtxInfo.mpi.event_flags, ef);
} else {
osRtxMemoryFree(osRtxInfo.mem.common, ef);
}
}
EvrRtxEventFlagsDestroyed(ef);
return osOK;
}
// ==== ISR Calls ====
/// Set the specified Event Flags.
/// \note API identical to osEventFlagsSet
__STATIC_INLINE
uint32_t isrRtxEventFlagsSet (osEventFlagsId_t ef_id, uint32_t flags) {
os_event_flags_t *ef = (os_event_flags_t *)ef_id;
uint32_t event_flags;
// Check parameters
if ((ef == NULL) || (ef->id != osRtxIdEventFlags) ||
(flags & ~((1U << osRtxEventFlagsLimit) - 1U))) {
EvrRtxEventFlagsError(ef, osErrorParameter);
return ((uint32_t)osErrorParameter);
}
// Check object state
if (ef->state == osRtxObjectInactive) {
EvrRtxEventFlagsError(ef, osErrorResource);
return ((uint32_t)osErrorResource);
}
// Set Event Flags
event_flags = EventFlagsSet(ef, flags);
// Register post ISR processing
osRtxPostProcess((os_object_t *)ef);
EvrRtxEventFlagsSetDone(ef, event_flags);
return event_flags;
}
/// Wait for one or more Event Flags to become signaled.
/// \note API identical to osEventFlagsWait
__STATIC_INLINE
uint32_t isrRtxEventFlagsWait (osEventFlagsId_t ef_id, uint32_t flags, uint32_t options, uint32_t timeout) {
os_event_flags_t *ef = (os_event_flags_t *)ef_id;
uint32_t event_flags;
// Check parameters
if ((ef == NULL) || (ef->id != osRtxIdEventFlags) || (timeout != 0U) ||
(flags & ~((1U << osRtxEventFlagsLimit) - 1U))) {
EvrRtxEventFlagsError(ef, osErrorParameter);
return ((uint32_t)osErrorParameter);
}
// Check object state
if (ef->state == osRtxObjectInactive) {
EvrRtxEventFlagsError(ef, osErrorResource);
return ((uint32_t)osErrorResource);
}
// Check Event Flags
event_flags = EventFlagsCheck(ef, flags, options);
if (event_flags != 0U) {
EvrRtxEventFlagsWaitCompleted(ef, flags, options, event_flags);
return ((uint32_t)event_flags);
}
EvrRtxEventFlagsWaitNotCompleted(ef, flags, options);
return ((uint32_t)osErrorResource);
}
// ==== Public API ====
/// Create and Initialize an Event Flags object.
osEventFlagsId_t osEventFlagsNew (const osEventFlagsAttr_t *attr) {
EvrRtxEventFlagsNew(attr);
if (IS_IRQ_MODE() || IS_IRQ_MASKED()) {
EvrRtxEventFlagsError(NULL, osErrorISR);
return NULL;
}
return __svcEventFlagsNew(attr);
}
/// Get name of an Event Flags object.
const char *osEventFlagsGetName (osEventFlagsId_t ef_id) {
if (IS_IRQ_MODE() || IS_IRQ_MASKED()) {
EvrRtxEventFlagsGetName(ef_id, NULL);
return NULL;
}
return __svcEventFlagsGetName(ef_id);
}
/// Set the specified Event Flags.
uint32_t osEventFlagsSet (osEventFlagsId_t ef_id, uint32_t flags) {
EvrRtxEventFlagsSet(ef_id, flags);
if (IS_IRQ_MODE() || IS_IRQ_MASKED()) {
return isrRtxEventFlagsSet(ef_id, flags);
} else {
return __svcEventFlagsSet(ef_id, flags);
}
}
/// Clear the specified Event Flags.
uint32_t osEventFlagsClear (osEventFlagsId_t ef_id, uint32_t flags) {
EvrRtxEventFlagsClear(ef_id, flags);
if (IS_IRQ_MODE() || IS_IRQ_MASKED()) {
return svcRtxEventFlagsClear(ef_id, flags);
} else {
return __svcEventFlagsClear(ef_id, flags);
}
}
/// Get the current Event Flags.
uint32_t osEventFlagsGet (osEventFlagsId_t ef_id) {
if (IS_IRQ_MODE() || IS_IRQ_MASKED()) {
return svcRtxEventFlagsGet(ef_id);
} else {
return __svcEventFlagsGet(ef_id);
}
}
/// Wait for one or more Event Flags to become signaled.
uint32_t osEventFlagsWait (osEventFlagsId_t ef_id, uint32_t flags, uint32_t options, uint32_t timeout) {
EvrRtxEventFlagsWait(ef_id, flags, options, timeout);
if (IS_IRQ_MODE() || IS_IRQ_MASKED()) {
return isrRtxEventFlagsWait(ef_id, flags, options, timeout);
} else {
return __svcEventFlagsWait(ef_id, flags, options, timeout);
}
}
/// Delete an Event Flags object.
osStatus_t osEventFlagsDelete (osEventFlagsId_t ef_id) {
EvrRtxEventFlagsDelete(ef_id);
if (IS_IRQ_MODE() || IS_IRQ_MASKED()) {
EvrRtxEventFlagsError(ef_id, osErrorISR);
return osErrorISR;
}
return __svcEventFlagsDelete(ef_id);
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,633 @@
/*
* Copyright (c) 2013-2017 ARM Limited. All rights reserved.
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the License); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an AS IS BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* -----------------------------------------------------------------------------
*
* Project: CMSIS-RTOS RTX
* Title: Kernel functions
*
* -----------------------------------------------------------------------------
*/
#include "rtx_lib.h"
// OS Runtime Information
osRtxInfo_t osRtxInfo __attribute__((section(".data.os"))) =
{ .os_id = osRtxKernelId, .version = osRtxVersionKernel, .kernel.state = osRtxKernelInactive };
// ==== Helper functions ====
/// Block Kernel (disable: thread switching, time tick, post ISR processing).
static void KernelBlock (void) {
if (osRtxInfo.tick_irqn >= 0) {
ExtTick_DisableIRQ(osRtxInfo.tick_irqn);
}
osRtxSysTimerDisable();
osRtxInfo.kernel.blocked = 1U;
__DSB();
if (osRtxInfo.tick_irqn < 0) {
osRtxInfo.kernel.pendISR = GetPendSV_ST();
ClrPendSV_ST();
} else {
osRtxInfo.kernel.pendISR = GetPendSV();
ClrPendSV();
}
}
/// Unblock Kernel
static void KernelUnblock (void) {
osRtxInfo.kernel.blocked = 0U;
__DSB();
if (osRtxInfo.kernel.pendSV != 0U) {
osRtxInfo.kernel.pendSV = 0U;
SetPendSV();
}
if (osRtxInfo.kernel.pendISR != 0U) {
SetPendFlags(osRtxInfo.kernel.pendISR);
}
if (osRtxInfo.tick_irqn >= 0) {
ExtTick_EnableIRQ(osRtxInfo.tick_irqn);
}
osRtxSysTimerEnable();
}
// ==== Service Calls ====
// Service Calls definitions
SVC0_0M(KernelInitialize, osStatus_t)
SVC0_3 (KernelGetInfo, osStatus_t, osVersion_t *, char *, uint32_t)
SVC0_0M(KernelStart, osStatus_t)
SVC0_0 (KernelLock, int32_t)
SVC0_0 (KernelUnlock, int32_t)
SVC0_1 (KernelRestoreLock, int32_t, int32_t)
SVC0_0 (KernelSuspend, uint32_t)
SVC0_1N(KernelResume, void, uint32_t)
SVC0_0 (KernelGetState, osKernelState_t)
SVC0_0D(KernelGetTickCount, uint64_t)
SVC0_0 (KernelGetTickFreq, uint32_t)
SVC0_0 (KernelGetSysTimerCount, uint32_t)
SVC0_0 (KernelGetSysTimerFreq, uint32_t)
/// Initialize the RTOS Kernel.
/// \note API identical to osKernelInitialize
osStatus_t svcRtxKernelInitialize (void) {
if (osRtxInfo.kernel.state == osRtxKernelReady) {
EvrRtxKernelInitializeCompleted();
return osOK;
}
if (osRtxInfo.kernel.state != osKernelInactive) {
EvrRtxKernelError(osError);
return osError;
}
// Initialize osRtxInfo
memset(&osRtxInfo.kernel, 0, sizeof(osRtxInfo) - offsetof(osRtxInfo_t, kernel));
if (osRtxConfig.thread_stack_size < (64U + 8U)) {
EvrRtxKernelError(osRtxErrorInvalidThreadStack);
return osError;
}
if ((osRtxConfig.isr_queue.data == NULL) || (osRtxConfig.isr_queue.max == 0U)) {
EvrRtxKernelError(osError);
return osError;
}
osRtxInfo.isr_queue.data = osRtxConfig.isr_queue.data;
osRtxInfo.isr_queue.max = osRtxConfig.isr_queue.max;
osRtxInfo.thread.robin.timeout = osRtxConfig.robin_timeout;
// Initialize Memory Pools (Variable Block Size)
if (osRtxMemoryInit(osRtxConfig.mem.common_addr, osRtxConfig.mem.common_size) != 0U) {
osRtxInfo.mem.common = osRtxConfig.mem.common_addr;
}
if (osRtxMemoryInit(osRtxConfig.mem.stack_addr, osRtxConfig.mem.stack_size) != 0U) {
osRtxInfo.mem.stack = osRtxConfig.mem.stack_addr;
} else {
osRtxInfo.mem.stack = osRtxInfo.mem.common;
}
if (osRtxMemoryInit(osRtxConfig.mem.mp_data_addr, osRtxConfig.mem.mp_data_size) != 0U) {
osRtxInfo.mem.mp_data = osRtxConfig.mem.mp_data_addr;
} else {
osRtxInfo.mem.mp_data = osRtxInfo.mem.common;
}
if (osRtxMemoryInit(osRtxConfig.mem.mq_data_addr, osRtxConfig.mem.mq_data_size) != 0U) {
osRtxInfo.mem.mq_data = osRtxConfig.mem.mq_data_addr;
} else {
osRtxInfo.mem.mq_data = osRtxInfo.mem.common;
}
// Initialize Memory Pools (Fixed Block Size)
if ((osRtxConfig.mpi.stack != NULL) &&
(osRtxMemoryPoolInit(osRtxConfig.mpi.stack,
osRtxConfig.mpi.stack->max_blocks,
osRtxConfig.mpi.stack->block_size,
osRtxConfig.mpi.stack->block_base) != 0U)) {
osRtxInfo.mpi.stack = osRtxConfig.mpi.stack;
}
if ((osRtxConfig.mpi.thread != NULL) &&
(osRtxMemoryPoolInit(osRtxConfig.mpi.thread,
osRtxConfig.mpi.thread->max_blocks,
osRtxConfig.mpi.thread->block_size,
osRtxConfig.mpi.thread->block_base) != 0U)) {
osRtxInfo.mpi.thread = osRtxConfig.mpi.thread;
}
if ((osRtxConfig.mpi.timer != NULL) &&
(osRtxMemoryPoolInit(osRtxConfig.mpi.timer,
osRtxConfig.mpi.timer->max_blocks,
osRtxConfig.mpi.timer->block_size,
osRtxConfig.mpi.timer->block_base) != 0U)) {
osRtxInfo.mpi.timer = osRtxConfig.mpi.timer;
}
if ((osRtxConfig.mpi.event_flags != NULL) &&
(osRtxMemoryPoolInit(osRtxConfig.mpi.event_flags,
osRtxConfig.mpi.event_flags->max_blocks,
osRtxConfig.mpi.event_flags->block_size,
osRtxConfig.mpi.event_flags->block_base) != 0U)) {
osRtxInfo.mpi.event_flags = osRtxConfig.mpi.event_flags;
}
if ((osRtxConfig.mpi.mutex != NULL) &&
(osRtxMemoryPoolInit(osRtxConfig.mpi.mutex,
osRtxConfig.mpi.mutex->max_blocks,
osRtxConfig.mpi.mutex->block_size,
osRtxConfig.mpi.mutex->block_base) != 0U)) {
osRtxInfo.mpi.mutex = osRtxConfig.mpi.mutex;
}
if ((osRtxConfig.mpi.semaphore != NULL) &&
(osRtxMemoryPoolInit(osRtxConfig.mpi.semaphore,
osRtxConfig.mpi.semaphore->max_blocks,
osRtxConfig.mpi.semaphore->block_size,
osRtxConfig.mpi.semaphore->block_base) != 0U)) {
osRtxInfo.mpi.semaphore = osRtxConfig.mpi.semaphore;
}
if ((osRtxConfig.mpi.memory_pool != NULL) &&
(osRtxMemoryPoolInit(osRtxConfig.mpi.memory_pool,
osRtxConfig.mpi.memory_pool->max_blocks,
osRtxConfig.mpi.memory_pool->block_size,
osRtxConfig.mpi.memory_pool->block_base) != 0U)) {
osRtxInfo.mpi.memory_pool = osRtxConfig.mpi.memory_pool;
}
if ((osRtxConfig.mpi.message_queue != NULL) &&
(osRtxMemoryPoolInit(osRtxConfig.mpi.message_queue,
osRtxConfig.mpi.message_queue->max_blocks,
osRtxConfig.mpi.message_queue->block_size,
osRtxConfig.mpi.message_queue->block_base) != 0U)) {
osRtxInfo.mpi.message_queue = osRtxConfig.mpi.message_queue;
}
#if (__DOMAIN_NS == 1U)
// Initialize Secure Process Stack
if (TZ_InitContextSystem_S() == 0U) {
EvrRtxKernelError(osRtxErrorTZ_InitContext_S);
return osError;
}
#endif
// Initialize SVC and PendSV System Service Calls
SVC_Initialize();
osRtxInfo.kernel.state = osRtxKernelReady;
EvrRtxKernelInitializeCompleted();
return osOK;
}
/// Get RTOS Kernel Information.
/// \note API identical to osKernelGetInfo
osStatus_t svcRtxKernelGetInfo (osVersion_t *version, char *id_buf, uint32_t id_size) {
if (version != NULL) {
version->api = osRtxVersionAPI;
version->kernel = osRtxVersionKernel;
}
if ((id_buf != NULL) && (id_size != 0U)) {
if (id_size > sizeof(osRtxKernelId)) {
id_size = sizeof(osRtxKernelId);
}
memcpy(id_buf, osRtxKernelId, id_size);
}
EvrRtxKernelInfoRetrieved(version, id_buf);
return osOK;
}
/// Get the current RTOS Kernel state.
/// \note API identical to osKernelGetState
osKernelState_t svcRtxKernelGetState (void) {
EvrRtxKernelGetState((osKernelState_t)(osRtxInfo.kernel.state));
return ((osKernelState_t)(osRtxInfo.kernel.state));
}
/// Start the RTOS Kernel scheduler.
/// \note API identical to osKernelStart
osStatus_t svcRtxKernelStart (void) {
os_thread_t *thread;
if (osRtxInfo.kernel.state != osRtxKernelReady) {
EvrRtxKernelError(osRtxErrorKernelNotReady);
return osError;
}
// Create Idle Thread
if (osRtxInfo.thread.idle == NULL) {
osRtxInfo.thread.idle = svcRtxThreadNew(osRtxIdleThread, NULL, osRtxConfig.idle_thread_attr);
if (osRtxInfo.thread.idle == NULL) {
EvrRtxKernelError(osError);
return osError;
}
}
// Create Timer Thread
if (osRtxConfig.timer_mq_mcnt != 0U) {
if (osRtxInfo.timer.thread == NULL) {
osRtxInfo.timer.thread = svcRtxThreadNew(osRtxTimerThread, NULL, osRtxConfig.timer_thread_attr);
if (osRtxInfo.timer.thread == NULL) {
EvrRtxKernelError(osError);
return osError;
}
}
}
// Switch to Ready Thread with highest Priority
thread = osRtxThreadListGet(&osRtxInfo.thread.ready);
if (thread == NULL) {
EvrRtxKernelError(osError);
return osError;
}
osRtxThreadSwitch(thread);
if ((osRtxConfig.flags & osRtxConfigPrivilegedMode) != 0U) {
// Privileged Thread mode & PSP
__set_CONTROL(0x02U);
} else {
// Unprivileged Thread mode & PSP
__set_CONTROL(0x03U);
}
osRtxInfo.kernel.sys_freq = SystemCoreClock;
// Setup and Enable System Timer
osRtxInfo.tick_irqn = osRtxSysTimerSetup();
if (osRtxInfo.tick_irqn >= 0) {
ExtTick_SetupIRQ (osRtxInfo.tick_irqn);
ExtTick_EnableIRQ(osRtxInfo.tick_irqn);
}
osRtxSysTimerEnable();
osRtxInfo.kernel.state = osRtxKernelRunning;
EvrRtxKernelStarted();
return osOK;
}
/// Lock the RTOS Kernel scheduler.
/// \note API identical to osKernelLock
int32_t svcRtxKernelLock (void) {
if (osRtxInfo.kernel.state == osRtxKernelLocked) {
EvrRtxKernelLocked(1);
return 1;
}
if (osRtxInfo.kernel.state == osRtxKernelRunning) {
osRtxInfo.kernel.state = osRtxKernelLocked;
EvrRtxKernelLocked(0);
return 0;
}
EvrRtxKernelError(osError);
return osError;
}
/// Unlock the RTOS Kernel scheduler.
/// \note API identical to osKernelUnlock
int32_t svcRtxKernelUnlock (void) {
if (osRtxInfo.kernel.state == osRtxKernelLocked) {
osRtxInfo.kernel.state = osRtxKernelRunning;
EvrRtxKernelUnlocked(1);
return 1;
}
if (osRtxInfo.kernel.state == osRtxKernelRunning) {
EvrRtxKernelUnlocked(0);
return 0;
}
EvrRtxKernelError(osError);
return osError;
}
/// Restore the RTOS Kernel scheduler lock state.
/// \note API identical to osKernelRestoreLock
int32_t svcRtxKernelRestoreLock (int32_t lock) {
if ((osRtxInfo.kernel.state == osRtxKernelRunning) ||
(osRtxInfo.kernel.state == osRtxKernelLocked)) {
switch (lock) {
case 1:
osRtxInfo.kernel.state = osRtxKernelLocked;
EvrRtxKernelLockRestored(1);
return 1;
case 0:
osRtxInfo.kernel.state = osRtxKernelRunning;
EvrRtxKernelLockRestored(0);
return 0;
default:
break;
}
}
EvrRtxKernelError(osError);
return osError;
}
/// Suspend the RTOS Kernel scheduler.
/// \note API identical to osKernelSuspend
uint32_t svcRtxKernelSuspend (void) {
os_thread_t *thread;
os_timer_t *timer;
uint32_t delay;
if (osRtxInfo.kernel.state != osRtxKernelRunning) {
EvrRtxKernelError(osRtxErrorKernelNotRunning);
return 0U;
}
KernelBlock();
delay = osWaitForever;
// Check Thread Delay list
thread = osRtxInfo.thread.delay_list;
if (thread != NULL) {
delay = thread->delay;
}
// Check Active Timer list
timer = osRtxInfo.timer.list;
if (timer != NULL) {
if (timer->tick < delay) {
delay = timer->tick;
}
}
osRtxInfo.kernel.state = osRtxKernelSuspended;
EvrRtxKernelSuspended(delay);
return delay;
}
/// Resume the RTOS Kernel scheduler.
/// \note API identical to osKernelResume
void svcRtxKernelResume (uint32_t sleep_ticks) {
os_thread_t *thread;
os_timer_t *timer;
uint32_t delay;
if (osRtxInfo.kernel.state != osRtxKernelSuspended) {
EvrRtxKernelResumed();
return;
}
// Process Thread Delay list
thread = osRtxInfo.thread.delay_list;
if (thread != NULL) {
delay = sleep_ticks;
if (delay >= thread->delay) {
delay -= thread->delay;
osRtxInfo.kernel.tick += thread->delay;
thread->delay = 1U;
do {
osRtxThreadDelayTick();
if (delay == 0U) {
break;
}
delay--;
osRtxInfo.kernel.tick++;
} while (osRtxInfo.thread.delay_list != NULL);
} else {
thread->delay -= delay;
osRtxInfo.kernel.tick += delay;
}
} else {
osRtxInfo.kernel.tick += sleep_ticks;
}
// Process Active Timer list
timer = osRtxInfo.timer.list;
if (timer != NULL) {
if (sleep_ticks >= timer->tick) {
sleep_ticks -= timer->tick;
timer->tick = 1U;
do {
osRtxInfo.timer.tick();
if (sleep_ticks == 0U) {
break;
}
sleep_ticks--;
} while (osRtxInfo.timer.list != NULL);
} else {
timer->tick -= sleep_ticks;
}
}
osRtxInfo.kernel.state = osRtxKernelRunning;
osRtxThreadDispatch(NULL);
KernelUnblock();
EvrRtxKernelResumed();
}
/// Get the RTOS kernel tick count.
/// \note API identical to osKernelGetTickCount
uint64_t svcRtxKernelGetTickCount (void) {
EvrRtxKernelGetTickCount(osRtxInfo.kernel.tick);
return osRtxInfo.kernel.tick;
}
/// Get the RTOS kernel tick frequency.
/// \note API identical to osKernelGetTickFreq
uint32_t svcRtxKernelGetTickFreq (void) {
EvrRtxKernelGetTickFreq(osRtxConfig.tick_freq);
return osRtxConfig.tick_freq;
}
/// Get the RTOS kernel system timer count.
/// \note API identical to osKernelGetSysTimerCount
uint32_t svcRtxKernelGetSysTimerCount (void) {
uint32_t count = osRtxSysTimerGetCount();
EvrRtxKernelGetSysTimerCount(count);
return count;
}
/// Get the RTOS kernel system timer frequency.
/// \note API identical to osKernelGetSysTimerFreq
uint32_t svcRtxKernelGetSysTimerFreq (void) {
uint32_t freq = osRtxSysTimerGetFreq();
EvrRtxKernelGetSysTimerFreq(freq);
return freq;
}
// ==== Public API ====
/// Initialize the RTOS Kernel.
osStatus_t osKernelInitialize (void) {
EvrRtxKernelInitialize();
if (IS_IRQ_MODE() || IS_IRQ_MASKED()) {
EvrRtxKernelError(osErrorISR);
return osErrorISR;
}
return __svcKernelInitialize();
}
/// Get RTOS Kernel Information.
osStatus_t osKernelGetInfo (osVersion_t *version, char *id_buf, uint32_t id_size) {
EvrRtxKernelGetInfo(version, id_buf, id_size);
if (IS_IRQ_MODE() || IS_IRQ_MASKED()) {
EvrRtxKernelError(osErrorISR);
return osErrorISR;
}
if (IS_PRIVILEGED()) {
return svcRtxKernelGetInfo(version, id_buf, id_size);
} else {
return __svcKernelGetInfo(version, id_buf, id_size);
}
}
/// Get the current RTOS Kernel state.
osKernelState_t osKernelGetState (void) {
if (IS_IRQ_MODE() || IS_IRQ_MASKED()) {
EvrRtxKernelGetState(osKernelError);
return osKernelError;
}
if (IS_PRIVILEGED()) {
return svcRtxKernelGetState();
} else {
return __svcKernelGetState();
}
}
/// Start the RTOS Kernel scheduler.
osStatus_t osKernelStart (void) {
EvrRtxKernelStart();
if (IS_IRQ_MODE() || IS_IRQ_MASKED()) {
EvrRtxKernelError(osErrorISR);
return osErrorISR;
}
return __svcKernelStart();
}
/// Lock the RTOS Kernel scheduler.
int32_t osKernelLock (void) {
EvrRtxKernelLock();
if (IS_IRQ_MODE() || IS_IRQ_MASKED()) {
EvrRtxKernelError(osErrorISR);
return osErrorISR;
}
return __svcKernelLock();
}
/// Unlock the RTOS Kernel scheduler.
int32_t osKernelUnlock (void) {
EvrRtxKernelUnlock();
if (IS_IRQ_MODE() || IS_IRQ_MASKED()) {
EvrRtxKernelError(osErrorISR);
return osErrorISR;
}
return __svcKernelUnlock();
}
/// Restore the RTOS Kernel scheduler lock state.
int32_t osKernelRestoreLock (int32_t lock) {
EvrRtxKernelRestoreLock(lock);
if (IS_IRQ_MODE() || IS_IRQ_MASKED()) {
EvrRtxKernelError(osErrorISR);
return osErrorISR;
}
return __svcKernelRestoreLock(lock);
}
/// Suspend the RTOS Kernel scheduler.
uint32_t osKernelSuspend (void) {
EvrRtxKernelSuspend();
if (IS_IRQ_MODE() || IS_IRQ_MASKED()) {
EvrRtxKernelError(osErrorISR);
return 0U;
}
return __svcKernelSuspend();
}
/// Resume the RTOS Kernel scheduler.
void osKernelResume (uint32_t sleep_ticks) {
EvrRtxKernelResume(sleep_ticks);
if (IS_IRQ_MODE() || IS_IRQ_MASKED()) {
EvrRtxKernelError(osErrorISR);
return;
}
__svcKernelResume(sleep_ticks);
}
/// Get the RTOS kernel tick count.
uint64_t osKernelGetTickCount (void) {
if (IS_IRQ_MODE() || IS_IRQ_MASKED()) {
EvrRtxKernelGetTickCount(0U);
return 0U;
} else {
return __svcKernelGetTickCount();
}
}
/// Get the RTOS kernel tick frequency.
uint32_t osKernelGetTickFreq (void) {
if (IS_IRQ_MODE() || IS_IRQ_MASKED()) {
EvrRtxKernelGetTickFreq(0U);
return 0U;
} else {
return __svcKernelGetTickFreq();
}
}
/// Get the RTOS kernel system timer count.
uint32_t osKernelGetSysTimerCount (void) {
if (IS_IRQ_MODE() || IS_IRQ_MASKED()) {
return svcRtxKernelGetSysTimerCount();
} else {
return __svcKernelGetSysTimerCount();
}
}
/// Get the RTOS kernel system timer frequency.
uint32_t osKernelGetSysTimerFreq (void) {
if (IS_IRQ_MODE() || IS_IRQ_MASKED()) {
return svcRtxKernelGetSysTimerFreq();
} else {
return __svcKernelGetSysTimerFreq();
}
}

View File

@ -0,0 +1,634 @@
/*
* Copyright (c) 2013-2017 ARM Limited. All rights reserved.
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the License); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an AS IS BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* -----------------------------------------------------------------------------
*
* Project: CMSIS-RTOS RTX
* Title: RTX Library Configuration
*
* -----------------------------------------------------------------------------
*/
#include "cmsis_compiler.h"
#include "rtx_os.h"
#include "RTX_Config.h"
// System Configuration
// ====================
// Dynamic Memory
#if (OS_DYNAMIC_MEM_SIZE != 0)
#if ((OS_DYNAMIC_MEM_SIZE & 7) != 0)
#error "Invalid Dynamic Memory size!"
#endif
static uint64_t os_mem[OS_DYNAMIC_MEM_SIZE/8] \
__attribute__((section(".bss.os")));
#endif
// Kernel Tick Frequency
#if (OS_TICK_FREQ < 1)
#error "Invalid Kernel Tick Frequency!"
#endif
// ISR FIFO Queue
static void *os_isr_queue[OS_ISR_FIFO_QUEUE] \
__attribute__((section(".bss.os")));
// Thread Configuration
// ====================
#if (((OS_STACK_SIZE & 7) != 0) || (OS_STACK_SIZE < 72))
#error "Invalid default Thread Stack size!"
#endif
#if (((OS_IDLE_THREAD_STACK_SIZE & 7) != 0) || (OS_IDLE_THREAD_STACK_SIZE < 72))
#error "Invalid Idle Thread Stack size!"
#endif
#if (OS_THREAD_OBJ_MEM != 0)
#if (OS_THREAD_NUM == 0)
#error "Invalid number of user Threads!"
#endif
#if ((OS_THREAD_USER_STACK_SIZE != 0) && ((OS_THREAD_USER_STACK_SIZE & 7) != 0))
#error "Invalid total Stack size!"
#endif
// Thread Control Blocks
static osRtxThread_t os_thread_cb[OS_THREAD_NUM] \
__attribute__((section(".bss.os.thread.cb")));
// Thread Default Stack
#if (OS_THREAD_DEF_STACK_NUM != 0)
static uint64_t os_thread_def_stack[OS_THREAD_DEF_STACK_NUM*(OS_STACK_SIZE/8)] \
__attribute__((section(".bss.os.thread.stack")));
#endif
// Memory Pool for Thread Control Blocks
static osRtxMpInfo_t os_mpi_thread \
__attribute__((section(".data.os.thread.mpi"))) =
{ (uint32_t)OS_THREAD_NUM, 0U, (uint32_t)osRtxThreadCbSize, &os_thread_cb, NULL, NULL };
// Memory Pool for Thread Default Stack
#if (OS_THREAD_DEF_STACK_NUM != 0)
static osRtxMpInfo_t os_mpi_def_stack \
__attribute__((section(".data.os.thread.mpi"))) =
{ (uint32_t)OS_THREAD_DEF_STACK_NUM, 0U, (uint32_t)OS_STACK_SIZE, &os_thread_def_stack, NULL, NULL };
#endif
// Memory Pool for Thread Stack
#if (OS_THREAD_USER_STACK_SIZE != 0)
static uint64_t os_thread_stack[OS_THREAD_USER_STACK_SIZE/8] \
__attribute__((section(".bss.os.thread.stack")));
#endif
#endif // (OS_THREAD_OBJ_MEM != 0)
// Stack overrun checking
#if (OS_STACK_CHECK == 0)
// Override library function
void osRtxThreadStackCheck (void);
void osRtxThreadStackCheck (void) {}
#endif
// Idle Thread Control Block
static osRtxThread_t os_idle_thread_cb \
__attribute__((section(".bss.os.thread.cb")));
// Idle Thread Stack
static uint64_t os_idle_thread_stack[OS_IDLE_THREAD_STACK_SIZE/8] \
__attribute__((section(".bss.os.thread.stack")));
// Idle Thread Attributes
static const osThreadAttr_t os_idle_thread_attr = {
NULL,
osThreadDetached,
&os_idle_thread_cb,
(uint32_t)sizeof(os_idle_thread_cb),
&os_idle_thread_stack,
(uint32_t)sizeof(os_idle_thread_stack),
osPriorityIdle,
0U, 0U
};
// Timer Configuration
// ===================
#if (OS_TIMER_OBJ_MEM != 0)
#if (OS_TIMER_NUM == 0)
#error "Invalid number of Timer objects!"
#endif
// Timer Control Blocks
static osRtxTimer_t os_timer_cb[OS_TIMER_NUM] \
__attribute__((section(".bss.os.timer.cb")));
// Memory Pool for Timer Control Blocks
static osRtxMpInfo_t os_mpi_timer \
__attribute__((section(".data.os.timer.mpi"))) =
{ (uint32_t)OS_TIMER_NUM, 0U, (uint32_t)osRtxTimerCbSize, &os_timer_cb, NULL, NULL };
#endif // (OS_TIMER_OBJ_MEM != 0)
#if ((OS_TIMER_THREAD_STACK_SIZE != 0) && (OS_TIMER_CB_QUEUE != 0))
#if (((OS_TIMER_THREAD_STACK_SIZE & 7) != 0) || (OS_TIMER_THREAD_STACK_SIZE < 96))
#error "Invalid Timer Thread Stack size!"
#endif
// Timer Thread Control Block
static osRtxThread_t os_timer_thread_cb \
__attribute__((section(".bss.os.thread.cb")));
// Timer Thread Stack
static uint64_t os_timer_thread_stack[OS_TIMER_THREAD_STACK_SIZE/8] \
__attribute__((section(".bss.os.thread.stack")));
// Timer Thread Attributes
static const osThreadAttr_t os_timer_thread_attr = {
NULL,
osThreadDetached,
&os_timer_thread_cb,
(uint32_t)sizeof(os_timer_thread_cb),
&os_timer_thread_stack,
(uint32_t)sizeof(os_timer_thread_stack),
(osPriority_t)OS_TIMER_THREAD_PRIO,
0U, 0U
};
// Timer Message Queue Control Block
static osRtxMessageQueue_t os_timer_mq_cb \
__attribute__((section(".bss.os.msgqueue.cb")));
// Timer Message Queue Data
static uint32_t os_timer_mq_data[osRtxMessageQueueMemSize(OS_TIMER_CB_QUEUE,8)/4] \
__attribute__((section(".bss.os.msgqueue.mem")));
// Timer Message Queue Attributes
static const osMessageQueueAttr_t os_timer_mq_attr = {
NULL,
0U,
&os_timer_mq_cb,
(uint32_t)sizeof(os_timer_mq_cb),
&os_timer_mq_data,
(uint32_t)sizeof(os_timer_mq_data)
};
#else
extern void osRtxTimerThread (void *argument);
void osRtxTimerThread (void *argument) {}
#endif // ((OS_TIMER_THREAD_STACK_SIZE != 0) && (OS_TIMER_CB_QUEUE != 0))
// Event Flags Configuration
// =========================
#if (OS_EVFLAGS_OBJ_MEM != 0)
#if (OS_EVFLAGS_NUM == 0)
#error "Invalid number of Event Flags objects!"
#endif
// Event Flags Control Blocks
static osRtxEventFlags_t os_ef_cb[OS_EVFLAGS_NUM] \
__attribute__((section(".bss.os.evflags.cb")));
// Memory Pool for Event Flags Control Blocks
static osRtxMpInfo_t os_mpi_ef \
__attribute__((section(".data.os.evflags.mpi"))) =
{ (uint32_t)OS_EVFLAGS_NUM, 0U, (uint32_t)osRtxEventFlagsCbSize, &os_ef_cb, NULL, NULL };
#endif // (OS_EVFLAGS_OBJ_MEM != 0)
// Mutex Configuration
// ===================
#if (OS_MUTEX_OBJ_MEM != 0)
#if (OS_MUTEX_NUM == 0)
#error "Invalid number of Mutex objects!"
#endif
// Mutex Control Blocks
static osRtxMutex_t os_mutex_cb[OS_MUTEX_NUM] \
__attribute__((section(".bss.os.mutex.cb")));
// Memory Pool for Mutex Control Blocks
static osRtxMpInfo_t os_mpi_mutex \
__attribute__((section(".data.os.mutex.mpi"))) =
{ (uint32_t)OS_MUTEX_NUM, 0U, (uint32_t)osRtxMutexCbSize, &os_mutex_cb, NULL, NULL };
#endif // (OS_MUTEX_OBJ_MEM != 0)
// Semaphore Configuration
// =======================
#if (OS_SEMAPHORE_OBJ_MEM != 0)
#if (OS_SEMAPHORE_NUM == 0)
#error "Invalid number of Semaphore objects!"
#endif
// Semaphore Control Blocks
static osRtxSemaphore_t os_semaphore_cb[OS_SEMAPHORE_NUM] \
__attribute__((section(".bss.os.semaphore.cb")));
// Memory Pool for Semaphore Control Blocks
static osRtxMpInfo_t os_mpi_semaphore \
__attribute__((section(".data.os.semaphore.mpi"))) =
{ (uint32_t)OS_SEMAPHORE_NUM, 0U, (uint32_t)osRtxSemaphoreCbSize, &os_semaphore_cb, NULL, NULL };
#endif // (OS_SEMAPHORE_OBJ_MEM != 0)
// Memory Pool Configuration
// =========================
#if (OS_MEMPOOL_OBJ_MEM != 0)
#if (OS_MEMPOOL_NUM == 0)
#error "Invalid number of Memory Pool objects!"
#endif
// Memory Pool Control Blocks
static osRtxMemoryPool_t os_mp_cb[OS_MEMPOOL_NUM] \
__attribute__((section(".bss.os.mempool.cb")));
// Memory Pool for Memory Pool Control Blocks
static osRtxMpInfo_t os_mpi_mp \
__attribute__((section(".data.os.mempool.mpi"))) =
{ (uint32_t)OS_MEMPOOL_NUM, 0U, (uint32_t)osRtxMemoryPoolCbSize, &os_mp_cb, NULL, NULL };
// Memory Pool for Memory Pool Data Storage
#if (OS_MEMPOOL_DATA_SIZE != 0)
#if ((OS_MEMPOOL_DATA_SIZE & 7) != 0)
#error "Invalid Data Memory size for Memory Pools!"
#endif
static uint64_t os_mp_data[OS_MEMPOOL_DATA_SIZE/8] \
__attribute__((section(".bss.os.mempool.mem")));
#endif
#endif // (OS_MEMPOOL_OBJ_MEM != 0)
// Message Queue Configuration
// ===========================
#if (OS_MSGQUEUE_OBJ_MEM != 0)
#if (OS_MSGQUEUE_NUM == 0)
#error "Invalid number of Message Queue objects!"
#endif
// Message Queue Control Blocks
static osRtxMessageQueue_t os_mq_cb[OS_MSGQUEUE_NUM] \
__attribute__((section(".bss.os.msgqueue.cb")));
// Memory Pool for Message Queue Control Blocks
static osRtxMpInfo_t os_mpi_mq \
__attribute__((section(".data.os.msgqueue.mpi"))) =
{ (uint32_t)OS_MSGQUEUE_NUM, 0U, (uint32_t)osRtxMessageQueueCbSize, &os_mq_cb, NULL, NULL };
// Memory Pool for Message Queue Data Storage
#if (OS_MSGQUEUE_DATA_SIZE != 0)
#if ((OS_MSGQUEUE_DATA_SIZE & 7) != 0)
#error "Invalid Data Memory size for Message Queues!"
#endif
static uint64_t os_mq_data[OS_MSGQUEUE_DATA_SIZE/8] \
__attribute__((section(".bss.os.msgqueue.mem")));
#endif
#endif // (OS_MSGQUEUE_OBJ_MEM != 0)
// OS Configuration
// ================
__USED
__attribute__((section(".rodata")))
const osRtxConfig_t osRtxConfig = {
0U // Flags
#if (OS_PRIVILEGE_MODE != 0)
| osRtxConfigPrivilegedMode
#endif
#if (OS_STACK_CHECK != 0)
| osRtxConfigStackCheck
#endif
#if (OS_STACK_WATERMARK != 0)
| osRtxConfigStackWatermark
#endif
,
(uint32_t)OS_TICK_FREQ,
#if (OS_ROBIN_ENABLE != 0)
(uint32_t)OS_ROBIN_TIMEOUT,
#else
0U,
#endif
{ &os_isr_queue[0], sizeof(os_isr_queue)/sizeof(void *), 0U },
{
// Memory Pools (Variable Block Size)
#if ((OS_THREAD_OBJ_MEM != 0) && (OS_THREAD_USER_STACK_SIZE != 0))
&os_thread_stack, (uint32_t)OS_THREAD_USER_STACK_SIZE,
#else
NULL, 0U,
#endif
#if ((OS_MEMPOOL_OBJ_MEM != 0) && (OS_MEMPOOL_DATA_SIZE != 0))
&os_mp_data, (uint32_t)OS_MEMPOOL_DATA_SIZE,
#else
NULL, 0U,
#endif
#if ((OS_MSGQUEUE_OBJ_MEM != 0) && (OS_MSGQUEUE_DATA_SIZE != 0))
&os_mq_data, (uint32_t)OS_MSGQUEUE_DATA_SIZE,
#else
NULL, 0U,
#endif
#if (OS_DYNAMIC_MEM_SIZE != 0)
&os_mem, (uint32_t)OS_DYNAMIC_MEM_SIZE,
#else
NULL, 0U
#endif
},
{
// Memory Pools (Fixed Block Size)
#if (OS_THREAD_OBJ_MEM != 0)
#if (OS_THREAD_DEF_STACK_NUM != 0)
&os_mpi_def_stack,
#else
NULL,
#endif
&os_mpi_thread,
#else
NULL,
NULL,
#endif
#if (OS_TIMER_OBJ_MEM != 0)
&os_mpi_timer,
#else
NULL,
#endif
#if (OS_EVFLAGS_OBJ_MEM != 0)
&os_mpi_ef,
#else
NULL,
#endif
#if (OS_MUTEX_OBJ_MEM != 0)
&os_mpi_mutex,
#else
NULL,
#endif
#if (OS_SEMAPHORE_OBJ_MEM != 0)
&os_mpi_semaphore,
#else
NULL,
#endif
#if (OS_MEMPOOL_OBJ_MEM != 0)
&os_mpi_mp,
#else
NULL,
#endif
#if (OS_MSGQUEUE_OBJ_MEM != 0)
&os_mpi_mq,
#else
NULL,
#endif
},
(uint32_t)OS_STACK_SIZE,
&os_idle_thread_attr,
#if ((OS_TIMER_THREAD_STACK_SIZE != 0) && (OS_TIMER_CB_QUEUE != 0))
&os_timer_thread_attr,
&os_timer_mq_attr,
(uint32_t)OS_TIMER_CB_QUEUE
#else
NULL,
NULL,
0U
#endif
};
// Non weak reference to library irq module
extern uint8_t irqRtxLib;
extern const uint8_t *irqRtxLibRef;
const uint8_t *irqRtxLibRef = &irqRtxLib;
// Default User SVC Table
extern void * const osRtxUserSVC[];
__WEAK void * const osRtxUserSVC[1] = { (void *)0 };
// OS Sections
// ===========
#if (defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050))
__asm (
".weakref __os_thread_cb_start__, .bss.os.thread.cb$$Base\n\t"
".weakref __os_thread_cb_end__, .bss.os.thread.cb$$Limit\n\t"
".weakref __os_timer_cb_start__, .bss.os.timer.cb$$Base\n\t"
".weakref __os_timer_cb_end__, .bss.os.timer.cb$$Limit\n\t"
".weakref __os_evflags_cb_start__, .bss.os.evflags.cb$$Base\n\t"
".weakref __os_evflags_cb_end__, .bss.os.evflags.cb$$Limit\n\t"
".weakref __os_mutex_cb_start__, .bss.os.mutex.cb$$Base\n\t"
".weakref __os_mutex_cb_end__, .bss.os.mutex.cb$$Limit\n\t"
".weakref __os_semaphore_cb_start__, .bss.os.semaphore.cb$$Base\n\t"
".weakref __os_semaphore_cb_end__, .bss.os.semaphore.cb$$Limit\n\t"
".weakref __os_mempool_cb_start__, .bss.os.mempool.cb$$Base\n\t"
".weakref __os_mempool_cb_end__, .bss.os.mempool.cb$$Limit\n\t"
".weakref __os_msgqueue_cb_start__, .bss.os.msgqueue.cb$$Base\n\t"
".weakref __os_msgqueue_cb_end__, .bss.os.msgqueue.cb$$Limit\n\t"
);
#endif
#if (defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050)) || \
(defined(__GNUC__) && !defined(__CC_ARM))
extern __attribute__((weak)) uint32_t __os_thread_cb_start__;
extern __attribute__((weak)) uint32_t __os_thread_cb_end__;
extern __attribute__((weak)) uint32_t __os_timer_cb_start__;
extern __attribute__((weak)) uint32_t __os_timer_cb_end__;
extern __attribute__((weak)) uint32_t __os_evflags_cb_start__;
extern __attribute__((weak)) uint32_t __os_evflags_cb_end__;
extern __attribute__((weak)) uint32_t __os_mutex_cb_start__;
extern __attribute__((weak)) uint32_t __os_mutex_cb_end__;
extern __attribute__((weak)) uint32_t __os_semaphore_cb_start__;
extern __attribute__((weak)) uint32_t __os_semaphore_cb_end__;
extern __attribute__((weak)) uint32_t __os_mempool_cb_start__;
extern __attribute__((weak)) uint32_t __os_mempool_cb_end__;
extern __attribute__((weak)) uint32_t __os_msgqueue_cb_start__;
extern __attribute__((weak)) uint32_t __os_msgqueue_cb_end__;
__asm (".global os_cb_sections");
extern const uint32_t os_cb_sections[];
__attribute__((section(".rodata")))
const uint32_t os_cb_sections[] = {
(uint32_t)&__os_thread_cb_start__,
(uint32_t)&__os_thread_cb_end__,
(uint32_t)&__os_timer_cb_start__,
(uint32_t)&__os_timer_cb_end__,
(uint32_t)&__os_evflags_cb_start__,
(uint32_t)&__os_evflags_cb_end__,
(uint32_t)&__os_mutex_cb_start__,
(uint32_t)&__os_mutex_cb_end__,
(uint32_t)&__os_semaphore_cb_start__,
(uint32_t)&__os_semaphore_cb_end__,
(uint32_t)&__os_mempool_cb_start__,
(uint32_t)&__os_mempool_cb_end__,
(uint32_t)&__os_msgqueue_cb_start__,
(uint32_t)&__os_msgqueue_cb_end__
};
#endif
// OS Initialization
// =================
#if defined(__CC_ARM) || \
(defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050))
#ifndef __MICROLIB
extern void _platform_post_stackheap_init (void);
__WEAK void _platform_post_stackheap_init (void) {
osKernelInitialize();
}
#endif
#elif defined(__GNUC__)
extern void software_init_hook (void);
__WEAK void software_init_hook (void) {
osKernelInitialize();
}
#endif
// C/C++ Standard Library Multithreading Interface
// ===============================================
#if (( defined(__CC_ARM) || \
(defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050))) && \
!defined(__MICROLIB))
#define LIBSPACE_SIZE 96
// Memory for libspace
static uint32_t os_libspace[OS_THREAD_LIBSPACE_NUM+1][LIBSPACE_SIZE/sizeof(uint32_t)] \
__attribute__((section(".bss.os")));
// Thread IDs for libspace
static osThreadId_t os_libspace_id[OS_THREAD_LIBSPACE_NUM] \
__attribute__((section(".bss.os")));
// Check if Kernel has been started
static uint32_t os_kernel_is_active (void) {
static uint8_t os_kernel_active = 0U;
if (os_kernel_active == 0U) {
if (osKernelGetState() > osKernelReady) {
os_kernel_active = 1U;
return 1U;
}
return 0U;
} else {
return 1U;
}
}
// Provide libspace for current thread
void *__user_perthread_libspace (void);
void *__user_perthread_libspace (void) {
osThreadId_t id;
uint32_t n;
if (!os_kernel_is_active()) {
return (void *)&os_libspace[OS_THREAD_LIBSPACE_NUM][0];
}
id = osThreadGetId();
for (n = 0U; n < OS_THREAD_LIBSPACE_NUM; n++) {
if (os_libspace_id[n] == NULL) {
os_libspace_id[n] = id;
return (void *)&os_libspace[n][0];
}
if (os_libspace_id[n] == id) {
return (void *)&os_libspace[n][0];
}
}
if (n == OS_THREAD_LIBSPACE_NUM) {
osRtxErrorNotify(osRtxErrorClibSpace, id);
}
return (void *)&os_libspace[n][0];
}
// Mutex identifier
typedef void *mutex;
// Initialize mutex
__USED
int _mutex_initialize(mutex *m);
int _mutex_initialize(mutex *m) {
*m = osMutexNew(NULL);
if (*m == NULL) {
osRtxErrorNotify(osRtxErrorClibMutex, m);
return 0;
}
return 1;
}
// Acquire mutex
__USED
void _mutex_acquire(mutex *m);
void _mutex_acquire(mutex *m) {
if (os_kernel_is_active()) {
osMutexAcquire(*m, osWaitForever);
}
}
// Release mutex
__USED
void _mutex_release(mutex *m);
void _mutex_release(mutex *m) {
if (os_kernel_is_active()) {
osMutexRelease(*m);
}
}
// Free mutex
__USED
void _mutex_free(mutex *m);
void _mutex_free(mutex *m) {
osMutexDelete(*m);
}
#endif

View File

@ -0,0 +1,214 @@
/*
* Copyright (c) 2013-2017 ARM Limited. All rights reserved.
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the License); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an AS IS BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* -----------------------------------------------------------------------------
*
* Project: CMSIS-RTOS RTX
* Title: RTX Library definitions
*
* -----------------------------------------------------------------------------
*/
#ifndef RTX_LIB_H_
#define RTX_LIB_H_
#include <string.h>
#include <stdbool.h>
#include "core_cm.h" // Cortex-M definitions
#include "tz_context.h" // TrustZone Context API
#include "cmsis_os2.h" // CMSIS RTOS API
#include "rtx_os.h" // RTX OS definitions
#include "rtx_evr.h" // RTX Event Recorder definitions
// ==== Library defines ====
#define os_thread_t osRtxThread_t
#define os_timer_t osRtxTimer_t
#define os_timer_finfo_t osRtxTimerFinfo_t
#define os_event_flags_t osRtxEventFlags_t
#define os_mutex_t osRtxMutex_t
#define os_semaphore_t osRtxSemaphore_t
#define os_mp_info_t osRtxMpInfo_t
#define os_memory_pool_t osRtxMemoryPool_t
#define os_message_t osRtxMessage_t
#define os_message_queue_t osRtxMessageQueue_t
#define os_object_t osRtxObject_t
// ==== Inline functions ====
// Kernel Inline functions
__STATIC_INLINE uint8_t osRtxKernelGetState (void) { return osRtxInfo.kernel.state; }
// Thread Inline functions
__STATIC_INLINE os_thread_t *osRtxThreadGetRunning (void) { return osRtxInfo.thread.run.curr; }
__STATIC_INLINE void osRtxThreadSetRunning (os_thread_t *thread) { osRtxInfo.thread.run.curr = thread; }
// ==== Library functions ====
// Thread Library functions
extern void osRtxThreadListPut (volatile os_object_t *object, os_thread_t *thread);
extern os_thread_t *osRtxThreadListGet (volatile os_object_t *object);
extern void *osRtxThreadListRoot (os_thread_t *thread);
extern void osRtxThreadListSort (os_thread_t *thread);
extern void osRtxThreadListRemove (os_thread_t *thread);
extern void osRtxThreadListUnlink (os_thread_t **thread_list, os_thread_t *thread);
extern void osRtxThreadReadyPut (os_thread_t *thread);
extern void osRtxThreadDelayInsert (os_thread_t *thread, uint32_t delay);
extern void osRtxThreadDelayRemove (os_thread_t *thread);
extern void osRtxThreadDelayTick (void);
extern uint32_t *osRtxThreadRegPtr (os_thread_t *thread);
extern void osRtxThreadBlock (os_thread_t *thread);
extern void osRtxThreadSwitch (os_thread_t *thread);
extern void osRtxThreadDispatch (os_thread_t *thread);
extern void osRtxThreadWaitExit (os_thread_t *thread, uint32_t ret_val, bool dispatch);
extern bool osRtxThreadWaitEnter (uint8_t state, uint32_t timeout);
extern void osRtxThreadStackCheck (void);
// Timer Library functions
extern void osRtxTimerTick (void);
extern void osRtxTimerThread (void *argument);
// Mutex Library functions
extern void osRtxMutexOwnerRelease (os_mutex_t *mutex_list);
// Memory Heap Library functions
extern uint32_t osRtxMemoryInit (void *mem, uint32_t size);
extern void *osRtxMemoryAlloc(void *mem, uint32_t size, uint32_t type);
extern uint32_t osRtxMemoryFree (void *mem, void *block);
// Memory Pool Library functions
extern uint32_t osRtxMemoryPoolInit (os_mp_info_t *mp_info, uint32_t blocks, uint32_t block_size, void *block_mem);
extern void *osRtxMemoryPoolAlloc (os_mp_info_t *mp_info);
extern osStatus_t osRtxMemoryPoolFree (os_mp_info_t *mp_info, void *block);
// System Library functions
extern void osRtxTick_Handler (void);
extern void osRtxPendSV_Handler (void);
extern void osRtxPostProcess (os_object_t *object);
// Post ISR processing functions
extern void osRtxThreadPostProcess (os_thread_t *thread);
extern void osRtxEventFlagsPostProcess (os_event_flags_t *ef);
extern void osRtxSemaphorePostProcess (os_semaphore_t *semaphore);
extern void osRtxMemoryPoolPostProcess (os_memory_pool_t *mp);
extern void osRtxMessageQueuePostProcess (os_message_t *msg);
// ==== Service Calls ====
// Kernel Service Calls
extern osStatus_t svcRtxKernelInitialize (void);
extern osStatus_t svcRtxKernelGetInfo (osVersion_t *version, char *id_buf, uint32_t id_size);
extern osKernelState_t svcRtxKernelGetState (void);
extern osStatus_t svcRtxKernelStart (void);
extern int32_t svcRtxKernelLock (void);
extern int32_t svcRtxKernelUnlock (void);
extern int32_t svcRtxKernelRestoreLock (int32_t lock);
extern uint32_t svcRtxKernelSuspend (void);
extern void svcRtxKernelResume (uint32_t sleep_ticks);
extern uint64_t svcRtxKernelGetTickCount (void);
extern uint32_t svcRtxKernelGetTickFreq (void);
extern uint32_t svcRtxKernelGetSysTimerCount (void);
extern uint32_t svcRtxKernelGetSysTimerFreq (void);
// Thread Service Calls
extern osThreadId_t svcRtxThreadNew (osThreadFunc_t func, void *argument, const osThreadAttr_t *attr);
extern const char * svcRtxThreadGetName (osThreadId_t thread_id);
extern osThreadId_t svcRtxThreadGetId (void);
extern osThreadState_t svcRtxThreadGetState (osThreadId_t thread_id);
extern uint32_t svcRtxThreadGetStackSize (osThreadId_t thread_id);
extern uint32_t svcRtxThreadGetStackSpace(osThreadId_t thread_id);
extern osStatus_t svcRtxThreadSetPriority (osThreadId_t thread_id, osPriority_t priority);
extern osPriority_t svcRtxThreadGetPriority (osThreadId_t thread_id);
extern osStatus_t svcRtxThreadYield (void);
extern osStatus_t svcRtxThreadSuspend (osThreadId_t thread_id);
extern osStatus_t svcRtxThreadResume (osThreadId_t thread_id);
extern osStatus_t svcRtxThreadDetach (osThreadId_t thread_id);
extern osStatus_t svcRtxThreadJoin (osThreadId_t thread_id);
extern void svcRtxThreadExit (void);
extern osStatus_t svcRtxThreadTerminate (osThreadId_t thread_id);
extern uint32_t svcRtxThreadGetCount (void);
extern uint32_t svcRtxThreadEnumerate (osThreadId_t *thread_array, uint32_t array_items);
extern uint32_t svcRtxThreadFlagsSet (osThreadId_t thread_id, uint32_t flags);
extern uint32_t svcRtxThreadFlagsClear (uint32_t flags);
extern uint32_t svcRtxThreadFlagsGet (void);
extern uint32_t svcRtxThreadFlagsWait (uint32_t flags, uint32_t options, uint32_t timeout);
// Delay Service Calls
extern osStatus_t svcRtxDelay (uint32_t ticks);
extern osStatus_t svcRtxDelayUntil (uint32_t ticks_l, uint32_t ticks_h);
// Timer Service Calls
extern osTimerId_t svcRtxTimerNew (osTimerFunc_t func, osTimerType_t type, void *argument, const osTimerAttr_t *attr);
extern const char * svcRtxTimerGetName (osTimerId_t timer_id);
extern osStatus_t svcRtxTimerStart (osTimerId_t timer_id, uint32_t ticks);
extern osStatus_t svcRtxTimerStop (osTimerId_t timer_id);
extern uint32_t svcRtxTimerIsRunning (osTimerId_t timer_id);
extern osStatus_t svcRtxTimerDelete (osTimerId_t timer_id);
// Event Flags Service Calls
extern osEventFlagsId_t svcRtxEventFlagsNew (const osEventFlagsAttr_t *attr);
extern const char * svcRtxEventFlagsGetName (osEventFlagsId_t ef_id);
extern uint32_t svcRtxEventFlagsSet (osEventFlagsId_t ef_id, uint32_t flags);
extern uint32_t svcRtxEventFlagsClear (osEventFlagsId_t ef_id, uint32_t flags);
extern uint32_t svcRtxEventFlagsGet (osEventFlagsId_t ef_id);
extern uint32_t svcRtxEventFlagsWait (osEventFlagsId_t ef_id, uint32_t flags, uint32_t options, uint32_t timeout);
extern osStatus_t svcRtxEventFlagsDelete (osEventFlagsId_t ef_id);
// Mutex Service Calls
extern osMutexId_t svcRtxMutexNew (const osMutexAttr_t *attr);
extern const char * svcRtxMutexGetName (osMutexId_t mutex_id);
extern osStatus_t svcRtxMutexAcquire (osMutexId_t mutex_id, uint32_t timeout);
extern osStatus_t svcRtxMutexRelease (osMutexId_t mutex_id);
extern osThreadId_t svcRtxMutexGetOwner (osMutexId_t mutex_id);
extern osStatus_t svcRtxMutexDelete (osMutexId_t mutex_id);
// Semaphore Service Calls
extern osSemaphoreId_t svcRtxSemaphoreNew (uint32_t max_count, uint32_t initial_count, const osSemaphoreAttr_t *attr);
extern const char * svcRtxSemaphoreGetName (osSemaphoreId_t semaphore_id);
extern osStatus_t svcRtxSemaphoreRelease (osSemaphoreId_t semaphore_id);
extern osStatus_t svcRtxSemaphoreAcquire (osSemaphoreId_t semaphore_id, uint32_t timeout);
extern uint32_t svcRtxSemaphoreGetCount(osSemaphoreId_t semaphore_id);
extern osStatus_t svcRtxSemaphoreDelete (osSemaphoreId_t semaphore_id);
// Memory Pool Service Calls
extern osMemoryPoolId_t svcRtxMemoryPoolNew (uint32_t blocks, uint32_t block_size, const osMemoryPoolAttr_t *attr);
extern const char * svcRtxMemoryPoolGetName (osMemoryPoolId_t mp_id);
extern void * svcRtxMemoryPoolAlloc (osMemoryPoolId_t mp_id, uint32_t timeout);
extern osStatus_t svcRtxMemoryPoolFree (osMemoryPoolId_t mp_id, void *block);
extern uint32_t svcRtxMemoryPoolGetCapacity (osMemoryPoolId_t mp_id);
extern uint32_t svcRtxMemoryPoolGetBlockSize (osMemoryPoolId_t mp_id);
extern uint32_t svcRtxMemoryPoolGetCount (osMemoryPoolId_t mp_id);
extern uint32_t svcRtxMemoryPoolGetSpace (osMemoryPoolId_t mp_id);
extern osStatus_t svcRtxMemoryPoolDelete (osMemoryPoolId_t mp_id);
// Message Queue Service Calls
extern osMessageQueueId_t svcRtxMessageQueueNew (uint32_t msg_count, uint32_t msg_size, const osMessageQueueAttr_t *attr);
extern const char * svcRtxMessageQueueGetName (osMessageQueueId_t mq_id);
extern osStatus_t svcRtxMessageQueuePut (osMessageQueueId_t mq_id, const void *msg_ptr, uint8_t msg_prio, uint32_t timeout);
extern osStatus_t svcRtxMessageQueueGet (osMessageQueueId_t mq_id, void *msg_ptr, uint8_t *msg_prio, uint32_t timeout);
extern uint32_t svcRtxMessageQueueGetCapacity (osMessageQueueId_t mq_id);
extern uint32_t svcRtxMessageQueueGetMsgSize (osMessageQueueId_t mq_id);
extern uint32_t svcRtxMessageQueueGetCount (osMessageQueueId_t mq_id);
extern uint32_t svcRtxMessageQueueGetSpace (osMessageQueueId_t mq_id);
extern osStatus_t svcRtxMessageQueueReset (osMessageQueueId_t mq_id);
extern osStatus_t svcRtxMessageQueueDelete (osMessageQueueId_t mq_id);
#endif // RTX_LIB_H_

View File

@ -0,0 +1,171 @@
/*
* Copyright (c) 2013-2017 ARM Limited. All rights reserved.
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the License); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an AS IS BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* -----------------------------------------------------------------------------
*
* Project: CMSIS-RTOS RTX
* Title: Memory functions
*
* -----------------------------------------------------------------------------
*/
#include "rtx_lib.h"
// Memory Pool Header structure
typedef struct mem_head_s {
uint32_t size; // Memory Pool size
uint32_t used; // Used Memory
} mem_head_t;
// Memory Block Header structure
typedef struct mem_block_s {
struct mem_block_s *next; // Next Memory Block in list
uint32_t info; // Info: length = <31:2>:'00', type = <1:0>
} mem_block_t;
#define MB_INFO_LEN_MASK 0xFFFFFFFCU
#define MB_INFO_TYPE_MASK 0x00000003U
// ==== Library functions ====
/// Initialize Memory Pool with variable block size.
/// \param[in] mem pointer to memory pool.
/// \param[in] size size of a memory pool in bytes.
/// \return 1 - success, 0 - failure.
__WEAK uint32_t osRtxMemoryInit (void *mem, uint32_t size) {
mem_head_t *head;
mem_block_t *ptr;
if ((mem == NULL) || ((uint32_t)mem & 7U) || (size & 7U) ||
(size < (sizeof(mem_head_t) + 2*sizeof(mem_block_t)))) {
EvrRtxMemoryInit(mem, size, 0U);
return 0U;
}
head = (mem_head_t *)mem;
head->size = size;
head->used = sizeof(mem_head_t) + sizeof(mem_block_t);
ptr = (mem_block_t *)((uint32_t)mem + sizeof(mem_head_t));
ptr->next = (mem_block_t *)((uint32_t)mem + size - sizeof(mem_block_t));
ptr->next->next = NULL;
ptr->info = 0U;
EvrRtxMemoryInit(mem, size, 1U);
return 1U;
}
/// Allocate a memory block from a Memory Pool.
/// \param[in] mem pointer to memory pool.
/// \param[in] size size of a memory block in bytes.
/// \param[in] type memory block type: 0 - generic, 1 - control block
/// \return allocated memory block or NULL in case of no memory is available.
__WEAK void *osRtxMemoryAlloc (void *mem, uint32_t size, uint32_t type) {
mem_block_t *p, *p_new, *ptr;
uint32_t hole_size;
if ((mem == NULL) || (size == 0U) || (type & ~MB_INFO_TYPE_MASK)) {
EvrRtxMemoryAlloc(mem, size, type, NULL);
return NULL;
}
// Add header to size
size += sizeof(mem_block_t);
// Make sure that block is 8-byte aligned
size = (size + 7U) & ~((uint32_t)7U);
// Search for hole big enough
p = (mem_block_t *)((uint32_t)mem + sizeof(mem_head_t));
for (;;) {
hole_size = (uint32_t)p->next - (uint32_t)p;
hole_size -= p->info & MB_INFO_LEN_MASK;
if (hole_size >= size) {
// Hole found
break;
}
p = p->next;
if (p->next == NULL) {
// Failed (end of list)
EvrRtxMemoryAlloc(mem, size, type, NULL);
return NULL;
}
}
((mem_head_t *)mem)->used += size;
if (p->info == 0U) {
// No block allocated, set info of first element
p->info = size | type;
ptr = (mem_block_t *)((uint32_t)p + sizeof(mem_block_t));
} else {
// Insert new element into the list
p_new = (mem_block_t *)((uint32_t)p + (p->info & MB_INFO_LEN_MASK));
p_new->next = p->next;
p_new->info = size | type;
p->next = p_new;
ptr = (mem_block_t *)((uint32_t)p_new + sizeof(mem_block_t));
}
EvrRtxMemoryAlloc(mem, size, type, ptr);
return ptr;
}
/// Return an allocated memory block back to a Memory Pool.
/// \param[in] mem pointer to memory pool.
/// \param[in] block memory block to be returned to the memory pool.
/// \return 1 - success, 0 - failure.
__WEAK uint32_t osRtxMemoryFree (void *mem, void *block) {
mem_block_t *p, *p_prev, *ptr;
if ((mem == NULL) || (block == NULL)) {
EvrRtxMemoryFree(mem, block, 0U);
return 0U;
}
ptr = (mem_block_t *)((uint32_t)block - sizeof(mem_block_t));
// Search for header
p_prev = NULL;
p = (mem_block_t *)((uint32_t)mem + sizeof(mem_head_t));
while (p != ptr) {
p_prev = p;
p = p->next;
if (p == NULL) {
// Not found
EvrRtxMemoryFree(mem, block, 0U);
return 0U;
}
}
((mem_head_t *)mem)->used -= p->info & MB_INFO_LEN_MASK;
if (p_prev == NULL) {
// Release first block, only set info to 0
p->info = 0U;
} else {
// Discard block from chained list
p_prev->next = p->next;
}
EvrRtxMemoryFree(mem, block, 1U);
return 1U;
}

View File

@ -0,0 +1,685 @@
/*
* Copyright (c) 2013-2017 ARM Limited. All rights reserved.
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the License); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an AS IS BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* -----------------------------------------------------------------------------
*
* Project: CMSIS-RTOS RTX
* Title: Memory Pool functions
*
* -----------------------------------------------------------------------------
*/
#include "rtx_lib.h"
// ==== Library functions ====
/// Initialize Memory Pool.
/// \param[in] mp_info memory pool info.
/// \param[in] block_count maximum number of memory blocks in memory pool.
/// \param[in] block_size size of a memory block in bytes.
/// \param[in] block_mem pointer to memory for block storage.
/// \return 1 - success, 0 - failure.
uint32_t osRtxMemoryPoolInit (os_mp_info_t *mp_info, uint32_t block_count, uint32_t block_size, void *block_mem) {
void *block;
// Check parameters
if ((mp_info == NULL) || (block_count == 0U) || (block_size == 0U) || (block_mem == NULL)) {
return 0U;
}
// Initialize information structure
mp_info->max_blocks = block_count;
mp_info->used_blocks = 0U;
mp_info->block_size = block_size;
mp_info->block_base = block_mem;
mp_info->block_free = block_mem;
mp_info->block_lim = (uint8_t *)block_mem + (block_count * block_size);
EvrRtxMemoryBlockInit(mp_info, block_count, block_size, block_mem);
// Link all free blocks
while (--block_count) {
block = (uint8_t *)block_mem + block_size;
*((void **)block_mem) = block;
block_mem = block;
}
*((void **)block_mem) = NULL;
return 1U;
}
/// Allocate a memory block from a Memory Pool.
/// \param[in] mp_info memory pool info.
/// \return address of the allocated memory block or NULL in case of no memory is available.
void *osRtxMemoryPoolAlloc (os_mp_info_t *mp_info) {
#if (__EXCLUSIVE_ACCESS == 0U)
uint32_t primask = __get_PRIMASK();
#endif
void *block;
if (mp_info == NULL) {
EvrRtxMemoryBlockAlloc(NULL, NULL);
return NULL;
}
#if (__EXCLUSIVE_ACCESS == 0U)
__disable_irq();
if (mp_info->used_blocks < mp_info->max_blocks) {
mp_info->used_blocks++;
block = mp_info->block_free;
if (block != NULL) {
mp_info->block_free = *((void **)block);
}
} else {
block = NULL;
}
if (primask == 0U) {
__enable_irq();
}
#else
if (atomic_inc32_lt(&mp_info->used_blocks, mp_info->max_blocks) < mp_info->max_blocks) {
block = atomic_link_get(&mp_info->block_free);
} else {
block = NULL;
}
#endif
EvrRtxMemoryBlockAlloc(mp_info, block);
return block;
}
/// Return an allocated memory block back to a Memory Pool.
/// \param[in] mp_info memory pool info.
/// \param[in] block address of the allocated memory block to be returned to the memory pool.
/// \return status code that indicates the execution status of the function.
osStatus_t osRtxMemoryPoolFree (os_mp_info_t *mp_info, void *block) {
#if (__EXCLUSIVE_ACCESS == 0U)
uint32_t primask = __get_PRIMASK();
#endif
osStatus_t status;
if ((mp_info == NULL) || (block < mp_info->block_base) || (block >= mp_info->block_lim)) {
EvrRtxMemoryBlockFree(mp_info, block, osErrorParameter);
return osErrorParameter;
}
#if (__EXCLUSIVE_ACCESS == 0U)
__disable_irq();
if (mp_info->used_blocks != 0U) {
mp_info->used_blocks--;
*((void **)block) = mp_info->block_free;
mp_info->block_free = block;
status = osOK;
} else {
status = osErrorResource;
}
if (primask == 0U) {
__enable_irq();
}
#else
if (atomic_dec32_nz(&mp_info->used_blocks) != 0U) {
atomic_link_put(&mp_info->block_free, block);
status = osOK;
} else {
status = osErrorResource;
}
#endif
EvrRtxMemoryBlockFree(mp_info, block, status);
return status;
}
/// Memory Pool post ISR processing.
/// \param[in] mp memory pool object.
void osRtxMemoryPoolPostProcess (os_memory_pool_t *mp) {
void *block;
os_thread_t *thread;
if (mp->state == osRtxObjectInactive) {
return;
}
// Check if Thread is waiting to allocate memory
if (mp->thread_list != NULL) {
// Allocate memory
block = osRtxMemoryPoolAlloc(&mp->mp_info);
if (block != NULL) {
// Wakeup waiting Thread with highest Priority
thread = osRtxThreadListGet((os_object_t*)mp);
osRtxThreadWaitExit(thread, (uint32_t)block, false);
EvrRtxMemoryPoolAllocated(mp, block);
}
}
}
// ==== Service Calls ====
// Service Calls definitions
SVC0_3M(MemoryPoolNew, osMemoryPoolId_t, uint32_t, uint32_t, const osMemoryPoolAttr_t *)
SVC0_1 (MemoryPoolGetName, const char *, osMemoryPoolId_t)
SVC0_2 (MemoryPoolAlloc, void *, osMemoryPoolId_t, uint32_t)
SVC0_2 (MemoryPoolFree, osStatus_t, osMemoryPoolId_t, void *)
SVC0_1 (MemoryPoolGetCapacity, uint32_t, osMemoryPoolId_t)
SVC0_1 (MemoryPoolGetBlockSize, uint32_t, osMemoryPoolId_t)
SVC0_1 (MemoryPoolGetCount, uint32_t, osMemoryPoolId_t)
SVC0_1 (MemoryPoolGetSpace, uint32_t, osMemoryPoolId_t)
SVC0_1 (MemoryPoolDelete, osStatus_t, osMemoryPoolId_t)
/// Create and Initialize a Memory Pool object.
/// \note API identical to osMemoryPoolNew
osMemoryPoolId_t svcRtxMemoryPoolNew (uint32_t block_count, uint32_t block_size, const osMemoryPoolAttr_t *attr) {
os_memory_pool_t *mp;
void *mp_mem;
uint32_t mp_size;
uint32_t size;
uint8_t flags;
const char *name;
// Check parameters
if ((block_count == 0U) || (block_size == 0U)) {
EvrRtxMemoryPoolError(NULL, osErrorParameter);
return NULL;
}
block_size = (block_size + 3U) & ~3UL;
if ((__CLZ(block_count) + __CLZ(block_size)) < 32) {
EvrRtxMemoryPoolError(NULL, osErrorParameter);
return NULL;
}
size = block_count * block_size;
// Process attributes
if (attr != NULL) {
name = attr->name;
mp = attr->cb_mem;
mp_mem = attr->mp_mem;
mp_size = attr->mp_size;
if (mp != NULL) {
if (((uint32_t)mp & 3U) || (attr->cb_size < sizeof(os_memory_pool_t))) {
EvrRtxMemoryPoolError(NULL, osRtxErrorInvalidControlBlock);
return NULL;
}
} else {
if (attr->cb_size != 0U) {
EvrRtxMemoryPoolError(NULL, osRtxErrorInvalidControlBlock);
return NULL;
}
}
if (mp_mem != NULL) {
if (((uint32_t)mp_mem & 3U) || (mp_size < size)) {
EvrRtxMemoryPoolError(NULL, osRtxErrorInvalidDataMemory);
return NULL;
}
} else {
if (mp_size != 0U) {
EvrRtxMemoryPoolError(NULL, osRtxErrorInvalidDataMemory);
return NULL;
}
}
} else {
name = NULL;
mp = NULL;
mp_mem = NULL;
}
// Allocate object memory if not provided
if (mp == NULL) {
if (osRtxInfo.mpi.memory_pool != NULL) {
mp = osRtxMemoryPoolAlloc(osRtxInfo.mpi.memory_pool);
} else {
mp = osRtxMemoryAlloc(osRtxInfo.mem.common, sizeof(os_memory_pool_t), 1U);
}
if (mp == NULL) {
EvrRtxMemoryPoolError(NULL, osErrorNoMemory);
return NULL;
}
flags = osRtxFlagSystemObject;
} else {
flags = 0U;
}
// Allocate data memory if not provided
if (mp_mem == NULL) {
mp_mem = osRtxMemoryAlloc(osRtxInfo.mem.mp_data, size, 0U);
if (mp_mem == NULL) {
EvrRtxMemoryPoolError(NULL, osErrorNoMemory);
if (flags & osRtxFlagSystemObject) {
if (osRtxInfo.mpi.memory_pool != NULL) {
osRtxMemoryPoolFree(osRtxInfo.mpi.memory_pool, mp);
} else {
osRtxMemoryFree(osRtxInfo.mem.common, mp);
}
}
return NULL;
}
memset(mp_mem, 0, size);
flags |= osRtxFlagSystemMemory;
}
// Initialize control block
mp->id = osRtxIdMemoryPool;
mp->state = osRtxObjectActive;
mp->flags = flags;
mp->name = name;
mp->thread_list = NULL;
osRtxMemoryPoolInit(&mp->mp_info, block_count, block_size, mp_mem);
// Register post ISR processing function
osRtxInfo.post_process.memory_pool = osRtxMemoryPoolPostProcess;
EvrRtxMemoryPoolCreated(mp);
return mp;
}
/// Get name of a Memory Pool object.
/// \note API identical to osMemoryPoolGetName
const char *svcRtxMemoryPoolGetName (osMemoryPoolId_t mp_id) {
os_memory_pool_t *mp = (os_memory_pool_t *)mp_id;
// Check parameters
if ((mp == NULL) || (mp->id != osRtxIdMemoryPool)) {
EvrRtxMemoryPoolGetName(mp, NULL);
return NULL;
}
// Check object state
if (mp->state == osRtxObjectInactive) {
EvrRtxMemoryPoolGetName(mp, NULL);
return NULL;
}
EvrRtxMemoryPoolGetName(mp, mp->name);
return mp->name;
}
/// Allocate a memory block from a Memory Pool.
/// \note API identical to osMemoryPoolAlloc
void *svcRtxMemoryPoolAlloc (osMemoryPoolId_t mp_id, uint32_t timeout) {
os_memory_pool_t *mp = (os_memory_pool_t *)mp_id;
void *block;
// Check parameters
if ((mp == NULL) || (mp->id != osRtxIdMemoryPool)) {
EvrRtxMemoryPoolError(mp, osErrorParameter);
return NULL;
}
// Check object state
if (mp->state == osRtxObjectInactive) {
EvrRtxMemoryPoolError(mp, osErrorResource);
return NULL;
}
// Allocate memory
block = osRtxMemoryPoolAlloc(&mp->mp_info);
if (block == NULL) {
// No memory available
if (timeout != 0U) {
EvrRtxMemoryPoolAllocPending(mp, timeout);
// Suspend current Thread
osRtxThreadListPut((os_object_t*)mp, osRtxThreadGetRunning());
osRtxThreadWaitEnter(osRtxThreadWaitingMemoryPool, timeout);
} else {
EvrRtxMemoryPoolAllocFailed(mp);
}
} else {
EvrRtxMemoryPoolAllocated(mp, block);
}
return block;
}
/// Return an allocated memory block back to a Memory Pool.
/// \note API identical to osMemoryPoolFree
osStatus_t svcRtxMemoryPoolFree (osMemoryPoolId_t mp_id, void *block) {
os_memory_pool_t *mp = (os_memory_pool_t *)mp_id;
os_thread_t *thread;
osStatus_t status;
// Check parameters
if ((mp == NULL) || (mp->id != osRtxIdMemoryPool)) {
EvrRtxMemoryPoolError(mp, osErrorParameter);
return osErrorParameter;
}
// Check object state
if (mp->state == osRtxObjectInactive) {
EvrRtxMemoryPoolError(mp, osErrorResource);
return osErrorResource;
}
// Free memory
status = osRtxMemoryPoolFree(&mp->mp_info, block);
if (status == osOK) {
EvrRtxMemoryPoolDeallocated(mp, block);
// Check if Thread is waiting to allocate memory
if (mp->thread_list != NULL) {
// Allocate memory
block = osRtxMemoryPoolAlloc(&mp->mp_info);
if (block != NULL) {
// Wakeup waiting Thread with highest Priority
thread = osRtxThreadListGet((os_object_t*)mp);
osRtxThreadWaitExit(thread, (uint32_t)block, true);
EvrRtxMemoryPoolAllocated(mp, block);
}
}
} else {
EvrRtxMemoryPoolFreeFailed(mp, block);
}
return status;
}
/// Get maximum number of memory blocks in a Memory Pool.
/// \note API identical to osMemoryPoolGetCapacity
uint32_t svcRtxMemoryPoolGetCapacity (osMemoryPoolId_t mp_id) {
os_memory_pool_t *mp = (os_memory_pool_t *)mp_id;
// Check parameters
if ((mp == NULL) || (mp->id != osRtxIdMemoryPool)) {
EvrRtxMemoryPoolGetCapacity(mp, 0U);
return 0U;
}
// Check object state
if (mp->state == osRtxObjectInactive) {
EvrRtxMemoryPoolGetCapacity(mp, 0U);
return 0U;
}
EvrRtxMemoryPoolGetCapacity(mp, mp->mp_info.max_blocks);
return mp->mp_info.max_blocks;
}
/// Get memory block size in a Memory Pool.
/// \note API identical to osMemoryPoolGetBlockSize
uint32_t svcRtxMemoryPoolGetBlockSize (osMemoryPoolId_t mp_id) {
os_memory_pool_t *mp = (os_memory_pool_t *)mp_id;
// Check parameters
if ((mp == NULL) || (mp->id != osRtxIdMemoryPool)) {
EvrRtxMemoryPoolGetBlockSize(mp, 0U);
return 0U;
}
// Check object state
if (mp->state == osRtxObjectInactive) {
EvrRtxMemoryPoolGetBlockSize(mp, 0U);
return 0U;
}
EvrRtxMemoryPoolGetBlockSize(mp, mp->mp_info.block_size);
return mp->mp_info.block_size;
}
/// Get number of memory blocks used in a Memory Pool.
/// \note API identical to osMemoryPoolGetCount
uint32_t svcRtxMemoryPoolGetCount (osMemoryPoolId_t mp_id) {
os_memory_pool_t *mp = (os_memory_pool_t *)mp_id;
// Check parameters
if ((mp == NULL) || (mp->id != osRtxIdMemoryPool)) {
EvrRtxMemoryPoolGetCount(mp, 0U);
return 0U;
}
// Check object state
if (mp->state == osRtxObjectInactive) {
EvrRtxMemoryPoolGetCount(mp, 0U);
return 0U;
}
EvrRtxMemoryPoolGetCount(mp, mp->mp_info.used_blocks);
return mp->mp_info.used_blocks;
}
/// Get number of memory blocks available in a Memory Pool.
/// \note API identical to osMemoryPoolGetSpace
uint32_t svcRtxMemoryPoolGetSpace (osMemoryPoolId_t mp_id) {
os_memory_pool_t *mp = (os_memory_pool_t *)mp_id;
// Check parameters
if ((mp == NULL) || (mp->id != osRtxIdMemoryPool)) {
EvrRtxMemoryPoolGetSpace(mp, 0U);
return 0U;
}
// Check object state
if (mp->state == osRtxObjectInactive) {
EvrRtxMemoryPoolGetSpace(mp, 0U);
return 0U;
}
EvrRtxMemoryPoolGetSpace(mp, mp->mp_info.max_blocks - mp->mp_info.used_blocks);
return (mp->mp_info.max_blocks - mp->mp_info.used_blocks);
}
/// Delete a Memory Pool object.
/// \note API identical to osMemoryPoolDelete
osStatus_t svcRtxMemoryPoolDelete (osMemoryPoolId_t mp_id) {
os_memory_pool_t *mp = (os_memory_pool_t *)mp_id;
os_thread_t *thread;
// Check parameters
if ((mp == NULL) || (mp->id != osRtxIdMemoryPool)) {
EvrRtxMemoryPoolError(mp, osErrorParameter);
return osErrorParameter;
}
// Check object state
if (mp->state == osRtxObjectInactive) {
EvrRtxMemoryPoolError(mp, osErrorResource);
return osErrorResource;
}
// Mark object as inactive
mp->state = osRtxObjectInactive;
// Unblock waiting threads
if (mp->thread_list != NULL) {
do {
thread = osRtxThreadListGet((os_object_t*)mp);
osRtxThreadWaitExit(thread, 0U, false);
} while (mp->thread_list != NULL);
osRtxThreadDispatch(NULL);
}
// Free data memory
if (mp->flags & osRtxFlagSystemMemory) {
osRtxMemoryFree(osRtxInfo.mem.mp_data, mp->mp_info.block_base);
}
// Free object memory
if (mp->flags & osRtxFlagSystemObject) {
if (osRtxInfo.mpi.memory_pool != NULL) {
osRtxMemoryPoolFree(osRtxInfo.mpi.memory_pool, mp);
} else {
osRtxMemoryFree(osRtxInfo.mem.common, mp);
}
}
EvrRtxMemoryPoolDestroyed(mp);
return osOK;
}
// ==== ISR Calls ====
/// Allocate a memory block from a Memory Pool.
/// \note API identical to osMemoryPoolAlloc
__STATIC_INLINE
void *isrRtxMemoryPoolAlloc (osMemoryPoolId_t mp_id, uint32_t timeout) {
os_memory_pool_t *mp = (os_memory_pool_t *)mp_id;
void *block;
// Check parameters
if ((mp == NULL) || (mp->id != osRtxIdMemoryPool) || (timeout != 0U)) {
EvrRtxMemoryPoolError(mp, osErrorParameter);
return NULL;
}
// Check object state
if (mp->state == osRtxObjectInactive) {
EvrRtxMemoryPoolError(mp, osErrorResource);
return NULL;
}
// Allocate memory
block = osRtxMemoryPoolAlloc(&mp->mp_info);
if (block == NULL) {
EvrRtxMemoryPoolAllocFailed(mp);
} else {
EvrRtxMemoryPoolAllocated(mp, block);
}
return block;
}
/// Return an allocated memory block back to a Memory Pool.
/// \note API identical to osMemoryPoolFree
__STATIC_INLINE
osStatus_t isrRtxMemoryPoolFree (osMemoryPoolId_t mp_id, void *block) {
os_memory_pool_t *mp = (os_memory_pool_t *)mp_id;
osStatus_t status;
// Check parameters
if ((mp == NULL) || (mp->id != osRtxIdMemoryPool)) {
EvrRtxMemoryPoolError(mp, osErrorParameter);
return osErrorParameter;
}
// Check object state
if (mp->state == osRtxObjectInactive) {
EvrRtxMemoryPoolError(mp, osErrorResource);
return osErrorResource;
}
// Free memory
status = osRtxMemoryPoolFree(&mp->mp_info, block);
if (status == osOK) {
// Register post ISR processing
osRtxPostProcess((os_object_t *)mp);
EvrRtxMemoryPoolDeallocated(mp, block);
} else {
EvrRtxMemoryPoolFreeFailed(mp, block);
}
return status;
}
// ==== Public API ====
/// Create and Initialize a Memory Pool object.
osMemoryPoolId_t osMemoryPoolNew (uint32_t block_count, uint32_t block_size, const osMemoryPoolAttr_t *attr) {
EvrRtxMemoryPoolNew(block_count, block_size, attr);
if (IS_IRQ_MODE() || IS_IRQ_MASKED()) {
EvrRtxMemoryPoolError(NULL, osErrorISR);
return NULL;
}
return __svcMemoryPoolNew(block_count, block_size, attr);
}
/// Get name of a Memory Pool object.
const char *osMemoryPoolGetName (osMemoryPoolId_t mp_id) {
if (IS_IRQ_MODE() || IS_IRQ_MASKED()) {
EvrRtxMemoryPoolGetName(mp_id, NULL);
return NULL;
}
return __svcMemoryPoolGetName(mp_id);
}
/// Allocate a memory block from a Memory Pool.
void *osMemoryPoolAlloc (osMemoryPoolId_t mp_id, uint32_t timeout) {
EvrRtxMemoryPoolAlloc(mp_id, timeout);
if (IS_IRQ_MODE() || IS_IRQ_MASKED()) {
return isrRtxMemoryPoolAlloc(mp_id, timeout);
} else {
return __svcMemoryPoolAlloc(mp_id, timeout);
}
}
/// Return an allocated memory block back to a Memory Pool.
osStatus_t osMemoryPoolFree (osMemoryPoolId_t mp_id, void *block) {
EvrRtxMemoryPoolFree(mp_id, block);
if (IS_IRQ_MODE() || IS_IRQ_MASKED()) {
return isrRtxMemoryPoolFree(mp_id, block);
} else {
return __svcMemoryPoolFree(mp_id, block);
}
}
/// Get maximum number of memory blocks in a Memory Pool.
uint32_t osMemoryPoolGetCapacity (osMemoryPoolId_t mp_id) {
if (IS_IRQ_MODE() || IS_IRQ_MASKED()) {
return svcRtxMemoryPoolGetCapacity(mp_id);
} else {
return __svcMemoryPoolGetCapacity(mp_id);
}
}
/// Get memory block size in a Memory Pool.
uint32_t osMemoryPoolGetBlockSize (osMemoryPoolId_t mp_id) {
if (IS_IRQ_MODE() || IS_IRQ_MASKED()) {
return svcRtxMemoryPoolGetBlockSize(mp_id);
} else {
return __svcMemoryPoolGetBlockSize(mp_id);
}
}
/// Get number of memory blocks used in a Memory Pool.
uint32_t osMemoryPoolGetCount (osMemoryPoolId_t mp_id) {
if (IS_IRQ_MODE() || IS_IRQ_MASKED()) {
return svcRtxMemoryPoolGetCount(mp_id);
} else {
return __svcMemoryPoolGetCount(mp_id);
}
}
/// Get number of memory blocks available in a Memory Pool.
uint32_t osMemoryPoolGetSpace (osMemoryPoolId_t mp_id) {
if (IS_IRQ_MODE() || IS_IRQ_MASKED()) {
return svcRtxMemoryPoolGetSpace(mp_id);
} else {
return __svcMemoryPoolGetSpace(mp_id);
}
}
/// Delete a Memory Pool object.
osStatus_t osMemoryPoolDelete (osMemoryPoolId_t mp_id) {
EvrRtxMemoryPoolDelete(mp_id);
if (IS_IRQ_MODE() || IS_IRQ_MASKED()) {
EvrRtxMemoryPoolError(mp_id, osErrorISR);
return osErrorISR;
}
return __svcMemoryPoolDelete(mp_id);
}

View File

@ -0,0 +1,906 @@
/*
* Copyright (c) 2013-2017 ARM Limited. All rights reserved.
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the License); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an AS IS BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* -----------------------------------------------------------------------------
*
* Project: CMSIS-RTOS RTX
* Title: Message Queue functions
*
* -----------------------------------------------------------------------------
*/
#include "rtx_lib.h"
// ==== Helper functions ====
/// Put a Message into Queue sorted by Priority (Highest at Head).
/// \param[in] mq message queue object.
/// \param[in] msg message object.
static void MessageQueuePut (os_message_queue_t *mq, os_message_t *msg) {
#if (__EXCLUSIVE_ACCESS == 0U)
uint32_t primask = __get_PRIMASK();
#endif
os_message_t *prev, *next;
if (mq->msg_last != NULL) {
prev = mq->msg_last;
next = NULL;
while ((prev != NULL) && (prev->priority < msg->priority)) {
next = prev;
prev = prev->prev;
}
msg->prev = prev;
msg->next = next;
if (prev != NULL) {
prev->next = msg;
} else {
mq->msg_first = msg;
}
if (next != NULL) {
next->prev = msg;
} else {
mq->msg_last = msg;
}
} else {
msg->prev = NULL;
msg->next = NULL;
mq->msg_first= msg;
mq->msg_last = msg;
}
#if (__EXCLUSIVE_ACCESS == 0U)
__disable_irq();
mq->msg_count++;
if (primask == 0U) {
__enable_irq();
}
#else
atomic_inc32(&mq->msg_count);
#endif
}
/// Get a Message from Queue with Highest Priority.
/// \param[in] mq message queue object.
/// \return message object or NULL.
static os_message_t *MessageQueueGet (os_message_queue_t *mq) {
#if (__EXCLUSIVE_ACCESS == 0U)
uint32_t primask = __get_PRIMASK();
#endif
os_message_t *msg;
uint32_t count;
uint8_t flags;
#if (__EXCLUSIVE_ACCESS == 0U)
__disable_irq();
count = mq->msg_count;
if (count != 0U) {
mq->msg_count--;
}
if (primask == 0U) {
__enable_irq();
}
#else
count = atomic_dec32_nz(&mq->msg_count);
#endif
if (count == 0U) {
return NULL;
}
msg = mq->msg_first;
while (msg != NULL) {
#if (__EXCLUSIVE_ACCESS == 0U)
__disable_irq();
flags = msg->flags;
msg->flags = 1U;
if (primask == 0U) {
__enable_irq();
}
#else
flags = atomic_wr8(&msg->flags, 1U);
#endif
if (flags == 0U) {
break;
}
msg = msg->next;
}
return msg;
}
/// Remove a Message from Queue
/// \param[in] mq message queue object.
/// \param[in] msg message object.
static void MessageQueueRemove (os_message_queue_t *mq, os_message_t *msg) {
if (msg->prev != NULL) {
msg->prev->next = msg->next;
} else {
mq->msg_first = msg->next;
}
if (msg->next != NULL) {
msg->next->prev = msg->prev;
} else {
mq->msg_last = msg->prev;
}
}
// ==== Library functions ====
/// Message Queue post ISR processing.
/// \param[in] msg message object.
void osRtxMessageQueuePostProcess (os_message_t *msg) {
os_message_queue_t *mq;
os_thread_t *thread;
uint32_t *reg;
void **ptr;
if (msg->state == osRtxObjectInactive) {
return;
}
if (msg->flags != 0U) {
// Remove Message
ptr = (void *)((uint8_t *)msg + sizeof(os_message_t));
mq = *ptr;
if (mq->state == osRtxObjectInactive) {
return;
}
MessageQueueRemove(mq, msg);
// Free memory
msg->state = osRtxObjectInactive;
osRtxMemoryPoolFree(&mq->mp_info, msg);
// Check if Thread is waiting to send a Message
if ((mq->thread_list != NULL) && (mq->thread_list->state == osRtxThreadWaitingMessagePut)) {
// Try to allocate memory
msg = osRtxMemoryPoolAlloc(&mq->mp_info);
if (msg != NULL) {
// Wakeup waiting Thread with highest Priority
thread = osRtxThreadListGet((os_object_t*)mq);
osRtxThreadWaitExit(thread, (uint32_t)osOK, false);
// Copy Message (R2: const void *msg_ptr, R3: uint8_t msg_prio)
reg = osRtxThreadRegPtr(thread);
memcpy((uint8_t *)msg + sizeof(os_message_t), (void *)reg[2], mq->msg_size);
// Store Message into Queue
msg->id = osRtxIdMessage;
msg->state = osRtxObjectActive;
msg->flags = 0U;
msg->priority = (uint8_t)reg[3];
MessageQueuePut(mq, msg);
EvrRtxMessageQueueInserted(mq, (void *)reg[2]);
}
}
} else {
// New Message
mq = (void *)msg->next;
if (mq->state == osRtxObjectInactive) {
return;
}
// Check if Thread is waiting to receive a Message
if ((mq->thread_list != NULL) && (mq->thread_list->state == osRtxThreadWaitingMessageGet)) {
EvrRtxMessageQueueInserted(mq, (void *)msg->prev);
// Wakeup waiting Thread with highest Priority
thread = osRtxThreadListGet((os_object_t*)mq);
osRtxThreadWaitExit(thread, (uint32_t)osOK, false);
// Copy Message (R2: void *msg_ptr, R3: uint8_t *msg_prio)
reg = osRtxThreadRegPtr(thread);
memcpy((void *)reg[2], (uint8_t *)msg + sizeof(os_message_t), mq->msg_size);
if (reg[3] != 0U) {
*((uint8_t *)reg[3]) = msg->priority;
}
EvrRtxMessageQueueRetrieved(mq, (void *)reg[2]);
// Free memory
msg->state = osRtxObjectInactive;
osRtxMemoryPoolFree(&mq->mp_info, msg);
} else {
EvrRtxMessageQueueInserted(mq, (void *)msg->prev);
MessageQueuePut(mq, msg);
}
}
}
// ==== Service Calls ====
SVC0_3M(MessageQueueNew, osMessageQueueId_t, uint32_t, uint32_t, const osMessageQueueAttr_t *)
SVC0_1 (MessageQueueGetName, const char *, osMessageQueueId_t)
SVC0_4 (MessageQueuePut, osStatus_t, osMessageQueueId_t, const void *, uint8_t, uint32_t)
SVC0_4 (MessageQueueGet, osStatus_t, osMessageQueueId_t, void *, uint8_t *, uint32_t)
SVC0_1 (MessageQueueGetCapacity, uint32_t, osMessageQueueId_t)
SVC0_1 (MessageQueueGetMsgSize, uint32_t, osMessageQueueId_t)
SVC0_1 (MessageQueueGetCount, uint32_t, osMessageQueueId_t)
SVC0_1 (MessageQueueGetSpace, uint32_t, osMessageQueueId_t)
SVC0_1 (MessageQueueReset, osStatus_t, osMessageQueueId_t)
SVC0_1 (MessageQueueDelete, osStatus_t, osMessageQueueId_t)
/// Create and Initialize a Message Queue object.
/// \note API identical to osMessageQueueNew
osMessageQueueId_t svcRtxMessageQueueNew (uint32_t msg_count, uint32_t msg_size, const osMessageQueueAttr_t *attr) {
os_message_queue_t *mq;
void *mq_mem;
uint32_t mq_size;
uint32_t block_size;
uint32_t size;
uint8_t flags;
const char *name;
// Check parameters
if ((msg_count == 0U) || (msg_size == 0U)) {
EvrRtxMessageQueueError(NULL, osErrorParameter);
return NULL;
}
msg_size = (msg_size + 3U) & ~3UL;
block_size = msg_size + sizeof(os_message_t);
if ((__CLZ(msg_count) + __CLZ(block_size)) < 32) {
EvrRtxMessageQueueError(NULL, osErrorParameter);
return NULL;
}
size = msg_count * block_size;
// Process attributes
if (attr != NULL) {
name = attr->name;
mq = attr->cb_mem;
mq_mem = attr->mq_mem;
mq_size = attr->mq_size;
if (mq != NULL) {
if (((uint32_t)mq & 3U) || (attr->cb_size < sizeof(os_message_queue_t))) {
EvrRtxMessageQueueError(NULL, osRtxErrorInvalidControlBlock);
return NULL;
}
} else {
if (attr->cb_size != 0U) {
EvrRtxMessageQueueError(NULL, osRtxErrorInvalidControlBlock);
return NULL;
}
}
if (mq_mem != NULL) {
if (((uint32_t)mq_mem & 3U) || (mq_size < size)) {
EvrRtxMessageQueueError(NULL, osRtxErrorInvalidDataMemory);
return NULL;
}
} else {
if (mq_size != 0U) {
EvrRtxMessageQueueError(NULL, osRtxErrorInvalidDataMemory);
return NULL;
}
}
} else {
name = NULL;
mq = NULL;
mq_mem = NULL;
}
// Allocate object memory if not provided
if (mq == NULL) {
if (osRtxInfo.mpi.message_queue != NULL) {
mq = osRtxMemoryPoolAlloc(osRtxInfo.mpi.message_queue);
} else {
mq = osRtxMemoryAlloc(osRtxInfo.mem.common, sizeof(os_message_queue_t), 1U);
}
if (mq == NULL) {
EvrRtxMessageQueueError(NULL, osErrorNoMemory);
return NULL;
}
flags = osRtxFlagSystemObject;
} else {
flags = 0U;
}
// Allocate data memory if not provided
if (mq_mem == NULL) {
mq_mem = osRtxMemoryAlloc(osRtxInfo.mem.mq_data, size, 0U);
if (mq_mem == NULL) {
EvrRtxMessageQueueError(NULL, osErrorNoMemory);
if (flags & osRtxFlagSystemObject) {
if (osRtxInfo.mpi.message_queue != NULL) {
osRtxMemoryPoolFree(osRtxInfo.mpi.message_queue, mq);
} else {
osRtxMemoryFree(osRtxInfo.mem.common, mq);
}
}
return NULL;
}
memset(mq_mem, 0, size);
flags |= osRtxFlagSystemMemory;
}
// Initialize control block
mq->id = osRtxIdMessageQueue;
mq->state = osRtxObjectActive;
mq->flags = flags;
mq->name = name;
mq->thread_list = NULL;
mq->msg_size = msg_size;
mq->msg_count = 0U;
mq->msg_first = NULL;
mq->msg_last = NULL;
osRtxMemoryPoolInit(&mq->mp_info, msg_count, block_size, mq_mem);
// Register post ISR processing function
osRtxInfo.post_process.message_queue = osRtxMessageQueuePostProcess;
EvrRtxMessageQueueCreated(mq);
return mq;
}
/// Get name of a Message Queue object.
/// \note API identical to osMessageQueueGetName
const char *svcRtxMessageQueueGetName (osMessageQueueId_t mq_id) {
os_message_queue_t *mq = (os_message_queue_t *)mq_id;
// Check parameters
if ((mq == NULL) || (mq->id != osRtxIdMessageQueue)) {
EvrRtxMessageQueueGetName(mq, NULL);
return NULL;
}
// Check object state
if (mq->state == osRtxObjectInactive) {
EvrRtxMessageQueueGetName(mq, NULL);
return NULL;
}
EvrRtxMessageQueueGetName(mq, mq->name);
return mq->name;
}
/// Put a Message into a Queue or timeout if Queue is full.
/// \note API identical to osMessageQueuePut
osStatus_t svcRtxMessageQueuePut (osMessageQueueId_t mq_id, const void *msg_ptr, uint8_t msg_prio, uint32_t timeout) {
os_message_queue_t *mq = (os_message_queue_t *)mq_id;
os_message_t *msg;
os_thread_t *thread;
uint32_t *reg;
// Check parameters
if ((mq == NULL) || (mq->id != osRtxIdMessageQueue) || (msg_ptr == NULL)) {
EvrRtxMessageQueueError(mq, osErrorParameter);
return osErrorParameter;
}
// Check object state
if (mq->state == osRtxObjectInactive) {
EvrRtxMessageQueueError(mq, osErrorResource);
return osErrorResource;
}
// Check if Thread is waiting to receive a Message
if ((mq->thread_list != NULL) && (mq->thread_list->state == osRtxThreadWaitingMessageGet)) {
EvrRtxMessageQueueInserted(mq, msg_ptr);
// Wakeup waiting Thread with highest Priority
thread = osRtxThreadListGet((os_object_t*)mq);
osRtxThreadWaitExit(thread, (uint32_t)osOK, true);
// Copy Message (R2: void *msg_ptr, R3: uint8_t *msg_prio)
reg = osRtxThreadRegPtr(thread);
memcpy((void *)reg[2], msg_ptr, mq->msg_size);
if (reg[3] != 0U) {
*((uint8_t *)reg[3]) = msg_prio;
}
EvrRtxMessageQueueRetrieved(mq, (void *)reg[2]);
return osOK;
}
// Try to allocate memory
msg = osRtxMemoryPoolAlloc(&mq->mp_info);
if (msg != NULL) {
// Copy Message
memcpy((uint8_t *)msg + sizeof(os_message_t), msg_ptr, mq->msg_size);
// Put Message into Queue
msg->id = osRtxIdMessage;
msg->state = osRtxObjectActive;
msg->flags = 0U;
msg->priority = msg_prio;
MessageQueuePut(mq, msg);
} else {
// No memory available
if (timeout != 0U) {
EvrRtxMessageQueuePutPending(mq, msg_ptr, timeout);
// Suspend current Thread
osRtxThreadListPut((os_object_t*)mq, osRtxThreadGetRunning());
osRtxThreadWaitEnter(osRtxThreadWaitingMessagePut, timeout);
// Save arguments (R2: const void *msg_ptr, R3: uint8_t msg_prio)
reg = (uint32_t *)(__get_PSP());
reg[2] = (uint32_t)msg_ptr;
reg[3] = (uint32_t)msg_prio;
return osErrorTimeout;
} else {
EvrRtxMessageQueueNotInserted(mq, msg_ptr);
return osErrorResource;
}
}
EvrRtxMessageQueueInserted(mq, msg_ptr);
return osOK;
}
/// Get a Message from a Queue or timeout if Queue is empty.
/// \note API identical to osMessageQueueGet
osStatus_t svcRtxMessageQueueGet (osMessageQueueId_t mq_id, void *msg_ptr, uint8_t *msg_prio, uint32_t timeout) {
os_message_queue_t *mq = (os_message_queue_t *)mq_id;
os_message_t *msg;
os_thread_t *thread;
uint32_t *reg;
// Check parameters
if ((mq == NULL) || (mq->id != osRtxIdMessageQueue) || (msg_ptr == NULL)) {
EvrRtxMessageQueueError(mq, osErrorParameter);
return osErrorParameter;
}
// Check object state
if (mq->state == osRtxObjectInactive) {
EvrRtxMessageQueueError(mq, osErrorResource);
return osErrorResource;
}
// Get Message from Queue
msg = MessageQueueGet(mq);
if (msg != NULL) {
MessageQueueRemove(mq, msg);
// Copy Message
memcpy(msg_ptr, (uint8_t *)msg + sizeof(os_message_t), mq->msg_size);
if (msg_prio != NULL) {
*msg_prio = msg->priority;
}
EvrRtxMessageQueueRetrieved(mq, msg_ptr);
// Free memory
msg->state = osRtxObjectInactive;
osRtxMemoryPoolFree(&mq->mp_info, msg);
} else {
// No Message available
if (timeout != 0U) {
EvrRtxMessageQueueGetPending(mq, msg_ptr, timeout);
// Suspend current Thread
osRtxThreadListPut((os_object_t*)mq, osRtxThreadGetRunning());
osRtxThreadWaitEnter(osRtxThreadWaitingMessageGet, timeout);
// Save arguments (R2: void *msg_ptr, R3: uint8_t *msg_prio)
reg = (uint32_t *)(__get_PSP());
reg[2] = (uint32_t)msg_ptr;
reg[3] = (uint32_t)msg_prio;
return osErrorTimeout;
} else {
EvrRtxMessageQueueNotRetrieved(mq, msg_ptr);
return osErrorResource;
}
}
// Check if Thread is waiting to send a Message
if ((mq->thread_list != NULL) && (mq->thread_list->state == osRtxThreadWaitingMessagePut)) {
// Try to allocate memory
msg = osRtxMemoryPoolAlloc(&mq->mp_info);
if (msg != NULL) {
// Wakeup waiting Thread with highest Priority
thread = osRtxThreadListGet((os_object_t*)mq);
osRtxThreadWaitExit(thread, (uint32_t)osOK, true);
// Copy Message (R2: const void *msg_ptr, R3: uint8_t msg_prio)
reg = osRtxThreadRegPtr(thread);
memcpy((uint8_t *)msg + sizeof(os_message_t), (void *)reg[2], mq->msg_size);
// Store Message into Queue
msg->id = osRtxIdMessage;
msg->state = osRtxObjectActive;
msg->flags = 0U;
msg->priority = (uint8_t)reg[3];
MessageQueuePut(mq, msg);
EvrRtxMessageQueueInserted(mq, (void *)reg[2]);
}
}
return osOK;
}
/// Get maximum number of messages in a Message Queue.
/// \note API identical to osMessageGetCapacity
uint32_t svcRtxMessageQueueGetCapacity (osMessageQueueId_t mq_id) {
os_message_queue_t *mq = (os_message_queue_t *)mq_id;
// Check parameters
if ((mq == NULL) || (mq->id != osRtxIdMessageQueue)) {
EvrRtxMessageQueueGetCapacity(mq, 0U);
return 0U;
}
// Check object state
if (mq->state == osRtxObjectInactive) {
EvrRtxMessageQueueGetCapacity(mq, 0U);
return 0U;
}
EvrRtxMessageQueueGetCapacity(mq, mq->mp_info.max_blocks);
return mq->mp_info.max_blocks;
}
/// Get maximum message size in a Memory Pool.
/// \note API identical to osMessageGetMsgSize
uint32_t svcRtxMessageQueueGetMsgSize (osMessageQueueId_t mq_id) {
os_message_queue_t *mq = (os_message_queue_t *)mq_id;
// Check parameters
if ((mq == NULL) || (mq->id != osRtxIdMessageQueue)) {
EvrRtxMessageQueueGetMsgSize(mq, 0U);
return 0U;
}
// Check object state
if (mq->state == osRtxObjectInactive) {
EvrRtxMessageQueueGetMsgSize(mq, 0U);
return 0U;
}
EvrRtxMessageQueueGetMsgSize(mq, mq->msg_size);
return mq->msg_size;
}
/// Get number of queued messages in a Message Queue.
/// \note API identical to osMessageGetCount
uint32_t svcRtxMessageQueueGetCount (osMessageQueueId_t mq_id) {
os_message_queue_t *mq = (os_message_queue_t *)mq_id;
// Check parameters
if ((mq == NULL) || (mq->id != osRtxIdMessageQueue)) {
EvrRtxMessageQueueGetCount(mq, 0U);
return 0U;
}
// Check object state
if (mq->state == osRtxObjectInactive) {
EvrRtxMessageQueueGetCount(mq, 0U);
return 0U;
}
EvrRtxMessageQueueGetCount(mq, mq->msg_count);
return mq->msg_count;
}
/// Get number of available slots for messages in a Message Queue.
/// \note API identical to osMessageGetSpace
uint32_t svcRtxMessageQueueGetSpace (osMessageQueueId_t mq_id) {
os_message_queue_t *mq = (os_message_queue_t *)mq_id;
// Check parameters
if ((mq == NULL) || (mq->id != osRtxIdMessageQueue)) {
EvrRtxMessageQueueGetSpace(mq, 0U);
return 0U;
}
// Check object state
if (mq->state == osRtxObjectInactive) {
EvrRtxMessageQueueGetSpace(mq, 0U);
return 0U;
}
EvrRtxMessageQueueGetSpace(mq, mq->mp_info.max_blocks - mq->msg_count);
return (mq->mp_info.max_blocks - mq->msg_count);
}
/// Reset a Message Queue to initial empty state.
/// \note API identical to osMessageQueueReset
osStatus_t svcRtxMessageQueueReset (osMessageQueueId_t mq_id) {
os_message_queue_t *mq = (os_message_queue_t *)mq_id;
os_message_t *msg;
os_thread_t *thread;
uint32_t *reg;
// Check parameters
if ((mq == NULL) || (mq->id != osRtxIdMessageQueue)) {
EvrRtxMessageQueueError(mq, osErrorParameter);
return osErrorParameter;
}
// Check object state
if (mq->state == osRtxObjectInactive) {
EvrRtxMessageQueueError(mq, osErrorResource);
return osErrorResource;
}
// Remove Messages from Queue
for (;;) {
// Get Message from Queue
msg = MessageQueueGet(mq);
if (msg == NULL) {
break;
}
MessageQueueRemove(mq, msg);
EvrRtxMessageQueueRetrieved(mq, NULL);
// Free memory
msg->state = osRtxObjectInactive;
osRtxMemoryPoolFree(&mq->mp_info, msg);
}
// Check if Threads are waiting to send Messages
if ((mq->thread_list != NULL) && (mq->thread_list->state == osRtxThreadWaitingMessagePut)) {
do {
// Try to allocate memory
msg = osRtxMemoryPoolAlloc(&mq->mp_info);
if (msg != NULL) {
// Wakeup waiting Thread with highest Priority
thread = osRtxThreadListGet((os_object_t*)mq);
osRtxThreadWaitExit(thread, (uint32_t)osOK, false);
// Copy Message (R2: const void *msg_ptr, R3: uint8_t msg_prio)
reg = osRtxThreadRegPtr(thread);
memcpy((uint8_t *)msg + sizeof(os_message_t), (void *)reg[2], mq->msg_size);
// Store Message into Queue
msg->id = osRtxIdMessage;
msg->state = osRtxObjectActive;
msg->flags = 0U;
msg->priority = (uint8_t)reg[3];
MessageQueuePut(mq, msg);
EvrRtxMessageQueueInserted(mq, (void *)reg[2]);
}
} while ((msg != NULL) && (mq->thread_list != NULL));
osRtxThreadDispatch(NULL);
}
EvrRtxMessageQueueResetDone(mq);
return osOK;
}
/// Delete a Message Queue object.
/// \note API identical to osMessageQueueDelete
osStatus_t svcRtxMessageQueueDelete (osMessageQueueId_t mq_id) {
os_message_queue_t *mq = (os_message_queue_t *)mq_id;
os_thread_t *thread;
// Check parameters
if ((mq == NULL) || (mq->id != osRtxIdMessageQueue)) {
EvrRtxMessageQueueError(mq, osErrorParameter);
return osErrorParameter;
}
// Check object state
if (mq->state == osRtxObjectInactive) {
EvrRtxMessageQueueError(mq, osErrorResource);
return osErrorResource;
}
// Mark object as inactive
mq->state = osRtxObjectInactive;
// Unblock waiting threads
if (mq->thread_list != NULL) {
do {
thread = osRtxThreadListGet((os_object_t*)mq);
osRtxThreadWaitExit(thread, (uint32_t)osErrorResource, false);
} while (mq->thread_list != NULL);
osRtxThreadDispatch(NULL);
}
// Free data memory
if (mq->flags & osRtxFlagSystemMemory) {
osRtxMemoryFree(osRtxInfo.mem.mq_data, mq->mp_info.block_base);
}
// Free object memory
if (mq->flags & osRtxFlagSystemObject) {
if (osRtxInfo.mpi.message_queue != NULL) {
osRtxMemoryPoolFree(osRtxInfo.mpi.message_queue, mq);
} else {
osRtxMemoryFree(osRtxInfo.mem.common, mq);
}
}
EvrRtxMessageQueueDestroyed(mq);
return osOK;
}
// ==== ISR Calls ====
/// Put a Message into a Queue or timeout if Queue is full.
/// \note API identical to osMessageQueuePut
__STATIC_INLINE
osStatus_t isrRtxMessageQueuePut (osMessageQueueId_t mq_id, const void *msg_ptr, uint8_t msg_prio, uint32_t timeout) {
os_message_queue_t *mq = (os_message_queue_t *)mq_id;
os_message_t *msg;
const void **ptr;
// Check parameters
if ((mq == NULL) || (mq->id != osRtxIdMessageQueue) || (msg_ptr == NULL) || (timeout != 0U)) {
EvrRtxMessageQueueError(mq, osErrorParameter);
return osErrorParameter;
}
// Check object state
if (mq->state == osRtxObjectInactive) {
EvrRtxMessageQueueError(mq, osErrorResource);
return osErrorResource;
}
// Try to allocate memory
msg = osRtxMemoryPoolAlloc(&mq->mp_info);
if (msg != NULL) {
// Copy Message
memcpy((uint8_t *)msg + sizeof(os_message_t), msg_ptr, mq->msg_size);
msg->id = osRtxIdMessage;
msg->state = osRtxObjectActive;
msg->flags = 0U;
msg->priority = msg_prio;
// Register post ISR processing
ptr = (void *)&msg->prev;
*ptr = msg_ptr;
ptr = (void *)&msg->next;
*ptr = mq;
osRtxPostProcess((os_object_t *)msg);
} else {
// No memory available
EvrRtxMessageQueueNotInserted(mq, msg_ptr);
return osErrorResource;
}
EvrRtxMessageQueueInsertPending(mq, msg_ptr);
return osOK;
}
/// Get a Message from a Queue or timeout if Queue is empty.
/// \note API identical to osMessageQueueGet
__STATIC_INLINE
osStatus_t isrRtxMessageQueueGet (osMessageQueueId_t mq_id, void *msg_ptr, uint8_t *msg_prio, uint32_t timeout) {
os_message_queue_t *mq = (os_message_queue_t *)mq_id;
os_message_t *msg;
void **ptr;
// Check parameters
if ((mq == NULL) || (mq->id != osRtxIdMessageQueue) || (msg_ptr == NULL) || (timeout != 0U)) {
EvrRtxMessageQueueError(mq, osErrorParameter);
return osErrorParameter;
}
// Check object state
if (mq->state == osRtxObjectInactive) {
EvrRtxMessageQueueError(mq, osErrorResource);
return osErrorResource;
}
// Get Message from Queue
msg = MessageQueueGet(mq);
if (msg != NULL) {
// Copy Message
memcpy(msg_ptr, (uint8_t *)msg + sizeof(os_message_t), mq->msg_size);
if (msg_prio != NULL) {
*msg_prio = msg->priority;
}
EvrRtxMessageQueueRetrieved(mq, msg_ptr);
// Register post ISR processing
ptr = (void *)((uint8_t *)msg + sizeof(os_message_t));
*ptr = mq;
osRtxPostProcess((os_object_t *)msg);
} else {
// No Message available
EvrRtxMessageQueueNotRetrieved(mq, msg_ptr);
return osErrorResource;
}
return osOK;
}
// ==== Public API ====
/// Create and Initialize a Message Queue object.
osMessageQueueId_t osMessageQueueNew (uint32_t msg_count, uint32_t msg_size, const osMessageQueueAttr_t *attr) {
EvrRtxMessageQueueNew(msg_count, msg_size, attr);
if (IS_IRQ_MODE() || IS_IRQ_MASKED()) {
EvrRtxMessageQueueError(NULL, osErrorISR);
return NULL;
}
return __svcMessageQueueNew(msg_count, msg_size, attr);
}
/// Get name of a Message Queue object.
const char *osMessageQueueGetName (osMessageQueueId_t mq_id) {
if (IS_IRQ_MODE() || IS_IRQ_MASKED()) {
EvrRtxMessageQueueGetName(mq_id, NULL);
return NULL;
}
return __svcMessageQueueGetName(mq_id);
}
/// Put a Message into a Queue or timeout if Queue is full.
osStatus_t osMessageQueuePut (osMessageQueueId_t mq_id, const void *msg_ptr, uint8_t msg_prio, uint32_t timeout) {
EvrRtxMessageQueuePut(mq_id, msg_ptr, msg_prio, timeout);
if (IS_IRQ_MODE() || IS_IRQ_MASKED()) {
return isrRtxMessageQueuePut(mq_id, msg_ptr, msg_prio, timeout);
} else {
return __svcMessageQueuePut(mq_id, msg_ptr, msg_prio, timeout);
}
}
/// Get a Message from a Queue or timeout if Queue is empty.
osStatus_t osMessageQueueGet (osMessageQueueId_t mq_id, void *msg_ptr, uint8_t *msg_prio, uint32_t timeout) {
EvrRtxMessageQueueGet(mq_id, msg_ptr, msg_prio, timeout);
if (IS_IRQ_MODE() || IS_IRQ_MASKED()) {
return isrRtxMessageQueueGet(mq_id, msg_ptr, msg_prio, timeout);
} else {
return __svcMessageQueueGet(mq_id, msg_ptr, msg_prio, timeout);
}
}
/// Get maximum number of messages in a Message Queue.
uint32_t osMessageQueueGetCapacity (osMessageQueueId_t mq_id) {
if (IS_IRQ_MODE() || IS_IRQ_MASKED()) {
return svcRtxMessageQueueGetCapacity(mq_id);
} else {
return __svcMessageQueueGetCapacity(mq_id);
}
}
/// Get maximum message size in a Memory Pool.
uint32_t osMessageQueueGetMsgSize (osMessageQueueId_t mq_id) {
if (IS_IRQ_MODE() || IS_IRQ_MASKED()) {
return svcRtxMessageQueueGetMsgSize(mq_id);
} else {
return __svcMessageQueueGetMsgSize(mq_id);
}
}
/// Get number of queued messages in a Message Queue.
uint32_t osMessageQueueGetCount (osMessageQueueId_t mq_id) {
if (IS_IRQ_MODE() || IS_IRQ_MASKED()) {
return svcRtxMessageQueueGetCount(mq_id);
} else {
return __svcMessageQueueGetCount(mq_id);
}
}
/// Get number of available slots for messages in a Message Queue.
uint32_t osMessageQueueGetSpace (osMessageQueueId_t mq_id) {
if (IS_IRQ_MODE() || IS_IRQ_MASKED()) {
return svcRtxMessageQueueGetSpace(mq_id);
} else {
return __svcMessageQueueGetSpace(mq_id);
}
}
/// Reset a Message Queue to initial empty state.
osStatus_t osMessageQueueReset (osMessageQueueId_t mq_id) {
EvrRtxMessageQueueReset(mq_id);
if (IS_IRQ_MODE() || IS_IRQ_MASKED()) {
EvrRtxMessageQueueError(mq_id, osErrorISR);
return osErrorISR;
}
return __svcMessageQueueReset(mq_id);
}
/// Delete a Message Queue object.
osStatus_t osMessageQueueDelete (osMessageQueueId_t mq_id) {
EvrRtxMessageQueueDelete(mq_id);
if (IS_IRQ_MODE() || IS_IRQ_MASKED()) {
EvrRtxMessageQueueError(mq_id, osErrorISR);
return osErrorISR;
}
return __svcMessageQueueDelete(mq_id);
}

View File

@ -0,0 +1,491 @@
/*
* Copyright (c) 2013-2017 ARM Limited. All rights reserved.
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the License); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an AS IS BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* -----------------------------------------------------------------------------
*
* Project: CMSIS-RTOS RTX
* Title: Mutex functions
*
* -----------------------------------------------------------------------------
*/
#include "rtx_lib.h"
// ==== Library functions ====
/// Release Mutex list when owner Thread terminates.
/// \param[in] mutex mutex object.
/// \return 1 - success, 0 - failure.
void osRtxMutexOwnerRelease (os_mutex_t *mutex_list) {
os_mutex_t *mutex;
os_thread_t *thread;
mutex = mutex_list;
while (mutex) {
mutex_list = mutex->owner_next;
// Check if Mutex is Robust
if (mutex->attr & osMutexRobust) {
// Clear Lock counter
mutex->lock = 0U;
EvrRtxMutexReleased(mutex, 0U);
// Check if Thread is waiting for a Mutex
if (mutex->thread_list != NULL) {
// Wakeup waiting Thread with highest Priority
thread = osRtxThreadListGet((os_object_t*)mutex);
osRtxThreadWaitExit(thread, (uint32_t)osOK, false);
// Thread is the new Mutex owner
mutex->owner_thread = thread;
mutex->owner_next = thread->mutex_list;
mutex->owner_prev = NULL;
thread->mutex_list = mutex;
mutex->lock = 1U;
EvrRtxMutexAcquired(mutex, 1U);
}
}
mutex = mutex_list;
}
}
// ==== Service Calls ====
// Service Calls definitions
SVC0_1M(MutexNew, osMutexId_t, const osMutexAttr_t *)
SVC0_1 (MutexGetName, const char *, osMutexId_t)
SVC0_2 (MutexAcquire, osStatus_t, osMutexId_t, uint32_t)
SVC0_1 (MutexRelease, osStatus_t, osMutexId_t)
SVC0_1 (MutexGetOwner, osThreadId_t, osMutexId_t)
SVC0_1 (MutexDelete, osStatus_t, osMutexId_t)
/// Create and Initialize a Mutex object.
/// \note API identical to osMutexNew
osMutexId_t svcRtxMutexNew (const osMutexAttr_t *attr) {
os_mutex_t *mutex;
uint32_t attr_bits;
uint8_t flags;
const char *name;
// Process attributes
if (attr != NULL) {
name = attr->name;
attr_bits = attr->attr_bits;
mutex = attr->cb_mem;
if (mutex != NULL) {
if (((uint32_t)mutex & 3U) || (attr->cb_size < sizeof(os_mutex_t))) {
EvrRtxMutexError(NULL, osRtxErrorInvalidControlBlock);
return NULL;
}
} else {
if (attr->cb_size != 0U) {
EvrRtxMutexError(NULL, osRtxErrorInvalidControlBlock);
return NULL;
}
}
} else {
name = NULL;
attr_bits = 0U;
mutex = NULL;
}
// Allocate object memory if not provided
if (mutex == NULL) {
if (osRtxInfo.mpi.mutex != NULL) {
mutex = osRtxMemoryPoolAlloc(osRtxInfo.mpi.mutex);
} else {
mutex = osRtxMemoryAlloc(osRtxInfo.mem.common, sizeof(os_mutex_t), 1U);
}
if (mutex == NULL) {
EvrRtxMutexError(NULL, osErrorNoMemory);
return NULL;
}
flags = osRtxFlagSystemObject;
} else {
flags = 0U;
}
// Initialize control block
mutex->id = osRtxIdMutex;
mutex->state = osRtxObjectActive;
mutex->flags = flags;
mutex->attr = (uint8_t)attr_bits;
mutex->name = name;
mutex->thread_list = NULL;
mutex->owner_thread = NULL;
mutex->owner_prev = NULL;
mutex->owner_next = NULL;
mutex->lock = 0U;
EvrRtxMutexCreated(mutex);
return mutex;
}
/// Get name of a Mutex object.
/// \note API identical to osMutexGetName
const char *svcRtxMutexGetName (osMutexId_t mutex_id) {
os_mutex_t *mutex = (os_mutex_t *)mutex_id;
// Check parameters
if ((mutex == NULL) || (mutex->id != osRtxIdMutex)) {
EvrRtxMutexGetName(mutex, NULL);
return NULL;
}
// Check object state
if (mutex->state == osRtxObjectInactive) {
EvrRtxMutexGetName(mutex, NULL);
return NULL;
}
EvrRtxMutexGetName(mutex, mutex->name);
return mutex->name;
}
/// Acquire a Mutex or timeout if it is locked.
/// \note API identical to osMutexAcquire
osStatus_t svcRtxMutexAcquire (osMutexId_t mutex_id, uint32_t timeout) {
os_mutex_t *mutex = (os_mutex_t *)mutex_id;
os_thread_t *runnig_thread;
runnig_thread = osRtxThreadGetRunning();
if (runnig_thread == NULL) {
EvrRtxMutexError(mutex, osRtxErrorKernelNotRunning);
return osError;
}
// Check parameters
if ((mutex == NULL) || (mutex->id != osRtxIdMutex)) {
EvrRtxMutexError(mutex, osErrorParameter);
return osErrorParameter;
}
// Check object state
if (mutex->state == osRtxObjectInactive) {
EvrRtxMutexError(mutex, osErrorResource);
return osErrorResource;
}
// Check if Mutex is not locked
if (mutex->lock == 0U) {
// Acquire Mutex
mutex->owner_thread = runnig_thread;
mutex->owner_next = runnig_thread->mutex_list;
mutex->owner_prev = NULL;
runnig_thread->mutex_list = mutex;
mutex->lock = 1U;
EvrRtxMutexAcquired(mutex, mutex->lock);
return osOK;
}
// Check if Mutex is recursive and running Thread is the owner
if ((mutex->attr & osMutexRecursive) && (mutex->owner_thread == runnig_thread)) {
// Increment lock counter
if (mutex->lock == osRtxMutexLockLimit) {
EvrRtxMutexError(mutex, osRtxErrorMutexLockLimit);
return osErrorResource;
}
mutex->lock++;
EvrRtxMutexAcquired(mutex, mutex->lock);
return osOK;
}
// Check if timeout is specified
if (timeout != 0U) {
// Check if Priority inheritance protocol is enabled
if (mutex->attr & osMutexPrioInherit) {
// Raise priority of owner Thread if lower than priority of running Thread
if (mutex->owner_thread->priority < runnig_thread->priority) {
mutex->owner_thread->priority = runnig_thread->priority;
osRtxThreadListSort(mutex->owner_thread);
}
}
EvrRtxMutexAcquirePending(mutex, timeout);
// Suspend current Thread
osRtxThreadListPut((os_object_t*)mutex, runnig_thread);
osRtxThreadWaitEnter(osRtxThreadWaitingMutex, timeout);
return osErrorTimeout;
}
// Mutex was not acquired
EvrRtxMutexNotAcquired(mutex);
return osErrorResource;
}
/// Release a Mutex that was acquired by osMutexAcquire.
/// \note API identical to osMutexRelease
osStatus_t svcRtxMutexRelease (osMutexId_t mutex_id) {
os_mutex_t *mutex = (os_mutex_t *)mutex_id;
os_mutex_t *mutex0;
os_thread_t *thread;
os_thread_t *runnig_thread;
int8_t priority;
runnig_thread = osRtxThreadGetRunning();
if (runnig_thread == NULL) {
EvrRtxMutexError(mutex, osRtxErrorKernelNotRunning);
return osError;
}
// Check parameters
if ((mutex == NULL) || (mutex->id != osRtxIdMutex)) {
EvrRtxMutexError(mutex, osErrorParameter);
return osErrorParameter;
}
// Check object state
if (mutex->state == osRtxObjectInactive) {
EvrRtxMutexError(mutex, osErrorResource);
return osErrorResource;
}
// Check if running Thread is not the owner
if (mutex->owner_thread != runnig_thread) {
EvrRtxMutexError(mutex, osRtxErrorMutexNotOwned);
return osErrorResource;
}
// Check if Mutex is not locked
if (mutex->lock == 0U) {
EvrRtxMutexError(mutex, osRtxErrorMutexNotLocked);
return osErrorResource;
}
// Decrement Lock counter
mutex->lock--;
EvrRtxMutexReleased(mutex, mutex->lock);
// Check Lock counter
if (mutex->lock != 0U) {
return osOK;
}
// Remove Mutex from Thread owner list
if (mutex->owner_next != NULL) {
mutex->owner_next->owner_prev = mutex->owner_prev;
}
if (mutex->owner_prev != NULL) {
mutex->owner_prev->owner_next = mutex->owner_next;
} else {
runnig_thread->mutex_list = mutex->owner_next;
}
// Restore running Thread priority
if (mutex->attr & osMutexPrioInherit) {
priority = runnig_thread->priority_base;
mutex0 = runnig_thread->mutex_list;
while (mutex0) {
// Mutexes owned by running Thread
if ((mutex0->thread_list != NULL) && (mutex0->thread_list->priority > priority)) {
// Higher priority Thread is waiting for Mutex
priority = mutex0->thread_list->priority;
}
mutex0 = mutex0->owner_next;
}
runnig_thread->priority = priority;
}
// Check if Thread is waiting for a Mutex
if (mutex->thread_list != NULL) {
// Wakeup waiting Thread with highest Priority
thread = osRtxThreadListGet((os_object_t*)mutex);
osRtxThreadWaitExit(thread, (uint32_t)osOK, false);
// Thread is the new Mutex owner
mutex->owner_thread = thread;
mutex->owner_next = thread->mutex_list;
mutex->owner_prev = NULL;
thread->mutex_list = mutex;
mutex->lock = 1U;
EvrRtxMutexAcquired(mutex, 1U);
}
osRtxThreadDispatch(NULL);
return osOK;
}
/// Get Thread which owns a Mutex object.
/// \note API identical to osMutexGetOwner
osThreadId_t svcRtxMutexGetOwner (osMutexId_t mutex_id) {
os_mutex_t *mutex = (os_mutex_t *)mutex_id;
// Check parameters
if ((mutex == NULL) || (mutex->id != osRtxIdMutex)) {
EvrRtxMutexGetOwner(mutex, NULL);
return NULL;
}
// Check object state
if (mutex->state == osRtxObjectInactive) {
EvrRtxMutexGetOwner(mutex, NULL);
return NULL;
}
// Check if Mutex is not locked
if (mutex->lock == 0U) {
EvrRtxMutexGetOwner(mutex, NULL);
return NULL;
}
EvrRtxMutexGetOwner(mutex, mutex->owner_thread);
return mutex->owner_thread;
}
/// Delete a Mutex object.
/// \note API identical to osMutexDelete
osStatus_t svcRtxMutexDelete (osMutexId_t mutex_id) {
os_mutex_t *mutex = (os_mutex_t *)mutex_id;
os_mutex_t *mutex0;
os_thread_t *thread;
int8_t priority;
// Check parameters
if ((mutex == NULL) || (mutex->id != osRtxIdMutex)) {
EvrRtxMutexError(mutex, osErrorParameter);
return osErrorParameter;
}
// Check object state
if (mutex->state == osRtxObjectInactive) {
EvrRtxMutexError(mutex, osErrorResource);
return osErrorResource;
}
// Mark object as inactive
mutex->state = osRtxObjectInactive;
// Check if Mutex is locked
if (mutex->lock != 0U) {
thread = mutex->owner_thread;
// Remove Mutex from Thread owner list
if (mutex->owner_next != NULL) {
mutex->owner_next->owner_prev = mutex->owner_prev;
}
if (mutex->owner_prev != NULL) {
mutex->owner_prev->owner_next = mutex->owner_next;
} else {
thread->mutex_list = mutex->owner_next;
}
// Restore owner Thread priority
if (mutex->attr & osMutexPrioInherit) {
priority = thread->priority_base;
mutex0 = thread->mutex_list;
while (mutex0) {
// Mutexes owned by running Thread
if ((mutex0->thread_list != NULL) && (mutex0->thread_list->priority > priority)) {
// Higher priority Thread is waiting for Mutex
priority = mutex0->thread_list->priority;
}
mutex0 = mutex0->owner_next;
}
if (thread->priority != priority) {
thread->priority = priority;
osRtxThreadListSort(thread);
}
}
// Unblock waiting threads
if (mutex->thread_list != NULL) {
do {
thread = osRtxThreadListGet((os_object_t*)mutex);
osRtxThreadWaitExit(thread, (uint32_t)osErrorResource, false);
} while (mutex->thread_list != NULL);
}
osRtxThreadDispatch(NULL);
}
// Free object memory
if (mutex->flags & osRtxFlagSystemObject) {
if (osRtxInfo.mpi.mutex != NULL) {
osRtxMemoryPoolFree(osRtxInfo.mpi.mutex, mutex);
} else {
osRtxMemoryFree(osRtxInfo.mem.common, mutex);
}
}
EvrRtxMutexDestroyed(mutex);
return osOK;
}
// ==== Public API ====
/// Create and Initialize a Mutex object.
osMutexId_t osMutexNew (const osMutexAttr_t *attr) {
EvrRtxMutexNew(attr);
if (IS_IRQ_MODE() || IS_IRQ_MASKED()) {
EvrRtxMutexError(NULL, osErrorISR);
return NULL;
}
return __svcMutexNew(attr);
}
/// Get name of a Mutex object.
const char *osMutexGetName (osMutexId_t mutex_id) {
if (IS_IRQ_MODE() || IS_IRQ_MASKED()) {
EvrRtxMutexGetName(mutex_id, NULL);
return NULL;
}
return __svcMutexGetName(mutex_id);
}
/// Acquire a Mutex or timeout if it is locked.
osStatus_t osMutexAcquire (osMutexId_t mutex_id, uint32_t timeout) {
EvrRtxMutexAcquire(mutex_id, timeout);
if (IS_IRQ_MODE() || IS_IRQ_MASKED()) {
EvrRtxMutexError(mutex_id, osErrorISR);
return osErrorISR;
}
return __svcMutexAcquire(mutex_id, timeout);
}
/// Release a Mutex that was acquired by \ref osMutexAcquire.
osStatus_t osMutexRelease (osMutexId_t mutex_id) {
EvrRtxMutexRelease(mutex_id);
if (IS_IRQ_MODE() || IS_IRQ_MASKED()) {
EvrRtxMutexError(mutex_id, osErrorISR);
return osErrorISR;
}
return __svcMutexRelease(mutex_id);
}
/// Get Thread which owns a Mutex object.
osThreadId_t osMutexGetOwner (osMutexId_t mutex_id) {
if (IS_IRQ_MODE() || IS_IRQ_MASKED()) {
EvrRtxMutexGetOwner(mutex_id, NULL);
return NULL;
}
return __svcMutexGetOwner(mutex_id);
}
/// Delete a Mutex object.
osStatus_t osMutexDelete (osMutexId_t mutex_id) {
EvrRtxMutexDelete(mutex_id);
if (IS_IRQ_MODE() || IS_IRQ_MASKED()) {
EvrRtxMutexError(mutex_id, osErrorISR);
return osErrorISR;
}
return __svcMutexDelete(mutex_id);
}

View File

@ -0,0 +1,478 @@
/*
* Copyright (c) 2013-2017 ARM Limited. All rights reserved.
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the License); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an AS IS BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* -----------------------------------------------------------------------------
*
* Project: CMSIS-RTOS RTX
* Title: RTX OS definitions
*
* -----------------------------------------------------------------------------
*/
#ifndef RTX_OS_H_
#define RTX_OS_H_
#include <stdint.h>
#include <stddef.h>
#include "cmsis_os2.h"
#ifdef __cplusplus
extern "C"
{
#endif
/// Kernel Information
#define osRtxVersionAPI 20010000 ///< API version (2.1.0)
#define osRtxVersionKernel 50010001 ///< Kernel version (5.1.1)
#define osRtxKernelId "RTX V5.1.1" ///< Kernel identification string
// ==== Common definitions ====
/// Object Identifier definitions
#define osRtxIdInvalid 0x00U
#define osRtxIdThread 0x01U
#define osRtxIdTimer 0x02U
#define osRtxIdEventFlags 0x03U
#define osRtxIdMutex 0x04U
#define osRtxIdSemaphore 0x05U
#define osRtxIdMemoryPool 0x06U
#define osRtxIdMessage 0x07U
#define osRtxIdMessageQueue 0x08U
/// Object State definitions (except for Threads and Timers)
#define osRtxObjectInactive 0x00U
#define osRtxObjectActive 0x01U
/// Object Flags definitions
#define osRtxFlagSystemObject 0x01U
#define osRtxFlagSystemMemory 0x02U
// ==== Kernel definitions ====
/// Kernel State definitions
#define osRtxKernelInactive ((uint8_t)osKernelInactive)
#define osRtxKernelReady ((uint8_t)osKernelReady)
#define osRtxKernelRunning ((uint8_t)osKernelRunning)
#define osRtxKernelLocked ((uint8_t)osKernelLocked)
#define osRtxKernelSuspended ((uint8_t)osKernelSuspended)
// ==== Thread definitions ====
/// Thread State definitions (extending osThreadState)
#define osRtxThreadStateMask 0x0FU
#define osRtxThreadInactive ((uint8_t)osThreadInactive)
#define osRtxThreadReady ((uint8_t)osThreadReady)
#define osRtxThreadRunning ((uint8_t)osThreadRunning)
#define osRtxThreadBlocked ((uint8_t)osThreadBlocked)
#define osRtxThreadTerminated ((uint8_t)osThreadTerminated)
#define osRtxThreadWaitingDelay (osRtxThreadBlocked | 0x10U)
#define osRtxThreadWaitingJoin (osRtxThreadBlocked | 0x20U)
#define osRtxThreadWaitingThreadFlags (osRtxThreadBlocked | 0x30U)
#define osRtxThreadWaitingEventFlags (osRtxThreadBlocked | 0x40U)
#define osRtxThreadWaitingMutex (osRtxThreadBlocked | 0x50U)
#define osRtxThreadWaitingSemaphore (osRtxThreadBlocked | 0x60U)
#define osRtxThreadWaitingMemoryPool (osRtxThreadBlocked | 0x70U)
#define osRtxThreadWaitingMessageGet (osRtxThreadBlocked | 0x80U)
#define osRtxThreadWaitingMessagePut (osRtxThreadBlocked | 0x90U)
/// Thread Flags definitions
#define osRtxThreadFlagDefStack 0x10U ///< Default Stack flag
/// Stack Marker definitions
#define osRtxStackMagicWord 0xE25A2EA5U ///< Stack Magic Word (Stack Base)
#define osRtxStackFillPattern 0xCCCCCCCCU ///< Stack Fill Pattern
/// Thread Control Block
typedef struct osRtxThread_s {
uint8_t id; ///< Object Identifier
uint8_t state; ///< Object State
uint8_t flags; ///< Object Flags
uint8_t attr; ///< Object Attributes
const char *name; ///< Object Name
struct osRtxThread_s *thread_next; ///< Link pointer to next Thread in Object list
struct osRtxThread_s *thread_prev; ///< Link pointer to previous Thread in Object list
struct osRtxThread_s *delay_next; ///< Link pointer to next Thread in Delay list
struct osRtxThread_s *delay_prev; ///< Link pointer to previous Thread in Delay list
struct osRtxThread_s *thread_join; ///< Thread waiting to Join
uint32_t delay; ///< Delay Time
int8_t priority; ///< Thread Priority
int8_t priority_base; ///< Base Priority
uint8_t stack_frame; ///< Stack Frame (EXC_RETURN[7..0])
uint8_t flags_options; ///< Thread/Event Flags Options
uint32_t wait_flags; ///< Waiting Thread/Event Flags
uint32_t thread_flags; ///< Thread Flags
struct osRtxMutex_s *mutex_list; ///< Link pointer to list of owned Mutexes
void *stack_mem; ///< Stack Memory
uint32_t stack_size; ///< Stack Size
uint32_t sp; ///< Current Stack Pointer
uint32_t thread_addr; ///< Thread entry address
uint32_t tz_memory; ///< TrustZone Memory Identifier
} osRtxThread_t;
// ==== Timer definitions ====
/// Timer State definitions
#define osRtxTimerInactive 0x00U ///< Timer Inactive
#define osRtxTimerStopped 0x01U ///< Timer Stopped
#define osRtxTimerRunning 0x02U ///< Timer Running
/// Timer Type definitions
#define osRtxTimerPeriodic ((uint8_t)osTimerPeriodic)
/// Timer Function Information
typedef struct {
void *fp; ///< Function Pointer
void *arg; ///< Function Argument
} osRtxTimerFinfo_t;
/// Timer Control Block
typedef struct osRtxTimer_s {
uint8_t id; ///< Object Identifier
uint8_t state; ///< Object State
uint8_t flags; ///< Object Flags
uint8_t type; ///< Timer Type (Periodic/One-shot)
const char *name; ///< Object Name
struct osRtxTimer_s *prev; ///< Pointer to previous active Timer
struct osRtxTimer_s *next; ///< Pointer to next active Timer
uint32_t tick; ///< Timer current Tick
uint32_t load; ///< Timer Load value
osRtxTimerFinfo_t finfo; ///< Timer Function Info
} osRtxTimer_t;
// ==== Event Flags definitions ====
/// Event Flags Control Block
typedef struct osRtxEventFlags_s {
uint8_t id; ///< Object Identifier
uint8_t state; ///< Object State
uint8_t flags; ///< Object Flags
uint8_t reserved;
const char *name; ///< Object Name
osRtxThread_t *thread_list; ///< Waiting Threads List
uint32_t event_flags; ///< Event Flags
} osRtxEventFlags_t;
// ==== Mutex definitions ====
/// Mutex Control Block
typedef struct osRtxMutex_s {
uint8_t id; ///< Object Identifier
uint8_t state; ///< Object State
uint8_t flags; ///< Object Flags
uint8_t attr; ///< Object Attributes
const char *name; ///< Object Name
osRtxThread_t *thread_list; ///< Waiting Threads List
osRtxThread_t *owner_thread; ///< Owner Thread
struct osRtxMutex_s *owner_prev; ///< Pointer to previous owned Mutex
struct osRtxMutex_s *owner_next; ///< Pointer to next owned Mutex
uint8_t lock; ///< Lock counter
uint8_t padding[3];
} osRtxMutex_t;
// ==== Semaphore definitions ====
/// Semaphore Control Block
typedef struct osRtxSemaphore_s {
uint8_t id; ///< Object Identifier
uint8_t state; ///< Object State
uint8_t flags; ///< Object Flags
uint8_t reserved;
const char *name; ///< Object Name
osRtxThread_t *thread_list; ///< Waiting Threads List
uint16_t tokens; ///< Current number of tokens
uint16_t max_tokens; ///< Maximum number of tokens
} osRtxSemaphore_t;
// ==== Memory Pool definitions ====
/// Memory Pool Information
typedef struct osRtxMpInfo_s {
uint32_t max_blocks; ///< Maximum number of Blocks
uint32_t used_blocks; ///< Number of used Blocks
uint32_t block_size; ///< Block Size
void *block_base; ///< Block Memory Base Address
void *block_lim; ///< Block Memory Limit Address
void *block_free; ///< First free Block Address
} osRtxMpInfo_t;
/// Memory Pool Control Block
typedef struct osRtxMemoryPool_s {
uint8_t id; ///< Object Identifier
uint8_t state; ///< Object State
uint8_t flags; ///< Object Flags
uint8_t reserved;
const char *name; ///< Object Name
osRtxThread_t *thread_list; ///< Waiting Threads List
osRtxMpInfo_t mp_info; ///< Memory Pool Info
} osRtxMemoryPool_t;
// ==== Message Queue definitions ====
/// Message Control Block
typedef struct osRtxMessage_s {
uint8_t id; ///< Object Identifier
uint8_t state; ///< Object State
uint8_t flags; ///< Object Flags
uint8_t priority; ///< Message Priority
struct osRtxMessage_s *prev; ///< Pointer to previous Message
struct osRtxMessage_s *next; ///< Pointer to next Message
} osRtxMessage_t;
/// Message Queue Control Block
typedef struct osRtxMessageQueue_s {
uint8_t id; ///< Object Identifier
uint8_t state; ///< Object State
uint8_t flags; ///< Object Flags
uint8_t reserved;
const char *name; ///< Object Name
osRtxThread_t *thread_list; ///< Waiting Threads List
osRtxMpInfo_t mp_info; ///< Memory Pool Info
uint32_t msg_size; ///< Message Size
uint32_t msg_count; ///< Number of queued Messages
osRtxMessage_t *msg_first; ///< Pointer to first Message
osRtxMessage_t *msg_last; ///< Pointer to last Message
} osRtxMessageQueue_t;
// ==== Generic Object definitions ====
/// Generic Object Control Block
typedef struct osRtxObject_s {
uint8_t id; ///< Object Identifier
uint8_t state; ///< Object State
uint8_t flags; ///< Object Flags
uint8_t reserved;
const char *name; ///< Object Name
osRtxThread_t *thread_list; ///< Threads List
} osRtxObject_t;
// ==== OS Runtime Information definitions ====
/// OS Runtime Information structure
typedef struct {
const char *os_id; ///< OS Identification
uint32_t version; ///< OS Version
struct { ///< Kernel Info
uint8_t state; ///< State
volatile uint8_t blocked; ///< Blocked
uint8_t pendISR; ///< Pending ISR (SV and SysTick)
uint8_t pendSV; ///< Pending SV
uint32_t sys_freq; ///< System Frequency
uint64_t tick; ///< Tick counter
} kernel;
int32_t tick_irqn; ///< Tick Timer IRQ Number
struct { ///< Thread Info
struct { ///< Thread Run Info
osRtxThread_t *curr; ///< Current running Thread
osRtxThread_t *next; ///< Next Thread to Run
} run;
volatile osRtxObject_t ready; ///< Ready List Object
osRtxThread_t *idle; ///< Idle Thread
osRtxThread_t *delay_list; ///< Delay List
osRtxThread_t *wait_list; ///< Wait List (no Timeout)
osRtxThread_t *terminate_list; ///< Terminate Thread List
struct { ///< Thread Round Robin Info
osRtxThread_t *thread; ///< Round Robin Thread
uint32_t tick; ///< Round Robin Time Tick
uint32_t timeout; ///< Round Robin Timeout
} robin;
} thread;
struct { ///< Timer Info
osRtxTimer_t *list; ///< Active Timer List
osRtxThread_t *thread; ///< Timer Thread
osRtxMessageQueue_t *mq; ///< Timer Message Queue
void (*tick)(void); ///< Timer Tick Function
} timer;
struct { ///< ISR Post Processing Queue
uint16_t max; ///< Maximum Items
uint16_t cnt; ///< Item Count
uint16_t in; ///< Incoming Item Index
uint16_t out; ///< Outgoing Item Index
void **data; ///< Queue Data
} isr_queue;
struct { ///< ISR Post Processing functions
void (*thread)(osRtxThread_t*); ///< Thread Post Processing function
void (*event_flags)(osRtxEventFlags_t*); ///< Event Flags Post Processing function
void (*semaphore)(osRtxSemaphore_t*); ///< Semaphore Post Processing function
void (*memory_pool)(osRtxMemoryPool_t*); ///< Memory Pool Post Processing function
void (*message_queue)(osRtxMessage_t*); ///< Message Queue Post Processing function
} post_process;
struct { ///< Memory Pools (Variable Block Size)
void *stack; ///< Stack Memory
void *mp_data; ///< Memory Pool Data Memory
void *mq_data; ///< Message Queue Data Memory
void *common; ///< Common Memory
} mem;
struct { ///< Memory Pools (Fixed Block Size)
osRtxMpInfo_t *stack; ///< Stack for Threads
osRtxMpInfo_t *thread; ///< Thread Control Blocks
osRtxMpInfo_t *timer; ///< Timer Control Blocks
osRtxMpInfo_t *event_flags; ///< Event Flags Control Blocks
osRtxMpInfo_t *mutex; ///< Mutex Control Blocks
osRtxMpInfo_t *semaphore; ///< Semaphore Control Blocks
osRtxMpInfo_t *memory_pool; ///< Memory Pool Control Blocks
osRtxMpInfo_t *message_queue; ///< Message Queue Control Blocks
} mpi;
uint32_t padding;
} osRtxInfo_t;
extern osRtxInfo_t osRtxInfo; ///< OS Runtime Information
// ==== OS API definitions ====
/// Object Limits definitions
#define osRtxThreadFlagsLimit 31U ///< number of Thread Flags available per thread
#define osRtxEventFlagsLimit 31U ///< number of Event Flags available per object
#define osRtxMutexLockLimit 255U ///< maximum number of recursive mutex locks
#define osRtxSemaphoreTokenLimit 65535U ///< maximum number of tokens per semaphore
/// Control Block sizes
#define osRtxThreadCbSize sizeof(osRtxThread_t)
#define osRtxTimerCbSize sizeof(osRtxTimer_t)
#define osRtxEventFlagsCbSize sizeof(osRtxEventFlags_t)
#define osRtxMutexCbSize sizeof(osRtxMutex_t)
#define osRtxSemaphoreCbSize sizeof(osRtxSemaphore_t)
#define osRtxMemoryPoolCbSize sizeof(osRtxMemoryPool_t)
#define osRtxMessageQueueCbSize sizeof(osRtxMessageQueue_t)
/// Memory size in bytes for Memory Pool storage.
/// \param block_count maximum number of memory blocks in memory pool.
/// \param block_size memory block size in bytes.
#define osRtxMemoryPoolMemSize(block_count, block_size) \
(4*(block_count)*(((block_size)+3)/4))
/// Memory size in bytes for Message Queue storage.
/// \param msg_count maximum number of messages in queue.
/// \param msg_size maximum message size in bytes.
#define osRtxMessageQueueMemSize(msg_count, msg_size) \
(4*(msg_count)*(3+(((msg_size)+3)/4)))
// ==== OS External Functions ====
/// OS Error Codes
#define osRtxErrorStackUnderflow 1U
#define osRtxErrorISRQueueOverflow 2U
#define osRtxErrorTimerQueueOverflow 3U
#define osRtxErrorClibSpace 4U
#define osRtxErrorClibMutex 5U
/// OS Error Callback function
extern uint32_t osRtxErrorNotify (uint32_t code, void *object_id);
/// OS Idle Thread
extern void osRtxIdleThread (void *argument);
/// OS Exception handlers
extern void SVC_Handler (void);
extern void PendSV_Handler (void);
extern void SysTick_Handler (void);
/// OS System Timer functions (default implementation uses SysTick)
/// Setup System Timer.
/// \return system timer IRQ number.
extern int32_t osRtxSysTimerSetup (void);
/// Enable System Timer.
extern void osRtxSysTimerEnable (void);
/// Disable System Timer.
extern void osRtxSysTimerDisable (void);
/// Acknowledge System Timer IRQ.
extern void osRtxSysTimerAckIRQ (void);
/// Get System Timer count.
/// \return system timer count.
extern uint32_t osRtxSysTimerGetCount (void);
/// Get System Timer frequency.
/// \return system timer frequency.
extern uint32_t osRtxSysTimerGetFreq (void);
// ==== OS External Configuration ====
/// OS Configuration flags
#define osRtxConfigPrivilegedMode (1UL<<0) ///< Threads in Privileged mode
#define osRtxConfigStackCheck (1UL<<1) ///< Stack overrun checking
#define osRtxConfigStackWatermark (1UL<<2) ///< Stack usage Watermark
/// OS Configuration structure
typedef struct {
uint32_t flags; ///< OS Configuration Flags
uint32_t tick_freq; ///< Kernel Tick Frequency
uint32_t robin_timeout; ///< Round Robin Timeout Tick
struct { ///< ISR Post Processing Queue
void **data; ///< Queue Data
uint16_t max; ///< Maximum Items
uint16_t padding;
} isr_queue;
struct { ///< Memory Pools (Variable Block Size)
void *stack_addr; ///< Stack Memory Address
uint32_t stack_size; ///< Stack Memory Size
void *mp_data_addr; ///< Memory Pool Memory Address
uint32_t mp_data_size; ///< Memory Pool Memory Size
void *mq_data_addr; ///< Message Queue Data Memory Address
uint32_t mq_data_size; ///< Message Queue Data Memory Size
void *common_addr; ///< Common Memory Address
uint32_t common_size; ///< Common Memory Size
} mem;
struct { ///< Memory Pools (Fixed Block Size)
osRtxMpInfo_t *stack; ///< Stack for Threads
osRtxMpInfo_t *thread; ///< Thread Control Blocks
osRtxMpInfo_t *timer; ///< Timer Control Blocks
osRtxMpInfo_t *event_flags; ///< Event Flags Control Blocks
osRtxMpInfo_t *mutex; ///< Mutex Control Blocks
osRtxMpInfo_t *semaphore; ///< Semaphore Control Blocks
osRtxMpInfo_t *memory_pool; ///< Memory Pool Control Blocks
osRtxMpInfo_t *message_queue; ///< Message Queue Control Blocks
} mpi;
uint32_t thread_stack_size; ///< Default Thread Stack Size
const
osThreadAttr_t *idle_thread_attr; ///< Idle Thread Attributes
const
osThreadAttr_t *timer_thread_attr; ///< Timer Thread Attributes
const
osMessageQueueAttr_t *timer_mq_attr; ///< Timer Message Queue Attributes
uint32_t timer_mq_mcnt; ///< Timer Message Queue maximum Messages
} osRtxConfig_t;
extern const osRtxConfig_t osRtxConfig; ///< OS Configuration
#ifdef __cplusplus
}
#endif
#endif // RTX_OS_H_

View File

@ -0,0 +1,484 @@
/*
* Copyright (c) 2013-2017 ARM Limited. All rights reserved.
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the License); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an AS IS BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* -----------------------------------------------------------------------------
*
* Project: CMSIS-RTOS RTX
* Title: Semaphore functions
*
* -----------------------------------------------------------------------------
*/
#include "rtx_lib.h"
// ==== Helper functions ====
/// Decrement Semaphore tokens.
/// \param[in] semaphore semaphore object.
/// \return 1 - success, 0 - failure.
static uint32_t SemaphoreTokenDecrement (os_semaphore_t *semaphore) {
#if (__EXCLUSIVE_ACCESS == 0U)
uint32_t primask = __get_PRIMASK();
#endif
uint32_t ret;
#if (__EXCLUSIVE_ACCESS == 0U)
__disable_irq();
if (semaphore->tokens != 0U) {
semaphore->tokens--;
ret = 1U;
} else {
ret = 0U;
}
if (primask == 0U) {
__enable_irq();
}
#else
if (atomic_dec16_nz(&semaphore->tokens) != 0U) {
ret = 1U;
} else {
ret = 0U;
}
#endif
return ret;
}
/// Increment Semaphore tokens.
/// \param[in] semaphore semaphore object.
/// \return 1 - success, 0 - failure.
static uint32_t SemaphoreTokenIncrement (os_semaphore_t *semaphore) {
#if (__EXCLUSIVE_ACCESS == 0U)
uint32_t primask = __get_PRIMASK();
#endif
uint32_t ret;
#if (__EXCLUSIVE_ACCESS == 0U)
__disable_irq();
if (semaphore->tokens < semaphore->max_tokens) {
semaphore->tokens++;
ret = 1U;
} else {
ret = 0U;
}
if (primask == 0U) {
__enable_irq();
}
#else
if (atomic_inc16_lt(&semaphore->tokens, semaphore->max_tokens) < semaphore->max_tokens) {
ret = 1U;
} else {
ret = 0U;
}
#endif
return ret;
}
// ==== Library functions ====
/// Semaphore post ISR processing.
/// \param[in] semaphore semaphore object.
void osRtxSemaphorePostProcess (os_semaphore_t *semaphore) {
os_thread_t *thread;
if (semaphore->state == osRtxObjectInactive) {
return;
}
// Check if Thread is waiting for a token
if (semaphore->thread_list != NULL) {
// Try to acquire token
if (SemaphoreTokenDecrement(semaphore) != 0U) {
// Wakeup waiting Thread with highest Priority
thread = osRtxThreadListGet((os_object_t*)semaphore);
osRtxThreadWaitExit(thread, (uint32_t)osOK, false);
EvrRtxSemaphoreAcquired(semaphore);
}
}
}
// ==== Service Calls ====
// Service Calls definitions
SVC0_3M(SemaphoreNew, osSemaphoreId_t, uint32_t, uint32_t, const osSemaphoreAttr_t *)
SVC0_1 (SemaphoreGetName, const char *, osSemaphoreId_t)
SVC0_2 (SemaphoreAcquire, osStatus_t, osSemaphoreId_t, uint32_t)
SVC0_1 (SemaphoreRelease, osStatus_t, osSemaphoreId_t)
SVC0_1 (SemaphoreGetCount, uint32_t, osSemaphoreId_t)
SVC0_1 (SemaphoreDelete, osStatus_t, osSemaphoreId_t)
/// Create and Initialize a Semaphore object.
/// \note API identical to osSemaphoreNew
osSemaphoreId_t svcRtxSemaphoreNew (uint32_t max_count, uint32_t initial_count, const osSemaphoreAttr_t *attr) {
os_semaphore_t *semaphore;
uint8_t flags;
const char *name;
// Check parameters
if ((max_count == 0U) || (max_count > osRtxSemaphoreTokenLimit) || (initial_count > max_count)) {
EvrRtxSemaphoreError(NULL, osErrorParameter);
return NULL;
}
// Process attributes
if (attr != NULL) {
name = attr->name;
semaphore = attr->cb_mem;
if (semaphore != NULL) {
if (((uint32_t)semaphore & 3U) || (attr->cb_size < sizeof(os_semaphore_t))) {
EvrRtxSemaphoreError(NULL, osRtxErrorInvalidControlBlock);
return NULL;
}
} else {
if (attr->cb_size != 0U) {
EvrRtxSemaphoreError(NULL, osRtxErrorInvalidControlBlock);
return NULL;
}
}
} else {
name = NULL;
semaphore = NULL;
}
// Allocate object memory if not provided
if (semaphore == NULL) {
if (osRtxInfo.mpi.semaphore != NULL) {
semaphore = osRtxMemoryPoolAlloc(osRtxInfo.mpi.semaphore);
} else {
semaphore = osRtxMemoryAlloc(osRtxInfo.mem.common, sizeof(os_semaphore_t), 1U);
}
if (semaphore == NULL) {
EvrRtxSemaphoreError(NULL, osErrorNoMemory);
return NULL;
}
flags = osRtxFlagSystemObject;
} else {
flags = 0U;
}
// Initialize control block
semaphore->id = osRtxIdSemaphore;
semaphore->state = osRtxObjectActive;
semaphore->flags = flags;
semaphore->name = name;
semaphore->thread_list = NULL;
semaphore->tokens = (uint16_t)initial_count;
semaphore->max_tokens = (uint16_t)max_count;
// Register post ISR processing function
osRtxInfo.post_process.semaphore = osRtxSemaphorePostProcess;
EvrRtxSemaphoreCreated(semaphore);
return semaphore;
}
/// Get name of a Semaphore object.
/// \note API identical to osSemaphoreGetName
const char *svcRtxSemaphoreGetName (osSemaphoreId_t semaphore_id) {
os_semaphore_t *semaphore = (os_semaphore_t *)semaphore_id;
// Check parameters
if ((semaphore == NULL) || (semaphore->id != osRtxIdSemaphore)) {
EvrRtxSemaphoreGetName(semaphore, NULL);
return NULL;
}
// Check object state
if (semaphore->state == osRtxObjectInactive) {
EvrRtxSemaphoreGetName(semaphore, NULL);
return NULL;
}
EvrRtxSemaphoreGetName(semaphore, semaphore->name);
return semaphore->name;
}
/// Acquire a Semaphore token or timeout if no tokens are available.
/// \note API identical to osSemaphoreAcquire
osStatus_t svcRtxSemaphoreAcquire (osSemaphoreId_t semaphore_id, uint32_t timeout) {
os_semaphore_t *semaphore = (os_semaphore_t *)semaphore_id;
// Check parameters
if ((semaphore == NULL) || (semaphore->id != osRtxIdSemaphore)) {
EvrRtxSemaphoreError(semaphore, osErrorParameter);
return osErrorParameter;
}
// Check object state
if (semaphore->state == osRtxObjectInactive) {
EvrRtxSemaphoreError(semaphore, osErrorResource);
return osErrorResource;
}
// Try to acquire token
if (SemaphoreTokenDecrement(semaphore) == 0U) {
// No token available
if (timeout != 0U) {
EvrRtxSemaphoreAcquirePending(semaphore, timeout);
// Suspend current Thread
osRtxThreadListPut((os_object_t*)semaphore, osRtxThreadGetRunning());
osRtxThreadWaitEnter(osRtxThreadWaitingSemaphore, timeout);
return osErrorTimeout;
} else {
EvrRtxSemaphoreNotAcquired(semaphore);
return osErrorResource;
}
}
EvrRtxSemaphoreAcquired(semaphore);
return osOK;
}
/// Release a Semaphore token that was acquired by osSemaphoreAcquire.
/// \note API identical to osSemaphoreRelease
osStatus_t svcRtxSemaphoreRelease (osSemaphoreId_t semaphore_id) {
os_semaphore_t *semaphore = (os_semaphore_t *)semaphore_id;
os_thread_t *thread;
// Check parameters
if ((semaphore == NULL) || (semaphore->id != osRtxIdSemaphore)) {
EvrRtxSemaphoreError(semaphore, osErrorParameter);
return osErrorParameter;
}
// Check object state
if (semaphore->state == osRtxObjectInactive) {
EvrRtxSemaphoreError(semaphore, osErrorResource);
return osErrorResource;
}
// Check if Thread is waiting for a token
if (semaphore->thread_list != NULL) {
EvrRtxSemaphoreReleased(semaphore);
// Wakeup waiting Thread with highest Priority
thread = osRtxThreadListGet((os_object_t*)semaphore);
osRtxThreadWaitExit(thread, (uint32_t)osOK, true);
EvrRtxSemaphoreAcquired(semaphore);
} else {
// Try to release token
if (SemaphoreTokenIncrement(semaphore) == 0U) {
EvrRtxSemaphoreError(semaphore, osRtxErrorSemaphoreCountLimit);
return osErrorResource;
}
EvrRtxSemaphoreReleased(semaphore);
}
return osOK;
}
/// Get current Semaphore token count.
/// \note API identical to osSemaphoreGetCount
uint32_t svcRtxSemaphoreGetCount (osSemaphoreId_t semaphore_id) {
os_semaphore_t *semaphore = (os_semaphore_t *)semaphore_id;
// Check parameters
if ((semaphore == NULL) || (semaphore->id != osRtxIdSemaphore)) {
EvrRtxSemaphoreGetCount(semaphore, 0U);
return 0U;
}
// Check object state
if (semaphore->state == osRtxObjectInactive) {
EvrRtxSemaphoreGetCount(semaphore, 0U);
return 0U;
}
EvrRtxSemaphoreGetCount(semaphore, semaphore->tokens);
return semaphore->tokens;
}
/// Delete a Semaphore object.
/// \note API identical to osSemaphoreDelete
osStatus_t svcRtxSemaphoreDelete (osSemaphoreId_t semaphore_id) {
os_semaphore_t *semaphore = (os_semaphore_t *)semaphore_id;
os_thread_t *thread;
// Check parameters
if ((semaphore == NULL) || (semaphore->id != osRtxIdSemaphore)) {
EvrRtxSemaphoreError(semaphore, osErrorParameter);
return osErrorParameter;
}
// Check object state
if (semaphore->state == osRtxObjectInactive) {
EvrRtxSemaphoreError(semaphore, osErrorResource);
return osErrorResource;
}
// Mark object as inactive
semaphore->state = osRtxObjectInactive;
// Unblock waiting threads
if (semaphore->thread_list != NULL) {
do {
thread = osRtxThreadListGet((os_object_t*)semaphore);
osRtxThreadWaitExit(thread, (uint32_t)osErrorResource, false);
} while (semaphore->thread_list != NULL);
osRtxThreadDispatch(NULL);
}
// Free object memory
if (semaphore->flags & osRtxFlagSystemObject) {
if (osRtxInfo.mpi.semaphore != NULL) {
osRtxMemoryPoolFree(osRtxInfo.mpi.semaphore, semaphore);
} else {
osRtxMemoryFree(osRtxInfo.mem.common, semaphore);
}
}
EvrRtxSemaphoreDestroyed(semaphore);
return osOK;
}
// ==== ISR Calls ====
/// Acquire a Semaphore token or timeout if no tokens are available.
/// \note API identical to osSemaphoreAcquire
__STATIC_INLINE
osStatus_t isrRtxSemaphoreAcquire (osSemaphoreId_t semaphore_id, uint32_t timeout) {
os_semaphore_t *semaphore = (os_semaphore_t *)semaphore_id;
// Check parameters
if ((semaphore == NULL) || (semaphore->id != osRtxIdSemaphore) || (timeout != 0U)) {
EvrRtxSemaphoreError(semaphore, osErrorParameter);
return osErrorParameter;
}
// Check object state
if (semaphore->state == osRtxObjectInactive) {
EvrRtxSemaphoreError(semaphore, osErrorResource);
return osErrorResource;
}
// Try to acquire token
if (SemaphoreTokenDecrement(semaphore) == 0U) {
// No token available
EvrRtxSemaphoreNotAcquired(semaphore);
return osErrorResource;
}
EvrRtxSemaphoreAcquired(semaphore);
return osOK;
}
/// Release a Semaphore token that was acquired by osSemaphoreAcquire.
/// \note API identical to osSemaphoreRelease
__STATIC_INLINE
osStatus_t isrRtxSemaphoreRelease (osSemaphoreId_t semaphore_id) {
os_semaphore_t *semaphore = (os_semaphore_t *)semaphore_id;
// Check parameters
if ((semaphore == NULL) || (semaphore->id != osRtxIdSemaphore)) {
EvrRtxSemaphoreError(semaphore, osErrorParameter);
return osErrorParameter;
}
// Check object state
if (semaphore->state == osRtxObjectInactive) {
EvrRtxSemaphoreError(semaphore, osErrorResource);
return osErrorResource;
}
// Try to release token
if (SemaphoreTokenIncrement(semaphore) != 0U) {
// Register post ISR processing
osRtxPostProcess((os_object_t *)semaphore);
} else {
EvrRtxSemaphoreError(semaphore, osRtxErrorSemaphoreCountLimit);
return osErrorResource;
}
EvrRtxSemaphoreReleased(semaphore);
return osOK;
}
// ==== Public API ====
/// Create and Initialize a Semaphore object.
osSemaphoreId_t osSemaphoreNew (uint32_t max_count, uint32_t initial_count, const osSemaphoreAttr_t *attr) {
EvrRtxSemaphoreNew(max_count, initial_count, attr);
if (IS_IRQ_MODE() || IS_IRQ_MASKED()) {
EvrRtxSemaphoreError(NULL, osErrorISR);
return NULL;
}
return __svcSemaphoreNew(max_count, initial_count, attr);
}
/// Get name of a Semaphore object.
const char *osSemaphoreGetName (osSemaphoreId_t semaphore_id) {
if (IS_IRQ_MODE() || IS_IRQ_MASKED()) {
EvrRtxSemaphoreGetName(semaphore_id, NULL);
return NULL;
}
return __svcSemaphoreGetName(semaphore_id);
}
/// Acquire a Semaphore token or timeout if no tokens are available.
osStatus_t osSemaphoreAcquire (osSemaphoreId_t semaphore_id, uint32_t timeout) {
EvrRtxSemaphoreAcquire(semaphore_id, timeout);
if (IS_IRQ_MODE() || IS_IRQ_MASKED()) {
return isrRtxSemaphoreAcquire(semaphore_id, timeout);
} else {
return __svcSemaphoreAcquire(semaphore_id, timeout);
}
}
/// Release a Semaphore token that was acquired by osSemaphoreAcquire.
osStatus_t osSemaphoreRelease (osSemaphoreId_t semaphore_id) {
EvrRtxSemaphoreRelease(semaphore_id);
if (IS_IRQ_MODE() || IS_IRQ_MASKED()) {
return isrRtxSemaphoreRelease(semaphore_id);
} else {
return __svcSemaphoreRelease(semaphore_id);
}
}
/// Get current Semaphore token count.
uint32_t osSemaphoreGetCount (osSemaphoreId_t semaphore_id) {
if (IS_IRQ_MODE() || IS_IRQ_MASKED()) {
return svcRtxSemaphoreGetCount(semaphore_id);
} else {
return __svcSemaphoreGetCount(semaphore_id);
}
}
/// Delete a Semaphore object.
osStatus_t osSemaphoreDelete (osSemaphoreId_t semaphore_id) {
EvrRtxSemaphoreDelete(semaphore_id);
if (IS_IRQ_MODE() || IS_IRQ_MASKED()) {
EvrRtxSemaphoreError(semaphore_id, osErrorISR);
return osErrorISR;
}
return __svcSemaphoreDelete(semaphore_id);
}

View File

@ -0,0 +1,257 @@
/*
* Copyright (c) 2013-2017 ARM Limited. All rights reserved.
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the License); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an AS IS BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* -----------------------------------------------------------------------------
*
* Project: CMSIS-RTOS RTX
* Title: System functions
*
* -----------------------------------------------------------------------------
*/
#include "rtx_lib.h"
// ==== Helper functions ====
/// Put Object into ISR Queue.
/// \param[in] object object.
/// \return 1 - success, 0 - failure.
static uint32_t isr_queue_put (void *object) {
#if (__EXCLUSIVE_ACCESS == 0U)
uint32_t primask = __get_PRIMASK();
#else
uint32_t n;
#endif
uint16_t max;
uint32_t ret;
max = osRtxInfo.isr_queue.max;
#if (__EXCLUSIVE_ACCESS == 0U)
__disable_irq();
if (osRtxInfo.isr_queue.cnt < max) {
osRtxInfo.isr_queue.cnt++;
osRtxInfo.isr_queue.data[osRtxInfo.isr_queue.in] = object;
if (++osRtxInfo.isr_queue.in == max) {
osRtxInfo.isr_queue.in = 0U;
}
ret = 1U;
} else {
ret = 0U;
}
if (primask == 0U) {
__enable_irq();
}
#else
if (atomic_inc16_lt(&osRtxInfo.isr_queue.cnt, max) < max) {
n = atomic_inc16_lim(&osRtxInfo.isr_queue.in, max);
osRtxInfo.isr_queue.data[n] = object;
ret = 1U;
} else {
ret = 0U;
}
#endif
return ret;
}
/// Get Object from ISR Queue.
/// \return object or NULL.
static void *isr_queue_get (void) {
#if (__EXCLUSIVE_ACCESS == 0U)
uint32_t primask = __get_PRIMASK();
#else
uint32_t n;
#endif
uint16_t max;
void *ret;
max = osRtxInfo.isr_queue.max;
#if (__EXCLUSIVE_ACCESS == 0U)
__disable_irq();
if (osRtxInfo.isr_queue.cnt != 0U) {
osRtxInfo.isr_queue.cnt--;
ret = osRtxInfo.isr_queue.data[osRtxInfo.isr_queue.out];
if (++osRtxInfo.isr_queue.out == max) {
osRtxInfo.isr_queue.out = 0U;
}
} else {
ret = NULL;
}
if (primask == 0U) {
__enable_irq();
}
#else
if (atomic_dec16_nz(&osRtxInfo.isr_queue.cnt) != 0U) {
n = atomic_inc16_lim(&osRtxInfo.isr_queue.out, max);
ret = osRtxInfo.isr_queue.data[n];
} else {
ret = NULL;
}
#endif
return ret;
}
// ==== Library Functions ====
/// Tick Handler.
void osRtxTick_Handler (void) {
os_thread_t *thread;
osRtxSysTimerAckIRQ();
osRtxInfo.kernel.tick++;
// Process Timers
if (osRtxInfo.timer.tick != NULL) {
osRtxInfo.timer.tick();
}
// Process Thread Delays
osRtxThreadDelayTick();
osRtxThreadDispatch(NULL);
// Check Round Robin timeout
if (osRtxInfo.thread.robin.timeout != 0U) {
if (osRtxInfo.thread.robin.thread != osRtxInfo.thread.run.next) {
// Reset Round Robin
osRtxInfo.thread.robin.thread = osRtxInfo.thread.run.next;
osRtxInfo.thread.robin.tick = osRtxInfo.thread.robin.timeout;
} else {
if (osRtxInfo.thread.robin.tick != 0U) {
osRtxInfo.thread.robin.tick--;
}
if (osRtxInfo.thread.robin.tick == 0U) {
// Round Robin Timeout
if (osRtxKernelGetState() == osRtxKernelRunning) {
thread = osRtxInfo.thread.ready.thread_list;
if ((thread != NULL) && (thread->priority == osRtxInfo.thread.robin.thread->priority)) {
osRtxThreadListRemove(thread);
osRtxThreadReadyPut(osRtxInfo.thread.robin.thread);
osRtxThreadSwitch(thread);
osRtxInfo.thread.robin.thread = thread;
osRtxInfo.thread.robin.tick = osRtxInfo.thread.robin.timeout;
}
}
}
}
}
}
/// Pending Service Call Handler.
void osRtxPendSV_Handler (void) {
os_object_t *object;
for (;;) {
object = isr_queue_get();
if (object == NULL) {
break;
}
switch (object->id) {
case osRtxIdThread:
osRtxInfo.post_process.thread((os_thread_t *)object);
break;
case osRtxIdEventFlags:
osRtxInfo.post_process.event_flags((os_event_flags_t *)object);
break;
case osRtxIdSemaphore:
osRtxInfo.post_process.semaphore((os_semaphore_t *)object);
break;
case osRtxIdMemoryPool:
osRtxInfo.post_process.memory_pool((os_memory_pool_t *)object);
break;
case osRtxIdMessage:
osRtxInfo.post_process.message_queue((os_message_t *)object);
break;
default:
break;
}
}
osRtxThreadDispatch(NULL);
}
/// Register post ISR processing.
/// \param[in] object generic object.
void osRtxPostProcess (os_object_t *object) {
if (isr_queue_put(object) != 0U) {
if (osRtxInfo.kernel.blocked == 0U) {
SetPendSV();
} else {
osRtxInfo.kernel.pendSV = 1U;
}
} else {
osRtxErrorNotify(osRtxErrorISRQueueOverflow, object);
}
}
// ==== Public API ====
/// Setup System Timer.
__WEAK int32_t osRtxSysTimerSetup (void) {
// Setup SysTick Timer
SysTick_Setup(osRtxInfo.kernel.sys_freq / osRtxConfig.tick_freq);
return SysTick_IRQn; // Return IRQ number of SysTick
}
/// Enable System Timer.
__WEAK void osRtxSysTimerEnable (void) {
SysTick_Enable();
}
/// Disable System Timer.
__WEAK void osRtxSysTimerDisable (void) {
SysTick_Disable();
}
/// Acknowledge System Timer IRQ.
__WEAK void osRtxSysTimerAckIRQ (void) {
SysTick_GetOvf();
}
/// Get System Timer count.
__WEAK uint32_t osRtxSysTimerGetCount (void) {
uint32_t tick;
uint32_t val;
tick = (uint32_t)osRtxInfo.kernel.tick;
val = SysTick_GetVal();
if (SysTick_GetOvf()) {
val = SysTick_GetVal();
tick++;
}
val += tick * SysTick_GetPeriod();
return val;
}
/// Get System Timer frequency.
__WEAK uint32_t osRtxSysTimerGetFreq (void) {
return osRtxInfo.kernel.sys_freq;
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,415 @@
/*
* Copyright (c) 2013-2017 ARM Limited. All rights reserved.
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the License); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an AS IS BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* -----------------------------------------------------------------------------
*
* Project: CMSIS-RTOS RTX
* Title: Timer functions
*
* -----------------------------------------------------------------------------
*/
#include "rtx_lib.h"
// ==== Helper functions ====
/// Insert Timer into the Timer List sorted by Time.
/// \param[in] timer timer object.
/// \param[in] tick timer tick.
static void TimerInsert (os_timer_t *timer, uint32_t tick) {
os_timer_t *prev, *next;
prev = NULL;
next = osRtxInfo.timer.list;
while ((next != NULL) && (next->tick <= tick)) {
tick -= next->tick;
prev = next;
next = next->next;
}
timer->tick = tick;
timer->prev = prev;
timer->next = next;
if (next != NULL) {
next->tick -= timer->tick;
next->prev = timer;
}
if (prev != NULL) {
prev->next = timer;
} else {
osRtxInfo.timer.list = timer;
}
}
/// Remove Timer from the Timer List.
/// \param[in] timer timer object.
static void TimerRemove (os_timer_t *timer) {
if (timer->next != NULL) {
timer->next->tick += timer->tick;
timer->next->prev = timer->prev;
}
if (timer->prev != NULL) {
timer->prev->next = timer->next;
} else {
osRtxInfo.timer.list = timer->next;
}
}
/// Unlink Timer from the Timer List Head.
/// \param[in] timer timer object.
static void TimerUnlink (os_timer_t *timer) {
if (timer->next != NULL) {
timer->next->prev = timer->prev;
}
osRtxInfo.timer.list = timer->next;
}
// ==== Library functions ====
/// Timer Tick (called each SysTick).
void osRtxTimerTick (void) {
os_timer_t *timer;
osStatus_t status;
timer = osRtxInfo.timer.list;
if (timer == NULL) {
return;
}
timer->tick--;
while ((timer != NULL) && (timer->tick == 0U)) {
TimerUnlink(timer);
status = osMessageQueuePut(osRtxInfo.timer.mq, &timer->finfo, 0U, 0U);
if (status != osOK) {
osRtxErrorNotify(osRtxErrorTimerQueueOverflow, timer);
}
if (timer->type == osRtxTimerPeriodic) {
TimerInsert(timer, timer->load);
} else {
timer->state = osRtxTimerStopped;
}
timer = osRtxInfo.timer.list;
}
}
/// Timer Thread
__WEAK void osRtxTimerThread (void *argument) {
os_timer_finfo_t finfo;
osStatus_t status;
(void) argument;
osRtxInfo.timer.mq = osMessageQueueNew(osRtxConfig.timer_mq_mcnt, sizeof(os_timer_finfo_t), osRtxConfig.timer_mq_attr);
if (osRtxInfo.timer.mq == NULL) {
return;
}
osRtxInfo.timer.tick = osRtxTimerTick;
for (;;) {
status = osMessageQueueGet(osRtxInfo.timer.mq, &finfo, NULL, osWaitForever);
if (status == osOK) {
EvrRtxTimerCallback(*(osTimerFunc_t)finfo.fp, finfo.arg);
(*(osTimerFunc_t)finfo.fp)(finfo.arg);
}
}
}
// ==== Service Calls ====
// Service Calls definitions
SVC0_4M(TimerNew, osTimerId_t, osTimerFunc_t, osTimerType_t, void *, const osTimerAttr_t *)
SVC0_1 (TimerGetName, const char *, osTimerId_t)
SVC0_2 (TimerStart, osStatus_t, osTimerId_t, uint32_t)
SVC0_1 (TimerStop, osStatus_t, osTimerId_t)
SVC0_1 (TimerIsRunning, uint32_t, osTimerId_t)
SVC0_1 (TimerDelete, osStatus_t, osTimerId_t)
/// Create and Initialize a timer.
/// \note API identical to osTimerNew
osTimerId_t svcRtxTimerNew (osTimerFunc_t func, osTimerType_t type, void *argument, const osTimerAttr_t *attr) {
os_timer_t *timer;
uint8_t flags;
const char *name;
// Check parameters
if ((func == NULL) || ((type != osTimerOnce) && (type != osTimerPeriodic))) {
EvrRtxTimerError(NULL, osErrorParameter);
return NULL;
}
// Process attributes
if (attr != NULL) {
name = attr->name;
timer = attr->cb_mem;
if (timer != NULL) {
if (((uint32_t)timer & 3U) || (attr->cb_size < sizeof(os_timer_t))) {
EvrRtxTimerError(NULL, osRtxErrorInvalidControlBlock);
return NULL;
}
} else {
if (attr->cb_size != 0U) {
EvrRtxTimerError(NULL, osRtxErrorInvalidControlBlock);
return NULL;
}
}
} else {
name = NULL;
timer = NULL;
}
// Allocate object memory if not provided
if (timer == NULL) {
if (osRtxInfo.mpi.timer != NULL) {
timer = osRtxMemoryPoolAlloc(osRtxInfo.mpi.timer);
} else {
timer = osRtxMemoryAlloc(osRtxInfo.mem.common, sizeof(os_timer_t), 1U);
}
if (timer == NULL) {
EvrRtxTimerError(NULL, osErrorNoMemory);
return NULL;
}
flags = osRtxFlagSystemObject;
} else {
flags = 0U;
}
// Initialize control block
timer->id = osRtxIdTimer;
timer->state = osRtxTimerStopped;
timer->flags = flags;
timer->type = (uint8_t)type;
timer->name = name;
timer->prev = NULL;
timer->next = NULL;
timer->tick = 0U;
timer->load = 0U;
timer->finfo.fp = (void *)func;
timer->finfo.arg = argument;
EvrRtxTimerCreated(timer);
return timer;
}
/// Get name of a timer.
/// \note API identical to osTimerGetName
const char *svcRtxTimerGetName (osTimerId_t timer_id) {
os_timer_t *timer = (os_timer_t *)timer_id;
// Check parameters
if ((timer == NULL) || (timer->id != osRtxIdTimer)) {
EvrRtxTimerGetName(timer, NULL);
return NULL;
}
// Check object state
if (timer->state == osRtxObjectInactive) {
EvrRtxTimerGetName(timer, NULL);
return NULL;
}
EvrRtxTimerGetName(timer, timer->name);
return timer->name;
}
/// Start or restart a timer.
/// \note API identical to osTimerStart
osStatus_t svcRtxTimerStart (osTimerId_t timer_id, uint32_t ticks) {
os_timer_t *timer = (os_timer_t *)timer_id;
// Check parameters
if ((timer == NULL) || (timer->id != osRtxIdTimer) || (ticks == 0U)) {
EvrRtxTimerError(timer, osErrorParameter);
return osErrorParameter;
}
// Check object state
switch (timer->state) {
case osRtxTimerStopped:
if (osRtxInfo.timer.tick == NULL) {
EvrRtxTimerError(timer, osErrorResource);
return osErrorResource;
}
timer->state = osRtxTimerRunning;
timer->load = ticks;
break;
case osRtxTimerRunning:
TimerRemove(timer);
break;
case osRtxTimerInactive:
default:
EvrRtxTimerError(timer, osErrorResource);
return osErrorResource;
}
TimerInsert(timer, ticks);
EvrRtxTimerStarted(timer);
return osOK;
}
/// Stop a timer.
/// \note API identical to osTimerStop
osStatus_t svcRtxTimerStop (osTimerId_t timer_id) {
os_timer_t *timer = (os_timer_t *)timer_id;
// Check parameters
if ((timer == NULL) || (timer->id != osRtxIdTimer)) {
EvrRtxTimerError(timer, osErrorParameter);
return osErrorParameter;
}
// Check object state
if (timer->state != osRtxTimerRunning) {
EvrRtxTimerError(timer, osErrorResource);
return osErrorResource;
}
timer->state = osRtxTimerStopped;
TimerRemove(timer);
EvrRtxTimerStopped(timer);
return osOK;
}
/// Check if a timer is running.
/// \note API identical to osTimerIsRunning
uint32_t svcRtxTimerIsRunning (osTimerId_t timer_id) {
os_timer_t *timer = (os_timer_t *)timer_id;
// Check parameters
if ((timer == NULL) || (timer->id != osRtxIdTimer)) {
EvrRtxTimerIsRunning(timer, 0U);
return 0U;
}
// Check object state
if (timer->state == osRtxTimerRunning) {
EvrRtxTimerIsRunning(timer, 1U);
return 1U;
}
EvrRtxTimerIsRunning(timer, 0U);
return 0U;
}
/// Delete a timer.
/// \note API identical to osTimerDelete
osStatus_t svcRtxTimerDelete (osTimerId_t timer_id) {
os_timer_t *timer = (os_timer_t *)timer_id;
// Check parameters
if ((timer == NULL) || (timer->id != osRtxIdTimer)) {
EvrRtxTimerError(timer, osErrorParameter);
return osErrorParameter;
}
// Check object state
switch (timer->state) {
case osRtxTimerStopped:
break;
case osRtxTimerRunning:
TimerRemove(timer);
break;
case osRtxTimerInactive:
default:
EvrRtxTimerError(timer, osErrorResource);
return osErrorResource;
}
// Mark object as inactive
timer->state = osRtxTimerInactive;
// Free object memory
if (timer->flags & osRtxFlagSystemObject) {
if (osRtxInfo.mpi.timer != NULL) {
osRtxMemoryPoolFree(osRtxInfo.mpi.timer, timer);
} else {
osRtxMemoryFree(osRtxInfo.mem.common, timer);
}
}
EvrRtxTimerDestroyed(timer);
return osOK;
}
// ==== Public API ====
/// Create and Initialize a timer.
osTimerId_t osTimerNew (osTimerFunc_t func, osTimerType_t type, void *argument, const osTimerAttr_t *attr) {
EvrRtxTimerNew(func, type, argument, attr);
if (IS_IRQ_MODE() || IS_IRQ_MASKED()) {
EvrRtxTimerError(NULL, osErrorISR);
return NULL;
}
return __svcTimerNew(func, type, argument, attr);
}
/// Get name of a timer.
const char *osTimerGetName (osTimerId_t timer_id) {
if (IS_IRQ_MODE() || IS_IRQ_MASKED()) {
EvrRtxTimerGetName(timer_id, NULL);
return NULL;
}
return __svcTimerGetName(timer_id);
}
/// Start or restart a timer.
osStatus_t osTimerStart (osTimerId_t timer_id, uint32_t ticks) {
EvrRtxTimerStart(timer_id, ticks);
if (IS_IRQ_MODE() || IS_IRQ_MASKED()) {
EvrRtxTimerError(timer_id, osErrorISR);
return osErrorISR;
}
return __svcTimerStart(timer_id, ticks);
}
/// Stop a timer.
osStatus_t osTimerStop (osTimerId_t timer_id) {
EvrRtxTimerStop(timer_id);
if (IS_IRQ_MODE() || IS_IRQ_MASKED()) {
EvrRtxTimerError(timer_id, osErrorISR);
return osErrorISR;
}
return __svcTimerStop(timer_id);
}
/// Check if a timer is running.
uint32_t osTimerIsRunning (osTimerId_t timer_id) {
if (IS_IRQ_MODE() || IS_IRQ_MASKED()) {
EvrRtxTimerIsRunning(timer_id, 0U);
return 0U;
}
return __svcTimerIsRunning(timer_id);
}
/// Delete a timer.
osStatus_t osTimerDelete (osTimerId_t timer_id) {
EvrRtxTimerDelete(timer_id);
if (IS_IRQ_MODE() || IS_IRQ_MASKED()) {
EvrRtxTimerError(timer_id, osErrorISR);
return osErrorISR;
}
return __svcTimerDelete(timer_id);
}