diff options
Diffstat (limited to 'libraries/mbed/rtos/rtx')
31 files changed, 7376 insertions, 0 deletions
diff --git a/libraries/mbed/rtos/rtx/TARGET_CORTEX_M/HAL_CM.c b/libraries/mbed/rtos/rtx/TARGET_CORTEX_M/HAL_CM.c new file mode 100644 index 0000000..efbe04c --- /dev/null +++ b/libraries/mbed/rtos/rtx/TARGET_CORTEX_M/HAL_CM.c @@ -0,0 +1,170 @@ +/*---------------------------------------------------------------------------- + * RL-ARM - RTX + *---------------------------------------------------------------------------- + * Name: HAL_CM.C + * Purpose: Hardware Abstraction Layer for Cortex-M + * Rev.: V4.60 + *---------------------------------------------------------------------------- + * + * Copyright (c) 1999-2009 KEIL, 2009-2012 ARM Germany GmbH + * All rights reserved. + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * - Neither the name of ARM nor the names of its contributors may be used + * to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDERS AND CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + *---------------------------------------------------------------------------*/ + +#include "rt_TypeDef.h" +#include "RTX_Conf.h" +#include "rt_HAL_CM.h" + + +/*---------------------------------------------------------------------------- + * Global Variables + *---------------------------------------------------------------------------*/ + +#ifdef DBG_MSG +BIT dbg_msg; +#endif + +/*---------------------------------------------------------------------------- + * Functions + *---------------------------------------------------------------------------*/ + + +/*--------------------------- rt_init_stack ---------------------------------*/ + +void rt_init_stack (P_TCB p_TCB, FUNCP task_body) { + /* Prepare TCB and saved context for a first time start of a task. */ + U32 *stk,i,size; + + /* Prepare a complete interrupt frame for first task start */ + size = p_TCB->priv_stack >> 2; + + /* Write to the top of stack. */ + stk = &p_TCB->stack[size]; + + /* Auto correct to 8-byte ARM stack alignment. */ + if ((U32)stk & 0x04) { + stk--; + } + + stk -= 16; + + /* Default xPSR and initial PC */ + stk[15] = INITIAL_xPSR; + stk[14] = (U32)task_body; + + /* Clear R4-R11,R0-R3,R12,LR registers. */ + for (i = 0; i < 14; i++) { + stk[i] = 0; + } + + /* Assign a void pointer to R0. */ + stk[8] = (U32)p_TCB->msg; + + /* Initial Task stack pointer. */ + p_TCB->tsk_stack = (U32)stk; + + /* Task entry point. */ + p_TCB->ptask = task_body; + + /* Set a magic word for checking of stack overflow. + For the main thread (ID: 0x01) the stack is in a memory area shared with the + heap, therefore the last word of the stack is a moving target. + We want to do stack/heap collision detection instead. + */ + if (p_TCB->task_id != 0x01) + p_TCB->stack[0] = MAGIC_WORD; +} + + +/*--------------------------- rt_ret_val ----------------------------------*/ + +static __inline U32 *rt_ret_regs (P_TCB p_TCB) { + /* Get pointer to task return value registers (R0..R3) in Stack */ +#if (__TARGET_FPU_VFP) + if (p_TCB->stack_frame) { + /* Extended Stack Frame: R4-R11,S16-S31,R0-R3,R12,LR,PC,xPSR,S0-S15,FPSCR */ + return (U32 *)(p_TCB->tsk_stack + 8*4 + 16*4); + } else { + /* Basic Stack Frame: R4-R11,R0-R3,R12,LR,PC,xPSR */ + return (U32 *)(p_TCB->tsk_stack + 8*4); + } +#else + /* Stack Frame: R4-R11,R0-R3,R12,LR,PC,xPSR */ + return (U32 *)(p_TCB->tsk_stack + 8*4); +#endif +} + +void rt_ret_val (P_TCB p_TCB, U32 v0) { + U32 *ret; + + ret = rt_ret_regs(p_TCB); + ret[0] = v0; +} + +void rt_ret_val2(P_TCB p_TCB, U32 v0, U32 v1) { + U32 *ret; + + ret = rt_ret_regs(p_TCB); + ret[0] = v0; + ret[1] = v1; +} + + +/*--------------------------- dbg_init --------------------------------------*/ + +#ifdef DBG_MSG +void dbg_init (void) { + if ((DEMCR & DEMCR_TRCENA) && + (ITM_CONTROL & ITM_ITMENA) && + (ITM_ENABLE & (1UL << 31))) { + dbg_msg = __TRUE; + } +} +#endif + +/*--------------------------- dbg_task_notify -------------------------------*/ + +#ifdef DBG_MSG +void dbg_task_notify (P_TCB p_tcb, BOOL create) { + while (ITM_PORT31_U32 == 0); + ITM_PORT31_U32 = (U32)p_tcb->ptask; + while (ITM_PORT31_U32 == 0); + ITM_PORT31_U16 = (create << 8) | p_tcb->task_id; +} +#endif + +/*--------------------------- dbg_task_switch -------------------------------*/ + +#ifdef DBG_MSG +void dbg_task_switch (U32 task_id) { + while (ITM_PORT31_U32 == 0); + ITM_PORT31_U8 = task_id; +} +#endif + + +/*---------------------------------------------------------------------------- + * end of file + *---------------------------------------------------------------------------*/ + diff --git a/libraries/mbed/rtos/rtx/TARGET_CORTEX_M/RTX_CM_lib.h b/libraries/mbed/rtos/rtx/TARGET_CORTEX_M/RTX_CM_lib.h new file mode 100755 index 0000000..23697ef --- /dev/null +++ b/libraries/mbed/rtos/rtx/TARGET_CORTEX_M/RTX_CM_lib.h @@ -0,0 +1,537 @@ +/*---------------------------------------------------------------------------- + * RL-ARM - RTX + *---------------------------------------------------------------------------- + * Name: RTX_CM_LIB.H + * Purpose: RTX Kernel System Configuration + * Rev.: V4.60 + *---------------------------------------------------------------------------- + * + * Copyright (c) 1999-2009 KEIL, 2009-2012 ARM Germany GmbH + * All rights reserved. + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * - Neither the name of ARM nor the names of its contributors may be used + * to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDERS AND CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + *---------------------------------------------------------------------------*/ +#include "mbed_error.h" + +#if defined (__CC_ARM) +#pragma O3 +#define __USED __attribute__((used)) +#elif defined (__GNUC__) +#pragma GCC optimize ("O3") +#define __USED __attribute__((used)) +#elif defined (__ICCARM__) +#define __USED __root +#endif + + +/*---------------------------------------------------------------------------- + * Definitions + *---------------------------------------------------------------------------*/ + +#define _declare_box(pool,size,cnt) uint32_t pool[(((size)+3)/4)*(cnt) + 3] +#define _declare_box8(pool,size,cnt) uint64_t pool[(((size)+7)/8)*(cnt) + 2] + +#define OS_TCB_SIZE 48 +#define OS_TMR_SIZE 8 + +#if defined (__CC_ARM) && !defined (__MICROLIB) + +typedef void *OS_ID; +typedef uint32_t OS_TID; +typedef uint32_t OS_MUT[3]; +typedef uint32_t OS_RESULT; + +#define runtask_id() rt_tsk_self() +#define mutex_init(m) rt_mut_init(m) +#define mutex_wait(m) os_mut_wait(m,0xFFFF) +#define mutex_rel(m) os_mut_release(m) + +extern OS_TID rt_tsk_self (void); +extern void rt_mut_init (OS_ID mutex); +extern OS_RESULT rt_mut_release (OS_ID mutex); +extern OS_RESULT rt_mut_wait (OS_ID mutex, uint16_t timeout); + +#define os_mut_wait(mutex,timeout) _os_mut_wait((uint32_t)rt_mut_wait,mutex,timeout) +#define os_mut_release(mutex) _os_mut_release((uint32_t)rt_mut_release,mutex) + +OS_RESULT _os_mut_release (uint32_t p, OS_ID mutex) __svc_indirect(0); +OS_RESULT _os_mut_wait (uint32_t p, OS_ID mutex, uint16_t timeout) __svc_indirect(0); + +#endif + + +/*---------------------------------------------------------------------------- + * Global Variables + *---------------------------------------------------------------------------*/ + +#if (OS_TIMERS != 0) +#define OS_TASK_CNT (OS_TASKCNT + 1) +#else +#define OS_TASK_CNT OS_TASKCNT +#endif + +uint16_t const os_maxtaskrun = OS_TASK_CNT; +uint32_t const os_rrobin = (OS_ROBIN << 16) | OS_ROBINTOUT; +uint32_t const os_trv = OS_TRV; +uint8_t const os_flags = OS_RUNPRIV; + +/* Export following defines to uVision debugger. */ +__USED uint32_t const os_clockrate = OS_TICK; +__USED uint32_t const os_timernum = 0; + +/* Stack for the os_idle_demon */ +unsigned int idle_task_stack[OS_IDLESTKSIZE]; +unsigned short const idle_task_stack_size = OS_IDLESTKSIZE; + +#ifndef OS_FIFOSZ + #define OS_FIFOSZ 16 +#endif + +/* Fifo Queue buffer for ISR requests.*/ +uint32_t os_fifo[OS_FIFOSZ*2+1]; +uint8_t const os_fifo_size = OS_FIFOSZ; + +/* An array of Active task pointers. */ +void *os_active_TCB[OS_TASK_CNT]; + +/* User Timers Resources */ +#if (OS_TIMERS != 0) +extern void osTimerThread (void const *argument); +osThreadDef(osTimerThread, (osPriority)(OS_TIMERPRIO-3), 4*OS_TIMERSTKSZ); +osThreadId osThreadId_osTimerThread; +osMessageQDef(osTimerMessageQ, OS_TIMERCBQS, void *); +osMessageQId osMessageQId_osTimerMessageQ; +#else +osThreadDef_t os_thread_def_osTimerThread = { NULL }; +osThreadId osThreadId_osTimerThread; +osMessageQDef(osTimerMessageQ, 0, void *); +osMessageQId osMessageQId_osTimerMessageQ; +#endif + + +/*---------------------------------------------------------------------------- + * RTX Optimizations (empty functions) + *---------------------------------------------------------------------------*/ + +#if OS_ROBIN == 0 + void rt_init_robin (void) {;} + void rt_chk_robin (void) {;} +#endif + +#if OS_STKCHECK == 0 + void rt_stk_check (void) {;} +#endif + + +/*---------------------------------------------------------------------------- + * Standard Library multithreading interface + *---------------------------------------------------------------------------*/ + +#if defined (__CC_ARM) && !defined (__MICROLIB) + static OS_MUT std_libmutex[OS_MUTEXCNT]; + static uint32_t nr_mutex; + + /*--------------------------- _mutex_initialize -----------------------------*/ + +int _mutex_initialize (OS_ID *mutex) { + /* Allocate and initialize a system mutex. */ + + if (nr_mutex >= OS_MUTEXCNT) { + /* If you are here, you need to increase the number OS_MUTEXCNT. */ + error("Not enough stdlib mutexes\n"); + } + *mutex = &std_libmutex[nr_mutex++]; + mutex_init (*mutex); + return (1); +} + + +/*--------------------------- _mutex_acquire --------------------------------*/ + +__attribute__((used)) void _mutex_acquire (OS_ID *mutex) { + /* Acquire a system mutex, lock stdlib resources. */ + if (runtask_id ()) { + /* RTX running, acquire a mutex. */ + mutex_wait (*mutex); + } +} + + +/*--------------------------- _mutex_release --------------------------------*/ + +__attribute__((used)) void _mutex_release (OS_ID *mutex) { + /* Release a system mutex, unlock stdlib resources. */ + if (runtask_id ()) { + /* RTX running, release a mutex. */ + mutex_rel (*mutex); + } +} + +#endif + + +/*---------------------------------------------------------------------------- + * RTX Startup + *---------------------------------------------------------------------------*/ + +/* Main Thread definition */ +extern int main (void); +osThreadDef_t os_thread_def_main = {(os_pthread)main, osPriorityNormal, 0, NULL}; + +// This define should be probably moved to the CMSIS layer +#if defined(TARGET_LPC1768) +#define INITIAL_SP (0x10008000UL) + +#elif defined(TARGET_LPC11U24) +#define INITIAL_SP (0x10002000UL) + +#elif defined(TARGET_LPC11U35_401) || defined(TARGET_LPC11U35_501) || defined(TARGET_LPCCAPPUCCINO) +#define INITIAL_SP (0x10002000UL) + +#elif defined(TARGET_LPC1114) +#define INITIAL_SP (0x10001000UL) + +#elif defined(TARGET_LPC812) +#define INITIAL_SP (0x10001000UL) + +#elif defined(TARGET_LPC824) || defined(TARGET_SSCI824) +#define INITIAL_SP (0x10002000UL) + +#elif defined(TARGET_KL25Z) +#define INITIAL_SP (0x20003000UL) + +#elif defined(TARGET_KL26Z) +#define INITIAL_SP (0x20003000UL) + +#elif defined(TARGET_K64F) +#define INITIAL_SP (0x20030000UL) + +#elif defined(TARGET_K22F) +#define INITIAL_SP (0x20010000UL) + +#elif defined(TARGET_KL46Z) +#define INITIAL_SP (0x20006000UL) + +#elif defined(TARGET_KL43Z) +#define INITIAL_SP (0x20006000UL) + +#elif defined(TARGET_KL05Z) +#define INITIAL_SP (0x20000C00UL) + +#elif defined(TARGET_LPC4088) || defined(TARGET_LPC4088_DM) +#define INITIAL_SP (0x10010000UL) + +#elif defined(TARGET_LPC4330) +#define INITIAL_SP (0x10008000UL) + +#elif defined(TARGET_LPC4337) +#define INITIAL_SP (0x10008000UL) + +#elif defined(TARGET_LPC1347) +#define INITIAL_SP (0x10002000UL) + +#elif defined(TARGET_STM32F100RB) || defined(TARGET_STM32F051R8) +#define INITIAL_SP (0x20002000UL) + +#elif defined(TARGET_DISCO_F303VC) +#define INITIAL_SP (0x2000A000UL) + +#elif defined(TARGET_STM32F407) || defined(TARGET_F407VG) +#define INITIAL_SP (0x20020000UL) + +#elif defined(TARGET_STM32F401RE) +#define INITIAL_SP (0x20018000UL) + +#elif defined(TARGET_LPC1549) +#define INITIAL_SP (0x02009000UL) + +#elif defined(TARGET_LPC11U68) +#define INITIAL_SP (0x10008000UL) + +#elif defined(TARGET_STM32F411RE) +#define INITIAL_SP (0x20020000UL) + +#elif defined(TARGET_STM32F410RB) +#define INITIAL_SP (0x20008000UL) + +#elif defined(TARGET_STM32F103RB) || defined(TARGET_STM32L073RZ) +#define INITIAL_SP (0x20005000UL) + +#elif defined(TARGET_STM32F302R8) +#define INITIAL_SP (0x20004000UL) + +#elif defined(TARGET_STM32F334R8) +#define INITIAL_SP (0x20003000UL) + +#elif defined(TARGET_STM32F334C8) +#define INITIAL_SP (0x20003000UL) + +#elif defined(TARGET_STM32F405RG) +#define INITIAL_SP (0x20020000UL) + +#elif defined(TARGET_STM32F429ZI) +#define INITIAL_SP (0x20030000UL) + +#elif defined(TARGET_STM32L053R8) || defined(TARGET_STM32L053C8) +#define INITIAL_SP (0x20002000UL) + +#elif defined(TARGET_STM32F072RB) +#define INITIAL_SP (0x20004000UL) + +#elif defined(TARGET_STM32F091RC) +#define INITIAL_SP (0x20008000UL) + +#elif defined(TARGET_STM32F401VC) +#define INITIAL_SP (0x20010000UL) + +#elif defined(TARGET_STM32F303RE) +#define INITIAL_SP (0x20010000UL) + +#elif defined(TARGET_STM32F303K8) +#define INITIAL_SP (0x20003000UL) + +#elif (defined(TARGET_STM32F746NG) || defined(TARGET_STM32F746ZG)) +#define INITIAL_SP (0x20050000UL) + +#elif defined(TARGET_MAX32610) || defined(TARGET_MAX32600) +#define INITIAL_SP (0x20008000UL) + +#elif defined(TARGET_TEENSY3_1) +#define INITIAL_SP (0x20008000UL) + +#elif defined(TARGET_STM32L152RE) +#define INITIAL_SP (0x20014000UL) + +#elif defined(TARGET_NZ32_SC151) +#define INITIAL_SP (0x20008000UL) + +#elif (defined(TARGET_STM32F446RE) || defined(TARGET_STM32F446VE)) +#define INITIAL_SP (0x20020000UL) + +#elif defined(TARGET_STM32F070RB) || defined(TARGET_STM32F030R8) +#define INITIAL_SP (0x20002000UL) + +#elif defined(TARGET_STM32L476VG) +#define INITIAL_SP (0x20018000UL) + +#elif defined(TARGET_STM32L476RG) +#define INITIAL_SP (0x20018000UL) + +#elif defined(TARGET_STM32F469NI) +#define INITIAL_SP (0x20050000UL) + +#elif defined(TARGET_STM32L152RC) +#define INITIAL_SP (0x20008000UL) + + +#else +#error "no target defined" + +#endif + +#ifdef __CC_ARM +extern uint32_t Image$$RW_IRAM1$$ZI$$Limit[]; +#define HEAP_START (Image$$RW_IRAM1$$ZI$$Limit) +#elif defined(__GNUC__) +extern uint32_t __end__[]; +#define HEAP_START (__end__) +#elif defined(__ICCARM__) +#pragma section="HEAP" +#define HEAP_START (void *)__section_begin("HEAP") +#endif + +void set_main_stack(void) { + // That is the bottom of the main stack block: no collision detection + os_thread_def_main.stack_pointer = HEAP_START; + + // Leave OS_SCHEDULERSTKSIZE words for the scheduler and interrupts + os_thread_def_main.stacksize = (INITIAL_SP - (unsigned int)HEAP_START) - (OS_SCHEDULERSTKSIZE * 4); +} + +#if defined (__CC_ARM) +#ifdef __MICROLIB +void _main_init (void) __attribute__((section(".ARM.Collect$$$$000000FF"))); +void _main_init (void) { + osKernelInitialize(); + set_main_stack(); + osThreadCreate(&os_thread_def_main, NULL); + osKernelStart(); + for (;;); +} +#else + +/* The single memory model is checking for stack collision at run time, verifing + that the heap pointer is underneath the stack pointer. + + With the RTOS there is not only one stack above the heap, there are multiple + stacks and some of them are underneath the heap pointer. +*/ +#pragma import(__use_two_region_memory) + +__asm void __rt_entry (void) { + + IMPORT __user_setup_stackheap + IMPORT __rt_lib_init + IMPORT os_thread_def_main + IMPORT osKernelInitialize + IMPORT set_main_stack + IMPORT osKernelStart + IMPORT osThreadCreate + IMPORT exit + + BL __user_setup_stackheap + MOV R1,R2 + BL __rt_lib_init + BL osKernelInitialize + BL set_main_stack + LDR R0,=os_thread_def_main + MOVS R1,#0 + BL osThreadCreate + BL osKernelStart + BL exit + + ALIGN +} +#endif + +#elif defined (__GNUC__) + +#ifdef __CS3__ + +/* CS3 start_c routine. + * + * Copyright (c) 2006, 2007 CodeSourcery Inc + * + * The authors hereby grant permission to use, copy, modify, distribute, + * and license this software and its documentation for any purpose, provided + * that existing copyright notices are retained in all copies and that this + * notice is included verbatim in any distributions. No written agreement, + * license, or royalty fee is required for any of the authorized uses. + * Modifications to this software may be copyrighted by their authors + * and need not follow the licensing terms described here, provided that + * the new terms are clearly indicated on the first page of each file where + * they apply. + */ + +#include "cs3.h" + +extern void __libc_init_array (void); + +__attribute ((noreturn)) void __cs3_start_c (void){ + unsigned regions = __cs3_region_num; + const struct __cs3_region *rptr = __cs3_regions; + + /* Initialize memory */ + for (regions = __cs3_region_num, rptr = __cs3_regions; regions--; rptr++) { + long long *src = (long long *)rptr->init; + long long *dst = (long long *)rptr->data; + unsigned limit = rptr->init_size; + unsigned count; + + if (src != dst) + for (count = 0; count != limit; count += sizeof (long long)) + *dst++ = *src++; + else + dst = (long long *)((char *)dst + limit); + limit = rptr->zero_size; + for (count = 0; count != limit; count += sizeof (long long)) + *dst++ = 0; + } + + /* Run initializers. */ + __libc_init_array (); + + osKernelInitialize(); + set_main_stack(); + osThreadCreate(&os_thread_def_main, NULL); + osKernelStart(); + for (;;); +} + +#else + +__attribute__((naked)) void software_init_hook (void) { + __asm ( + ".syntax unified\n" + ".thumb\n" + "movs r0,#0\n" + "movs r1,#0\n" + "mov r4,r0\n" + "mov r5,r1\n" + "ldr r0,= __libc_fini_array\n" + "bl atexit\n" + "bl __libc_init_array\n" + "mov r0,r4\n" + "mov r1,r5\n" + "bl osKernelInitialize\n" + "bl set_main_stack\n" + "ldr r0,=os_thread_def_main\n" + "movs r1,#0\n" + "bl osThreadCreate\n" + "bl osKernelStart\n" + "bl exit\n" + ); +} + +#endif + +#elif defined (__ICCARM__) + +extern void* __vector_table; +extern int __low_level_init(void); +extern void __iar_data_init3(void); +extern __weak void __iar_init_core( void ); +extern __weak void __iar_init_vfp( void ); +extern void __iar_dynamic_initialization(void); +extern void mbed_sdk_init(void); +extern void exit(int arg); + +#pragma required=__vector_table +void __iar_program_start( void ) +{ + __iar_init_core(); + __iar_init_vfp(); + + int a; + + if (__low_level_init() != 0) { + __iar_data_init3(); + mbed_sdk_init(); + __iar_dynamic_initialization(); + } + osKernelInitialize(); + set_main_stack(); + osThreadCreate(&os_thread_def_main, NULL); + a = osKernelStart(); + exit(a); + +} + +#endif + + +/*---------------------------------------------------------------------------- + * end of file + *---------------------------------------------------------------------------*/ + + diff --git a/libraries/mbed/rtos/rtx/TARGET_CORTEX_M/RTX_Conf.h b/libraries/mbed/rtos/rtx/TARGET_CORTEX_M/RTX_Conf.h new file mode 100644 index 0000000..0b0d461 --- /dev/null +++ b/libraries/mbed/rtos/rtx/TARGET_CORTEX_M/RTX_Conf.h @@ -0,0 +1,72 @@ +/*---------------------------------------------------------------------------- + * RL-ARM - RTX + *---------------------------------------------------------------------------- + * Name: RTX_CONFIG.H + * Purpose: Exported functions of RTX_Config.c + * Rev.: V4.60 + *---------------------------------------------------------------------------- + * + * Copyright (c) 1999-2009 KEIL, 2009-2012 ARM Germany GmbH + * All rights reserved. + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * - Neither the name of ARM nor the names of its contributors may be used + * to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDERS AND CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + *---------------------------------------------------------------------------*/ + + +/* Error Codes */ +#define OS_ERR_STK_OVF 1 +#define OS_ERR_FIFO_OVF 2 +#define OS_ERR_MBX_OVF 3 + +/* Definitions */ +#define BOX_ALIGN_8 0x80000000 +#define _declare_box(pool,size,cnt) U32 pool[(((size)+3)/4)*(cnt) + 3] +#define _declare_box8(pool,size,cnt) U64 pool[(((size)+7)/8)*(cnt) + 2] +#define _init_box8(pool,size,bsize) _init_box (pool,size,(bsize) | BOX_ALIGN_8) + +/* Variables */ +extern U32 idle_task_stack[]; +extern U32 os_fifo[]; +extern void *os_active_TCB[]; + +/* Constants */ +extern U16 const os_maxtaskrun; +extern U32 const os_trv; +extern U8 const os_flags; +extern U32 const os_rrobin; +extern U32 const os_clockrate; +extern U32 const os_timernum; +extern U16 const idle_task_stack_size; + +extern U8 const os_fifo_size; + +/* Functions */ +extern void os_idle_demon (void); +extern int os_tick_init (void); +extern void os_tick_irqack (void); +extern void os_tmr_call (U16 info); +extern void os_error (U32 err_code); + +/*---------------------------------------------------------------------------- + * end of file + *---------------------------------------------------------------------------*/ diff --git a/libraries/mbed/rtos/rtx/TARGET_CORTEX_M/RTX_Conf_CM.c b/libraries/mbed/rtos/rtx/TARGET_CORTEX_M/RTX_Conf_CM.c new file mode 100755 index 0000000..788edfd --- /dev/null +++ b/libraries/mbed/rtos/rtx/TARGET_CORTEX_M/RTX_Conf_CM.c @@ -0,0 +1,342 @@ +/*---------------------------------------------------------------------------- + * RL-ARM - RTX + *---------------------------------------------------------------------------- + * Name: RTX_Conf_CM.C + * Purpose: Configuration of CMSIS RTX Kernel for Cortex-M + * Rev.: V4.60 + *---------------------------------------------------------------------------- + * + * Copyright (c) 1999-2009 KEIL, 2009-2012 ARM Germany GmbH + * All rights reserved. + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * - Neither the name of ARM nor the names of its contributors may be used + * to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDERS AND CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + *---------------------------------------------------------------------------*/ + +#include "cmsis_os.h" + + +/*---------------------------------------------------------------------------- + * RTX User configuration part BEGIN + *---------------------------------------------------------------------------*/ + +//-------- <<< Use Configuration Wizard in Context Menu >>> ----------------- +// +// <h>Thread Configuration +// ======================= +// +// <o>Number of concurrent running threads <0-250> +// <i> Defines max. number of threads that will run at the same time. +// counting "main", but not counting "osTimerThread" +// <i> Default: 6 +#ifndef OS_TASKCNT +# if defined(TARGET_LPC1768) || defined(TARGET_LPC2368) || defined(TARGET_LPC4088) || defined(TARGET_LPC4088_DM) || defined(TARGET_LPC4330) || defined(TARGET_LPC4337) || defined(TARGET_LPC1347) || defined(TARGET_K64F) || defined(TARGET_STM32F401RE)\ + || defined(TARGET_STM32F410RB) || defined(TARGET_KL46Z) || defined(TARGET_KL43Z) || defined(TARGET_STM32F407) || defined(TARGET_F407VG) || defined(TARGET_STM32F303VC) || defined(TARGET_LPC1549) || defined(TARGET_LPC11U68) \ + || defined(TARGET_STM32F411RE) || defined(TARGET_STM32F405RG) || defined(TARGET_K22F) || defined(TARGET_STM32F429ZI) || defined(TARGET_STM32F401VC) || defined(TARGET_MAX32610) || defined(TARGET_MAX32600) || defined(TARGET_TEENSY3_1) \ + || defined(TARGET_STM32L152RE) || defined(TARGET_STM32F446RE) || defined(TARGET_STM32F446VE) || defined(TARGET_STM32L476VG) || defined(TARGET_STM32L476RG) || defined(TARGET_STM32F469NI) || defined(TARGET_STM32F746NG) || defined(TARGET_STM32F746ZG) || defined(TARGET_STM32L152RC) +# define OS_TASKCNT 14 +# elif defined(TARGET_LPC11U24) || defined(TARGET_STM32F303RE) || defined(TARGET_STM32F303K8) || defined(TARGET_LPC11U35_401) || defined(TARGET_LPC11U35_501) || defined(TARGET_LPCCAPPUCCINO) || defined(TARGET_LPC1114) \ + || defined(TARGET_LPC812) || defined(TARGET_KL25Z) || defined(TARGET_KL26Z) || defined(TARGET_KL05Z) || defined(TARGET_STM32F100RB) || defined(TARGET_STM32F051R8) \ + || defined(TARGET_STM32F103RB) || defined(TARGET_LPC824) || defined(TARGET_STM32F302R8) || defined(TARGET_STM32F334R8) || defined(TARGET_STM32F334C8) \ + || defined(TARGET_STM32L053R8) || defined(TARGET_STM32L053C8) || defined(TARGET_STM32L073RZ) || defined(TARGET_STM32F072RB) || defined(TARGET_STM32F091RC) || defined(TARGET_NZ32_SC151) \ + || defined(TARGET_SSCI824) || defined(TARGET_STM32F030R8) || defined(TARGET_STM32F070RB) +# define OS_TASKCNT 6 +# else +# error "no target defined" +# endif +#endif + +// <o>Scheduler (+ interrupts) stack size [bytes] <64-4096:8><#/4> +#ifndef OS_SCHEDULERSTKSIZE +# if defined(TARGET_LPC1768) || defined(TARGET_LPC2368) || defined(TARGET_LPC4088) || defined(TARGET_LPC4088_DM) || defined(TARGET_LPC4330) || defined(TARGET_LPC4337) || defined(TARGET_LPC1347) || defined(TARGET_K64F) || defined(TARGET_STM32F401RE)\ + || defined(TARGET_STM32F410RB) || defined(TARGET_KL46Z) || defined(TARGET_KL43Z) || defined(TARGET_STM32F407) || defined(TARGET_F407VG) || defined(TARGET_STM32F303VC) || defined(TARGET_LPC1549) || defined(TARGET_LPC11U68) \ + || defined(TARGET_STM32F411RE) || defined(TARGET_STM32F405RG) || defined(TARGET_K22F) || defined(TARGET_STM32F429ZI) || defined(TARGET_STM32F401VC) || defined(TARGET_MAX32610) || defined(TARGET_MAX32600) || defined(TARGET_TEENSY3_1) \ + || defined(TARGET_STM32L152RE) || defined(TARGET_STM32F446RE) || defined(TARGET_STM32F446VE) || defined(TARGET_STM32L476VG) || defined(TARGET_STM32L476RG) || defined(TARGET_STM32F469NI) || defined(TARGET_STM32F746NG) || defined(TARGET_STM32F746ZG) || defined(TARGET_STM32L152RC) +# define OS_SCHEDULERSTKSIZE 256 +# elif defined(TARGET_LPC11U24) || defined(TARGET_LPC11U35_401) || defined(TARGET_LPC11U35_501) || defined(TARGET_LPCCAPPUCCINO) || defined(TARGET_LPC1114) \ + || defined(TARGET_LPC812) || defined(TARGET_KL25Z) || defined(TARGET_KL26Z) || defined(TARGET_KL05Z) || defined(TARGET_STM32F100RB) || defined(TARGET_STM32F051R8) \ + || defined(TARGET_STM32F103RB) || defined(TARGET_LPC824) || defined(TARGET_STM32F302R8) || defined(TARGET_STM32F072RB) || defined(TARGET_STM32F091RC) || defined(TARGET_NZ32_SC151) \ + || defined(TARGET_SSCI824) || defined(TARGET_STM32F030R8) || defined(TARGET_STM32F070RB) +# define OS_SCHEDULERSTKSIZE 128 +# elif defined(TARGET_STM32F334R8) || defined(TARGET_STM32F303RE) || defined(TARGET_STM32F303K8) || defined(TARGET_STM32F334C8) || defined(TARGET_STM32L053R8) || defined(TARGET_STM32L053C8) || defined(TARGET_STM32L073RZ) +# define OS_SCHEDULERSTKSIZE 112 +# else +# error "no target defined" +# endif +#endif + +// <o>Idle stack size [bytes] <64-4096:8><#/4> +// <i> Defines default stack size for the Idle thread. +#ifndef OS_IDLESTKSIZE + #define OS_IDLESTKSIZE 128 +#endif + +// <o>Timer Thread stack size [bytes] <64-4096:8><#/4> +// <i> Defines stack size for Timer thread. +// <i> Default: 200 +#ifndef OS_TIMERSTKSZ + #define OS_TIMERSTKSZ WORDS_STACK_SIZE +#endif + +// <q>Check for stack overflow +// <i> Includes the stack checking code for stack overflow. +// <i> Note that additional code reduces the Kernel performance. +#ifndef OS_STKCHECK + #define OS_STKCHECK 1 +#endif + +// <o>Processor mode for thread execution +// <0=> Unprivileged mode +// <1=> Privileged mode +// <i> Default: Privileged mode +#ifndef OS_RUNPRIV + #define OS_RUNPRIV 1 +#endif + +// </h> +// <h>SysTick Timer Configuration +// ============================== +// +// <o>Timer clock value [Hz] <1-1000000000> +// <i> Defines the timer clock value. +// <i> Default: 6000000 (6MHz) +#ifndef OS_CLOCK +# if defined(TARGET_LPC1768) || defined(TARGET_LPC2368) || defined(TARGET_TEENSY3_1) +# define OS_CLOCK 96000000 + +# elif defined(TARGET_LPC1347) || defined(TARGET_STM32F303VC) || defined(TARGET_LPC1549) || defined(TARGET_STM32F334R8) || defined(TARGET_STM32F334C8) || defined(TARGET_STM32F303RE) +# define OS_CLOCK 72000000 + +# elif defined(TARGET_STM32F303K8) +# define OS_CLOCK 64000000 + +# elif defined(TARGET_LPC11U24) || defined(TARGET_LPC11U35_401) || defined(TARGET_LPC11U35_501) || defined(TARGET_LPCCAPPUCCINO) || defined(TARGET_LPC1114) || defined(TARGET_KL25Z) \ + || defined(TARGET_KL26Z) || defined(TARGET_KL05Z) || defined(TARGET_KL46Z) || defined(TARGET_KL43Z) || defined(TARGET_STM32F051R8) || defined(TARGET_LPC11U68) || defined(TARGET_STM32F072RB) || defined(TARGET_STM32F091RC) +# define OS_CLOCK 48000000 + +# elif defined(TARGET_LPC812) +# define OS_CLOCK 36000000 + +# elif defined(TARGET_LPC824) || defined(TARGET_SSCI824) +# define OS_CLOCK 30000000 + +# elif defined(TARGET_STM32F100RB) +# define OS_CLOCK 24000000 + +# elif defined(TARGET_LPC4088) || defined(TARGET_LPC4088_DM) || defined(TARGET_K64F) || defined(TARGET_K22F) +# define OS_CLOCK 120000000 + +# elif defined(TARGET_LPC4330) +# define OS_CLOCK 204000000 + +# elif defined(TARGET_LPC4337) +# define OS_CLOCK 204000000 + +# elif defined(TARGET_STM32F407) || defined(TARGET_F407VG) +# define OS_CLOCK 168000000 + +# elif defined(TARGET_STM32F401RE) +# define OS_CLOCK 84000000 + +# elif defined(TARGET_STM32F411RE) +# define OS_CLOCK 100000000 + +# elif defined(TARGET_STM32F410RB) +# define OS_CLOCK 100000000 + +#elif defined(TARGET_STM32F103RB) +# define OS_CLOCK 72000000 + +#elif defined(TARGET_STM32F429ZI) +# define OS_CLOCK 168000000 + +#elif defined(TARGET_STM32F302R8) +# define OS_CLOCK 72000000 + +#elif defined(TARGET_STM32L053R8) || defined(TARGET_STM32L053C8) || defined(TARGET_STM32L073RZ) +# define OS_CLOCK 32000000 + +#elif defined(TARGET_STM32F401VC) +# define OS_CLOCK 84000000 + +# elif defined(TARGET_STM32F746NG) || defined(TARGET_STM32F746ZG) +# define OS_CLOCK 216000000 + +#elif defined(TARGET_MAX32610) || defined(TARGET_MAX32600) +# define OS_CLOCK 24000000 + +#elif defined(TARGET_NZ32_SC151) +# define OS_CLOCK 32000000 + +#elif defined(TARGET_STM32L152RE) +# define OS_CLOCK 24000000 + +#elif (defined(TARGET_STM32F446RE) || defined(TARGET_STM32F446VE)) +# define OS_CLOCK 180000000 + +#elif defined(TARGET_STM32F030R8) +# define OS_CLOCK 48000000 + +#elif defined(TARGET_STM32F070RB) +# define OS_CLOCK 48000000 + +#elif defined(TARGET_STM32L476VG) || defined(TARGET_STM32L476RG) +# define OS_CLOCK 80000000 + +#elif defined(TARGET_STM32F469NI) +# define OS_CLOCK 168000000 + +#elif defined(TARGET_STM32L152RC) +# define OS_CLOCK 24000000 + +# else +# error "no target defined" +# endif +#endif + +// <o>Timer tick value [us] <1-1000000> +// <i> Defines the timer tick value. +// <i> Default: 1000 (1ms) +#ifndef OS_TICK + #define OS_TICK 1000 +#endif + +// </h> + +// <h>System Configuration +// ======================= +// +// <e>Round-Robin Thread switching +// =============================== +// +// <i> Enables Round-Robin Thread switching. +#ifndef OS_ROBIN + #define OS_ROBIN 1 +#endif + +// <o>Round-Robin Timeout [ticks] <1-1000> +// <i> Defines how long a thread will execute before a thread switch. +// <i> Default: 5 +#ifndef OS_ROBINTOUT + #define OS_ROBINTOUT 5 +#endif + +// </e> + +// <e>User Timers +// ============== +// <i> Enables user Timers +#ifndef OS_TIMERS + #define OS_TIMERS 1 +#endif + +// <o>Timer Thread Priority +// <1=> Low +// <2=> Below Normal +// <3=> Normal +// <4=> Above Normal +// <5=> High +// <6=> Realtime (highest) +// <i> Defines priority for Timer Thread +// <i> Default: High +#ifndef OS_TIMERPRIO + #define OS_TIMERPRIO 5 +#endif + +// <o>Timer Callback Queue size <1-32> +// <i> Number of concurrent active timer callback functions. +// <i> Default: 4 +#ifndef OS_TIMERCBQSZ + #define OS_TIMERCBQS 4 +#endif + +// </e> + +// <o>ISR FIFO Queue size<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 +// <i> ISR functions store requests to this buffer, +// <i> when they are called from the interrupt handler. +// <i> Default: 16 entries +#ifndef OS_FIFOSZ + #define OS_FIFOSZ 16 +#endif + +// </h> + +//------------- <<< end of configuration section >>> ----------------------- + +// Standard library system mutexes +// =============================== +// Define max. number system mutexes that are used to protect +// the arm standard runtime library. For microlib they are not used. +#ifndef OS_MUTEXCNT + #define OS_MUTEXCNT 12 +#endif + +/*---------------------------------------------------------------------------- + * RTX User configuration part END + *---------------------------------------------------------------------------*/ + +#define OS_TRV ((uint32_t)(((double)OS_CLOCK*(double)OS_TICK)/1E6)-1) + + +/*---------------------------------------------------------------------------- + * OS Idle daemon + *---------------------------------------------------------------------------*/ +extern void rtos_idle_loop(void); + +void os_idle_demon (void) { + /* The idle demon is a system thread, running when no other thread is */ + /* ready to run. */ + rtos_idle_loop(); +} + +/*---------------------------------------------------------------------------- + * RTX Errors + *---------------------------------------------------------------------------*/ +extern void mbed_die(void); + +void os_error (uint32_t err_code) { + /* This function is called when a runtime error is detected. Parameter */ + /* 'err_code' holds the runtime error code (defined in RTX_Conf.h). */ + mbed_die(); +} + +void sysThreadError(osStatus status) { + if (status != osOK) { + mbed_die(); + } +} + +/*---------------------------------------------------------------------------- + * RTX Configuration Functions + *---------------------------------------------------------------------------*/ + +#include "RTX_CM_lib.h" + +/*---------------------------------------------------------------------------- + * end of file + *---------------------------------------------------------------------------*/ + diff --git a/libraries/mbed/rtos/rtx/TARGET_CORTEX_M/TARGET_RTOS_M4_M7/TOOLCHAIN_GCC/HAL_CM4.S b/libraries/mbed/rtos/rtx/TARGET_CORTEX_M/TARGET_RTOS_M4_M7/TOOLCHAIN_GCC/HAL_CM4.S new file mode 100644 index 0000000..ce3242b --- /dev/null +++ b/libraries/mbed/rtos/rtx/TARGET_CORTEX_M/TARGET_RTOS_M4_M7/TOOLCHAIN_GCC/HAL_CM4.S @@ -0,0 +1,405 @@ +/*---------------------------------------------------------------------------- + * RL-ARM - RTX + *---------------------------------------------------------------------------- + * Name: HAL_CM4.S + * Purpose: Hardware Abstraction Layer for Cortex-M4 + * Rev.: V4.70 + *---------------------------------------------------------------------------- + * + * Copyright (c) 1999-2009 KEIL, 2009-2013 ARM Germany GmbH + * All rights reserved. + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * - Neither the name of ARM nor the names of its contributors may be used + * to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDERS AND CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + *---------------------------------------------------------------------------*/ + + .file "HAL_CM4.S" + .syntax unified + + .equ TCB_STACKF, 32 + .equ TCB_TSTACK, 40 + + +/*---------------------------------------------------------------------------- + * Functions + *---------------------------------------------------------------------------*/ + + .thumb + + .section ".text" + .align 2 + + +/*--------------------------- rt_set_PSP ------------------------------------*/ + +# void rt_set_PSP (U32 stack); + + .thumb_func + .type rt_set_PSP, %function + .global rt_set_PSP +rt_set_PSP: + .fnstart + .cantunwind + + MSR PSP,R0 + BX LR + + .fnend + .size rt_set_PSP, .-rt_set_PSP + + +/*--------------------------- rt_get_PSP ------------------------------------*/ + +# U32 rt_get_PSP (void); + + .thumb_func + .type rt_get_PSP, %function + .global rt_get_PSP +rt_get_PSP: + .fnstart + .cantunwind + + MRS R0,PSP + BX LR + + .fnend + .size rt_get_PSP, .-rt_get_PSP + + +/*--------------------------- os_set_env ------------------------------------*/ + +# void os_set_env (void); + /* Switch to Unprivileged/Privileged Thread mode, use PSP. */ + + .thumb_func + .type os_set_env, %function + .global os_set_env +os_set_env: + .fnstart + .cantunwind + + MOV R0,SP /* PSP = MSP */ + MSR PSP,R0 + LDR R0,=os_flags + LDRB R0,[R0] + LSLS R0,#31 + ITE NE + MOVNE R0,#0x02 /* Privileged Thread mode, use PSP */ + MOVEQ R0,#0x03 /* Unprivileged Thread mode, use PSP */ + MSR CONTROL,R0 + BX LR + + .fnend + .size os_set_env, .-os_set_env + + +/*--------------------------- _alloc_box ------------------------------------*/ + +# void *_alloc_box (void *box_mem); + /* Function wrapper for Unprivileged/Privileged mode. */ + + .thumb_func + .type _alloc_box, %function + .global _alloc_box +_alloc_box: + .fnstart + .cantunwind + + LDR R12,=rt_alloc_box + MRS R3,IPSR + LSLS R3,#24 + IT NE + BXNE R12 + MRS R3,CONTROL + LSLS R3,#31 + IT EQ + BXEQ R12 + SVC 0 + BX LR + + .fnend + .size _alloc_box, .-_alloc_box + + +/*--------------------------- _free_box -------------------------------------*/ + +# int _free_box (void *box_mem, void *box); + /* Function wrapper for Unprivileged/Privileged mode. */ + + .thumb_func + .type _free_box, %function + .global _free_box +_free_box: + .fnstart + .cantunwind + + LDR R12,=rt_free_box + MRS R3,IPSR + LSLS R3,#24 + IT NE + BXNE R12 + MRS R3,CONTROL + LSLS R3,#31 + IT EQ + BXEQ R12 + SVC 0 + BX LR + + .fnend + .size _free_box, .-_free_box + + +/*-------------------------- SVC_Handler ------------------------------------*/ + +# void SVC_Handler (void); + + .thumb_func + .type SVC_Handler, %function + .global SVC_Handler +SVC_Handler: + .ifdef IFX_XMC4XXX + .global SVC_Handler_Veneer +SVC_Handler_Veneer: + .endif + .fnstart + .cantunwind + + MRS R0,PSP /* Read PSP */ + LDR R1,[R0,#24] /* Read Saved PC from Stack */ + LDRB R1,[R1,#-2] /* Load SVC Number */ + CBNZ R1,SVC_User + + LDM R0,{R0-R3,R12} /* Read R0-R3,R12 from stack */ + PUSH {R4,LR} /* Save EXC_RETURN */ + BLX R12 /* Call SVC Function */ + POP {R4,LR} /* Restore EXC_RETURN */ + + MRS R12,PSP /* Read PSP */ + STM R12,{R0-R2} /* Store return values */ + + LDR R3,=os_tsk + LDM R3,{R1,R2} /* os_tsk.run, os_tsk.new */ + CMP R1,R2 + .ifdef IFX_XMC4XXX + ITT EQ + PUSHEQ {LR} + POPEQ {PC} + .else + IT EQ + BXEQ LR /* RETI, no task switch */ + .endif + + CBZ R1,SVC_Next /* Runtask deleted? */ + TST LR,#0x10 /* is it extended frame? */ + #ifdef __FPU_PRESENT + ITTE EQ + VSTMDBEQ R12!,{S16-S31} /* yes, stack also VFP hi-regs */ + #else + ITE EQ + #endif + MOVEQ R0,#0x01 /* os_tsk->stack_frame val */ + MOVNE R0,#0x00 + STRB R0,[R1,#TCB_STACKF] /* os_tsk.run->stack_frame = val */ + STMDB R12!,{R4-R11} /* Save Old context */ + STR R12,[R1,#TCB_TSTACK] /* Update os_tsk.run->tsk_stack */ + + PUSH {R2,R3} + BL rt_stk_check /* Check for Stack overflow */ + POP {R2,R3} + +SVC_Next: + STR R2,[R3] /* os_tsk.run = os_tsk.new */ + + LDR R12,[R2,#TCB_TSTACK] /* os_tsk.new->tsk_stack */ + LDMIA R12!,{R4-R11} /* Restore New Context */ + LDRB R0,[R2,#TCB_STACKF] /* Stack Frame */ + CMP R0,#0 /* Basic/Extended Stack Frame */ + #ifdef __FPU_PRESENT + ITTE NE + VLDMIANE R12!,{S16-S31} /* restore VFP hi-registers */ + #else + ITE NE + #endif + MVNNE LR,#~0xFFFFFFED /* set EXC_RETURN value */ + MVNEQ LR,#~0xFFFFFFFD + MSR PSP,R12 /* Write PSP */ + +SVC_Exit: + .ifdef IFX_XMC4XXX + PUSH {LR} + POP {PC} + .else + BX LR + .endif + + /*------------------- User SVC ------------------------------*/ + +SVC_User: + PUSH {R4,LR} /* Save Registers */ + LDR R2,=SVC_Count + LDR R2,[R2] + CMP R1,R2 + BHI SVC_Done /* Overflow */ + + LDR R4,=SVC_Table-4 + LDR R4,[R4,R1,LSL #2] /* Load SVC Function Address */ + + LDM R0,{R0-R3,R12} /* Read R0-R3,R12 from stack */ + BLX R4 /* Call SVC Function */ + + MRS R12,PSP + STM R12,{R0-R3} /* Function return values */ +SVC_Done: + POP {R4,PC} /* RETI */ + + .fnend + .size SVC_Handler, .-SVC_Handler + + +/*-------------------------- PendSV_Handler ---------------------------------*/ + +# void PendSV_Handler (void); + + .thumb_func + .type PendSV_Handler, %function + .global PendSV_Handler + .global Sys_Switch +PendSV_Handler: + .ifdef IFX_XMC4XXX + .global PendSV_Handler_Veneer +PendSV_Handler_Veneer: + .endif + .fnstart + .cantunwind + + PUSH {R4,LR} /* Save EXC_RETURN */ + BL rt_pop_req + +Sys_Switch: + POP {R4,LR} /* Restore EXC_RETURN */ + + LDR R3,=os_tsk + LDM R3,{R1,R2} /* os_tsk.run, os_tsk.new */ + CMP R1,R2 + .ifdef IFX_XMC4XXX + ITT EQ + PUSHEQ {LR} + POPEQ {PC} + .else + IT EQ + BXEQ LR /* RETI, no task switch */ + .endif + + MRS R12,PSP /* Read PSP */ + TST LR,#0x10 /* is it extended frame? */ + #ifdef __FPU_PRESENT + ITTE EQ + VSTMDBEQ R12!,{S16-S31} /* yes, stack also VFP hi-regs */ + #else + ITE EQ + #endif + MOVEQ R0,#0x01 /* os_tsk->stack_frame val */ + MOVNE R0,#0x00 + STRB R0,[R1,#TCB_STACKF] /* os_tsk.run->stack_frame = val */ + STMDB R12!,{R4-R11} /* Save Old context */ + STR R12,[R1,#TCB_TSTACK] /* Update os_tsk.run->tsk_stack */ + + PUSH {R2,R3} + BL rt_stk_check /* Check for Stack overflow */ + POP {R2,R3} + + STR R2,[R3] /* os_tsk.run = os_tsk.new */ + + LDR R12,[R2,#TCB_TSTACK] /* os_tsk.new->tsk_stack */ + LDMIA R12!,{R4-R11} /* Restore New Context */ + LDRB R0,[R2,#TCB_STACKF] /* Stack Frame */ + CMP R0,#0 /* Basic/Extended Stack Frame */ + #ifdef __FPU_PRESENT + ITTE NE + VLDMIANE R12!,{S16-S31} /* restore VFP hi-registers */ + #else + ITE NE + #endif + MVNNE LR,#~0xFFFFFFED /* set EXC_RETURN value */ + MVNEQ LR,#~0xFFFFFFFD + MSR PSP,R12 /* Write PSP */ + +Sys_Exit: + .ifdef IFX_XMC4XXX + PUSH {LR} + POP {PC} + .else + BX LR /* Return to Thread Mode */ + .endif + + .fnend + .size PendSV_Handler, .-PendSV_Handler + + +/*-------------------------- SysTick_Handler --------------------------------*/ + +# void SysTick_Handler (void); + + .thumb_func + .type SysTick_Handler, %function + .global SysTick_Handler +SysTick_Handler: + .ifdef IFX_XMC4XXX + .global SysTick_Handler_Veneer +SysTick_Handler_Veneer: + .endif + .fnstart + .cantunwind + + PUSH {R4,LR} /* Save EXC_RETURN */ + BL rt_systick + B Sys_Switch + + .fnend + .size SysTick_Handler, .-SysTick_Handler + + +/*-------------------------- OS_Tick_Handler --------------------------------*/ + +# void OS_Tick_Handler (void); + + .thumb_func + .type OS_Tick_Handler, %function + .global OS_Tick_Handler +OS_Tick_Handler: + .fnstart + .cantunwind + + PUSH {R4,LR} /* Save EXC_RETURN */ + BL os_tick_irqack + BL rt_systick + B Sys_Switch + + .fnend + .size OS_Tick_Handler, .-OS_Tick_Handler + + + .end + +/*---------------------------------------------------------------------------- + * end of file + *---------------------------------------------------------------------------*/ diff --git a/libraries/mbed/rtos/rtx/TARGET_CORTEX_M/TARGET_RTOS_M4_M7/TOOLCHAIN_GCC/SVC_Table.S b/libraries/mbed/rtos/rtx/TARGET_CORTEX_M/TARGET_RTOS_M4_M7/TOOLCHAIN_GCC/SVC_Table.S new file mode 100644 index 0000000..2b99321 --- /dev/null +++ b/libraries/mbed/rtos/rtx/TARGET_CORTEX_M/TARGET_RTOS_M4_M7/TOOLCHAIN_GCC/SVC_Table.S @@ -0,0 +1,56 @@ +;/*---------------------------------------------------------------------------- +; * RL-ARM - RTX +; *---------------------------------------------------------------------------- +; * Name: SVC_TABLE.S +; * Purpose: Pre-defined SVC Table for Cortex-M +; * Rev.: V4.70 +; *---------------------------------------------------------------------------- +; * +; * Copyright (c) 1999-2009 KEIL, 2009-2013 ARM Germany GmbH +; * All rights reserved. +; * Redistribution and use in source and binary forms, with or without +; * modification, are permitted provided that the following conditions are met: +; * - Redistributions of source code must retain the above copyright +; * notice, this list of conditions and the following disclaimer. +; * - Redistributions in binary form must reproduce the above copyright +; * notice, this list of conditions and the following disclaimer in the +; * documentation and/or other materials provided with the distribution. +; * - Neither the name of ARM nor the names of its contributors may be used +; * to endorse or promote products derived from this software without +; * specific prior written permission. +; * +; * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +; * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +; * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +; * ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDERS AND CONTRIBUTORS BE +; * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +; * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +; * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +; * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +; * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +; * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +; * POSSIBILITY OF SUCH DAMAGE. +; *---------------------------------------------------------------------------*/ + + + .file "SVC_Table.S" + + + .section ".svc_table" + + .global SVC_Table +SVC_Table: +/* Insert user SVC functions here. SVC 0 used by RTL Kernel. */ +# .long __SVC_1 /* user SVC function */ +SVC_End: + + .global SVC_Count +SVC_Count: + .long (SVC_End-SVC_Table)/4 + + + .end + +/*---------------------------------------------------------------------------- + * end of file + *---------------------------------------------------------------------------*/ diff --git a/libraries/mbed/rtos/rtx/TARGET_CORTEX_M/cmsis_os.h b/libraries/mbed/rtos/rtx/TARGET_CORTEX_M/cmsis_os.h new file mode 100644 index 0000000..d1e7198 --- /dev/null +++ b/libraries/mbed/rtos/rtx/TARGET_CORTEX_M/cmsis_os.h @@ -0,0 +1,774 @@ +/* ---------------------------------------------------------------------- + * Copyright (C) 2012 ARM Limited. All rights reserved. + * + * $Date: 5. June 2012 + * $Revision: V1.01 + * + * 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 typedef's + * - const attribute added to the osXxxxDef macros + * Added: osTimerDelete, osMutexDelete, osSemaphoreDelete + * Added: osKernelInitialize + * -------------------------------------------------------------------- */ + +/** +\page cmsis_os_h Header File Template: cmsis_os.h + +The file \b cmsis_os.h is a template header file for a CMSIS-RTOS compliant Real-Time Operating System (RTOS). +Each RTOS that is compliant with CMSIS-RTOS shall provide a specific \b cmsis_os.h header file that represents +its implementation. + +The file cmsis_os.h contains: + - CMSIS-RTOS API function definitions + - struct definitions for parameters and return types + - status and priority values used by CMSIS-RTOS API functions + - macros for defining threads and other kernel objects + + +<b>Name conventions and header file modifications</b> + +All definitions are prefixed with \b os to give an unique name space for CMSIS-RTOS functions. +Definitions that are prefixed \b os_ are not used in the application code but local to this header file. +All definitions and functions that belong to a module are grouped and have a common prefix, i.e. \b osThread. + +Definitions that are marked with <b>CAN BE CHANGED</b> can be adapted towards the needs of the actual CMSIS-RTOS implementation. +These definitions can be specific to the underlying RTOS kernel. + +Definitions that are marked with <b>MUST REMAIN UNCHANGED</b> cannot be altered. Otherwise the CMSIS-RTOS implementation is no longer +compliant to the standard. Note that some functions are optional and need not to be provided by every CMSIS-RTOS implementation. + + +<b>Function calls from interrupt service routines</b> + +The following CMSIS-RTOS functions can be called from threads and interrupt service routines (ISR): + - \ref osSignalSet + - \ref osSemaphoreRelease + - \ref osPoolAlloc, \ref osPoolCAlloc, \ref osPoolFree + - \ref osMessagePut, \ref osMessageGet + - \ref osMailAlloc, \ref osMailCAlloc, \ref osMailGet, \ref osMailPut, \ref osMailFree + +Functions that cannot be called from an ISR are verifying the interrupt status and return in case that they are called +from an ISR context the status code \b osErrorISR. In some implementations this condition might be caught using the HARD FAULT vector. + +Some CMSIS-RTOS implementations support CMSIS-RTOS function calls from multiple ISR at the same time. +If this is impossible, the CMSIS-RTOS rejects calls by nested ISR functions with the status code \b osErrorISRRecursive. + + +<b>Define and reference object definitions</b> + +With <b>\#define osObjectsExternal</b> objects are defined as external symbols. This allows to create a consistent header file +that is used throughout a project as shown below: + +<i>Header File</i> +\code +#include <cmsis_os.h> // CMSIS RTOS header file + +// Thread definition +extern void thread_sample (void const *argument); // function prototype +osThreadDef (thread_sample, osPriorityBelowNormal, 1, 100); + +// Pool definition +osPoolDef(MyPool, 10, long); +\endcode + + +This header file defines all objects when included in a C/C++ source file. When <b>\#define osObjectsExternal</b> is +present before the header file, the objects are defined as external symbols. A single consistent header file can therefore be +used throughout the whole project. + +<i>Example</i> +\code +#include "osObjects.h" // Definition of the CMSIS-RTOS objects +\endcode + +\code +#define osObjectExternal // Objects will be defined as external symbols +#include "osObjects.h" // Reference to the CMSIS-RTOS objects +\endcode + +*/ + +#ifndef _CMSIS_OS_H +#define _CMSIS_OS_H + +/// \note MUST REMAIN UNCHANGED: \b osCMSIS identifies the CMSIS-RTOS API version. +#define osCMSIS 0x10001 ///< API version (main [31:16] .sub [15:0]) + +/// \note CAN BE CHANGED: \b osCMSIS_KERNEL identifies the underlying RTOS kernel and version number. +#define osCMSIS_RTX ((4<<16)|61) ///< RTOS identification and version (main [31:16] .sub [15:0]) + +/// \note MUST REMAIN UNCHANGED: \b osKernelSystemId shall be consistent in every CMSIS-RTOS. +#define osKernelSystemId "RTX V4.61" ///< RTOS identification string + + +#define CMSIS_OS_RTX + +// The stack space occupied is mainly dependent on the underling C standard library +#if defined(TOOLCHAIN_GCC) || defined(TOOLCHAIN_ARM_STD) || defined(TOOLCHAIN_IAR) +# define WORDS_STACK_SIZE 512 +#elif defined(TOOLCHAIN_ARM_MICRO) +# define WORDS_STACK_SIZE 128 +#endif + +#define DEFAULT_STACK_SIZE (WORDS_STACK_SIZE*4) + + +/// \note MUST REMAIN UNCHANGED: \b osFeature_xxx shall be consistent in every CMSIS-RTOS. +#define osFeature_MainThread 1 ///< main thread 1=main can be thread, 0=not available +#define osFeature_Pool 1 ///< Memory Pools: 1=available, 0=not available +#define osFeature_MailQ 1 ///< Mail Queues: 1=available, 0=not available +#define osFeature_MessageQ 1 ///< Message Queues: 1=available, 0=not available +#define osFeature_Signals 16 ///< maximum number of Signal Flags available per thread +#define osFeature_Semaphore 65535 ///< maximum count for \ref osSemaphoreCreate function +#define osFeature_Wait 0 ///< osWait function: 1=available, 0=not available + +#if defined (__CC_ARM) +#define os_InRegs __value_in_regs // Compiler specific: force struct in registers +#elif defined (__ICCARM__) +#define os_InRegs __value_in_regs // Compiler specific: force struct in registers +#else +#define os_InRegs +#endif + +#include <stdint.h> +#include <stddef.h> + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include "os_tcb.h" + +// ==== Enumeration, structures, defines ==== + +/// Priority used for thread control. +/// \note MUST REMAIN UNCHANGED: \b osPriority shall be consistent in every CMSIS-RTOS. +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 thread has illegal priority +} osPriority; + +/// Timeout value. +/// \note MUST REMAIN UNCHANGED: \b osWaitForever shall be consistent in every CMSIS-RTOS. +#define osWaitForever 0xFFFFFFFF ///< wait forever timeout value + +/// Status code values returned by CMSIS-RTOS functions. +/// \note MUST REMAIN UNCHANGED: \b osStatus shall be consistent in every CMSIS-RTOS. +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. + os_status_reserved = 0x7FFFFFFF ///< prevent from enum down-size compiler optimization. +} osStatus; + + +/// Timer type value for the timer definition. +/// \note MUST REMAIN UNCHANGED: \b os_timer_type shall be consistent in every CMSIS-RTOS. +typedef enum { + osTimerOnce = 0, ///< one-shot timer + osTimerPeriodic = 1 ///< repeating timer +} os_timer_type; + +/// Entry point of a thread. +/// \note MUST REMAIN UNCHANGED: \b os_pthread shall be consistent in every CMSIS-RTOS. +typedef void (*os_pthread) (void const *argument); + +/// Entry point of a timer call back function. +/// \note MUST REMAIN UNCHANGED: \b os_ptimer shall be consistent in every CMSIS-RTOS. +typedef void (*os_ptimer) (void const *argument); + +// >>> the following data type definitions may shall adapted towards a specific RTOS + +/// Thread ID identifies the thread (pointer to a thread control block). +/// \note CAN BE CHANGED: \b os_thread_cb is implementation specific in every CMSIS-RTOS. +typedef struct os_thread_cb *osThreadId; + +/// Timer ID identifies the timer (pointer to a timer control block). +/// \note CAN BE CHANGED: \b os_timer_cb is implementation specific in every CMSIS-RTOS. +typedef struct os_timer_cb *osTimerId; + +/// Mutex ID identifies the mutex (pointer to a mutex control block). +/// \note CAN BE CHANGED: \b os_mutex_cb is implementation specific in every CMSIS-RTOS. +typedef struct os_mutex_cb *osMutexId; + +/// Semaphore ID identifies the semaphore (pointer to a semaphore control block). +/// \note CAN BE CHANGED: \b os_semaphore_cb is implementation specific in every CMSIS-RTOS. +typedef struct os_semaphore_cb *osSemaphoreId; + +/// Pool ID identifies the memory pool (pointer to a memory pool control block). +/// \note CAN BE CHANGED: \b os_pool_cb is implementation specific in every CMSIS-RTOS. +typedef struct os_pool_cb *osPoolId; + +/// Message ID identifies the message queue (pointer to a message queue control block). +/// \note CAN BE CHANGED: \b os_messageQ_cb is implementation specific in every CMSIS-RTOS. +typedef struct os_messageQ_cb *osMessageQId; + +/// Mail ID identifies the mail queue (pointer to a mail queue control block). +/// \note CAN BE CHANGED: \b os_mailQ_cb is implementation specific in every CMSIS-RTOS. +typedef struct os_mailQ_cb *osMailQId; + + +/// Thread Definition structure contains startup information of a thread. +/// \note CAN BE CHANGED: \b os_thread_def is implementation specific in every CMSIS-RTOS. +typedef struct os_thread_def { + os_pthread pthread; ///< start address of thread function + osPriority tpriority; ///< initial thread priority + uint32_t stacksize; ///< stack size requirements in bytes + uint32_t *stack_pointer; ///< pointer to the stack memory block + struct OS_TCB tcb; +} osThreadDef_t; + +/// Timer Definition structure contains timer parameters. +/// \note CAN BE CHANGED: \b os_timer_def is implementation specific in every CMSIS-RTOS. +typedef struct os_timer_def { + os_ptimer ptimer; ///< start address of a timer function + void *timer; ///< pointer to internal data +} osTimerDef_t; + +/// Mutex Definition structure contains setup information for a mutex. +/// \note CAN BE CHANGED: \b os_mutex_def is implementation specific in every CMSIS-RTOS. +typedef struct os_mutex_def { + void *mutex; ///< pointer to internal data +} osMutexDef_t; + +/// Semaphore Definition structure contains setup information for a semaphore. +/// \note CAN BE CHANGED: \b os_semaphore_def is implementation specific in every CMSIS-RTOS. +typedef struct os_semaphore_def { + void *semaphore; ///< pointer to internal data +} osSemaphoreDef_t; + +/// Definition structure for memory block allocation. +/// \note CAN BE CHANGED: \b os_pool_def is implementation specific in every CMSIS-RTOS. +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; + +/// Definition structure for message queue. +/// \note CAN BE CHANGED: \b os_messageQ_def is implementation specific in every CMSIS-RTOS. +typedef struct os_messageQ_def { + uint32_t queue_sz; ///< number of elements in the queue + void *pool; ///< memory array for messages +} osMessageQDef_t; + +/// Definition structure for mail queue. +/// \note CAN BE CHANGED: \b os_mailQ_def is implementation specific in every CMSIS-RTOS. +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; + +/// Event structure contains detailed information about an event. +/// \note MUST REMAIN UNCHANGED: \b os_event shall be consistent in every CMSIS-RTOS. +/// However the struct may be extended at the end. +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 Control Functions ==== + +/// Initialize the RTOS Kernel for creating objects. +/// \return status code that indicates the execution status of the function. +/// \note MUST REMAIN UNCHANGED: \b osKernelInitialize shall be consistent in every CMSIS-RTOS. +osStatus osKernelInitialize (void); + +/// Start the RTOS Kernel. +/// \return status code that indicates the execution status of the function. +/// \note MUST REMAIN UNCHANGED: \b osKernelStart shall be consistent in every CMSIS-RTOS. +osStatus osKernelStart (void); + +/// Check if the RTOS kernel is already started. +/// \note MUST REMAIN UNCHANGED: \b osKernelRunning shall be consistent in every CMSIS-RTOS. +/// \return 0 RTOS is not started, 1 RTOS is started. +int32_t osKernelRunning(void); + + +// ==== Thread Management ==== + +/// 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 stacksz stack size (in bytes) requirements for the thread function. +/// \note CAN BE CHANGED: The parameters to \b osThreadDef shall be consistent but the +/// macro body is implementation specific in every CMSIS-RTOS. +#if defined (osObjectsExternal) // object is external +#define osThreadDef(name, priority, stacksz) \ +extern osThreadDef_t os_thread_def_##name +#else // define the object +#define osThreadDef(name, priority, stacksz) \ +uint32_t os_thread_def_stack_##name [stacksz / sizeof(uint32_t)]; \ +osThreadDef_t os_thread_def_##name = \ +{ (name), (priority), (stacksz), (os_thread_def_stack_##name)} +#endif + +/// Access a Thread definition. +/// \param name name of the thread definition object. +/// \note CAN BE CHANGED: The parameter to \b osThread shall be consistent but the +/// macro body is implementation specific in every CMSIS-RTOS. +#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. +/// \note MUST REMAIN UNCHANGED: \b osThreadCreate shall be consistent in every CMSIS-RTOS. +osThreadId osThreadCreate (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. +/// \note MUST REMAIN UNCHANGED: \b osThreadGetId shall be consistent in every CMSIS-RTOS. +osThreadId osThreadGetId (void); + +/// Terminate execution of a thread and remove it from Active Threads. +/// \param[in] thread_id thread ID obtained by \ref osThreadCreate or \ref osThreadGetId. +/// \return status code that indicates the execution status of the function. +/// \note MUST REMAIN UNCHANGED: \b osThreadTerminate shall be consistent in every CMSIS-RTOS. +osStatus osThreadTerminate (osThreadId thread_id); + +/// Pass control to next thread that is in state \b READY. +/// \return status code that indicates the execution status of the function. +/// \note MUST REMAIN UNCHANGED: \b osThreadYield shall be consistent in every CMSIS-RTOS. +osStatus osThreadYield (void); + +/// Change priority of an active 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. +/// \note MUST REMAIN UNCHANGED: \b osThreadSetPriority shall be consistent in every CMSIS-RTOS. +osStatus osThreadSetPriority (osThreadId thread_id, osPriority priority); + +/// Get current priority of an active thread. +/// \param[in] thread_id thread ID obtained by \ref osThreadCreate or \ref osThreadGetId. +/// \return current priority value of the thread function. +/// \note MUST REMAIN UNCHANGED: \b osThreadGetPriority shall be consistent in every CMSIS-RTOS. +osPriority osThreadGetPriority (osThreadId thread_id); + + +// ==== Generic Wait Functions ==== + +/// Wait for Timeout (Time Delay). +/// \param[in] millisec time delay value +/// \return status code that indicates the execution status of the function. +osStatus osDelay (uint32_t millisec); + +#if (defined (osFeature_Wait) && (osFeature_Wait != 0)) // Generic Wait available + +/// Wait for Signal, Message, Mail, or Timeout. +/// \param[in] millisec timeout value or 0 in case of no time-out +/// \return event that contains signal, message, or mail information or error code. +/// \note MUST REMAIN UNCHANGED: \b osWait shall be consistent in every CMSIS-RTOS. +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. +/// \note CAN BE CHANGED: The parameter to \b osTimerDef shall be consistent but the +/// macro body is implementation specific in every CMSIS-RTOS. +#if defined (osObjectsExternal) // object is external +#define osTimerDef(name, function) \ +extern osTimerDef_t os_timer_def_##name +#else // define the object +#define osTimerDef(name, function) \ +uint32_t os_timer_cb_##name[5]; \ +osTimerDef_t os_timer_def_##name = \ +{ (function), (os_timer_cb_##name) } +#endif + +/// Access a Timer definition. +/// \param name name of the timer object. +/// \note CAN BE CHANGED: The parameter to \b osTimer shall be consistent but the +/// macro body is implementation specific in every CMSIS-RTOS. +#define osTimer(name) \ +&os_timer_def_##name + +/// Create 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. +/// \note MUST REMAIN UNCHANGED: \b osTimerCreate shall be consistent in every CMSIS-RTOS. +osTimerId osTimerCreate (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 time delay value of the timer. +/// \return status code that indicates the execution status of the function. +/// \note MUST REMAIN UNCHANGED: \b osTimerStart shall be consistent in every CMSIS-RTOS. +osStatus osTimerStart (osTimerId timer_id, uint32_t millisec); + +/// Stop the timer. +/// \param[in] timer_id timer ID obtained by \ref osTimerCreate. +/// \return status code that indicates the execution status of the function. +/// \note MUST REMAIN UNCHANGED: \b osTimerStop shall be consistent in every CMSIS-RTOS. +osStatus osTimerStop (osTimerId timer_id); + +/// Delete a timer that was created by \ref osTimerCreate. +/// \param[in] timer_id timer ID obtained by \ref osTimerCreate. +/// \return status code that indicates the execution status of the function. +/// \note MUST REMAIN UNCHANGED: \b osTimerDelete shall be consistent in every CMSIS-RTOS. +osStatus osTimerDelete (osTimerId timer_id); + + +// ==== 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. +/// \note MUST REMAIN UNCHANGED: \b osSignalSet shall be consistent in every CMSIS-RTOS. +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. +/// \note MUST REMAIN UNCHANGED: \b osSignalClear shall be consistent in every CMSIS-RTOS. +int32_t osSignalClear (osThreadId thread_id, int32_t signals); + +/// Get Signal Flags status of an active thread. +/// \param[in] thread_id thread ID obtained by \ref osThreadCreate or \ref osThreadGetId. +/// \return previous signal flags of the specified thread or 0x80000000 in case of incorrect parameters. +/// \note MUST REMAIN UNCHANGED: \b osSignalGet shall be consistent in every CMSIS-RTOS. +int32_t osSignalGet (osThreadId thread_id); + +/// Wait for one or more Signal Flags to become signaled for the current \b RUNNING thread. +/// \param[in] signals wait until all specified signal flags set or 0 for any single signal flag. +/// \param[in] millisec timeout value or 0 in case of no time-out. +/// \return event flag information or error code. +/// \note MUST REMAIN UNCHANGED: \b osSignalWait shall be consistent in every CMSIS-RTOS. +os_InRegs osEvent osSignalWait (int32_t signals, uint32_t millisec); + + +// ==== Mutex Management ==== + +/// Define a Mutex. +/// \param name name of the mutex object. +/// \note CAN BE CHANGED: The parameter to \b osMutexDef shall be consistent but the +/// macro body is implementation specific in every CMSIS-RTOS. +#if defined (osObjectsExternal) // object is external +#define osMutexDef(name) \ +extern osMutexDef_t os_mutex_def_##name +#else // define the object +#define osMutexDef(name) \ +uint32_t os_mutex_cb_##name[3]; \ +osMutexDef_t os_mutex_def_##name = { (os_mutex_cb_##name) } +#endif + +/// Access a Mutex definition. +/// \param name name of the mutex object. +/// \note CAN BE CHANGED: The parameter to \b osMutex shall be consistent but the +/// macro body is implementation specific in every CMSIS-RTOS. +#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. +/// \note MUST REMAIN UNCHANGED: \b osMutexCreate shall be consistent in every CMSIS-RTOS. +osMutexId osMutexCreate (osMutexDef_t *mutex_def); + +/// Wait until a Mutex becomes available. +/// \param[in] mutex_id mutex ID obtained by \ref osMutexCreate. +/// \param[in] millisec timeout value or 0 in case of no time-out. +/// \return status code that indicates the execution status of the function. +/// \note MUST REMAIN UNCHANGED: \b osMutexWait shall be consistent in every CMSIS-RTOS. +osStatus osMutexWait (osMutexId mutex_id, uint32_t millisec); + +/// 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. +/// \note MUST REMAIN UNCHANGED: \b osMutexRelease shall be consistent in every CMSIS-RTOS. +osStatus osMutexRelease (osMutexId mutex_id); + +/// Delete a Mutex that was created by \ref osMutexCreate. +/// \param[in] mutex_id mutex ID obtained by \ref osMutexCreate. +/// \return status code that indicates the execution status of the function. +/// \note MUST REMAIN UNCHANGED: \b osMutexDelete shall be consistent in every CMSIS-RTOS. +osStatus osMutexDelete (osMutexId mutex_id); + + +// ==== Semaphore Management Functions ==== + +#if (defined (osFeature_Semaphore) && (osFeature_Semaphore != 0)) // Semaphore available + +/// Define a Semaphore object. +/// \param name name of the semaphore object. +/// \note CAN BE CHANGED: The parameter to \b osSemaphoreDef shall be consistent but the +/// macro body is implementation specific in every CMSIS-RTOS. +#if defined (osObjectsExternal) // object is external +#define osSemaphoreDef(name) \ +extern osSemaphoreDef_t os_semaphore_def_##name +#else // define the object +#define osSemaphoreDef(name) \ +uint32_t os_semaphore_cb_##name[2]; \ +osSemaphoreDef_t os_semaphore_def_##name = { (os_semaphore_cb_##name) } +#endif + +/// Access a Semaphore definition. +/// \param name name of the semaphore object. +/// \note CAN BE CHANGED: The parameter to \b osSemaphore shall be consistent but the +/// macro body is implementation specific in every CMSIS-RTOS. +#define osSemaphore(name) \ +&os_semaphore_def_##name + +/// Create and Initialize a Semaphore object used for managing resources. +/// \param[in] semaphore_def semaphore definition referenced with \ref osSemaphore. +/// \param[in] count number of available resources. +/// \return semaphore ID for reference by other functions or NULL in case of error. +/// \note MUST REMAIN UNCHANGED: \b osSemaphoreCreate shall be consistent in every CMSIS-RTOS. +osSemaphoreId osSemaphoreCreate (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 timeout value or 0 in case of no time-out. +/// \return number of available tokens, or -1 in case of incorrect parameters. +/// \note MUST REMAIN UNCHANGED: \b osSemaphoreWait shall be consistent in every CMSIS-RTOS. +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. +/// \note MUST REMAIN UNCHANGED: \b osSemaphoreRelease shall be consistent in every CMSIS-RTOS. +osStatus osSemaphoreRelease (osSemaphoreId semaphore_id); + +/// Delete a Semaphore that was created by \ref osSemaphoreCreate. +/// \param[in] semaphore_id semaphore object referenced with \ref osSemaphoreCreate. +/// \return status code that indicates the execution status of the function. +/// \note MUST REMAIN UNCHANGED: \b osSemaphoreDelete shall be consistent in every CMSIS-RTOS. +osStatus osSemaphoreDelete (osSemaphoreId semaphore_id); + +#endif // Semaphore available + + +// ==== Memory Pool Management Functions ==== + +#if (defined (osFeature_Pool) && (osFeature_Pool != 0)) // Memory Pool Management 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). +/// \note CAN BE CHANGED: The parameter to \b osPoolDef shall be consistent but the +/// macro body is implementation specific in every CMSIS-RTOS. +#if defined (osObjectsExternal) // object is external +#define osPoolDef(name, no, type) \ +extern osPoolDef_t os_pool_def_##name +#else // define the object +#define osPoolDef(name, no, type) \ +uint32_t os_pool_m_##name[3+((sizeof(type)+3)/4)*(no)]; \ +osPoolDef_t os_pool_def_##name = \ +{ (no), sizeof(type), (os_pool_m_##name) } +#endif + +/// \brief Access a Memory Pool definition. +/// \param name name of the memory pool +/// \note CAN BE CHANGED: The parameter to \b osPool shall be consistent but the +/// macro body is implementation specific in every CMSIS-RTOS. +#define osPool(name) \ +&os_pool_def_##name + +/// Create and Initialize a memory pool. +/// \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. +/// \note MUST REMAIN UNCHANGED: \b osPoolCreate shall be consistent in every CMSIS-RTOS. +osPoolId osPoolCreate (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. +/// \note MUST REMAIN UNCHANGED: \b osPoolAlloc shall be consistent in every CMSIS-RTOS. +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. +/// \note MUST REMAIN UNCHANGED: \b osPoolCAlloc shall be consistent in every CMSIS-RTOS. +void *osPoolCAlloc (osPoolId pool_id); + +/// Return an allocated memory block back to a specific memory pool. +/// \param[in] pool_id memory pool ID obtain referenced with \ref osPoolCreate. +/// \param[in] block address of the allocated memory block that is returned to the memory pool. +/// \return status code that indicates the execution status of the function. +/// \note MUST REMAIN UNCHANGED: \b osPoolFree shall be consistent in every CMSIS-RTOS. +osStatus osPoolFree (osPoolId pool_id, void *block); + +#endif // Memory Pool Management available + + +// ==== Message Queue Management Functions ==== + +#if (defined (osFeature_MessageQ) && (osFeature_MessageQ != 0)) // Message Queues 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). +/// \note CAN BE CHANGED: The parameter to \b osMessageQDef shall be consistent but the +/// macro body is implementation specific in every CMSIS-RTOS. +#if defined (osObjectsExternal) // object is external +#define osMessageQDef(name, queue_sz, type) \ +extern osMessageQDef_t os_messageQ_def_##name +#else // define the object +#define osMessageQDef(name, queue_sz, type) \ +uint32_t os_messageQ_q_##name[4+(queue_sz)]; \ +osMessageQDef_t os_messageQ_def_##name = \ +{ (queue_sz), (os_messageQ_q_##name) } +#endif + +/// \brief Access a Message Queue Definition. +/// \param name name of the queue +/// \note CAN BE CHANGED: The parameter to \b osMessageQ shall be consistent but the +/// macro body is implementation specific in every CMSIS-RTOS. +#define osMessageQ(name) \ +&os_messageQ_def_##name + +/// Create and Initialize a Message Queue. +/// \param[in] queue_def 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. +/// \note MUST REMAIN UNCHANGED: \b osMessageCreate shall be consistent in every CMSIS-RTOS. +osMessageQId osMessageCreate (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 timeout value or 0 in case of no time-out. +/// \return status code that indicates the execution status of the function. +/// \note MUST REMAIN UNCHANGED: \b osMessagePut shall be consistent in every CMSIS-RTOS. +osStatus osMessagePut (osMessageQId queue_id, uint32_t info, uint32_t millisec); + +/// Get a Message or Wait for a Message from a Queue. +/// \param[in] queue_id message queue ID obtained with \ref osMessageCreate. +/// \param[in] millisec timeout value or 0 in case of no time-out. +/// \return event information that includes status code. +/// \note MUST REMAIN UNCHANGED: \b osMessageGet shall be consistent in every CMSIS-RTOS. +os_InRegs osEvent osMessageGet (osMessageQId queue_id, uint32_t millisec); + +#endif // Message Queues available + + +// ==== Mail Queue Management Functions ==== + +#if (defined (osFeature_MailQ) && (osFeature_MailQ != 0)) // Mail Queues available + +/// \brief Create a Mail Queue Definition. +/// \param name name of the queue +/// \param queue_sz maximum number of messages in queue +/// \param type data type of a single message element +/// \note CAN BE CHANGED: The parameter to \b osMailQDef shall be consistent but the +/// macro body is implementation specific in every CMSIS-RTOS. +#if defined (osObjectsExternal) // object is external +#define osMailQDef(name, queue_sz, type) \ +extern osMailQDef_t os_mailQ_def_##name +#else // define the object +#define osMailQDef(name, queue_sz, type) \ +uint32_t os_mailQ_q_##name[4+(queue_sz)]; \ +uint32_t os_mailQ_m_##name[3+((sizeof(type)+3)/4)*(queue_sz)]; \ +void * os_mailQ_p_##name[2] = { (os_mailQ_q_##name), os_mailQ_m_##name }; \ +osMailQDef_t os_mailQ_def_##name = \ +{ (queue_sz), sizeof(type), (os_mailQ_p_##name) } +#endif + +/// \brief Access a Mail Queue Definition. +/// \param name name of the queue +/// \note CAN BE CHANGED: The parameter to \b osMailQ shall be consistent but the +/// macro body is implementation specific in every CMSIS-RTOS. +#define osMailQ(name) \ +&os_mailQ_def_##name + +/// Create and Initialize mail queue. +/// \param[in] queue_def reference to the mail queue definition obtain 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. +/// \note MUST REMAIN UNCHANGED: \b osMailCreate shall be consistent in every CMSIS-RTOS. +osMailQId osMailCreate (osMailQDef_t *queue_def, osThreadId thread_id); + +/// Allocate a memory block from a mail. +/// \param[in] queue_id mail queue ID obtained with \ref osMailCreate. +/// \param[in] millisec timeout value 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. +/// \note MUST REMAIN UNCHANGED: \b osMailAlloc shall be consistent in every CMSIS-RTOS. +void *osMailAlloc (osMailQId queue_id, uint32_t millisec); + +/// Allocate a memory block from a mail and set memory block to zero. +/// \param[in] queue_id mail queue ID obtained with \ref osMailCreate. +/// \param[in] millisec timeout value 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. +/// \note MUST REMAIN UNCHANGED: \b osMailCAlloc shall be consistent in every CMSIS-RTOS. +void *osMailCAlloc (osMailQId queue_id, uint32_t millisec); + +/// Put a mail to a queue. +/// \param[in] queue_id mail queue ID obtained with \ref osMailCreate. +/// \param[in] mail memory block previously allocated with \ref osMailAlloc or \ref osMailCAlloc. +/// \return status code that indicates the execution status of the function. +/// \note MUST REMAIN UNCHANGED: \b osMailPut shall be consistent in every CMSIS-RTOS. +osStatus osMailPut (osMailQId queue_id, void *mail); + +/// Get a mail from a queue. +/// \param[in] queue_id mail queue ID obtained with \ref osMailCreate. +/// \param[in] millisec timeout value or 0 in case of no time-out +/// \return event that contains mail information or error code. +/// \note MUST REMAIN UNCHANGED: \b osMailGet shall be consistent in every CMSIS-RTOS. +os_InRegs osEvent osMailGet (osMailQId queue_id, uint32_t millisec); + +/// Free a memory block from a mail. +/// \param[in] queue_id mail queue ID obtained with \ref osMailCreate. +/// \param[in] mail pointer to the memory block that was obtained with \ref osMailGet. +/// \return status code that indicates the execution status of the function. +/// \note MUST REMAIN UNCHANGED: \b osMailFree shall be consistent in every CMSIS-RTOS. +osStatus osMailFree (osMailQId queue_id, void *mail); + +#endif // Mail Queues available + + +#ifdef __cplusplus +} +#endif + +#endif // _CMSIS_OS_H diff --git a/libraries/mbed/rtos/rtx/TARGET_CORTEX_M/os_tcb.h b/libraries/mbed/rtos/rtx/TARGET_CORTEX_M/os_tcb.h new file mode 100644 index 0000000..800f7f5 --- /dev/null +++ b/libraries/mbed/rtos/rtx/TARGET_CORTEX_M/os_tcb.h @@ -0,0 +1,51 @@ +#ifndef OS_TCB_H +#define OS_TCB_H + +/* Types */ +typedef char S8; +typedef unsigned char U8; +typedef short S16; +typedef unsigned short U16; +typedef int S32; +typedef unsigned int U32; +typedef long long S64; +typedef unsigned long long U64; +typedef unsigned char BIT; +typedef unsigned int BOOL; +typedef void (*FUNCP)(void); + +typedef struct OS_TCB { + /* General part: identical for all implementations. */ + U8 cb_type; /* Control Block Type */ + U8 state; /* Task state */ + U8 prio; /* Execution priority */ + U8 task_id; /* Task ID value for optimized TCB access */ + struct OS_TCB *p_lnk; /* Link pointer for ready/sem. wait list */ + struct OS_TCB *p_rlnk; /* Link pointer for sem./mbx lst backwards */ + struct OS_TCB *p_dlnk; /* Link pointer for delay list */ + struct OS_TCB *p_blnk; /* Link pointer for delay list backwards */ + U16 delta_time; /* Time until time out */ + U16 interval_time; /* Time interval for periodic waits */ + U16 events; /* Event flags */ + U16 waits; /* Wait flags */ + void **msg; /* Direct message passing when task waits */ + + /* Hardware dependant part: specific for CM processor */ + U8 stack_frame; /* Stack frame: 0=Basic, 1=Extended */ + U8 reserved1; + U16 reserved2; + U32 priv_stack; /* Private stack size in bytes */ + U32 tsk_stack; /* Current task Stack pointer (R13) */ + U32 *stack; /* Pointer to Task Stack memory block */ + + /* Library dependant part */ +#if defined (__CC_ARM) && !defined (__MICROLIB) + /* A memory space for arm standard library. */ + U32 std_libspace[96/4]; +#endif + + /* Task entry point used for uVision debugger */ + FUNCP ptask; /* Task entry address */ +} *P_TCB; + +#endif diff --git a/libraries/mbed/rtos/rtx/TARGET_CORTEX_M/rt_CMSIS.c b/libraries/mbed/rtos/rtx/TARGET_CORTEX_M/rt_CMSIS.c new file mode 100644 index 0000000..a747caf --- /dev/null +++ b/libraries/mbed/rtos/rtx/TARGET_CORTEX_M/rt_CMSIS.c @@ -0,0 +1,1887 @@ +/*---------------------------------------------------------------------------- + * RL-ARM - RTX + *---------------------------------------------------------------------------- + * Name: rt_CMSIS.c + * Purpose: CMSIS RTOS API + * Rev.: V4.60 + *---------------------------------------------------------------------------- + * + * Copyright (c) 1999-2009 KEIL, 2009-2012 ARM Germany GmbH + * All rights reserved. + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * - Neither the name of ARM nor the names of its contributors may be used + * to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDERS AND CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + *---------------------------------------------------------------------------*/ + +#define __CMSIS_GENERIC + +#if defined (__CORTEX_M4) || defined (__CORTEX_M4F) + #include "core_cm4.h" +#elif defined (__CORTEX_M7) || defined (__CORTEX_M7F) + #include "core_cm7.h" +#elif defined (__CORTEX_M3) + #include "core_cm3.h" +#elif defined (__CORTEX_M0) + #include "core_cm0.h" +#elif defined (__CORTEX_M0PLUS) + #include "core_cm0plus.h" +#else + #error "Missing __CORTEX_Mx definition" +#endif + +#include "rt_TypeDef.h" +#include "RTX_Conf.h" +#include "rt_System.h" +#include "rt_Task.h" +#include "rt_Event.h" +#include "rt_List.h" +#include "rt_Time.h" +#include "rt_Mutex.h" +#include "rt_Semaphore.h" +#include "rt_Mailbox.h" +#include "rt_MemBox.h" +#include "rt_HAL_CM.h" + +#define os_thread_cb OS_TCB + +#include "cmsis_os.h" + +#if (osFeature_Signals != 16) +#error Invalid "osFeature_Signals" value! +#endif +#if (osFeature_Semaphore > 65535) +#error Invalid "osFeature_Semaphore" value! +#endif +#if (osFeature_Wait != 0) +#error osWait not supported! +#endif + + +// ==== Enumeration, structures, defines ==== + +// Service Calls defines + +#if defined (__CC_ARM) /* ARM Compiler */ + +#define __NO_RETURN __declspec(noreturn) + +#define osEvent_type osEvent +#define osEvent_ret_status ret +#define osEvent_ret_value ret +#define osEvent_ret_msg ret +#define osEvent_ret_mail ret + +#define osCallback_type osCallback +#define osCallback_ret ret + +#define SVC_0_1(f,t,...) \ +__svc_indirect(0) t _##f (t(*)()); \ + t f (void); \ +__attribute__((always_inline)) \ +static __inline t __##f (void) { \ + return _##f(f); \ +} + +#define SVC_1_1(f,t,t1,...) \ +__svc_indirect(0) t _##f (t(*)(t1),t1); \ + t f (t1 a1); \ +__attribute__((always_inline)) \ +static __inline t __##f (t1 a1) { \ + return _##f(f,a1); \ +} + +#define SVC_2_1(f,t,t1,t2,...) \ +__svc_indirect(0) t _##f (t(*)(t1,t2),t1,t2); \ + t f (t1 a1, t2 a2); \ +__attribute__((always_inline)) \ +static __inline t __##f (t1 a1, t2 a2) { \ + return _##f(f,a1,a2); \ +} + +#define SVC_3_1(f,t,t1,t2,t3,...) \ +__svc_indirect(0) t _##f (t(*)(t1,t2,t3),t1,t2,t3); \ + t f (t1 a1, t2 a2, t3 a3); \ +__attribute__((always_inline)) \ +static __inline t __##f (t1 a1, t2 a2, t3 a3) { \ + return _##f(f,a1,a2,a3); \ +} + +#define SVC_4_1(f,t,t1,t2,t3,t4,...) \ +__svc_indirect(0) t _##f (t(*)(t1,t2,t3,t4),t1,t2,t3,t4); \ + t f (t1 a1, t2 a2, t3 a3, t4 a4); \ +__attribute__((always_inline)) \ +static __inline t __##f (t1 a1, t2 a2, t3 a3, t4 a4) { \ + return _##f(f,a1,a2,a3,a4); \ +} + +#define SVC_1_2 SVC_1_1 +#define SVC_1_3 SVC_1_1 +#define SVC_2_3 SVC_2_1 + +#elif defined (__GNUC__) /* GNU Compiler */ + +#define __NO_RETURN __attribute__((noreturn)) + +typedef uint32_t __attribute__((vector_size(8))) ret64; +typedef uint32_t __attribute__((vector_size(16))) ret128; + +#define RET_pointer __r0 +#define RET_int32_t __r0 +#define RET_osStatus __r0 +#define RET_osPriority __r0 +#define RET_osEvent {(osStatus)__r0, {(uint32_t)__r1}, {(void *)__r2}} +#define RET_osCallback {(void *)__r0, (void *)__r1} + +#define osEvent_type ret128 +#define osEvent_ret_status (ret128){ret.status} +#define osEvent_ret_value (ret128){ret.status, ret.value.v} +#define osEvent_ret_msg (ret128){ret.status, ret.value.v, (uint32_t)ret.def.message_id} +#define osEvent_ret_mail (ret128){ret.status, ret.value.v, (uint32_t)ret.def.mail_id} + +#define osCallback_type ret64 +#define osCallback_ret (ret64) {(uint32_t)ret.fp, (uint32_t)ret.arg} + +#define SVC_ArgN(n) \ + register int __r##n __asm("r"#n); + +#define SVC_ArgR(n,t,a) \ + register t __r##n __asm("r"#n) = a; + +#define SVC_Arg0() \ + SVC_ArgN(0) \ + SVC_ArgN(1) \ + SVC_ArgN(2) \ + SVC_ArgN(3) + +#define SVC_Arg1(t1) \ + SVC_ArgR(0,t1,a1) \ + SVC_ArgN(1) \ + SVC_ArgN(2) \ + SVC_ArgN(3) + +#define SVC_Arg2(t1,t2) \ + SVC_ArgR(0,t1,a1) \ + SVC_ArgR(1,t2,a2) \ + SVC_ArgN(2) \ + SVC_ArgN(3) + +#define SVC_Arg3(t1,t2,t3) \ + SVC_ArgR(0,t1,a1) \ + SVC_ArgR(1,t2,a2) \ + SVC_ArgR(2,t3,a3) \ + SVC_ArgN(3) + +#define SVC_Arg4(t1,t2,t3,t4) \ + SVC_ArgR(0,t1,a1) \ + SVC_ArgR(1,t2,a2) \ + SVC_ArgR(2,t3,a3) \ + SVC_ArgR(3,t4,a4) + +#if (defined (__CORTEX_M0)) || defined (__CORTEX_M0PLUS) +#define SVC_Call(f) \ + __asm volatile \ + ( \ + "ldr r7,="#f"\n\t" \ + "mov r12,r7\n\t" \ + "svc 0" \ + : "=r" (__r0), "=r" (__r1), "=r" (__r2), "=r" (__r3) \ + : "r" (__r0), "r" (__r1), "r" (__r2), "r" (__r3) \ + : "r7", "r12", "lr", "cc" \ + ); +#else +#define SVC_Call(f) \ + __asm volatile \ + ( \ + "ldr r12,="#f"\n\t" \ + "svc 0" \ + : "=r" (__r0), "=r" (__r1), "=r" (__r2), "=r" (__r3) \ + : "r" (__r0), "r" (__r1), "r" (__r2), "r" (__r3) \ + : "r12", "lr", "cc" \ + ); +#endif + +#define SVC_0_1(f,t,rv) \ +__attribute__((always_inline)) \ +static inline t __##f (void) { \ + SVC_Arg0(); \ + SVC_Call(f); \ + return (t) rv; \ +} + +#define SVC_1_1(f,t,t1,rv) \ +__attribute__((always_inline)) \ +static inline t __##f (t1 a1) { \ + SVC_Arg1(t1); \ + SVC_Call(f); \ + return (t) rv; \ +} + +#define SVC_2_1(f,t,t1,t2,rv) \ +__attribute__((always_inline)) \ +static inline t __##f (t1 a1, t2 a2) { \ + SVC_Arg2(t1,t2); \ + SVC_Call(f); \ + return (t) rv; \ +} + +#define SVC_3_1(f,t,t1,t2,t3,rv) \ +__attribute__((always_inline)) \ +static inline t __##f (t1 a1, t2 a2, t3 a3) { \ + SVC_Arg3(t1,t2,t3); \ + SVC_Call(f); \ + return (t) rv; \ +} + +#define SVC_4_1(f,t,t1,t2,t3,t4,rv) \ +__attribute__((always_inline)) \ +static inline t __##f (t1 a1, t2 a2, t3 a3, t4 a4) { \ + SVC_Arg4(t1,t2,t3,t4); \ + SVC_Call(f); \ + return (t) rv; \ +} + +#define SVC_1_2 SVC_1_1 +#define SVC_1_3 SVC_1_1 +#define SVC_2_3 SVC_2_1 + +#elif defined (__ICCARM__) /* IAR Compiler */ + +#define __NO_RETURN __noreturn + +#define osEvent_type osEvent +#define osEvent_ret_status ret +#define osEvent_ret_value ret +#define osEvent_ret_msg ret +#define osEvent_ret_mail ret + +#define osCallback_type osCallback +#define osCallback_ret ret + +#define RET_osEvent osEvent +#define RET_osCallback osCallback + +#define SVC_Setup(f) \ + __asm( \ + "mov r12,%0\n" \ + :: "r"(&f): "r12" \ + ); + + +#define SVC_0_1(f,t,...) \ +t f (void); \ +_Pragma("swi_number=0") __swi t _##f (void); \ +static inline t __##f (void) { \ + SVC_Setup(f); \ + return _##f(); \ +} + +#define SVC_1_1(f,t,t1,...) \ +t f (t1 a1); \ +_Pragma("swi_number=0") __swi t _##f (t1 a1); \ +static inline t __##f (t1 a1) { \ + SVC_Setup(f); \ + return _##f(a1); \ +} + +#define SVC_2_1(f,t,t1,t2,...) \ +t f (t1 a1, t2 a2); \ +_Pragma("swi_number=0") __swi t _##f (t1 a1, t2 a2); \ +static inline t __##f (t1 a1, t2 a2) { \ + SVC_Setup(f); \ + return _##f(a1,a2); \ +} + +#define SVC_3_1(f,t,t1,t2,t3,...) \ +t f (t1 a1, t2 a2, t3 a3); \ +_Pragma("swi_number=0") __swi t _##f (t1 a1, t2 a2, t3 a3); \ +static inline t __##f (t1 a1, t2 a2, t3 a3) { \ + SVC_Setup(f); \ + return _##f(a1,a2,a3); \ +} + +#define SVC_4_1(f,t,t1,t2,t3,t4,...) \ +t f (t1 a1, t2 a2, t3 a3, t4 a4); \ +_Pragma("swi_number=0") __swi t _##f (t1 a1, t2 a2, t3 a3, t4 a4); \ +static inline t __##f (t1 a1, t2 a2, t3 a3, t4 a4) { \ + SVC_Setup(f); \ + return _##f(a1,a2,a3,a4); \ +} + +#define SVC_1_2 SVC_1_1 +#define SVC_1_3 SVC_1_1 +#define SVC_2_3 SVC_2_1 + +#endif + + +// Callback structure +typedef struct { + void *fp; // Function pointer + void *arg; // Function argument +} osCallback; + + +// OS Section definitions +#ifdef OS_SECTIONS_LINK_INFO +extern const uint32_t os_section_id$$Base; +extern const uint32_t os_section_id$$Limit; +#endif + +// OS Timers external resources +extern osThreadDef_t os_thread_def_osTimerThread; +extern osThreadId osThreadId_osTimerThread; +extern osMessageQDef_t os_messageQ_def_osTimerMessageQ; +extern osMessageQId osMessageQId_osTimerMessageQ; + + +// ==== Helper Functions ==== + +/// Convert timeout in millisec to system ticks +static uint32_t rt_ms2tick (uint32_t millisec) { + uint32_t tick; + + if (millisec == osWaitForever) return 0xFFFF; // Indefinite timeout + if (millisec > 4000000) return 0xFFFE; // Max ticks supported + + tick = ((1000 * millisec) + os_clockrate - 1) / os_clockrate; + if (tick > 0xFFFE) return 0xFFFE; + + return tick; +} + +/// Convert Thread ID to TCB pointer +static P_TCB rt_tid2ptcb (osThreadId thread_id) { + P_TCB ptcb; + + if (thread_id == NULL) return NULL; + + if ((uint32_t)thread_id & 3) return NULL; + +#ifdef OS_SECTIONS_LINK_INFO + if ((os_section_id$$Base != 0) && (os_section_id$$Limit != 0)) { + if (thread_id < (osThreadId)os_section_id$$Base) return NULL; + if (thread_id >= (osThreadId)os_section_id$$Limit) return NULL; + } +#endif + + ptcb = thread_id; + + if (ptcb->cb_type != TCB) return NULL; + + return ptcb; +} + +/// Convert ID pointer to Object pointer +static void *rt_id2obj (void *id) { + + if ((uint32_t)id & 3) return NULL; + +#ifdef OS_SECTIONS_LINK_INFO + if ((os_section_id$$Base != 0) && (os_section_id$$Limit != 0)) { + if (id < (void *)os_section_id$$Base) return NULL; + if (id >= (void *)os_section_id$$Limit) return NULL; + } +#endif + + return id; +} + + +// ==== Kernel Control ==== + +uint8_t os_initialized; // Kernel Initialized flag +uint8_t os_running; // Kernel Running flag + +// Kernel Control Service Calls declarations +SVC_0_1(svcKernelInitialize, osStatus, RET_osStatus) +SVC_0_1(svcKernelStart, osStatus, RET_osStatus) +SVC_0_1(svcKernelRunning, int32_t, RET_int32_t) + +extern void sysThreadError (osStatus status); +osThreadId svcThreadCreate (osThreadDef_t *thread_def, void *argument); +osMessageQId svcMessageCreate (osMessageQDef_t *queue_def, osThreadId thread_id); + +// Kernel Control Service Calls + +/// Initialize the RTOS Kernel for creating objects +osStatus svcKernelInitialize (void) { + if (os_initialized) return osOK; + + rt_sys_init(); // RTX System Initialization + os_tsk.run->prio = 255; // Highest priority + + sysThreadError(osOK); + + os_initialized = 1; + + return osOK; +} + +/// Start the RTOS Kernel +osStatus svcKernelStart (void) { + + if (os_running) return osOK; + + // Create OS Timers resources (Message Queue & Thread) + osMessageQId_osTimerMessageQ = svcMessageCreate (&os_messageQ_def_osTimerMessageQ, NULL); + osThreadId_osTimerThread = svcThreadCreate(&os_thread_def_osTimerThread, NULL); + + rt_tsk_prio(0, 0); // Lowest priority + __set_PSP(os_tsk.run->tsk_stack + 8*4); // New context + os_tsk.run = NULL; // Force context switch + + rt_sys_start(); + + os_running = 1; + + return osOK; +} + +/// Check if the RTOS kernel is already started +int32_t svcKernelRunning(void) { + return os_running; +} + +// Kernel Control Public API + +/// Initialize the RTOS Kernel for creating objects +osStatus osKernelInitialize (void) { + if (__get_IPSR() != 0) return osErrorISR; // Not allowed in ISR + if ((__get_CONTROL() & 1) == 0) { // Privileged mode + return svcKernelInitialize(); + } else { + return __svcKernelInitialize(); + } +} + +/// Start the RTOS Kernel +osStatus osKernelStart (void) { + uint32_t stack[8]; + + if (__get_IPSR() != 0) return osErrorISR; // Not allowed in ISR + switch (__get_CONTROL() & 0x03) { + case 0x00: // Privileged Thread mode & MSP + __set_PSP((uint32_t)(stack + 8)); // Initial PSP + if (os_flags & 1) { + __set_CONTROL(0x02); // Set Privileged Thread mode & PSP + } else { + __set_CONTROL(0x03); // Set Unprivileged Thread mode & PSP + } + __DSB(); + __ISB(); + break; + case 0x01: // Unprivileged Thread mode & MSP + return osErrorOS; + case 0x02: // Privileged Thread mode & PSP + if ((os_flags & 1) == 0) { // Unprivileged Thread mode requested + __set_CONTROL(0x03); // Set Unprivileged Thread mode & PSP + __DSB(); + __ISB(); + } + break; + case 0x03: // Unprivileged Thread mode & PSP + if (os_flags & 1) return osErrorOS; // Privileged Thread mode requested + break; + } + return __svcKernelStart(); +} + +/// Check if the RTOS kernel is already started +int32_t osKernelRunning(void) { + if ((__get_IPSR() != 0) || ((__get_CONTROL() & 1) == 0)) { + // in ISR or Privileged + return os_running; + } else { + return __svcKernelRunning(); + } +} + + +// ==== Thread Management ==== + +__NO_RETURN void osThreadExit (void); + +// Thread Service Calls declarations +SVC_2_1(svcThreadCreate, osThreadId, osThreadDef_t *, void *, RET_pointer) +SVC_0_1(svcThreadGetId, osThreadId, RET_pointer) +SVC_1_1(svcThreadTerminate, osStatus, osThreadId, RET_osStatus) +SVC_0_1(svcThreadYield, osStatus, RET_osStatus) +SVC_2_1(svcThreadSetPriority, osStatus, osThreadId, osPriority, RET_osStatus) +SVC_1_1(svcThreadGetPriority, osPriority, osThreadId, RET_osPriority) + +// Thread Service Calls +extern OS_TID rt_get_TID (void); +extern void rt_init_context (P_TCB p_TCB, U8 priority, FUNCP task_body); + +/// Create a thread and add it to Active Threads and set it to state READY +osThreadId svcThreadCreate (osThreadDef_t *thread_def, void *argument) { + P_TCB ptcb; + + if ((thread_def == NULL) || + (thread_def->pthread == NULL) || + (thread_def->tpriority < osPriorityIdle) || + (thread_def->tpriority > osPriorityRealtime) || + (thread_def->stacksize == 0) || + (thread_def->stack_pointer == NULL) ) { + sysThreadError(osErrorParameter); + return NULL; + } + + U8 priority = thread_def->tpriority - osPriorityIdle + 1; + P_TCB task_context = &thread_def->tcb; + + /* Utilize the user provided stack. */ + task_context->stack = (U32*)thread_def->stack_pointer; + task_context->priv_stack = thread_def->stacksize; + /* Find a free entry in 'os_active_TCB' table. */ + OS_TID tsk = rt_get_TID (); + os_active_TCB[tsk-1] = task_context; + task_context->task_id = tsk; + /* Pass parameter 'argv' to 'rt_init_context' */ + task_context->msg = argument; + /* Initialize thread context structure, including the thread's stack. */ + rt_init_context (task_context, priority, (FUNCP)thread_def->pthread); + + /* Dispatch this task to the scheduler for execution. */ + DBG_TASK_NOTIFY(task_context, __TRUE); + rt_dispatch (task_context); + + ptcb = (P_TCB)os_active_TCB[tsk - 1]; // TCB pointer + + *((uint32_t *)ptcb->tsk_stack + 13) = (uint32_t)osThreadExit; + + return ptcb; +} + +/// Return the thread ID of the current running thread +osThreadId svcThreadGetId (void) { + OS_TID tsk; + + tsk = rt_tsk_self(); + if (tsk == 0) return NULL; + return (P_TCB)os_active_TCB[tsk - 1]; +} + +/// Terminate execution of a thread and remove it from ActiveThreads +osStatus svcThreadTerminate (osThreadId thread_id) { + OS_RESULT res; + P_TCB ptcb; + + ptcb = rt_tid2ptcb(thread_id); // Get TCB pointer + if (ptcb == NULL) return osErrorParameter; + + res = rt_tsk_delete(ptcb->task_id); // Delete task + + if (res == OS_R_NOK) return osErrorResource; // Delete task failed + + return osOK; +} + +/// Pass control to next thread that is in state READY +osStatus svcThreadYield (void) { + rt_tsk_pass(); // Pass control to next task + return osOK; +} + +/// Change priority of an active thread +osStatus svcThreadSetPriority (osThreadId thread_id, osPriority priority) { + OS_RESULT res; + P_TCB ptcb; + + ptcb = rt_tid2ptcb(thread_id); // Get TCB pointer + if (ptcb == NULL) return osErrorParameter; + + if ((priority < osPriorityIdle) || (priority > osPriorityRealtime)) { + return osErrorValue; + } + + res = rt_tsk_prio( // Change task priority + ptcb->task_id, // Task ID + priority - osPriorityIdle + 1 // New task priority + ); + + if (res == OS_R_NOK) return osErrorResource; // Change task priority failed + + return osOK; +} + +/// Get current priority of an active thread +osPriority svcThreadGetPriority (osThreadId thread_id) { + P_TCB ptcb; + + ptcb = rt_tid2ptcb(thread_id); // Get TCB pointer + if (ptcb == NULL) return osPriorityError; + + return (osPriority)(ptcb->prio - 1 + osPriorityIdle); +} + + +// Thread Public API + +/// Create a thread and add it to Active Threads and set it to state READY +osThreadId osThreadCreate (osThreadDef_t *thread_def, void *argument) { + if (__get_IPSR() != 0) return NULL; // Not allowed in ISR + if (((__get_CONTROL() & 1) == 0) && (os_running == 0)) { + // Privileged and not running + return svcThreadCreate(thread_def, argument); + } else { + return __svcThreadCreate(thread_def, argument); + } +} + +/// Return the thread ID of the current running thread +osThreadId osThreadGetId (void) { + if (__get_IPSR() != 0) return NULL; // Not allowed in ISR + return __svcThreadGetId(); +} + +/// Terminate execution of a thread and remove it from ActiveThreads +osStatus osThreadTerminate (osThreadId thread_id) { + if (__get_IPSR() != 0) return osErrorISR; // Not allowed in ISR + return __svcThreadTerminate(thread_id); +} + +/// Pass control to next thread that is in state READY +osStatus osThreadYield (void) { + if (__get_IPSR() != 0) return osErrorISR; // Not allowed in ISR + return __svcThreadYield(); +} + +/// Change priority of an active thread +osStatus osThreadSetPriority (osThreadId thread_id, osPriority priority) { + if (__get_IPSR() != 0) return osErrorISR; // Not allowed in ISR + return __svcThreadSetPriority(thread_id, priority); +} + +/// Get current priority of an active thread +osPriority osThreadGetPriority (osThreadId thread_id) { + if (__get_IPSR() != 0) return osPriorityError;// Not allowed in ISR + return __svcThreadGetPriority(thread_id); +} + +/// INTERNAL - Not Public +/// Auto Terminate Thread on exit (used implicitly when thread exists) +__NO_RETURN void osThreadExit (void) { + __svcThreadTerminate(__svcThreadGetId()); + for (;;); // Should never come here +} + + +// ==== Generic Wait Functions ==== + +// Generic Wait Service Calls declarations +SVC_1_1(svcDelay, osStatus, uint32_t, RET_osStatus) +#if osFeature_Wait != 0 +SVC_1_3(svcWait, os_InRegs osEvent, uint32_t, RET_osEvent) +#endif + +// Generic Wait Service Calls + +/// Wait for Timeout (Time Delay) +osStatus svcDelay (uint32_t millisec) { + if (millisec == 0) return osOK; + rt_dly_wait(rt_ms2tick(millisec)); + return osEventTimeout; +} + +/// Wait for Signal, Message, Mail, or Timeout +#if osFeature_Wait != 0 +os_InRegs osEvent_type svcWait (uint32_t millisec) { + osEvent ret; + + if (millisec == 0) { + ret.status = osOK; + return osEvent_ret_status; + } + + /* To Do: osEventSignal, osEventMessage, osEventMail */ + rt_dly_wait(rt_ms2tick(millisec)); + ret.status = osEventTimeout; + + return osEvent_ret_status; +} +#endif + + +// Generic Wait API + +/// Wait for Timeout (Time Delay) +osStatus osDelay (uint32_t millisec) { + if (__get_IPSR() != 0) return osErrorISR; // Not allowed in ISR + return __svcDelay(millisec); +} + +/// Wait for Signal, Message, Mail, or Timeout +os_InRegs osEvent osWait (uint32_t millisec) { + osEvent ret; + +#if osFeature_Wait == 0 + ret.status = osErrorOS; + return ret; +#else + if (__get_IPSR() != 0) { // Not allowed in ISR + ret.status = osErrorISR; + return ret; + } + return __svcWait(millisec); +#endif +} + + +// ==== Timer Management ==== + +// Timer definitions +#define osTimerInvalid 0 +#define osTimerStopped 1 +#define osTimerRunning 2 + +// Timer structures + +typedef struct os_timer_cb_ { // Timer Control Block + struct os_timer_cb_ *next; // Pointer to next active Timer + uint8_t state; // Timer State + uint8_t type; // Timer Type (Periodic/One-shot) + uint16_t reserved; // Reserved + uint16_t tcnt; // Timer Delay Count + uint16_t icnt; // Timer Initial Count + void *arg; // Timer Function Argument + osTimerDef_t *timer; // Pointer to Timer definition +} os_timer_cb; + +// Timer variables +os_timer_cb *os_timer_head; // Pointer to first active Timer + + +// Timer Helper Functions + +// Insert Timer into the list sorted by time +static void rt_timer_insert (os_timer_cb *pt, uint32_t tcnt) { + os_timer_cb *p, *prev; + + prev = NULL; + p = os_timer_head; + while (p != NULL) { + if (tcnt < p->tcnt) break; + tcnt -= p->tcnt; + prev = p; + p = p->next; + } + pt->next = p; + pt->tcnt = (uint16_t)tcnt; + if (p != NULL) { + p->tcnt -= pt->tcnt; + } + if (prev != NULL) { + prev->next = pt; + } else { + os_timer_head = pt; + } +} + +// Remove Timer from the list +static int rt_timer_remove (os_timer_cb *pt) { + os_timer_cb *p, *prev; + + prev = NULL; + p = os_timer_head; + while (p != NULL) { + if (p == pt) break; + prev = p; + p = p->next; + } + if (p == NULL) return -1; + if (prev != NULL) { + prev->next = pt->next; + } else { + os_timer_head = pt->next; + } + if (pt->next != NULL) { + pt->next->tcnt += pt->tcnt; + } + + return 0; +} + + +// Timer Service Calls declarations +SVC_3_1(svcTimerCreate, osTimerId, osTimerDef_t *, os_timer_type, void *, RET_pointer) +SVC_2_1(svcTimerStart, osStatus, osTimerId, uint32_t, RET_osStatus) +SVC_1_1(svcTimerStop, osStatus, osTimerId, RET_osStatus) +SVC_1_1(svcTimerDelete, osStatus, osTimerId, RET_osStatus) +SVC_1_2(svcTimerCall, os_InRegs osCallback, osTimerId, RET_osCallback) + +// Timer Management Service Calls + +/// Create timer +osTimerId svcTimerCreate (osTimerDef_t *timer_def, os_timer_type type, void *argument) { + os_timer_cb *pt; + + if ((timer_def == NULL) || (timer_def->ptimer == NULL)) { + sysThreadError(osErrorParameter); + return NULL; + } + + pt = timer_def->timer; + if (pt == NULL) { + sysThreadError(osErrorParameter); + return NULL; + } + + if ((type != osTimerOnce) && (type != osTimerPeriodic)) { + sysThreadError(osErrorValue); + return NULL; + } + + if (osThreadId_osTimerThread == NULL) { + sysThreadError(osErrorResource); + return NULL; + } + + if (pt->state != osTimerInvalid){ + sysThreadError(osErrorResource); + return NULL; + } + + pt->state = osTimerStopped; + pt->type = (uint8_t)type; + pt->arg = argument; + pt->timer = timer_def; + + return (osTimerId)pt; +} + +/// Start or restart timer +osStatus svcTimerStart (osTimerId timer_id, uint32_t millisec) { + os_timer_cb *pt; + uint32_t tcnt; + + pt = rt_id2obj(timer_id); + if (pt == NULL) return osErrorParameter; + + tcnt = rt_ms2tick(millisec); + if (tcnt == 0) return osErrorValue; + + switch (pt->state) { + case osTimerRunning: + if (rt_timer_remove(pt) != 0) { + return osErrorResource; + } + break; + case osTimerStopped: + pt->state = osTimerRunning; + pt->icnt = (uint16_t)tcnt; + break; + default: + return osErrorResource; + } + + rt_timer_insert(pt, tcnt); + + return osOK; +} + +/// Stop timer +osStatus svcTimerStop (osTimerId timer_id) { + os_timer_cb *pt; + + pt = rt_id2obj(timer_id); + if (pt == NULL) return osErrorParameter; + + if (pt->state != osTimerRunning) return osErrorResource; + + pt->state = osTimerStopped; + + if (rt_timer_remove(pt) != 0) { + return osErrorResource; + } + + return osOK; +} + +/// Delete timer +osStatus svcTimerDelete (osTimerId timer_id) { + os_timer_cb *pt; + + pt = rt_id2obj(timer_id); + if (pt == NULL) return osErrorParameter; + + switch (pt->state) { + case osTimerRunning: + rt_timer_remove(pt); + break; + case osTimerStopped: + break; + default: + return osErrorResource; + } + + pt->state = osTimerInvalid; + + return osOK; +} + +/// Get timer callback parameters +os_InRegs osCallback_type svcTimerCall (osTimerId timer_id) { + os_timer_cb *pt; + osCallback ret; + + pt = rt_id2obj(timer_id); + if (pt == NULL) { + ret.fp = NULL; + ret.arg = NULL; + return osCallback_ret; + } + + ret.fp = (void *)pt->timer->ptimer; + ret.arg = pt->arg; + + return osCallback_ret; +} + +static __INLINE osStatus isrMessagePut (osMessageQId queue_id, uint32_t info, uint32_t millisec); + +/// Timer Tick (called each SysTick) +void sysTimerTick (void) { + os_timer_cb *pt, *p; + + p = os_timer_head; + if (p == NULL) return; + + p->tcnt--; + while ((p != NULL) && (p->tcnt == 0)) { + pt = p; + p = p->next; + os_timer_head = p; + isrMessagePut(osMessageQId_osTimerMessageQ, (uint32_t)pt, 0); + if (pt->type == osTimerPeriodic) { + rt_timer_insert(pt, pt->icnt); + } else { + pt->state = osTimerStopped; + } + } +} + + +// Timer Management Public API + +/// Create timer +osTimerId osTimerCreate (osTimerDef_t *timer_def, os_timer_type type, void *argument) { + if (__get_IPSR() != 0) return NULL; // Not allowed in ISR + if (((__get_CONTROL() & 1) == 0) && (os_running == 0)) { + // Privileged and not running + return svcTimerCreate(timer_def, type, argument); + } else { + return __svcTimerCreate(timer_def, type, argument); + } +} + +/// Start or restart timer +osStatus osTimerStart (osTimerId timer_id, uint32_t millisec) { + if (__get_IPSR() != 0) return osErrorISR; // Not allowed in ISR + return __svcTimerStart(timer_id, millisec); +} + +/// Stop timer +osStatus osTimerStop (osTimerId timer_id) { + if (__get_IPSR() != 0) return osErrorISR; // Not allowed in ISR + return __svcTimerStop(timer_id); +} + +/// Delete timer +osStatus osTimerDelete (osTimerId timer_id) { + if (__get_IPSR() != 0) return osErrorISR; // Not allowed in ISR + return __svcTimerDelete(timer_id); +} + +/// INTERNAL - Not Public +/// Get timer callback parameters (used by OS Timer Thread) +os_InRegs osCallback osTimerCall (osTimerId timer_id) { + return __svcTimerCall(timer_id); +} + + +// Timer Thread +__NO_RETURN void osTimerThread (void const *argument) { + osCallback cb; + osEvent evt; + + for (;;) { + evt = osMessageGet(osMessageQId_osTimerMessageQ, osWaitForever); + if (evt.status == osEventMessage) { + cb = osTimerCall(evt.value.p); + if (cb.fp != NULL) { + (*(os_ptimer)cb.fp)(cb.arg); + } + } + } +} + + +// ==== Signal Management ==== + +// Signal Service Calls declarations +SVC_2_1(svcSignalSet, int32_t, osThreadId, int32_t, RET_int32_t) +SVC_2_1(svcSignalClear, int32_t, osThreadId, int32_t, RET_int32_t) +SVC_1_1(svcSignalGet, int32_t, osThreadId, RET_int32_t) +SVC_2_3(svcSignalWait, os_InRegs osEvent, int32_t, uint32_t, RET_osEvent) + +// Signal Service Calls + +/// Set the specified Signal Flags of an active thread +int32_t svcSignalSet (osThreadId thread_id, int32_t signals) { + P_TCB ptcb; + int32_t sig; + + ptcb = rt_tid2ptcb(thread_id); // Get TCB pointer + if (ptcb == NULL) return 0x80000000; + + if (signals & (0xFFFFFFFF << osFeature_Signals)) return 0x80000000; + + sig = ptcb->events; // Previous signal flags + + rt_evt_set(signals, ptcb->task_id); // Set event flags + + return sig; +} + +/// Clear the specified Signal Flags of an active thread +int32_t svcSignalClear (osThreadId thread_id, int32_t signals) { + P_TCB ptcb; + int32_t sig; + + ptcb = rt_tid2ptcb(thread_id); // Get TCB pointer + if (ptcb == NULL) return 0x80000000; + + if (signals & (0xFFFFFFFF << osFeature_Signals)) return 0x80000000; + + sig = ptcb->events; // Previous signal flags + + rt_evt_clr(signals, ptcb->task_id); // Clear event flags + + return sig; +} + +/// Get Signal Flags status of an active thread +int32_t svcSignalGet (osThreadId thread_id) { + P_TCB ptcb; + + ptcb = rt_tid2ptcb(thread_id); // Get TCB pointer + if (ptcb == NULL) return 0x80000000; + + return ptcb->events; // Return event flags +} + +/// Wait for one or more Signal Flags to become signaled for the current RUNNING thread +os_InRegs osEvent_type svcSignalWait (int32_t signals, uint32_t millisec) { + OS_RESULT res; + osEvent ret; + + if (signals & (0xFFFFFFFF << osFeature_Signals)) { + ret.status = osErrorValue; + return osEvent_ret_status; + } + + if (signals != 0) { // Wait for all specified signals + res = rt_evt_wait(signals, rt_ms2tick(millisec), __TRUE); + } else { // Wait for any signal + res = rt_evt_wait(0xFFFF, rt_ms2tick(millisec), __FALSE); + } + + if (res == OS_R_EVT) { + ret.status = osEventSignal; + ret.value.signals = signals ? signals : os_tsk.run->waits; + } else { + ret.status = millisec ? osEventTimeout : osOK; + ret.value.signals = 0; + } + + return osEvent_ret_value; +} + + +// Signal ISR Calls + +/// Set the specified Signal Flags of an active thread +static __INLINE int32_t isrSignalSet (osThreadId thread_id, int32_t signals) { + P_TCB ptcb; + int32_t sig; + + ptcb = rt_tid2ptcb(thread_id); // Get TCB pointer + if (ptcb == NULL) return 0x80000000; + + if (signals & (0xFFFFFFFF << osFeature_Signals)) return 0x80000000; + + sig = ptcb->events; // Previous signal flags + + isr_evt_set(signals, ptcb->task_id); // Set event flags + + return sig; +} + + +// Signal Public API + +/// Set the specified Signal Flags of an active thread +int32_t osSignalSet (osThreadId thread_id, int32_t signals) { + if (__get_IPSR() != 0) { // in ISR + return isrSignalSet(thread_id, signals); + } else { // in Thread + return __svcSignalSet(thread_id, signals); + } +} + +/// Clear the specified Signal Flags of an active thread +int32_t osSignalClear (osThreadId thread_id, int32_t signals) { + if (__get_IPSR() != 0) return osErrorISR; // Not allowed in ISR + return __svcSignalClear(thread_id, signals); +} + +/// Get Signal Flags status of an active thread +int32_t osSignalGet (osThreadId thread_id) { + if (__get_IPSR() != 0) return osErrorISR; // Not allowed in ISR + return __svcSignalGet(thread_id); +} + +/// Wait for one or more Signal Flags to become signaled for the current RUNNING thread +os_InRegs osEvent osSignalWait (int32_t signals, uint32_t millisec) { + osEvent ret; + + if (__get_IPSR() != 0) { // Not allowed in ISR + ret.status = osErrorISR; + return ret; + } + return __svcSignalWait(signals, millisec); +} + + +// ==== Mutex Management ==== + +// Mutex Service Calls declarations +SVC_1_1(svcMutexCreate, osMutexId, osMutexDef_t *, RET_pointer) +SVC_2_1(svcMutexWait, osStatus, osMutexId, uint32_t, RET_osStatus) +SVC_1_1(svcMutexRelease, osStatus, osMutexId, RET_osStatus) +SVC_1_1(svcMutexDelete, osStatus, osMutexId, RET_osStatus) + +// Mutex Service Calls + +/// Create and Initialize a Mutex object +osMutexId svcMutexCreate (osMutexDef_t *mutex_def) { + OS_ID mut; + + if (mutex_def == NULL) { + sysThreadError(osErrorParameter); + return NULL; + } + + mut = mutex_def->mutex; + if (mut == NULL) { + sysThreadError(osErrorParameter); + return NULL; + } + + if (((P_MUCB)mut)->cb_type != 0) { + sysThreadError(osErrorParameter); + return NULL; + } + + rt_mut_init(mut); // Initialize Mutex + + return mut; +} + +/// Wait until a Mutex becomes available +osStatus svcMutexWait (osMutexId mutex_id, uint32_t millisec) { + OS_ID mut; + OS_RESULT res; + + mut = rt_id2obj(mutex_id); + if (mut == NULL) return osErrorParameter; + + if (((P_MUCB)mut)->cb_type != MUCB) return osErrorParameter; + + res = rt_mut_wait(mut, rt_ms2tick(millisec)); // Wait for Mutex + + if (res == OS_R_TMO) { + return (millisec ? osErrorTimeoutResource : osErrorResource); + } + + return osOK; +} + +/// Release a Mutex that was obtained with osMutexWait +osStatus svcMutexRelease (osMutexId mutex_id) { + OS_ID mut; + OS_RESULT res; + + mut = rt_id2obj(mutex_id); + if (mut == NULL) return osErrorParameter; + + if (((P_MUCB)mut)->cb_type != MUCB) return osErrorParameter; + + res = rt_mut_release(mut); // Release Mutex + + if (res == OS_R_NOK) return osErrorResource; // Thread not owner or Zero Counter + + return osOK; +} + +/// Delete a Mutex that was created by osMutexCreate +osStatus svcMutexDelete (osMutexId mutex_id) { + OS_ID mut; + + mut = rt_id2obj(mutex_id); + if (mut == NULL) return osErrorParameter; + + if (((P_MUCB)mut)->cb_type != MUCB) return osErrorParameter; + + rt_mut_delete(mut); // Release Mutex + + return osOK; +} + + +// Mutex Public API + +/// Create and Initialize a Mutex object +osMutexId osMutexCreate (osMutexDef_t *mutex_def) { + if (__get_IPSR() != 0) return NULL; // Not allowed in ISR + if (((__get_CONTROL() & 1) == 0) && (os_running == 0)) { + // Privileged and not running + return svcMutexCreate(mutex_def); + } else { + return __svcMutexCreate(mutex_def); + } +} + +/// Wait until a Mutex becomes available +osStatus osMutexWait (osMutexId mutex_id, uint32_t millisec) { + if (__get_IPSR() != 0) return osErrorISR; // Not allowed in ISR + return __svcMutexWait(mutex_id, millisec); +} + +/// Release a Mutex that was obtained with osMutexWait +osStatus osMutexRelease (osMutexId mutex_id) { + if (__get_IPSR() != 0) return osErrorISR; // Not allowed in ISR + return __svcMutexRelease(mutex_id); +} + +/// Delete a Mutex that was created by osMutexCreate +osStatus osMutexDelete (osMutexId mutex_id) { + if (__get_IPSR() != 0) return osErrorISR; // Not allowed in ISR + return __svcMutexDelete(mutex_id); +} + + +// ==== Semaphore Management ==== + +// Semaphore Service Calls declarations +SVC_2_1(svcSemaphoreCreate, osSemaphoreId, const osSemaphoreDef_t *, int32_t, RET_pointer) +SVC_2_1(svcSemaphoreWait, int32_t, osSemaphoreId, uint32_t, RET_int32_t) +SVC_1_1(svcSemaphoreRelease, osStatus, osSemaphoreId, RET_osStatus) +SVC_1_1(svcSemaphoreDelete, osStatus, osSemaphoreId, RET_osStatus) + +// Semaphore Service Calls + +/// Create and Initialize a Semaphore object +osSemaphoreId svcSemaphoreCreate (const osSemaphoreDef_t *semaphore_def, int32_t count) { + OS_ID sem; + + if (semaphore_def == NULL) { + sysThreadError(osErrorParameter); + return NULL; + } + + sem = semaphore_def->semaphore; + if (sem == NULL) { + sysThreadError(osErrorParameter); + return NULL; + } + + if (((P_SCB)sem)->cb_type != 0) { + sysThreadError(osErrorParameter); + return NULL; + } + + if (count > osFeature_Semaphore) { + sysThreadError(osErrorValue); + return NULL; + } + + rt_sem_init(sem, count); // Initialize Semaphore + + return sem; +} + +/// Wait until a Semaphore becomes available +int32_t svcSemaphoreWait (osSemaphoreId semaphore_id, uint32_t millisec) { + OS_ID sem; + OS_RESULT res; + + sem = rt_id2obj(semaphore_id); + if (sem == NULL) return -1; + + if (((P_SCB)sem)->cb_type != SCB) return -1; + + res = rt_sem_wait(sem, rt_ms2tick(millisec)); // Wait for Semaphore + + if (res == OS_R_TMO) return 0; // Timeout + + return (((P_SCB)sem)->tokens + 1); +} + +/// Release a Semaphore +osStatus svcSemaphoreRelease (osSemaphoreId semaphore_id) { + OS_ID sem; + + sem = rt_id2obj(semaphore_id); + if (sem == NULL) return osErrorParameter; + + if (((P_SCB)sem)->cb_type != SCB) return osErrorParameter; + + if (((P_SCB)sem)->tokens == osFeature_Semaphore) return osErrorResource; + + rt_sem_send(sem); // Release Semaphore + + return osOK; +} + +/// Delete a Semaphore that was created by osSemaphoreCreate +osStatus svcSemaphoreDelete (osSemaphoreId semaphore_id) { + OS_ID sem; + + sem = rt_id2obj(semaphore_id); + if (sem == NULL) return osErrorParameter; + + if (((P_SCB)sem)->cb_type != SCB) return osErrorParameter; + + rt_sem_delete(sem); // Delete Semaphore + + return osOK; +} + + +// Semaphore ISR Calls + +/// Release a Semaphore +static __INLINE osStatus isrSemaphoreRelease (osSemaphoreId semaphore_id) { + OS_ID sem; + + sem = rt_id2obj(semaphore_id); + if (sem == NULL) return osErrorParameter; + + if (((P_SCB)sem)->cb_type != SCB) return osErrorParameter; + + if (((P_SCB)sem)->tokens == osFeature_Semaphore) return osErrorResource; + + isr_sem_send(sem); // Release Semaphore + + return osOK; +} + + +// Semaphore Public API + +/// Create and Initialize a Semaphore object +osSemaphoreId osSemaphoreCreate (osSemaphoreDef_t *semaphore_def, int32_t count) { + if (__get_IPSR() != 0) return NULL; // Not allowed in ISR + if (((__get_CONTROL() & 1) == 0) && (os_running == 0)) { + // Privileged and not running + return svcSemaphoreCreate(semaphore_def, count); + } else { + return __svcSemaphoreCreate(semaphore_def, count); + } +} + +/// Wait until a Semaphore becomes available +int32_t osSemaphoreWait (osSemaphoreId semaphore_id, uint32_t millisec) { + if (__get_IPSR() != 0) return -1; // Not allowed in ISR + return __svcSemaphoreWait(semaphore_id, millisec); +} + +/// Release a Semaphore +osStatus osSemaphoreRelease (osSemaphoreId semaphore_id) { + if (__get_IPSR() != 0) { // in ISR + return isrSemaphoreRelease(semaphore_id); + } else { // in Thread + return __svcSemaphoreRelease(semaphore_id); + } +} + +/// Delete a Semaphore that was created by osSemaphoreCreate +osStatus osSemaphoreDelete (osSemaphoreId semaphore_id) { + if (__get_IPSR() != 0) return osErrorISR; // Not allowed in ISR + return __svcSemaphoreDelete(semaphore_id); +} + + +// ==== Memory Management Functions ==== + +// Memory Management Helper Functions + +// Clear Memory Box (Zero init) +static void rt_clr_box (void *box_mem, void *box) { + uint32_t *p, n; + + if (box) { + p = box; + for (n = ((P_BM)box_mem)->blk_size; n; n -= 4) { + *p++ = 0; + } + } +} + +// Memory Management Service Calls declarations +SVC_1_1(svcPoolCreate, osPoolId, const osPoolDef_t *, RET_pointer) +SVC_2_1(sysPoolAlloc, void *, osPoolId, uint32_t, RET_pointer) +SVC_2_1(sysPoolFree, osStatus, osPoolId, void *, RET_osStatus) + +// Memory Management Service & ISR Calls + +/// Create and Initialize memory pool +osPoolId svcPoolCreate (const osPoolDef_t *pool_def) { + uint32_t blk_sz; + + if ((pool_def == NULL) || + (pool_def->pool_sz == 0) || + (pool_def->item_sz == 0) || + (pool_def->pool == NULL)) { + sysThreadError(osErrorParameter); + return NULL; + } + + blk_sz = (pool_def->item_sz + 3) & ~3; + + _init_box(pool_def->pool, sizeof(struct OS_BM) + pool_def->pool_sz * blk_sz, blk_sz); + + return pool_def->pool; +} + +/// Allocate a memory block from a memory pool +void *sysPoolAlloc (osPoolId pool_id, uint32_t clr) { + void *ptr; + + if (pool_id == NULL) return NULL; + + ptr = rt_alloc_box(pool_id); + if (clr) { + rt_clr_box(pool_id, ptr); + } + + return ptr; +} + +/// Return an allocated memory block back to a specific memory pool +osStatus sysPoolFree (osPoolId pool_id, void *block) { + int32_t res; + + if (pool_id == NULL) return osErrorParameter; + + res = rt_free_box(pool_id, block); + if (res != 0) return osErrorValue; + + return osOK; +} + + +// Memory Management Public API + +/// Create and Initialize memory pool +osPoolId osPoolCreate (osPoolDef_t *pool_def) { + if (__get_IPSR() != 0) return NULL; // Not allowed in ISR + if (((__get_CONTROL() & 1) == 0) && (os_running == 0)) { + // Privileged and not running + return svcPoolCreate(pool_def); + } else { + return __svcPoolCreate(pool_def); + } +} + +/// Allocate a memory block from a memory pool +void *osPoolAlloc (osPoolId pool_id) { + if ((__get_IPSR() != 0) || ((__get_CONTROL() & 1) == 0)) { // in ISR or Privileged + return sysPoolAlloc(pool_id, 0); + } else { // in Thread + return __sysPoolAlloc(pool_id, 0); + } +} + +/// Allocate a memory block from a memory pool and set memory block to zero +void *osPoolCAlloc (osPoolId pool_id) { + if ((__get_IPSR() != 0) || ((__get_CONTROL() & 1) == 0)) { // in ISR or Privileged + return sysPoolAlloc(pool_id, 1); + } else { // in Thread + return __sysPoolAlloc(pool_id, 1); + } +} + +/// Return an allocated memory block back to a specific memory pool +osStatus osPoolFree (osPoolId pool_id, void *block) { + if ((__get_IPSR() != 0) || ((__get_CONTROL() & 1) == 0)) { // in ISR or Privileged + return sysPoolFree(pool_id, block); + } else { // in Thread + return __sysPoolFree(pool_id, block); + } +} + + +// ==== Message Queue Management Functions ==== + +// Message Queue Management Service Calls declarations +SVC_2_1(svcMessageCreate, osMessageQId, osMessageQDef_t *, osThreadId, RET_pointer) +SVC_3_1(svcMessagePut, osStatus, osMessageQId, uint32_t, uint32_t, RET_osStatus) +SVC_2_3(svcMessageGet, os_InRegs osEvent, osMessageQId, uint32_t, RET_osEvent) + +// Message Queue Service Calls + +/// Create and Initialize Message Queue +osMessageQId svcMessageCreate (osMessageQDef_t *queue_def, osThreadId thread_id) { + + if ((queue_def == NULL) || + (queue_def->queue_sz == 0) || + (queue_def->pool == NULL)) { + sysThreadError(osErrorParameter); + return NULL; + } + + if (((P_MCB)queue_def->pool)->cb_type != 0) { + sysThreadError(osErrorParameter); + return NULL; + } + + rt_mbx_init(queue_def->pool, 4*(queue_def->queue_sz + 4)); + + return queue_def->pool; +} + +/// Put a Message to a Queue +osStatus svcMessagePut (osMessageQId queue_id, uint32_t info, uint32_t millisec) { + OS_RESULT res; + + if (queue_id == NULL) return osErrorParameter; + + if (((P_MCB)queue_id)->cb_type != MCB) return osErrorParameter; + + res = rt_mbx_send(queue_id, (void *)info, rt_ms2tick(millisec)); + + if (res == OS_R_TMO) { + return (millisec ? osErrorTimeoutResource : osErrorResource); + } + + return osOK; +} + +/// Get a Message or Wait for a Message from a Queue +os_InRegs osEvent_type svcMessageGet (osMessageQId queue_id, uint32_t millisec) { + OS_RESULT res; + osEvent ret; + + if (queue_id == NULL) { + ret.status = osErrorParameter; + return osEvent_ret_status; + } + + if (((P_MCB)queue_id)->cb_type != MCB) { + ret.status = osErrorParameter; + return osEvent_ret_status; + } + + res = rt_mbx_wait(queue_id, &ret.value.p, rt_ms2tick(millisec)); + + if (res == OS_R_TMO) { + ret.status = millisec ? osEventTimeout : osOK; + return osEvent_ret_value; + } + + ret.status = osEventMessage; + + return osEvent_ret_value; +} + + +// Message Queue ISR Calls + +/// Put a Message to a Queue +static __INLINE osStatus isrMessagePut (osMessageQId queue_id, uint32_t info, uint32_t millisec) { + + if ((queue_id == NULL) || (millisec != 0)) { + return osErrorParameter; + } + + if (((P_MCB)queue_id)->cb_type != MCB) return osErrorParameter; + + if (rt_mbx_check(queue_id) == 0) { // Check if Queue is full + return osErrorResource; + } + + isr_mbx_send(queue_id, (void *)info); + + return osOK; +} + +/// Get a Message or Wait for a Message from a Queue +static __INLINE os_InRegs osEvent isrMessageGet (osMessageQId queue_id, uint32_t millisec) { + OS_RESULT res; + osEvent ret; + + if ((queue_id == NULL) || (millisec != 0)) { + ret.status = osErrorParameter; + return ret; + } + + if (((P_MCB)queue_id)->cb_type != MCB) { + ret.status = osErrorParameter; + return ret; + } + + res = isr_mbx_receive(queue_id, &ret.value.p); + + if (res != OS_R_MBX) { + ret.status = osOK; + return ret; + } + + ret.status = osEventMessage; + + return ret; +} + + +// Message Queue Management Public API + +/// Create and Initialize Message Queue +osMessageQId osMessageCreate (osMessageQDef_t *queue_def, osThreadId thread_id) { + if (__get_IPSR() != 0) return NULL; // Not allowed in ISR + if (((__get_CONTROL() & 1) == 0) && (os_running == 0)) { + // Privileged and not running + return svcMessageCreate(queue_def, thread_id); + } else { + return __svcMessageCreate(queue_def, thread_id); + } +} + +/// Put a Message to a Queue +osStatus osMessagePut (osMessageQId queue_id, uint32_t info, uint32_t millisec) { + if (__get_IPSR() != 0) { // in ISR + return isrMessagePut(queue_id, info, millisec); + } else { // in Thread + return __svcMessagePut(queue_id, info, millisec); + } +} + +/// Get a Message or Wait for a Message from a Queue +os_InRegs osEvent osMessageGet (osMessageQId queue_id, uint32_t millisec) { + if (__get_IPSR() != 0) { // in ISR + return isrMessageGet(queue_id, millisec); + } else { // in Thread + return __svcMessageGet(queue_id, millisec); + } +} + + +// ==== Mail Queue Management Functions ==== + +// Mail Queue Management Service Calls declarations +SVC_2_1(svcMailCreate, osMailQId, osMailQDef_t *, osThreadId, RET_pointer) +SVC_4_1(sysMailAlloc, void *, osMailQId, uint32_t, uint32_t, uint32_t, RET_pointer) +SVC_3_1(sysMailFree, osStatus, osMailQId, void *, uint32_t, RET_osStatus) + +// Mail Queue Management Service & ISR Calls + +/// Create and Initialize mail queue +osMailQId svcMailCreate (osMailQDef_t *queue_def, osThreadId thread_id) { + uint32_t blk_sz; + P_MCB pmcb; + void *pool; + + if ((queue_def == NULL) || + (queue_def->queue_sz == 0) || + (queue_def->item_sz == 0) || + (queue_def->pool == NULL)) { + sysThreadError(osErrorParameter); + return NULL; + } + + pmcb = *(((void **)queue_def->pool) + 0); + pool = *(((void **)queue_def->pool) + 1); + + if ((pool == NULL) || (pmcb == NULL) || (pmcb->cb_type != 0)) { + sysThreadError(osErrorParameter); + return NULL; + } + + blk_sz = (queue_def->item_sz + 3) & ~3; + + _init_box(pool, sizeof(struct OS_BM) + queue_def->queue_sz * blk_sz, blk_sz); + + rt_mbx_init(pmcb, 4*(queue_def->queue_sz + 4)); + + + return queue_def->pool; +} + +/// Allocate a memory block from a mail +void *sysMailAlloc (osMailQId queue_id, uint32_t millisec, uint32_t isr, uint32_t clr) { + P_MCB pmcb; + void *pool; + void *mem; + + if (queue_id == NULL) return NULL; + + pmcb = *(((void **)queue_id) + 0); + pool = *(((void **)queue_id) + 1); + + if ((pool == NULL) || (pmcb == NULL)) return NULL; + + if (isr && (millisec != 0)) return NULL; + + mem = rt_alloc_box(pool); + if (clr) { + rt_clr_box(pool, mem); + } + + if ((mem == NULL) && (millisec != 0)) { + // Put Task to sleep when Memory not available + if (pmcb->p_lnk != NULL) { + rt_put_prio((P_XCB)pmcb, os_tsk.run); + } else { + pmcb->p_lnk = os_tsk.run; + os_tsk.run->p_lnk = NULL; + os_tsk.run->p_rlnk = (P_TCB)pmcb; + // Task is waiting to allocate a message + pmcb->state = 3; + } + rt_block(rt_ms2tick(millisec), WAIT_MBX); + } + + return mem; +} + +/// Free a memory block from a mail +osStatus sysMailFree (osMailQId queue_id, void *mail, uint32_t isr) { + P_MCB pmcb; + P_TCB ptcb; + void *pool; + void *mem; + int32_t res; + + if (queue_id == NULL) return osErrorParameter; + + pmcb = *(((void **)queue_id) + 0); + pool = *(((void **)queue_id) + 1); + + if ((pmcb == NULL) || (pool == NULL)) return osErrorParameter; + + res = rt_free_box(pool, mail); + + if (res != 0) return osErrorValue; + + if (pmcb->state == 3) { + // Task is waiting to allocate a message + if (isr) { + rt_psq_enq (pmcb, (U32)pool); + rt_psh_req (); + } else { + mem = rt_alloc_box(pool); + if (mem != NULL) { + ptcb = rt_get_first((P_XCB)pmcb); + if (pmcb->p_lnk == NULL) { + pmcb->state = 0; + } + rt_ret_val(ptcb, (U32)mem); + rt_rmv_dly(ptcb); + rt_dispatch(ptcb); + } + } + } + + return osOK; +} + + +// Mail Queue Management Public API + +/// Create and Initialize mail queue +osMailQId osMailCreate (osMailQDef_t *queue_def, osThreadId thread_id) { + if (__get_IPSR() != 0) return NULL; // Not allowed in ISR + if (((__get_CONTROL() & 1) == 0) && (os_running == 0)) { + // Privileged and not running + return svcMailCreate(queue_def, thread_id); + } else { + return __svcMailCreate(queue_def, thread_id); + } +} + +/// Allocate a memory block from a mail +void *osMailAlloc (osMailQId queue_id, uint32_t millisec) { + if (__get_IPSR() != 0) { // in ISR + return sysMailAlloc(queue_id, millisec, 1, 0); + } else { // in Thread + return __sysMailAlloc(queue_id, millisec, 0, 0); + } +} + +/// Allocate a memory block from a mail and set memory block to zero +void *osMailCAlloc (osMailQId queue_id, uint32_t millisec) { + if (__get_IPSR() != 0) { // in ISR + return sysMailAlloc(queue_id, millisec, 1, 1); + } else { // in Thread + return __sysMailAlloc(queue_id, millisec, 0, 1); + } +} + +/// Free a memory block from a mail +osStatus osMailFree (osMailQId queue_id, void *mail) { + if (__get_IPSR() != 0) { // in ISR + return sysMailFree(queue_id, mail, 1); + } else { // in Thread + return __sysMailFree(queue_id, mail, 0); + } +} + +/// Put a mail to a queue +osStatus osMailPut (osMailQId queue_id, void *mail) { + if (queue_id == NULL) return osErrorParameter; + if (mail == NULL) return osErrorValue; + return osMessagePut(*((void **)queue_id), (uint32_t)mail, 0); +} + +#ifdef __CC_ARM +#pragma push +#pragma Ospace +#endif // __arm__ +/// Get a mail from a queue +os_InRegs osEvent osMailGet (osMailQId queue_id, uint32_t millisec) { + osEvent ret; + + if (queue_id == NULL) { + ret.status = osErrorParameter; + return ret; + } + + ret = osMessageGet(*((void **)queue_id), millisec); + if (ret.status == osEventMessage) ret.status = osEventMail; + + return ret; +} +#ifdef __CC_ARM +#pragma pop +#endif // __arm__ diff --git a/libraries/mbed/rtos/rtx/TARGET_CORTEX_M/rt_Event.c b/libraries/mbed/rtos/rtx/TARGET_CORTEX_M/rt_Event.c new file mode 100644 index 0000000..acd8ccc --- /dev/null +++ b/libraries/mbed/rtos/rtx/TARGET_CORTEX_M/rt_Event.c @@ -0,0 +1,190 @@ +/*---------------------------------------------------------------------------- + * RL-ARM - RTX + *---------------------------------------------------------------------------- + * Name: RT_EVENT.C + * Purpose: Implements waits and wake-ups for event flags + * Rev.: V4.60 + *---------------------------------------------------------------------------- + * + * Copyright (c) 1999-2009 KEIL, 2009-2012 ARM Germany GmbH + * All rights reserved. + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * - Neither the name of ARM nor the names of its contributors may be used + * to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDERS AND CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + *---------------------------------------------------------------------------*/ + +#include "rt_TypeDef.h" +#include "RTX_Conf.h" +#include "rt_System.h" +#include "rt_Event.h" +#include "rt_List.h" +#include "rt_Task.h" +#include "rt_HAL_CM.h" + + +/*---------------------------------------------------------------------------- + * Functions + *---------------------------------------------------------------------------*/ + + +/*--------------------------- rt_evt_wait -----------------------------------*/ + +OS_RESULT rt_evt_wait (U16 wait_flags, U16 timeout, BOOL and_wait) { + /* Wait for one or more event flags with optional time-out. */ + /* "wait_flags" identifies the flags to wait for. */ + /* "timeout" is the time-out limit in system ticks (0xffff if no time-out) */ + /* "and_wait" specifies the AND-ing of "wait_flags" as condition to be met */ + /* to complete the wait. (OR-ing if set to 0). */ + U32 block_state; + + if (and_wait) { + /* Check for AND-connected events */ + if ((os_tsk.run->events & wait_flags) == wait_flags) { + os_tsk.run->events &= ~wait_flags; + return (OS_R_EVT); + } + block_state = WAIT_AND; + } + else { + /* Check for OR-connected events */ + if (os_tsk.run->events & wait_flags) { + os_tsk.run->waits = os_tsk.run->events & wait_flags; + os_tsk.run->events &= ~wait_flags; + return (OS_R_EVT); + } + block_state = WAIT_OR; + } + /* Task has to wait */ + os_tsk.run->waits = wait_flags; + rt_block (timeout, (U8)block_state); + return (OS_R_TMO); +} + + +/*--------------------------- rt_evt_set ------------------------------------*/ + +void rt_evt_set (U16 event_flags, OS_TID task_id) { + /* Set one or more event flags of a selectable task. */ + P_TCB p_tcb; + + p_tcb = os_active_TCB[task_id-1]; + if (p_tcb == NULL) { + return; + } + p_tcb->events |= event_flags; + event_flags = p_tcb->waits; + /* If the task is not waiting for an event, it should not be put */ + /* to ready state. */ + if (p_tcb->state == WAIT_AND) { + /* Check for AND-connected events */ + if ((p_tcb->events & event_flags) == event_flags) { + goto wkup; + } + } + if (p_tcb->state == WAIT_OR) { + /* Check for OR-connected events */ + if (p_tcb->events & event_flags) { + p_tcb->waits &= p_tcb->events; +wkup: p_tcb->events &= ~event_flags; + rt_rmv_dly (p_tcb); + p_tcb->state = READY; +#ifdef __CMSIS_RTOS + rt_ret_val2(p_tcb, 0x08/*osEventSignal*/, p_tcb->waits); +#else + rt_ret_val (p_tcb, OS_R_EVT); +#endif + rt_dispatch (p_tcb); + } + } +} + + +/*--------------------------- rt_evt_clr ------------------------------------*/ + +void rt_evt_clr (U16 clear_flags, OS_TID task_id) { + /* Clear one or more event flags (identified by "clear_flags") of a */ + /* selectable task (identified by "task"). */ + P_TCB task = os_active_TCB[task_id-1]; + + if (task == NULL) { + return; + } + task->events &= ~clear_flags; +} + + +/*--------------------------- isr_evt_set -----------------------------------*/ + +void isr_evt_set (U16 event_flags, OS_TID task_id) { + /* Same function as "os_evt_set", but to be called by ISRs. */ + P_TCB p_tcb = os_active_TCB[task_id-1]; + + if (p_tcb == NULL) { + return; + } + rt_psq_enq (p_tcb, event_flags); + rt_psh_req (); +} + + +/*--------------------------- rt_evt_get ------------------------------------*/ + +U16 rt_evt_get (void) { + /* Get events of a running task after waiting for OR connected events. */ + return (os_tsk.run->waits); +} + + +/*--------------------------- rt_evt_psh ------------------------------------*/ + +void rt_evt_psh (P_TCB p_CB, U16 set_flags) { + /* Check if task has to be waken up */ + U16 event_flags; + + p_CB->events |= set_flags; + event_flags = p_CB->waits; + if (p_CB->state == WAIT_AND) { + /* Check for AND-connected events */ + if ((p_CB->events & event_flags) == event_flags) { + goto rdy; + } + } + if (p_CB->state == WAIT_OR) { + /* Check for OR-connected events */ + if (p_CB->events & event_flags) { + p_CB->waits &= p_CB->events; +rdy: p_CB->events &= ~event_flags; + rt_rmv_dly (p_CB); + p_CB->state = READY; +#ifdef __CMSIS_RTOS + rt_ret_val2(p_CB, 0x08/*osEventSignal*/, p_CB->waits); +#else + rt_ret_val (p_CB, OS_R_EVT); +#endif + rt_put_prio (&os_rdy, p_CB); + } + } +} + +/*---------------------------------------------------------------------------- + * end of file + *---------------------------------------------------------------------------*/ diff --git a/libraries/mbed/rtos/rtx/TARGET_CORTEX_M/rt_Event.h b/libraries/mbed/rtos/rtx/TARGET_CORTEX_M/rt_Event.h new file mode 100644 index 0000000..8b92f3c --- /dev/null +++ b/libraries/mbed/rtos/rtx/TARGET_CORTEX_M/rt_Event.h @@ -0,0 +1,46 @@ +/*---------------------------------------------------------------------------- + * RL-ARM - RTX + *---------------------------------------------------------------------------- + * Name: RT_EVENT.H + * Purpose: Implements waits and wake-ups for event flags + * Rev.: V4.60 + *---------------------------------------------------------------------------- + * + * Copyright (c) 1999-2009 KEIL, 2009-2012 ARM Germany GmbH + * All rights reserved. + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * - Neither the name of ARM nor the names of its contributors may be used + * to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDERS AND CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + *---------------------------------------------------------------------------*/ + +/* Functions */ +extern OS_RESULT rt_evt_wait (U16 wait_flags, U16 timeout, BOOL and_wait); +extern void rt_evt_set (U16 event_flags, OS_TID task_id); +extern void rt_evt_clr (U16 clear_flags, OS_TID task_id); +extern void isr_evt_set (U16 event_flags, OS_TID task_id); +extern U16 rt_evt_get (void); +extern void rt_evt_psh (P_TCB p_CB, U16 set_flags); + +/*---------------------------------------------------------------------------- + * end of file + *---------------------------------------------------------------------------*/ + diff --git a/libraries/mbed/rtos/rtx/TARGET_CORTEX_M/rt_HAL_CM.h b/libraries/mbed/rtos/rtx/TARGET_CORTEX_M/rt_HAL_CM.h new file mode 100644 index 0000000..2ab4b36 --- /dev/null +++ b/libraries/mbed/rtos/rtx/TARGET_CORTEX_M/rt_HAL_CM.h @@ -0,0 +1,276 @@ +/*---------------------------------------------------------------------------- + * RL-ARM - RTX + *---------------------------------------------------------------------------- + * Name: RT_HAL_CM.H + * Purpose: Hardware Abstraction Layer for Cortex-M definitions + * Rev.: V4.60 + *---------------------------------------------------------------------------- + * + * Copyright (c) 1999-2009 KEIL, 2009-2012 ARM Germany GmbH + * All rights reserved. + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * - Neither the name of ARM nor the names of its contributors may be used + * to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDERS AND CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + *---------------------------------------------------------------------------*/ + +/* Definitions */ +#define INITIAL_xPSR 0x01000000 +#define DEMCR_TRCENA 0x01000000 +#define ITM_ITMENA 0x00000001 +#define MAGIC_WORD 0xE25A2EA5 + +#if defined (__CC_ARM) /* ARM Compiler */ + +#if ((__TARGET_ARCH_7_M || __TARGET_ARCH_7E_M) && !NO_EXCLUSIVE_ACCESS) + #define __USE_EXCLUSIVE_ACCESS +#else + #undef __USE_EXCLUSIVE_ACCESS +#endif + +#elif defined (__GNUC__) /* GNU Compiler */ + +#undef __USE_EXCLUSIVE_ACCESS + +#if defined (__CORTEX_M0) || defined (__CORTEX_M0PLUS) +#define __TARGET_ARCH_6S_M 1 +#else +#define __TARGET_ARCH_6S_M 0 +#endif + +#if defined (__VFP_FP__) && !defined(__SOFTFP__) +#define __TARGET_FPU_VFP 1 +#else +#define __TARGET_FPU_VFP 0 +#endif + +#define __inline inline +#define __weak __attribute__((weak)) + +#ifndef __CMSIS_GENERIC + +__attribute__((always_inline)) static inline void __enable_irq(void) +{ + __asm volatile ("cpsie i"); +} + +__attribute__((always_inline)) static inline U32 __disable_irq(void) +{ + U32 result; + + __asm volatile ("mrs %0, primask" : "=r" (result)); + __asm volatile ("cpsid i"); + return(result & 1); +} + +#endif + +__attribute__(( always_inline)) static inline U8 __clz(U32 value) +{ + U8 result; + + __asm volatile ("clz %0, %1" : "=r" (result) : "r" (value)); + return(result); +} + +#elif defined (__ICCARM__) /* IAR Compiler */ + +#undef __USE_EXCLUSIVE_ACCESS + +#if (__CORE__ == __ARM6M__) +#define __TARGET_ARCH_6S_M 1 +#else +#define __TARGET_ARCH_6S_M 0 +#endif + +#if defined __ARMVFP__ +#define __TARGET_FPU_VFP 1 +#else +#define __TARGET_FPU_VFP 0 +#endif + +#define __inline inline + +#ifndef __CMSIS_GENERIC + +static inline void __enable_irq(void) +{ + __asm volatile ("cpsie i"); +} + +static inline U32 __disable_irq(void) +{ + U32 result; + + __asm volatile ("mrs %0, primask" : "=r" (result)); + __asm volatile ("cpsid i"); + return(result & 1); +} + +#endif + +static inline U8 __clz(U32 value) +{ + U8 result; + + __asm volatile ("clz %0, %1" : "=r" (result) : "r" (value)); + return(result); +} + +#endif + +/* NVIC registers */ +#define NVIC_ST_CTRL (*((volatile U32 *)0xE000E010)) +#define NVIC_ST_RELOAD (*((volatile U32 *)0xE000E014)) +#define NVIC_ST_CURRENT (*((volatile U32 *)0xE000E018)) +#define NVIC_ISER ((volatile U32 *)0xE000E100) +#define NVIC_ICER ((volatile U32 *)0xE000E180) +#if (__TARGET_ARCH_6S_M) +#define NVIC_IP ((volatile U32 *)0xE000E400) +#else +#define NVIC_IP ((volatile U8 *)0xE000E400) +#endif +#define NVIC_INT_CTRL (*((volatile U32 *)0xE000ED04)) +#define NVIC_AIR_CTRL (*((volatile U32 *)0xE000ED0C)) +#define NVIC_SYS_PRI2 (*((volatile U32 *)0xE000ED1C)) +#define NVIC_SYS_PRI3 (*((volatile U32 *)0xE000ED20)) + +#define OS_PEND_IRQ() NVIC_INT_CTRL = (1<<28) +#define OS_PENDING ((NVIC_INT_CTRL >> 26) & (1<<2 | 1)) +#define OS_UNPEND(fl) NVIC_INT_CTRL = (*fl = OS_PENDING) << 25 +#define OS_PEND(fl,p) NVIC_INT_CTRL = (fl | p<<2) << 26 +#define OS_LOCK() NVIC_ST_CTRL = 0x0005 +#define OS_UNLOCK() NVIC_ST_CTRL = 0x0007 + +#define OS_X_PENDING ((NVIC_INT_CTRL >> 28) & 1) +#define OS_X_UNPEND(fl) NVIC_INT_CTRL = (*fl = OS_X_PENDING) << 27 +#define OS_X_PEND(fl,p) NVIC_INT_CTRL = (fl | p) << 28 +#if (__TARGET_ARCH_6S_M) +#define OS_X_INIT(n) NVIC_IP[n>>2] |= 0xFF << (8*(n & 0x03)); \ + NVIC_ISER[n>>5] = 1 << (n & 0x1F) +#else +#define OS_X_INIT(n) NVIC_IP[n] = 0xFF; \ + NVIC_ISER[n>>5] = 1 << (n & 0x1F) +#endif +#define OS_X_LOCK(n) NVIC_ICER[n>>5] = 1 << (n & 0x1F) +#define OS_X_UNLOCK(n) NVIC_ISER[n>>5] = 1 << (n & 0x1F) + +/* Core Debug registers */ +#define DEMCR (*((volatile U32 *)0xE000EDFC)) + +/* ITM registers */ +#define ITM_CONTROL (*((volatile U32 *)0xE0000E80)) +#define ITM_ENABLE (*((volatile U32 *)0xE0000E00)) +#define ITM_PORT30_U32 (*((volatile U32 *)0xE0000078)) +#define ITM_PORT31_U32 (*((volatile U32 *)0xE000007C)) +#define ITM_PORT31_U16 (*((volatile U16 *)0xE000007C)) +#define ITM_PORT31_U8 (*((volatile U8 *)0xE000007C)) + +/* Variables */ +extern BIT dbg_msg; + +/* Functions */ +#ifdef __USE_EXCLUSIVE_ACCESS + #define rt_inc(p) while(__strex((__ldrex(p)+1),p)) + #define rt_dec(p) while(__strex((__ldrex(p)-1),p)) +#else + #define rt_inc(p) __disable_irq();(*p)++;__enable_irq(); + #define rt_dec(p) __disable_irq();(*p)--;__enable_irq(); +#endif + +__inline static U32 rt_inc_qi (U32 size, U8 *count, U8 *first) { + U32 cnt,c2; +#ifdef __USE_EXCLUSIVE_ACCESS + do { + if ((cnt = __ldrex(count)) == size) { + __clrex(); + return (cnt); } + } while (__strex(cnt+1, count)); + do { + c2 = (cnt = __ldrex(first)) + 1; + if (c2 == size) c2 = 0; + } while (__strex(c2, first)); +#else + __disable_irq(); + if ((cnt = *count) < size) { + *count = cnt+1; + c2 = (cnt = *first) + 1; + if (c2 == size) c2 = 0; + *first = c2; + } + __enable_irq (); +#endif + return (cnt); +} + +__inline static void rt_systick_init (void) { + NVIC_ST_RELOAD = os_trv; + NVIC_ST_CURRENT = 0; + NVIC_ST_CTRL = 0x0007; + NVIC_SYS_PRI3 |= 0xFF000000; +} + +__inline static void rt_svc_init (void) { +#if !(__TARGET_ARCH_6S_M) + int sh,prigroup; +#endif + NVIC_SYS_PRI3 |= 0x00FF0000; +#if (__TARGET_ARCH_6S_M) + NVIC_SYS_PRI2 |= (NVIC_SYS_PRI3<<(8+1)) & 0xFC000000; +#else + sh = 8 - __clz (~((NVIC_SYS_PRI3 << 8) & 0xFF000000)); + prigroup = ((NVIC_AIR_CTRL >> 8) & 0x07); + if (prigroup >= sh) { + sh = prigroup + 1; + } + NVIC_SYS_PRI2 = ((0xFEFFFFFF << sh) & 0xFF000000) | (NVIC_SYS_PRI2 & 0x00FFFFFF); +#endif +} + +extern void rt_set_PSP (U32 stack); +extern U32 rt_get_PSP (void); +extern void os_set_env (void); +extern void *_alloc_box (void *box_mem); +extern int _free_box (void *box_mem, void *box); + +extern void rt_init_stack (P_TCB p_TCB, FUNCP task_body); +extern void rt_ret_val (P_TCB p_TCB, U32 v0); +extern void rt_ret_val2 (P_TCB p_TCB, U32 v0, U32 v1); + +extern void dbg_init (void); +extern void dbg_task_notify (P_TCB p_tcb, BOOL create); +extern void dbg_task_switch (U32 task_id); + +#ifdef DBG_MSG +#define DBG_INIT() dbg_init() +#define DBG_TASK_NOTIFY(p_tcb,create) if (dbg_msg) dbg_task_notify(p_tcb,create) +#define DBG_TASK_SWITCH(task_id) if (dbg_msg && (os_tsk.new_tsk != os_tsk.run)) \ + dbg_task_switch(task_id) +#else +#define DBG_INIT() +#define DBG_TASK_NOTIFY(p_tcb,create) +#define DBG_TASK_SWITCH(task_id) +#endif + +/*---------------------------------------------------------------------------- + * end of file + *---------------------------------------------------------------------------*/ + diff --git a/libraries/mbed/rtos/rtx/TARGET_CORTEX_M/rt_List.c b/libraries/mbed/rtos/rtx/TARGET_CORTEX_M/rt_List.c new file mode 100644 index 0000000..2134d14 --- /dev/null +++ b/libraries/mbed/rtos/rtx/TARGET_CORTEX_M/rt_List.c @@ -0,0 +1,320 @@ +/*---------------------------------------------------------------------------- + * RL-ARM - RTX + *---------------------------------------------------------------------------- + * Name: RT_LIST.C + * Purpose: Functions for the management of different lists + * Rev.: V4.60 + *---------------------------------------------------------------------------- + * + * Copyright (c) 1999-2009 KEIL, 2009-2012 ARM Germany GmbH + * All rights reserved. + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * - Neither the name of ARM nor the names of its contributors may be used + * to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDERS AND CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + *---------------------------------------------------------------------------*/ + +#include "rt_TypeDef.h" +#include "RTX_Conf.h" +#include "rt_System.h" +#include "rt_List.h" +#include "rt_Task.h" +#include "rt_Time.h" +#include "rt_HAL_CM.h" + +/*---------------------------------------------------------------------------- + * Global Variables + *---------------------------------------------------------------------------*/ + +/* List head of chained ready tasks */ +struct OS_XCB os_rdy; +/* List head of chained delay tasks */ +struct OS_XCB os_dly; + + +/*---------------------------------------------------------------------------- + * Functions + *---------------------------------------------------------------------------*/ + + +/*--------------------------- rt_put_prio -----------------------------------*/ + +void rt_put_prio (P_XCB p_CB, P_TCB p_task) { + /* Put task identified with "p_task" into list ordered by priority. */ + /* "p_CB" points to head of list; list has always an element at end with */ + /* a priority less than "p_task->prio". */ + P_TCB p_CB2; + U32 prio; + BOOL sem_mbx = __FALSE; + + if (p_CB->cb_type == SCB || p_CB->cb_type == MCB || p_CB->cb_type == MUCB) { + sem_mbx = __TRUE; + } + prio = p_task->prio; + p_CB2 = p_CB->p_lnk; + /* Search for an entry in the list */ + while (p_CB2 != NULL && prio <= p_CB2->prio) { + p_CB = (P_XCB)p_CB2; + p_CB2 = p_CB2->p_lnk; + } + /* Entry found, insert the task into the list */ + p_task->p_lnk = p_CB2; + p_CB->p_lnk = p_task; + if (sem_mbx) { + if (p_CB2 != NULL) { + p_CB2->p_rlnk = p_task; + } + p_task->p_rlnk = (P_TCB)p_CB; + } + else { + p_task->p_rlnk = NULL; + } +} + + +/*--------------------------- rt_get_first ----------------------------------*/ + +P_TCB rt_get_first (P_XCB p_CB) { + /* Get task at head of list: it is the task with highest priority. */ + /* "p_CB" points to head of list. */ + P_TCB p_first; + + p_first = p_CB->p_lnk; + p_CB->p_lnk = p_first->p_lnk; + if (p_CB->cb_type == SCB || p_CB->cb_type == MCB || p_CB->cb_type == MUCB) { + if (p_first->p_lnk != NULL) { + p_first->p_lnk->p_rlnk = (P_TCB)p_CB; + p_first->p_lnk = NULL; + } + p_first->p_rlnk = NULL; + } + else { + p_first->p_lnk = NULL; + } + return (p_first); +} + + +/*--------------------------- rt_put_rdy_first ------------------------------*/ + +void rt_put_rdy_first (P_TCB p_task) { + /* Put task identified with "p_task" at the head of the ready list. The */ + /* task must have at least a priority equal to highest priority in list. */ + p_task->p_lnk = os_rdy.p_lnk; + p_task->p_rlnk = NULL; + os_rdy.p_lnk = p_task; +} + + +/*--------------------------- rt_get_same_rdy_prio --------------------------*/ + +P_TCB rt_get_same_rdy_prio (void) { + /* Remove a task of same priority from ready list if any exists. Other- */ + /* wise return NULL. */ + P_TCB p_first; + + p_first = os_rdy.p_lnk; + if (p_first->prio == os_tsk.run->prio) { + os_rdy.p_lnk = os_rdy.p_lnk->p_lnk; + return (p_first); + } + return (NULL); +} + + +/*--------------------------- rt_resort_prio --------------------------------*/ + +void rt_resort_prio (P_TCB p_task) { + /* Re-sort ordered lists after the priority of 'p_task' has changed. */ + P_TCB p_CB; + + if (p_task->p_rlnk == NULL) { + if (p_task->state == READY) { + /* Task is chained into READY list. */ + p_CB = (P_TCB)&os_rdy; + goto res; + } + } + else { + p_CB = p_task->p_rlnk; + while (p_CB->cb_type == TCB) { + /* Find a header of this task chain list. */ + p_CB = p_CB->p_rlnk; + } +res:rt_rmv_list (p_task); + rt_put_prio ((P_XCB)p_CB, p_task); + } +} + + +/*--------------------------- rt_put_dly ------------------------------------*/ + +void rt_put_dly (P_TCB p_task, U16 delay) { + /* Put a task identified with "p_task" into chained delay wait list using */ + /* a delay value of "delay". */ + P_TCB p; + U32 delta,idelay = delay; + + p = (P_TCB)&os_dly; + if (p->p_dlnk == NULL) { + /* Delay list empty */ + delta = 0; + goto last; + } + delta = os_dly.delta_time; + while (delta < idelay) { + if (p->p_dlnk == NULL) { + /* End of list found */ +last: p_task->p_dlnk = NULL; + p->p_dlnk = p_task; + p_task->p_blnk = p; + p->delta_time = (U16)(idelay - delta); + p_task->delta_time = 0; + return; + } + p = p->p_dlnk; + delta += p->delta_time; + } + /* Right place found */ + p_task->p_dlnk = p->p_dlnk; + p->p_dlnk = p_task; + p_task->p_blnk = p; + if (p_task->p_dlnk != NULL) { + p_task->p_dlnk->p_blnk = p_task; + } + p_task->delta_time = (U16)(delta - idelay); + p->delta_time -= p_task->delta_time; +} + + +/*--------------------------- rt_dec_dly ------------------------------------*/ + +void rt_dec_dly (void) { + /* Decrement delta time of list head: remove tasks having a value of zero.*/ + P_TCB p_rdy; + + if (os_dly.p_dlnk == NULL) { + return; + } + os_dly.delta_time--; + while ((os_dly.delta_time == 0) && (os_dly.p_dlnk != NULL)) { + p_rdy = os_dly.p_dlnk; + if (p_rdy->p_rlnk != NULL) { + /* Task is really enqueued, remove task from semaphore/mailbox */ + /* timeout waiting list. */ + p_rdy->p_rlnk->p_lnk = p_rdy->p_lnk; + if (p_rdy->p_lnk != NULL) { + p_rdy->p_lnk->p_rlnk = p_rdy->p_rlnk; + p_rdy->p_lnk = NULL; + } + p_rdy->p_rlnk = NULL; + } + rt_put_prio (&os_rdy, p_rdy); + os_dly.delta_time = p_rdy->delta_time; + if (p_rdy->state == WAIT_ITV) { + /* Calculate the next time for interval wait. */ + p_rdy->delta_time = p_rdy->interval_time + (U16)os_time; + } + p_rdy->state = READY; + os_dly.p_dlnk = p_rdy->p_dlnk; + if (p_rdy->p_dlnk != NULL) { + p_rdy->p_dlnk->p_blnk = (P_TCB)&os_dly; + p_rdy->p_dlnk = NULL; + } + p_rdy->p_blnk = NULL; + } +} + + +/*--------------------------- rt_rmv_list -----------------------------------*/ + +void rt_rmv_list (P_TCB p_task) { + /* Remove task identified with "p_task" from ready, semaphore or mailbox */ + /* waiting list if enqueued. */ + P_TCB p_b; + + if (p_task->p_rlnk != NULL) { + /* A task is enqueued in semaphore / mailbox waiting list. */ + p_task->p_rlnk->p_lnk = p_task->p_lnk; + if (p_task->p_lnk != NULL) { + p_task->p_lnk->p_rlnk = p_task->p_rlnk; + } + return; + } + + p_b = (P_TCB)&os_rdy; + while (p_b != NULL) { + /* Search the ready list for task "p_task" */ + if (p_b->p_lnk == p_task) { + p_b->p_lnk = p_task->p_lnk; + return; + } + p_b = p_b->p_lnk; + } +} + + +/*--------------------------- rt_rmv_dly ------------------------------------*/ + +void rt_rmv_dly (P_TCB p_task) { + /* Remove task identified with "p_task" from delay list if enqueued. */ + P_TCB p_b; + + p_b = p_task->p_blnk; + if (p_b != NULL) { + /* Task is really enqueued */ + p_b->p_dlnk = p_task->p_dlnk; + if (p_task->p_dlnk != NULL) { + /* 'p_task' is in the middle of list */ + p_b->delta_time += p_task->delta_time; + p_task->p_dlnk->p_blnk = p_b; + p_task->p_dlnk = NULL; + } + else { + /* 'p_task' is at the end of list */ + p_b->delta_time = 0; + } + p_task->p_blnk = NULL; + } +} + + +/*--------------------------- rt_psq_enq ------------------------------------*/ + +void rt_psq_enq (OS_ID entry, U32 arg) { + /* Insert post service request "entry" into ps-queue. */ + U32 idx; + + idx = rt_inc_qi (os_psq->size, &os_psq->count, &os_psq->first); + if (idx < os_psq->size) { + os_psq->q[idx].id = entry; + os_psq->q[idx].arg = arg; + } + else { + os_error (OS_ERR_FIFO_OVF); + } +} + + +/*---------------------------------------------------------------------------- + * end of file + *---------------------------------------------------------------------------*/ + diff --git a/libraries/mbed/rtos/rtx/TARGET_CORTEX_M/rt_List.h b/libraries/mbed/rtos/rtx/TARGET_CORTEX_M/rt_List.h new file mode 100644 index 0000000..cb3008e --- /dev/null +++ b/libraries/mbed/rtos/rtx/TARGET_CORTEX_M/rt_List.h @@ -0,0 +1,67 @@ +/*---------------------------------------------------------------------------- + * RL-ARM - RTX + *---------------------------------------------------------------------------- + * Name: RT_LIST.H + * Purpose: Functions for the management of different lists + * Rev.: V4.60 + *---------------------------------------------------------------------------- + * + * Copyright (c) 1999-2009 KEIL, 2009-2012 ARM Germany GmbH + * All rights reserved. + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * - Neither the name of ARM nor the names of its contributors may be used + * to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDERS AND CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + *---------------------------------------------------------------------------*/ + +/* Definitions */ + +/* Values for 'cb_type' */ +#define TCB 0 +#define MCB 1 +#define SCB 2 +#define MUCB 3 +#define HCB 4 + +/* Variables */ +extern struct OS_XCB os_rdy; +extern struct OS_XCB os_dly; + +/* Functions */ +extern void rt_put_prio (P_XCB p_CB, P_TCB p_task); +extern P_TCB rt_get_first (P_XCB p_CB); +extern void rt_put_rdy_first (P_TCB p_task); +extern P_TCB rt_get_same_rdy_prio (void); +extern void rt_resort_prio (P_TCB p_task); +extern void rt_put_dly (P_TCB p_task, U16 delay); +extern void rt_dec_dly (void); +extern void rt_rmv_list (P_TCB p_task); +extern void rt_rmv_dly (P_TCB p_task); +extern void rt_psq_enq (OS_ID entry, U32 arg); + +/* This is a fast macro generating in-line code */ +#define rt_rdy_prio(void) (os_rdy.p_lnk->prio) + + +/*---------------------------------------------------------------------------- + * end of file + *---------------------------------------------------------------------------*/ + diff --git a/libraries/mbed/rtos/rtx/TARGET_CORTEX_M/rt_Mailbox.c b/libraries/mbed/rtos/rtx/TARGET_CORTEX_M/rt_Mailbox.c new file mode 100644 index 0000000..ef28b76 --- /dev/null +++ b/libraries/mbed/rtos/rtx/TARGET_CORTEX_M/rt_Mailbox.c @@ -0,0 +1,292 @@ +/*---------------------------------------------------------------------------- + * RL-ARM - RTX + *---------------------------------------------------------------------------- + * Name: RT_MAILBOX.C + * Purpose: Implements waits and wake-ups for mailbox messages + * Rev.: V4.60 + *---------------------------------------------------------------------------- + * + * Copyright (c) 1999-2009 KEIL, 2009-2012 ARM Germany GmbH + * All rights reserved. + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * - Neither the name of ARM nor the names of its contributors may be used + * to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDERS AND CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + *---------------------------------------------------------------------------*/ + +#include "rt_TypeDef.h" +#include "RTX_Conf.h" +#include "rt_System.h" +#include "rt_List.h" +#include "rt_Mailbox.h" +#include "rt_MemBox.h" +#include "rt_Task.h" +#include "rt_HAL_CM.h" + + +/*---------------------------------------------------------------------------- + * Functions + *---------------------------------------------------------------------------*/ + + +/*--------------------------- rt_mbx_init -----------------------------------*/ + +void rt_mbx_init (OS_ID mailbox, U16 mbx_size) { + /* Initialize a mailbox */ + P_MCB p_MCB = mailbox; + + p_MCB->cb_type = MCB; + p_MCB->state = 0; + p_MCB->isr_st = 0; + p_MCB->p_lnk = NULL; + p_MCB->first = 0; + p_MCB->last = 0; + p_MCB->count = 0; + p_MCB->size = (mbx_size + sizeof(void *) - sizeof(struct OS_MCB)) / + (U32)sizeof (void *); +} + + +/*--------------------------- rt_mbx_send -----------------------------------*/ + +OS_RESULT rt_mbx_send (OS_ID mailbox, void *p_msg, U16 timeout) { + /* Send message to a mailbox */ + P_MCB p_MCB = mailbox; + P_TCB p_TCB; + + if ((p_MCB->p_lnk != NULL) && (p_MCB->state == 1)) { + /* A task is waiting for message */ + p_TCB = rt_get_first ((P_XCB)p_MCB); +#ifdef __CMSIS_RTOS + rt_ret_val2(p_TCB, 0x10/*osEventMessage*/, (U32)p_msg); +#else + *p_TCB->msg = p_msg; + rt_ret_val (p_TCB, OS_R_MBX); +#endif + rt_rmv_dly (p_TCB); + rt_dispatch (p_TCB); + } + else { + /* Store message in mailbox queue */ + if (p_MCB->count == p_MCB->size) { + /* No free message entry, wait for one. If message queue is full, */ + /* then no task is waiting for message. The 'p_MCB->p_lnk' list */ + /* pointer can now be reused for send message waits task list. */ + if (timeout == 0) { + return (OS_R_TMO); + } + if (p_MCB->p_lnk != NULL) { + rt_put_prio ((P_XCB)p_MCB, os_tsk.run); + } + else { + p_MCB->p_lnk = os_tsk.run; + os_tsk.run->p_lnk = NULL; + os_tsk.run->p_rlnk = (P_TCB)p_MCB; + /* Task is waiting to send a message */ + p_MCB->state = 2; + } + os_tsk.run->msg = p_msg; + rt_block (timeout, WAIT_MBX); + return (OS_R_TMO); + } + /* Yes, there is a free entry in a mailbox. */ + p_MCB->msg[p_MCB->first] = p_msg; + rt_inc (&p_MCB->count); + if (++p_MCB->first == p_MCB->size) { + p_MCB->first = 0; + } + } + return (OS_R_OK); +} + + +/*--------------------------- rt_mbx_wait -----------------------------------*/ + +OS_RESULT rt_mbx_wait (OS_ID mailbox, void **message, U16 timeout) { + /* Receive a message; possibly wait for it */ + P_MCB p_MCB = mailbox; + P_TCB p_TCB; + + /* If a message is available in the fifo buffer */ + /* remove it from the fifo buffer and return. */ + if (p_MCB->count) { + *message = p_MCB->msg[p_MCB->last]; + if (++p_MCB->last == p_MCB->size) { + p_MCB->last = 0; + } + if ((p_MCB->p_lnk != NULL) && (p_MCB->state == 2)) { + /* A task is waiting to send message */ + p_TCB = rt_get_first ((P_XCB)p_MCB); +#ifdef __CMSIS_RTOS + rt_ret_val(p_TCB, 0/*osOK*/); +#else + rt_ret_val(p_TCB, OS_R_OK); +#endif + p_MCB->msg[p_MCB->first] = p_TCB->msg; + if (++p_MCB->first == p_MCB->size) { + p_MCB->first = 0; + } + rt_rmv_dly (p_TCB); + rt_dispatch (p_TCB); + } + else { + rt_dec (&p_MCB->count); + } + return (OS_R_OK); + } + /* No message available: wait for one */ + if (timeout == 0) { + return (OS_R_TMO); + } + if (p_MCB->p_lnk != NULL) { + rt_put_prio ((P_XCB)p_MCB, os_tsk.run); + } + else { + p_MCB->p_lnk = os_tsk.run; + os_tsk.run->p_lnk = NULL; + os_tsk.run->p_rlnk = (P_TCB)p_MCB; + /* Task is waiting to receive a message */ + p_MCB->state = 1; + } + rt_block(timeout, WAIT_MBX); +#ifndef __CMSIS_RTOS + os_tsk.run->msg = message; +#endif + return (OS_R_TMO); +} + + +/*--------------------------- rt_mbx_check ----------------------------------*/ + +OS_RESULT rt_mbx_check (OS_ID mailbox) { + /* Check for free space in a mailbox. Returns the number of messages */ + /* that can be stored to a mailbox. It returns 0 when mailbox is full. */ + P_MCB p_MCB = mailbox; + + return (p_MCB->size - p_MCB->count); +} + + +/*--------------------------- isr_mbx_send ----------------------------------*/ + +void isr_mbx_send (OS_ID mailbox, void *p_msg) { + /* Same function as "os_mbx_send", but to be called by ISRs. */ + P_MCB p_MCB = mailbox; + + rt_psq_enq (p_MCB, (U32)p_msg); + rt_psh_req (); +} + + +/*--------------------------- isr_mbx_receive -------------------------------*/ + +OS_RESULT isr_mbx_receive (OS_ID mailbox, void **message) { + /* Receive a message in the interrupt function. The interrupt function */ + /* should not wait for a message since this would block the rtx os. */ + P_MCB p_MCB = mailbox; + + if (p_MCB->count) { + /* A message is available in the fifo buffer. */ + *message = p_MCB->msg[p_MCB->last]; + if (p_MCB->state == 2) { + /* A task is locked waiting to send message */ + rt_psq_enq (p_MCB, 0); + rt_psh_req (); + } + rt_dec (&p_MCB->count); + if (++p_MCB->last == p_MCB->size) { + p_MCB->last = 0; + } + return (OS_R_MBX); + } + return (OS_R_OK); +} + + +/*--------------------------- rt_mbx_psh ------------------------------------*/ + +void rt_mbx_psh (P_MCB p_CB, void *p_msg) { + /* Store the message to the mailbox queue or pass it to task directly. */ + P_TCB p_TCB; + void *mem; + + if (p_CB->p_lnk != NULL) switch (p_CB->state) { +#ifdef __CMSIS_RTOS + case 3: + /* Task is waiting to allocate memory, remove it from the waiting list */ + mem = rt_alloc_box(p_msg); + if (mem == NULL) break; + p_TCB = rt_get_first ((P_XCB)p_CB); + rt_ret_val(p_TCB, (U32)mem); + p_TCB->state = READY; + rt_rmv_dly (p_TCB); + rt_put_prio (&os_rdy, p_TCB); + break; +#endif + case 2: + /* Task is waiting to send a message, remove it from the waiting list */ + p_TCB = rt_get_first ((P_XCB)p_CB); +#ifdef __CMSIS_RTOS + rt_ret_val(p_TCB, 0/*osOK*/); +#else + rt_ret_val(p_TCB, OS_R_OK); +#endif + p_CB->msg[p_CB->first] = p_TCB->msg; + rt_inc (&p_CB->count); + if (++p_CB->first == p_CB->size) { + p_CB->first = 0; + } + p_TCB->state = READY; + rt_rmv_dly (p_TCB); + rt_put_prio (&os_rdy, p_TCB); + break; + case 1: + /* Task is waiting for a message, pass the message to the task directly */ + p_TCB = rt_get_first ((P_XCB)p_CB); +#ifdef __CMSIS_RTOS + rt_ret_val2(p_TCB, 0x10/*osEventMessage*/, (U32)p_msg); +#else + *p_TCB->msg = p_msg; + rt_ret_val (p_TCB, OS_R_MBX); +#endif + p_TCB->state = READY; + rt_rmv_dly (p_TCB); + rt_put_prio (&os_rdy, p_TCB); + break; + } else { + /* No task is waiting for a message, store it to the mailbox queue */ + if (p_CB->count < p_CB->size) { + p_CB->msg[p_CB->first] = p_msg; + rt_inc (&p_CB->count); + if (++p_CB->first == p_CB->size) { + p_CB->first = 0; + } + } + else { + os_error (OS_ERR_MBX_OVF); + } + } +} + +/*---------------------------------------------------------------------------- + * end of file + *---------------------------------------------------------------------------*/ + diff --git a/libraries/mbed/rtos/rtx/TARGET_CORTEX_M/rt_Mailbox.h b/libraries/mbed/rtos/rtx/TARGET_CORTEX_M/rt_Mailbox.h new file mode 100644 index 0000000..0c8e2f3 --- /dev/null +++ b/libraries/mbed/rtos/rtx/TARGET_CORTEX_M/rt_Mailbox.h @@ -0,0 +1,48 @@ +/*---------------------------------------------------------------------------- + * RL-ARM - RTX + *---------------------------------------------------------------------------- + * Name: RT_MAILBOX.H + * Purpose: Implements waits and wake-ups for mailbox messages + * Rev.: V4.60 + *---------------------------------------------------------------------------- + * + * Copyright (c) 1999-2009 KEIL, 2009-2012 ARM Germany GmbH + * All rights reserved. + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * - Neither the name of ARM nor the names of its contributors may be used + * to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDERS AND CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + *---------------------------------------------------------------------------*/ + +/* Functions */ +extern void rt_mbx_init (OS_ID mailbox, U16 mbx_size); +extern OS_RESULT rt_mbx_send (OS_ID mailbox, void *p_msg, U16 timeout); +extern OS_RESULT rt_mbx_wait (OS_ID mailbox, void **message, U16 timeout); +extern OS_RESULT rt_mbx_check (OS_ID mailbox); +extern void isr_mbx_send (OS_ID mailbox, void *p_msg); +extern OS_RESULT isr_mbx_receive (OS_ID mailbox, void **message); +extern void rt_mbx_psh (P_MCB p_CB, void *p_msg); + + +/*---------------------------------------------------------------------------- + * end of file + *---------------------------------------------------------------------------*/ + diff --git a/libraries/mbed/rtos/rtx/TARGET_CORTEX_M/rt_MemBox.c b/libraries/mbed/rtos/rtx/TARGET_CORTEX_M/rt_MemBox.c new file mode 100644 index 0000000..5b96ae0 --- /dev/null +++ b/libraries/mbed/rtos/rtx/TARGET_CORTEX_M/rt_MemBox.c @@ -0,0 +1,166 @@ +/*---------------------------------------------------------------------------- + * RL-ARM - RTX + *---------------------------------------------------------------------------- + * Name: RT_MEMBOX.C + * Purpose: Interface functions for fixed memory block management system + * Rev.: V4.60 + *---------------------------------------------------------------------------- + * + * Copyright (c) 1999-2009 KEIL, 2009-2012 ARM Germany GmbH + * All rights reserved. + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * - Neither the name of ARM nor the names of its contributors may be used + * to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDERS AND CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + *---------------------------------------------------------------------------*/ + +#include "rt_TypeDef.h" +#include "RTX_Conf.h" +#include "rt_System.h" +#include "rt_MemBox.h" +#include "rt_HAL_CM.h" + +/*---------------------------------------------------------------------------- + * Global Functions + *---------------------------------------------------------------------------*/ + + +/*--------------------------- _init_box -------------------------------------*/ + +int _init_box (void *box_mem, U32 box_size, U32 blk_size) { + /* Initialize memory block system, returns 0 if OK, 1 if fails. */ + void *end; + void *blk; + void *next; + U32 sizeof_bm; + + /* Create memory structure. */ + if (blk_size & BOX_ALIGN_8) { + /* Memory blocks 8-byte aligned. */ + blk_size = ((blk_size & ~BOX_ALIGN_8) + 7) & ~7; + sizeof_bm = (sizeof (struct OS_BM) + 7) & ~7; + } + else { + /* Memory blocks 4-byte aligned. */ + blk_size = (blk_size + 3) & ~3; + sizeof_bm = sizeof (struct OS_BM); + } + if (blk_size == 0) { + return (1); + } + if ((blk_size + sizeof_bm) > box_size) { + return (1); + } + /* Create a Memory structure. */ + blk = ((U8 *) box_mem) + sizeof_bm; + ((P_BM) box_mem)->free = blk; + end = ((U8 *) box_mem) + box_size; + ((P_BM) box_mem)->end = end; + ((P_BM) box_mem)->blk_size = blk_size; + + /* Link all free blocks using offsets. */ + end = ((U8 *) end) - blk_size; + while (1) { + next = ((U8 *) blk) + blk_size; + if (next > end) break; + *((void **)blk) = next; + blk = next; + } + /* end marker */ + *((void **)blk) = 0; + return (0); +} + +/*--------------------------- rt_alloc_box ----------------------------------*/ + +void *rt_alloc_box (void *box_mem) { + /* Allocate a memory block and return start address. */ + void **free; +#ifndef __USE_EXCLUSIVE_ACCESS + int irq_dis; + + irq_dis = __disable_irq (); + free = ((P_BM) box_mem)->free; + if (free) { + ((P_BM) box_mem)->free = *free; + } + if (!irq_dis) __enable_irq (); +#else + do { + if ((free = (void **)__ldrex(&((P_BM) box_mem)->free)) == 0) { + __clrex(); + break; + } + } while (__strex((U32)*free, &((P_BM) box_mem)->free)); +#endif + return (free); +} + + +/*--------------------------- _calloc_box -----------------------------------*/ + +void *_calloc_box (void *box_mem) { + /* Allocate a 0-initialized memory block and return start address. */ + void *free; + U32 *p; + U32 i; + + free = _alloc_box (box_mem); + if (free) { + p = free; + for (i = ((P_BM) box_mem)->blk_size; i; i -= 4) { + *p = 0; + p++; + } + } + return (free); +} + + +/*--------------------------- rt_free_box -----------------------------------*/ + +int rt_free_box (void *box_mem, void *box) { + /* Free a memory block, returns 0 if OK, 1 if box does not belong to box_mem */ +#ifndef __USE_EXCLUSIVE_ACCESS + int irq_dis; +#endif + + if (box < box_mem || box >= ((P_BM) box_mem)->end) { + return (1); + } + +#ifndef __USE_EXCLUSIVE_ACCESS + irq_dis = __disable_irq (); + *((void **)box) = ((P_BM) box_mem)->free; + ((P_BM) box_mem)->free = box; + if (!irq_dis) __enable_irq (); +#else + do { + *((void **)box) = (void *)__ldrex(&((P_BM) box_mem)->free); + } while (__strex ((U32)box, &((P_BM) box_mem)->free)); +#endif + return (0); +} + +/*---------------------------------------------------------------------------- + * end of file + *---------------------------------------------------------------------------*/ + diff --git a/libraries/mbed/rtos/rtx/TARGET_CORTEX_M/rt_MemBox.h b/libraries/mbed/rtos/rtx/TARGET_CORTEX_M/rt_MemBox.h new file mode 100644 index 0000000..c10a1cb --- /dev/null +++ b/libraries/mbed/rtos/rtx/TARGET_CORTEX_M/rt_MemBox.h @@ -0,0 +1,46 @@ +/*---------------------------------------------------------------------------- + * RL-ARM - RTX + *---------------------------------------------------------------------------- + * Name: RT_MEMBOX.H + * Purpose: Interface functions for fixed memory block management system + * Rev.: V4.60 + *---------------------------------------------------------------------------- + * + * Copyright (c) 1999-2009 KEIL, 2009-2012 ARM Germany GmbH + * All rights reserved. + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * - Neither the name of ARM nor the names of its contributors may be used + * to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDERS AND CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + *---------------------------------------------------------------------------*/ + +/* Functions */ +#define rt_init_box _init_box +#define rt_calloc_box _calloc_box +extern int _init_box (void *box_mem, U32 box_size, U32 blk_size); +extern void *rt_alloc_box (void *box_mem); +extern void * _calloc_box (void *box_mem); +extern int rt_free_box (void *box_mem, void *box); + +/*---------------------------------------------------------------------------- + * end of file + *---------------------------------------------------------------------------*/ + diff --git a/libraries/mbed/rtos/rtx/TARGET_CORTEX_M/rt_Mutex.c b/libraries/mbed/rtos/rtx/TARGET_CORTEX_M/rt_Mutex.c new file mode 100644 index 0000000..c7a996b --- /dev/null +++ b/libraries/mbed/rtos/rtx/TARGET_CORTEX_M/rt_Mutex.c @@ -0,0 +1,197 @@ +/*---------------------------------------------------------------------------- + * RL-ARM - RTX + *---------------------------------------------------------------------------- + * Name: RT_MUTEX.C + * Purpose: Implements mutex synchronization objects + * Rev.: V4.60 + *---------------------------------------------------------------------------- + * + * Copyright (c) 1999-2009 KEIL, 2009-2012 ARM Germany GmbH + * All rights reserved. + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * - Neither the name of ARM nor the names of its contributors may be used + * to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDERS AND CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + *---------------------------------------------------------------------------*/ + +#include "rt_TypeDef.h" +#include "RTX_Conf.h" +#include "rt_List.h" +#include "rt_Task.h" +#include "rt_Mutex.h" +#include "rt_HAL_CM.h" + + +/*---------------------------------------------------------------------------- + * Functions + *---------------------------------------------------------------------------*/ + + +/*--------------------------- rt_mut_init -----------------------------------*/ + +void rt_mut_init (OS_ID mutex) { + /* Initialize a mutex object */ + P_MUCB p_MCB = mutex; + + p_MCB->cb_type = MUCB; + p_MCB->prio = 0; + p_MCB->level = 0; + p_MCB->p_lnk = NULL; + p_MCB->owner = NULL; +} + + +/*--------------------------- rt_mut_delete ---------------------------------*/ + +#ifdef __CMSIS_RTOS +OS_RESULT rt_mut_delete (OS_ID mutex) { + /* Delete a mutex object */ + P_MUCB p_MCB = mutex; + P_TCB p_TCB; + + /* Restore owner task's priority. */ + if (p_MCB->level != 0) { + p_MCB->owner->prio = p_MCB->prio; + if (p_MCB->owner != os_tsk.run) { + rt_resort_prio (p_MCB->owner); + } + } + + while (p_MCB->p_lnk != NULL) { + /* A task is waiting for mutex. */ + p_TCB = rt_get_first ((P_XCB)p_MCB); + rt_ret_val(p_TCB, 0/*osOK*/); + rt_rmv_dly(p_TCB); + p_TCB->state = READY; + rt_put_prio (&os_rdy, p_TCB); + } + + if (os_rdy.p_lnk && (os_rdy.p_lnk->prio > os_tsk.run->prio)) { + /* preempt running task */ + rt_put_prio (&os_rdy, os_tsk.run); + os_tsk.run->state = READY; + rt_dispatch (NULL); + } + + p_MCB->cb_type = 0; + + return (OS_R_OK); +} +#endif + + +/*--------------------------- rt_mut_release --------------------------------*/ + +OS_RESULT rt_mut_release (OS_ID mutex) { + /* Release a mutex object */ + P_MUCB p_MCB = mutex; + P_TCB p_TCB; + + if (p_MCB->level == 0 || p_MCB->owner != os_tsk.run) { + /* Unbalanced mutex release or task is not the owner */ + return (OS_R_NOK); + } + if (--p_MCB->level != 0) { + return (OS_R_OK); + } + /* Restore owner task's priority. */ + os_tsk.run->prio = p_MCB->prio; + if (p_MCB->p_lnk != NULL) { + /* A task is waiting for mutex. */ + p_TCB = rt_get_first ((P_XCB)p_MCB); +#ifdef __CMSIS_RTOS + rt_ret_val(p_TCB, 0/*osOK*/); +#else + rt_ret_val(p_TCB, OS_R_MUT); +#endif + rt_rmv_dly (p_TCB); + /* A waiting task becomes the owner of this mutex. */ + p_MCB->level = 1; + p_MCB->owner = p_TCB; + p_MCB->prio = p_TCB->prio; + /* Priority inversion, check which task continues. */ + if (os_tsk.run->prio >= rt_rdy_prio()) { + rt_dispatch (p_TCB); + } + else { + /* Ready task has higher priority than running task. */ + rt_put_prio (&os_rdy, os_tsk.run); + rt_put_prio (&os_rdy, p_TCB); + os_tsk.run->state = READY; + p_TCB->state = READY; + rt_dispatch (NULL); + } + } + else { + /* Check if own priority raised by priority inversion. */ + if (rt_rdy_prio() > os_tsk.run->prio) { + rt_put_prio (&os_rdy, os_tsk.run); + os_tsk.run->state = READY; + rt_dispatch (NULL); + } + } + return (OS_R_OK); +} + + +/*--------------------------- rt_mut_wait -----------------------------------*/ + +OS_RESULT rt_mut_wait (OS_ID mutex, U16 timeout) { + /* Wait for a mutex, continue when mutex is free. */ + P_MUCB p_MCB = mutex; + + if (p_MCB->level == 0) { + p_MCB->owner = os_tsk.run; + p_MCB->prio = os_tsk.run->prio; + goto inc; + } + if (p_MCB->owner == os_tsk.run) { + /* OK, running task is the owner of this mutex. */ +inc:p_MCB->level++; + return (OS_R_OK); + } + /* Mutex owned by another task, wait until released. */ + if (timeout == 0) { + return (OS_R_TMO); + } + /* Raise the owner task priority if lower than current priority. */ + /* This priority inversion is called priority inheritance. */ + if (p_MCB->prio < os_tsk.run->prio) { + p_MCB->owner->prio = os_tsk.run->prio; + rt_resort_prio (p_MCB->owner); + } + if (p_MCB->p_lnk != NULL) { + rt_put_prio ((P_XCB)p_MCB, os_tsk.run); + } + else { + p_MCB->p_lnk = os_tsk.run; + os_tsk.run->p_lnk = NULL; + os_tsk.run->p_rlnk = (P_TCB)p_MCB; + } + rt_block(timeout, WAIT_MUT); + return (OS_R_TMO); +} + + +/*---------------------------------------------------------------------------- + * end of file + *---------------------------------------------------------------------------*/ + diff --git a/libraries/mbed/rtos/rtx/TARGET_CORTEX_M/rt_Mutex.h b/libraries/mbed/rtos/rtx/TARGET_CORTEX_M/rt_Mutex.h new file mode 100644 index 0000000..bf15c4d --- /dev/null +++ b/libraries/mbed/rtos/rtx/TARGET_CORTEX_M/rt_Mutex.h @@ -0,0 +1,44 @@ +/*---------------------------------------------------------------------------- + * RL-ARM - RTX + *---------------------------------------------------------------------------- + * Name: RT_MUTEX.H + * Purpose: Implements mutex synchronization objects + * Rev.: V4.60 + *---------------------------------------------------------------------------- + * + * Copyright (c) 1999-2009 KEIL, 2009-2012 ARM Germany GmbH + * All rights reserved. + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * - Neither the name of ARM nor the names of its contributors may be used + * to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDERS AND CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + *---------------------------------------------------------------------------*/ + +/* Functions */ +extern void rt_mut_init (OS_ID mutex); +extern OS_RESULT rt_mut_delete (OS_ID mutex); +extern OS_RESULT rt_mut_release (OS_ID mutex); +extern OS_RESULT rt_mut_wait (OS_ID mutex, U16 timeout); + +/*---------------------------------------------------------------------------- + * end of file + *---------------------------------------------------------------------------*/ + diff --git a/libraries/mbed/rtos/rtx/TARGET_CORTEX_M/rt_Robin.c b/libraries/mbed/rtos/rtx/TARGET_CORTEX_M/rt_Robin.c new file mode 100644 index 0000000..d693dc6 --- /dev/null +++ b/libraries/mbed/rtos/rtx/TARGET_CORTEX_M/rt_Robin.c @@ -0,0 +1,84 @@ +/*---------------------------------------------------------------------------- + * RL-ARM - RTX + *---------------------------------------------------------------------------- + * Name: RT_ROBIN.C + * Purpose: Round Robin Task switching + * Rev.: V4.60 + *---------------------------------------------------------------------------- + * + * Copyright (c) 1999-2009 KEIL, 2009-2012 ARM Germany GmbH + * All rights reserved. + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * - Neither the name of ARM nor the names of its contributors may be used + * to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDERS AND CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + *---------------------------------------------------------------------------*/ + +#include "rt_TypeDef.h" +#include "RTX_Conf.h" +#include "rt_List.h" +#include "rt_Task.h" +#include "rt_Time.h" +#include "rt_Robin.h" +#include "rt_HAL_CM.h" + +/*---------------------------------------------------------------------------- + * Global Variables + *---------------------------------------------------------------------------*/ + +struct OS_ROBIN os_robin; + + +/*---------------------------------------------------------------------------- + * Global Functions + *---------------------------------------------------------------------------*/ + +/*--------------------------- rt_init_robin ---------------------------------*/ + +__weak void rt_init_robin (void) { + /* Initialize Round Robin variables. */ + os_robin.task = NULL; + os_robin.tout = (U16)os_rrobin; +} + +/*--------------------------- rt_chk_robin ----------------------------------*/ + +__weak void rt_chk_robin (void) { + /* Check if Round Robin timeout expired and switch to the next ready task.*/ + P_TCB p_new; + + if (os_robin.task != os_rdy.p_lnk) { + /* New task was suspended, reset Round Robin timeout. */ + os_robin.task = os_rdy.p_lnk; + os_robin.time = (U16)os_time + os_robin.tout - 1; + } + if (os_robin.time == (U16)os_time) { + /* Round Robin timeout has expired, swap Robin tasks. */ + os_robin.task = NULL; + p_new = rt_get_first (&os_rdy); + rt_put_prio ((P_XCB)&os_rdy, p_new); + } +} + +/*---------------------------------------------------------------------------- + * end of file + *---------------------------------------------------------------------------*/ + diff --git a/libraries/mbed/rtos/rtx/TARGET_CORTEX_M/rt_Robin.h b/libraries/mbed/rtos/rtx/TARGET_CORTEX_M/rt_Robin.h new file mode 100644 index 0000000..3ccbffc --- /dev/null +++ b/libraries/mbed/rtos/rtx/TARGET_CORTEX_M/rt_Robin.h @@ -0,0 +1,45 @@ +/*---------------------------------------------------------------------------- + * RL-ARM - RTX + *---------------------------------------------------------------------------- + * Name: RT_ROBIN.H + * Purpose: Round Robin Task switching definitions + * Rev.: V4.60 + *---------------------------------------------------------------------------- + * + * Copyright (c) 1999-2009 KEIL, 2009-2012 ARM Germany GmbH + * All rights reserved. + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * - Neither the name of ARM nor the names of its contributors may be used + * to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDERS AND CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + *---------------------------------------------------------------------------*/ + +/* Variables */ +extern struct OS_ROBIN os_robin; + +/* Functions */ +extern void rt_init_robin (void); +extern void rt_chk_robin (void); + +/*---------------------------------------------------------------------------- + * end of file + *---------------------------------------------------------------------------*/ + diff --git a/libraries/mbed/rtos/rtx/TARGET_CORTEX_M/rt_Semaphore.c b/libraries/mbed/rtos/rtx/TARGET_CORTEX_M/rt_Semaphore.c new file mode 100644 index 0000000..93ff2bf --- /dev/null +++ b/libraries/mbed/rtos/rtx/TARGET_CORTEX_M/rt_Semaphore.c @@ -0,0 +1,183 @@ +/*---------------------------------------------------------------------------- + * RL-ARM - RTX + *---------------------------------------------------------------------------- + * Name: RT_SEMAPHORE.C + * Purpose: Implements binary and counting semaphores + * Rev.: V4.60 + *---------------------------------------------------------------------------- + * + * Copyright (c) 1999-2009 KEIL, 2009-2012 ARM Germany GmbH + * All rights reserved. + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * - Neither the name of ARM nor the names of its contributors may be used + * to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDERS AND CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + *---------------------------------------------------------------------------*/ + +#include "rt_TypeDef.h" +#include "RTX_Conf.h" +#include "rt_System.h" +#include "rt_List.h" +#include "rt_Task.h" +#include "rt_Semaphore.h" +#include "rt_HAL_CM.h" + + +/*---------------------------------------------------------------------------- + * Functions + *---------------------------------------------------------------------------*/ + + +/*--------------------------- rt_sem_init -----------------------------------*/ + +void rt_sem_init (OS_ID semaphore, U16 token_count) { + /* Initialize a semaphore */ + P_SCB p_SCB = semaphore; + + p_SCB->cb_type = SCB; + p_SCB->p_lnk = NULL; + p_SCB->tokens = token_count; +} + + +/*--------------------------- rt_sem_delete ---------------------------------*/ + +#ifdef __CMSIS_RTOS +OS_RESULT rt_sem_delete (OS_ID semaphore) { + /* Delete semaphore */ + P_SCB p_SCB = semaphore; + P_TCB p_TCB; + + while (p_SCB->p_lnk != NULL) { + /* A task is waiting for token */ + p_TCB = rt_get_first ((P_XCB)p_SCB); + rt_ret_val(p_TCB, 0); + rt_rmv_dly(p_TCB); + p_TCB->state = READY; + rt_put_prio (&os_rdy, p_TCB); + } + + if (os_rdy.p_lnk && (os_rdy.p_lnk->prio > os_tsk.run->prio)) { + /* preempt running task */ + rt_put_prio (&os_rdy, os_tsk.run); + os_tsk.run->state = READY; + rt_dispatch (NULL); + } + + p_SCB->cb_type = 0; + + return (OS_R_OK); +} +#endif + + +/*--------------------------- rt_sem_send -----------------------------------*/ + +OS_RESULT rt_sem_send (OS_ID semaphore) { + /* Return a token to semaphore */ + P_SCB p_SCB = semaphore; + P_TCB p_TCB; + + if (p_SCB->p_lnk != NULL) { + /* A task is waiting for token */ + p_TCB = rt_get_first ((P_XCB)p_SCB); +#ifdef __CMSIS_RTOS + rt_ret_val(p_TCB, 1); +#else + rt_ret_val(p_TCB, OS_R_SEM); +#endif + rt_rmv_dly (p_TCB); + rt_dispatch (p_TCB); + } + else { + /* Store token. */ + p_SCB->tokens++; + } + return (OS_R_OK); +} + + +/*--------------------------- rt_sem_wait -----------------------------------*/ + +OS_RESULT rt_sem_wait (OS_ID semaphore, U16 timeout) { + /* Obtain a token; possibly wait for it */ + P_SCB p_SCB = semaphore; + + if (p_SCB->tokens) { + p_SCB->tokens--; + return (OS_R_OK); + } + /* No token available: wait for one */ + if (timeout == 0) { + return (OS_R_TMO); + } + if (p_SCB->p_lnk != NULL) { + rt_put_prio ((P_XCB)p_SCB, os_tsk.run); + } + else { + p_SCB->p_lnk = os_tsk.run; + os_tsk.run->p_lnk = NULL; + os_tsk.run->p_rlnk = (P_TCB)p_SCB; + } + rt_block(timeout, WAIT_SEM); + return (OS_R_TMO); +} + + +/*--------------------------- isr_sem_send ----------------------------------*/ + +void isr_sem_send (OS_ID semaphore) { + /* Same function as "os_sem"send", but to be called by ISRs */ + P_SCB p_SCB = semaphore; + + rt_psq_enq (p_SCB, 0); + rt_psh_req (); +} + + +/*--------------------------- rt_sem_psh ------------------------------------*/ + +void rt_sem_psh (P_SCB p_CB) { + /* Check if task has to be waken up */ + P_TCB p_TCB; + + if (p_CB->p_lnk != NULL) { + /* A task is waiting for token */ + p_TCB = rt_get_first ((P_XCB)p_CB); + rt_rmv_dly (p_TCB); + p_TCB->state = READY; +#ifdef __CMSIS_RTOS + rt_ret_val(p_TCB, 1); +#else + rt_ret_val(p_TCB, OS_R_SEM); +#endif + rt_put_prio (&os_rdy, p_TCB); + } + else { + /* Store token */ + p_CB->tokens++; + } +} + +/*---------------------------------------------------------------------------- + * end of file + *---------------------------------------------------------------------------*/ + diff --git a/libraries/mbed/rtos/rtx/TARGET_CORTEX_M/rt_Semaphore.h b/libraries/mbed/rtos/rtx/TARGET_CORTEX_M/rt_Semaphore.h new file mode 100644 index 0000000..ec45480 --- /dev/null +++ b/libraries/mbed/rtos/rtx/TARGET_CORTEX_M/rt_Semaphore.h @@ -0,0 +1,46 @@ +/*---------------------------------------------------------------------------- + * RL-ARM - RTX + *---------------------------------------------------------------------------- + * Name: RT_SEMAPHORE.H + * Purpose: Implements binary and counting semaphores + * Rev.: V4.60 + *---------------------------------------------------------------------------- + * + * Copyright (c) 1999-2009 KEIL, 2009-2012 ARM Germany GmbH + * All rights reserved. + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * - Neither the name of ARM nor the names of its contributors may be used + * to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDERS AND CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + *---------------------------------------------------------------------------*/ + +/* Functions */ +extern void rt_sem_init (OS_ID semaphore, U16 token_count); +extern OS_RESULT rt_sem_delete(OS_ID semaphore); +extern OS_RESULT rt_sem_send (OS_ID semaphore); +extern OS_RESULT rt_sem_wait (OS_ID semaphore, U16 timeout); +extern void isr_sem_send (OS_ID semaphore); +extern void rt_sem_psh (P_SCB p_CB); + +/*---------------------------------------------------------------------------- + * end of file + *---------------------------------------------------------------------------*/ + diff --git a/libraries/mbed/rtos/rtx/TARGET_CORTEX_M/rt_System.c b/libraries/mbed/rtos/rtx/TARGET_CORTEX_M/rt_System.c new file mode 100644 index 0000000..f48b67b --- /dev/null +++ b/libraries/mbed/rtos/rtx/TARGET_CORTEX_M/rt_System.c @@ -0,0 +1,299 @@ +/*---------------------------------------------------------------------------- + * RL-ARM - RTX + *---------------------------------------------------------------------------- + * Name: RT_SYSTEM.C + * Purpose: System Task Manager + * Rev.: V4.60 + *---------------------------------------------------------------------------- + * + * Copyright (c) 1999-2009 KEIL, 2009-2012 ARM Germany GmbH + * All rights reserved. + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * - Neither the name of ARM nor the names of its contributors may be used + * to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDERS AND CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + *---------------------------------------------------------------------------*/ + +#include "rt_TypeDef.h" +#include "RTX_Conf.h" +#include "rt_Task.h" +#include "rt_System.h" +#include "rt_Event.h" +#include "rt_List.h" +#include "rt_Mailbox.h" +#include "rt_Semaphore.h" +#include "rt_Time.h" +#include "rt_Robin.h" +#include "rt_HAL_CM.h" + +/*---------------------------------------------------------------------------- + * Global Variables + *---------------------------------------------------------------------------*/ + +int os_tick_irqn; + +/*---------------------------------------------------------------------------- + * Local Variables + *---------------------------------------------------------------------------*/ + +static volatile BIT os_lock; +static volatile BIT os_psh_flag; +static U8 pend_flags; + +/*---------------------------------------------------------------------------- + * Global Functions + *---------------------------------------------------------------------------*/ + +#if defined (__CC_ARM) +__asm void $$RTX$$version (void) { + /* Export a version number symbol for a version control. */ + + EXPORT __RL_RTX_VER + +__RL_RTX_VER EQU 0x450 +} +#endif + + +/*--------------------------- rt_suspend ------------------------------------*/ +U32 rt_suspend (void) { + /* Suspend OS scheduler */ + U32 delta = 0xFFFF; + + rt_tsk_lock(); + + if (os_dly.p_dlnk) { + delta = os_dly.delta_time; + } +#ifndef __CMSIS_RTOS + if (os_tmr.next) { + if (os_tmr.tcnt < delta) delta = os_tmr.tcnt; + } +#endif + + return (delta); +} + + +/*--------------------------- rt_resume -------------------------------------*/ +void rt_resume (U32 sleep_time) { + /* Resume OS scheduler after suspend */ + P_TCB next; + U32 delta; + + os_tsk.run->state = READY; + rt_put_rdy_first (os_tsk.run); + + os_robin.task = NULL; + + /* Update delays. */ + if (os_dly.p_dlnk) { + delta = sleep_time; + if (delta >= os_dly.delta_time) { + delta -= os_dly.delta_time; + os_time += os_dly.delta_time; + os_dly.delta_time = 1; + while (os_dly.p_dlnk) { + rt_dec_dly(); + if (delta == 0) break; + delta--; + os_time++; + } + } else { + os_time += delta; + os_dly.delta_time -= delta; + } + } else { + os_time += sleep_time; + } + +#ifndef __CMSIS_RTOS + /* Check the user timers. */ + if (os_tmr.next) { + delta = sleep_time; + if (delta >= os_tmr.tcnt) { + delta -= os_tmr.tcnt; + os_tmr.tcnt = 1; + while (os_tmr.next) { + rt_tmr_tick(); + if (delta == 0) break; + delta--; + } + } else { + os_tmr.tcnt -= delta; + } + } +#endif + + /* Switch back to highest ready task */ + next = rt_get_first (&os_rdy); + rt_switch_req (next); + + rt_tsk_unlock(); +} + + +/*--------------------------- rt_tsk_lock -----------------------------------*/ + +void rt_tsk_lock (void) { + /* Prevent task switching by locking out scheduler */ + if (os_tick_irqn < 0) { + OS_LOCK(); + os_lock = __TRUE; + OS_UNPEND (&pend_flags); + } else { + OS_X_LOCK(os_tick_irqn); + os_lock = __TRUE; + OS_X_UNPEND (&pend_flags); + } +} + + +/*--------------------------- rt_tsk_unlock ---------------------------------*/ + +void rt_tsk_unlock (void) { + /* Unlock scheduler and re-enable task switching */ + if (os_tick_irqn < 0) { + OS_UNLOCK(); + os_lock = __FALSE; + OS_PEND (pend_flags, os_psh_flag); + os_psh_flag = __FALSE; + } else { + OS_X_UNLOCK(os_tick_irqn); + os_lock = __FALSE; + OS_X_PEND (pend_flags, os_psh_flag); + os_psh_flag = __FALSE; + } +} + + +/*--------------------------- rt_psh_req ------------------------------------*/ + +void rt_psh_req (void) { + /* Initiate a post service handling request if required. */ + if (os_lock == __FALSE) { + OS_PEND_IRQ (); + } + else { + os_psh_flag = __TRUE; + } +} + + +/*--------------------------- rt_pop_req ------------------------------------*/ + +void rt_pop_req (void) { + /* Process an ISR post service requests. */ + struct OS_XCB *p_CB; + P_TCB next; + U32 idx; + + os_tsk.run->state = READY; + rt_put_rdy_first (os_tsk.run); + + idx = os_psq->last; + while (os_psq->count) { + p_CB = os_psq->q[idx].id; + if (p_CB->cb_type == TCB) { + /* Is of TCB type */ + rt_evt_psh ((P_TCB)p_CB, (U16)os_psq->q[idx].arg); + } + else if (p_CB->cb_type == MCB) { + /* Is of MCB type */ + rt_mbx_psh ((P_MCB)p_CB, (void *)os_psq->q[idx].arg); + } + else { + /* Must be of SCB type */ + rt_sem_psh ((P_SCB)p_CB); + } + if (++idx == os_psq->size) idx = 0; + rt_dec (&os_psq->count); + } + os_psq->last = idx; + + next = rt_get_first (&os_rdy); + rt_switch_req (next); +} + + +/*--------------------------- os_tick_init ----------------------------------*/ + +__weak int os_tick_init (void) { + /* Initialize SysTick timer as system tick timer. */ + rt_systick_init (); + return (-1); /* Return IRQ number of SysTick timer */ +} + + +/*--------------------------- os_tick_irqack --------------------------------*/ + +__weak void os_tick_irqack (void) { + /* Acknowledge timer interrupt. */ +} + + +/*--------------------------- rt_systick ------------------------------------*/ + +extern void sysTimerTick(void); + +void rt_systick (void) { + /* Check for system clock update, suspend running task. */ + P_TCB next; + + os_tsk.run->state = READY; + rt_put_rdy_first (os_tsk.run); + + /* Check Round Robin timeout. */ + rt_chk_robin (); + + /* Update delays. */ + os_time++; + rt_dec_dly (); + + /* Check the user timers. */ +#ifdef __CMSIS_RTOS + sysTimerTick(); +#else + rt_tmr_tick (); +#endif + + /* Switch back to highest ready task */ + next = rt_get_first (&os_rdy); + rt_switch_req (next); +} + +/*--------------------------- rt_stk_check ----------------------------------*/ +__weak void rt_stk_check (void) { + /* Check for stack overflow. */ + if (os_tsk.run->task_id == 0x01) { + // TODO: For the main thread the check should be done against the main heap pointer + } else { + if ((os_tsk.run->tsk_stack < (U32)os_tsk.run->stack) || + (os_tsk.run->stack[0] != MAGIC_WORD)) { + os_error (OS_ERR_STK_OVF); + } + } +} + +/*---------------------------------------------------------------------------- + * end of file + *---------------------------------------------------------------------------*/ + diff --git a/libraries/mbed/rtos/rtx/TARGET_CORTEX_M/rt_System.h b/libraries/mbed/rtos/rtx/TARGET_CORTEX_M/rt_System.h new file mode 100644 index 0000000..91db648 --- /dev/null +++ b/libraries/mbed/rtos/rtx/TARGET_CORTEX_M/rt_System.h @@ -0,0 +1,52 @@ +/*---------------------------------------------------------------------------- + * RL-ARM - RTX + *---------------------------------------------------------------------------- + * Name: RT_SYSTEM.H + * Purpose: System Task Manager definitions + * Rev.: V4.60 + *---------------------------------------------------------------------------- + * + * Copyright (c) 1999-2009 KEIL, 2009-2012 ARM Germany GmbH + * All rights reserved. + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * - Neither the name of ARM nor the names of its contributors may be used + * to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDERS AND CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + *---------------------------------------------------------------------------*/ + +/* Variables */ +#define os_psq ((P_PSQ)&os_fifo) +extern int os_tick_irqn; + +/* Functions */ +extern U32 rt_suspend (void); +extern void rt_resume (U32 sleep_time); +extern void rt_tsk_lock (void); +extern void rt_tsk_unlock (void); +extern void rt_psh_req (void); +extern void rt_pop_req (void); +extern void rt_systick (void); +extern void rt_stk_check (void); + +/*---------------------------------------------------------------------------- + * end of file + *---------------------------------------------------------------------------*/ + diff --git a/libraries/mbed/rtos/rtx/TARGET_CORTEX_M/rt_Task.c b/libraries/mbed/rtos/rtx/TARGET_CORTEX_M/rt_Task.c new file mode 100644 index 0000000..518f78f --- /dev/null +++ b/libraries/mbed/rtos/rtx/TARGET_CORTEX_M/rt_Task.c @@ -0,0 +1,339 @@ +/*---------------------------------------------------------------------------- + * RL-ARM - RTX + *---------------------------------------------------------------------------- + * Name: RT_TASK.C + * Purpose: Task functions and system start up. + * Rev.: V4.60 + *---------------------------------------------------------------------------- + * + * Copyright (c) 1999-2009 KEIL, 2009-2012 ARM Germany GmbH + * All rights reserved. + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * - Neither the name of ARM nor the names of its contributors may be used + * to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDERS AND CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + *---------------------------------------------------------------------------*/ + +#include "rt_TypeDef.h" +#include "RTX_Conf.h" +#include "rt_System.h" +#include "rt_Task.h" +#include "rt_List.h" +#include "rt_MemBox.h" +#include "rt_Robin.h" +#include "rt_HAL_CM.h" + +/*---------------------------------------------------------------------------- + * Global Variables + *---------------------------------------------------------------------------*/ + +/* Running and next task info. */ +struct OS_TSK os_tsk; + +/* Task Control Blocks of idle demon */ +struct OS_TCB os_idle_TCB; + + +/*---------------------------------------------------------------------------- + * Local Functions + *---------------------------------------------------------------------------*/ + +OS_TID rt_get_TID (void) { + U32 tid; + + for (tid = 1; tid <= os_maxtaskrun; tid++) { + if (os_active_TCB[tid-1] == NULL) { + return ((OS_TID)tid); + } + } + return (0); +} + +#if defined (__CC_ARM) && !defined (__MICROLIB) +/*--------------------------- __user_perthread_libspace ---------------------*/ +extern void *__libspace_start; + +void *__user_perthread_libspace (void) { + /* Provide a separate libspace for each task. */ + if (os_tsk.run == NULL) { + /* RTX not running yet. */ + return (&__libspace_start); + } + return (void *)(os_tsk.run->std_libspace); +} +#endif + +/*--------------------------- rt_init_context -------------------------------*/ + +void rt_init_context (P_TCB p_TCB, U8 priority, FUNCP task_body) { + /* Initialize general part of the Task Control Block. */ + p_TCB->cb_type = TCB; + p_TCB->state = READY; + p_TCB->prio = priority; + p_TCB->p_lnk = NULL; + p_TCB->p_rlnk = NULL; + p_TCB->p_dlnk = NULL; + p_TCB->p_blnk = NULL; + p_TCB->delta_time = 0; + p_TCB->interval_time = 0; + p_TCB->events = 0; + p_TCB->waits = 0; + p_TCB->stack_frame = 0; + + rt_init_stack (p_TCB, task_body); +} + + +/*--------------------------- rt_switch_req ---------------------------------*/ + +void rt_switch_req (P_TCB p_new) { + /* Switch to next task (identified by "p_new"). */ + os_tsk.new_tsk = p_new; + p_new->state = RUNNING; + DBG_TASK_SWITCH(p_new->task_id); +} + + +/*--------------------------- rt_dispatch -----------------------------------*/ + +void rt_dispatch (P_TCB next_TCB) { + /* Dispatch next task if any identified or dispatch highest ready task */ + /* "next_TCB" identifies a task to run or has value NULL (=no next task) */ + if (next_TCB == NULL) { + /* Running task was blocked: continue with highest ready task */ + next_TCB = rt_get_first (&os_rdy); + rt_switch_req (next_TCB); + } + else { + /* Check which task continues */ + if (next_TCB->prio > os_tsk.run->prio) { + /* preempt running task */ + rt_put_rdy_first (os_tsk.run); + os_tsk.run->state = READY; + rt_switch_req (next_TCB); + } + else { + /* put next task into ready list, no task switch takes place */ + next_TCB->state = READY; + rt_put_prio (&os_rdy, next_TCB); + } + } +} + + +/*--------------------------- rt_block --------------------------------------*/ + +void rt_block (U16 timeout, U8 block_state) { + /* Block running task and choose next ready task. */ + /* "timeout" sets a time-out value or is 0xffff (=no time-out). */ + /* "block_state" defines the appropriate task state */ + P_TCB next_TCB; + + if (timeout) { + if (timeout < 0xffff) { + rt_put_dly (os_tsk.run, timeout); + } + os_tsk.run->state = block_state; + next_TCB = rt_get_first (&os_rdy); + rt_switch_req (next_TCB); + } +} + + +/*--------------------------- rt_tsk_pass -----------------------------------*/ + +void rt_tsk_pass (void) { + /* Allow tasks of same priority level to run cooperatively.*/ + P_TCB p_new; + + p_new = rt_get_same_rdy_prio(); + if (p_new != NULL) { + rt_put_prio ((P_XCB)&os_rdy, os_tsk.run); + os_tsk.run->state = READY; + rt_switch_req (p_new); + } +} + + +/*--------------------------- rt_tsk_self -----------------------------------*/ + +OS_TID rt_tsk_self (void) { + /* Return own task identifier value. */ + if (os_tsk.run == NULL) { + return (0); + } + return (os_tsk.run->task_id); +} + + +/*--------------------------- rt_tsk_prio -----------------------------------*/ + +OS_RESULT rt_tsk_prio (OS_TID task_id, U8 new_prio) { + /* Change execution priority of a task to "new_prio". */ + P_TCB p_task; + + if (task_id == 0) { + /* Change execution priority of calling task. */ + os_tsk.run->prio = new_prio; +run:if (rt_rdy_prio() > new_prio) { + rt_put_prio (&os_rdy, os_tsk.run); + os_tsk.run->state = READY; + rt_dispatch (NULL); + } + return (OS_R_OK); + } + + /* Find the task in the "os_active_TCB" array. */ + if (task_id > os_maxtaskrun || os_active_TCB[task_id-1] == NULL) { + /* Task with "task_id" not found or not started. */ + return (OS_R_NOK); + } + p_task = os_active_TCB[task_id-1]; + p_task->prio = new_prio; + if (p_task == os_tsk.run) { + goto run; + } + rt_resort_prio (p_task); + if (p_task->state == READY) { + /* Task enqueued in a ready list. */ + p_task = rt_get_first (&os_rdy); + rt_dispatch (p_task); + } + return (OS_R_OK); +} + +/*--------------------------- rt_tsk_delete ---------------------------------*/ + +OS_RESULT rt_tsk_delete (OS_TID task_id) { + /* Terminate the task identified with "task_id". */ + P_TCB task_context; + + if (task_id == 0 || task_id == os_tsk.run->task_id) { + /* Terminate itself. */ + os_tsk.run->state = INACTIVE; + os_tsk.run->tsk_stack = rt_get_PSP (); + rt_stk_check (); + os_active_TCB[os_tsk.run->task_id-1] = NULL; + + os_tsk.run->stack = NULL; + DBG_TASK_NOTIFY(os_tsk.run, __FALSE); + os_tsk.run = NULL; + rt_dispatch (NULL); + /* The program should never come to this point. */ + } + else { + /* Find the task in the "os_active_TCB" array. */ + if (task_id > os_maxtaskrun || os_active_TCB[task_id-1] == NULL) { + /* Task with "task_id" not found or not started. */ + return (OS_R_NOK); + } + task_context = os_active_TCB[task_id-1]; + rt_rmv_list (task_context); + rt_rmv_dly (task_context); + os_active_TCB[task_id-1] = NULL; + + task_context->stack = NULL; + DBG_TASK_NOTIFY(task_context, __FALSE); + } + return (OS_R_OK); +} + + +/*--------------------------- rt_sys_init -----------------------------------*/ + +#ifdef __CMSIS_RTOS +void rt_sys_init (void) { +#else +void rt_sys_init (FUNCP first_task, U32 prio_stksz, void *stk) { +#endif + /* Initialize system and start up task declared with "first_task". */ + U32 i; + + DBG_INIT(); + + /* Initialize dynamic memory and task TCB pointers to NULL. */ + for (i = 0; i < os_maxtaskrun; i++) { + os_active_TCB[i] = NULL; + } + + /* Set up TCB of idle demon */ + os_idle_TCB.task_id = 255; + os_idle_TCB.priv_stack = idle_task_stack_size; + os_idle_TCB.stack = idle_task_stack; + rt_init_context (&os_idle_TCB, 0, os_idle_demon); + + /* Set up ready list: initially empty */ + os_rdy.cb_type = HCB; + os_rdy.p_lnk = NULL; + /* Set up delay list: initially empty */ + os_dly.cb_type = HCB; + os_dly.p_dlnk = NULL; + os_dly.p_blnk = NULL; + os_dly.delta_time = 0; + + /* Fix SP and systemvariables to assume idle task is running */ + /* Transform main program into idle task by assuming idle TCB */ +#ifndef __CMSIS_RTOS + rt_set_PSP (os_idle_TCB.tsk_stack+32); +#endif + os_tsk.run = &os_idle_TCB; + os_tsk.run->state = RUNNING; + + /* Initialize ps queue */ + os_psq->first = 0; + os_psq->last = 0; + os_psq->size = os_fifo_size; + + rt_init_robin (); + + /* Intitialize SVC and PendSV */ + rt_svc_init (); + +#ifndef __CMSIS_RTOS + /* Intitialize and start system clock timer */ + os_tick_irqn = os_tick_init (); + if (os_tick_irqn >= 0) { + OS_X_INIT(os_tick_irqn); + } + + /* Start up first user task before entering the endless loop */ + rt_tsk_create (first_task, prio_stksz, stk, NULL); +#endif +} + + +/*--------------------------- rt_sys_start ----------------------------------*/ + +#ifdef __CMSIS_RTOS +void rt_sys_start (void) { + /* Start system */ + + /* Intitialize and start system clock timer */ + os_tick_irqn = os_tick_init (); + if (os_tick_irqn >= 0) { + OS_X_INIT(os_tick_irqn); + } +} +#endif + +/*---------------------------------------------------------------------------- + * end of file + *---------------------------------------------------------------------------*/ diff --git a/libraries/mbed/rtos/rtx/TARGET_CORTEX_M/rt_Task.h b/libraries/mbed/rtos/rtx/TARGET_CORTEX_M/rt_Task.h new file mode 100644 index 0000000..9d3727b --- /dev/null +++ b/libraries/mbed/rtos/rtx/TARGET_CORTEX_M/rt_Task.h @@ -0,0 +1,73 @@ +/*---------------------------------------------------------------------------- + * RL-ARM - RTX + *---------------------------------------------------------------------------- + * Name: RT_TASK.H + * Purpose: Task functions and system start up. + * Rev.: V4.60 + *---------------------------------------------------------------------------- + * + * Copyright (c) 1999-2009 KEIL, 2009-2012 ARM Germany GmbH + * All rights reserved. + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * - Neither the name of ARM nor the names of its contributors may be used + * to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDERS AND CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + *---------------------------------------------------------------------------*/ + +/* Definitions */ +#define __CMSIS_RTOS 1 + +/* Values for 'state' */ +#define INACTIVE 0 +#define READY 1 +#define RUNNING 2 +#define WAIT_DLY 3 +#define WAIT_ITV 4 +#define WAIT_OR 5 +#define WAIT_AND 6 +#define WAIT_SEM 7 +#define WAIT_MBX 8 +#define WAIT_MUT 9 + +/* Return codes */ +#define OS_R_TMO 0x01 +#define OS_R_EVT 0x02 +#define OS_R_SEM 0x03 +#define OS_R_MBX 0x04 +#define OS_R_MUT 0x05 + +#define OS_R_OK 0x00 +#define OS_R_NOK 0xff + +/* Variables */ +extern struct OS_TSK os_tsk; +extern struct OS_TCB os_idle_TCB; + +/* Functions */ +extern void rt_switch_req (P_TCB p_new); +extern void rt_dispatch (P_TCB next_TCB); +extern void rt_block (U16 timeout, U8 block_state); +extern void rt_tsk_pass (void); +extern OS_TID rt_tsk_self (void); +extern OS_RESULT rt_tsk_prio (OS_TID task_id, U8 new_prio); +extern OS_RESULT rt_tsk_delete (OS_TID task_id); +extern void rt_sys_init (void); +extern void rt_sys_start (void); diff --git a/libraries/mbed/rtos/rtx/TARGET_CORTEX_M/rt_Time.c b/libraries/mbed/rtos/rtx/TARGET_CORTEX_M/rt_Time.c new file mode 100644 index 0000000..b02cceb --- /dev/null +++ b/libraries/mbed/rtos/rtx/TARGET_CORTEX_M/rt_Time.c @@ -0,0 +1,94 @@ +/*---------------------------------------------------------------------------- + * RL-ARM - RTX + *---------------------------------------------------------------------------- + * Name: RT_TIME.C + * Purpose: Delay and interval wait functions + * Rev.: V4.60 + *---------------------------------------------------------------------------- + * + * Copyright (c) 1999-2009 KEIL, 2009-2012 ARM Germany GmbH + * All rights reserved. + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * - Neither the name of ARM nor the names of its contributors may be used + * to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDERS AND CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + *---------------------------------------------------------------------------*/ + +#include "rt_TypeDef.h" +#include "RTX_Conf.h" +#include "rt_Task.h" +#include "rt_Time.h" + +/*---------------------------------------------------------------------------- + * Global Variables + *---------------------------------------------------------------------------*/ + +/* Free running system tick counter */ +U32 os_time; + + +/*---------------------------------------------------------------------------- + * Functions + *---------------------------------------------------------------------------*/ + + +/*--------------------------- rt_time_get -----------------------------------*/ + +U32 rt_time_get (void) { + /* Get system time tick */ + return (os_time); +} + + +/*--------------------------- rt_dly_wait -----------------------------------*/ + +void rt_dly_wait (U16 delay_time) { + /* Delay task by "delay_time" */ + rt_block (delay_time, WAIT_DLY); +} + + +/*--------------------------- rt_itv_set ------------------------------------*/ + +void rt_itv_set (U16 interval_time) { + /* Set interval length and define start of first interval */ + os_tsk.run->interval_time = interval_time; + os_tsk.run->delta_time = interval_time + (U16)os_time; +} + + +/*--------------------------- rt_itv_wait -----------------------------------*/ + +void rt_itv_wait (void) { + /* Wait for interval end and define start of next one */ + U16 delta; + + delta = os_tsk.run->delta_time - (U16)os_time; + os_tsk.run->delta_time += os_tsk.run->interval_time; + if ((delta & 0x8000) == 0) { + rt_block (delta, WAIT_ITV); + } +} + +/*---------------------------------------------------------------------------- + * end of file + *---------------------------------------------------------------------------*/ + diff --git a/libraries/mbed/rtos/rtx/TARGET_CORTEX_M/rt_Time.h b/libraries/mbed/rtos/rtx/TARGET_CORTEX_M/rt_Time.h new file mode 100644 index 0000000..2770637 --- /dev/null +++ b/libraries/mbed/rtos/rtx/TARGET_CORTEX_M/rt_Time.h @@ -0,0 +1,47 @@ +/*---------------------------------------------------------------------------- + * RL-ARM - RTX + *---------------------------------------------------------------------------- + * Name: RT_TIME.H + * Purpose: Delay and interval wait functions definitions + * Rev.: V4.60 + *---------------------------------------------------------------------------- + * + * Copyright (c) 1999-2009 KEIL, 2009-2012 ARM Germany GmbH + * All rights reserved. + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * - Neither the name of ARM nor the names of its contributors may be used + * to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDERS AND CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + *---------------------------------------------------------------------------*/ + +/* Variables */ +extern U32 os_time; + +/* Functions */ +extern U32 rt_time_get (void); +extern void rt_dly_wait (U16 delay_time); +extern void rt_itv_set (U16 interval_time); +extern void rt_itv_wait (void); + +/*---------------------------------------------------------------------------- + * end of file + *---------------------------------------------------------------------------*/ + diff --git a/libraries/mbed/rtos/rtx/TARGET_CORTEX_M/rt_TypeDef.h b/libraries/mbed/rtos/rtx/TARGET_CORTEX_M/rt_TypeDef.h new file mode 100644 index 0000000..27416c5 --- /dev/null +++ b/libraries/mbed/rtos/rtx/TARGET_CORTEX_M/rt_TypeDef.h @@ -0,0 +1,128 @@ +/*---------------------------------------------------------------------------- + * RL-ARM - RTX + *---------------------------------------------------------------------------- + * Name: RT_TYPEDEF.H + * Purpose: Type Definitions + * Rev.: V4.60 + *---------------------------------------------------------------------------- + * + * Copyright (c) 1999-2009 KEIL, 2009-2012 ARM Germany GmbH + * All rights reserved. + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * - Neither the name of ARM nor the names of its contributors may be used + * to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDERS AND CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + *---------------------------------------------------------------------------*/ +#ifndef RT_TYPE_DEF_H +#define RT_TYPE_DEF_H + +#include "os_tcb.h" + +typedef U32 OS_TID; +typedef void *OS_ID; +typedef U32 OS_RESULT; + +#define TCB_STACKF 32 /* 'stack_frame' offset */ +#define TCB_TSTACK 40 /* 'tsk_stack' offset */ + +typedef struct OS_PSFE { /* Post Service Fifo Entry */ + void *id; /* Object Identification */ + U32 arg; /* Object Argument */ +} *P_PSFE; + +typedef struct OS_PSQ { /* Post Service Queue */ + U8 first; /* FIFO Head Index */ + U8 last; /* FIFO Tail Index */ + U8 count; /* Number of stored items in FIFO */ + U8 size; /* FIFO Size */ + struct OS_PSFE q[1]; /* FIFO Content */ +} *P_PSQ; + +typedef struct OS_TSK { + P_TCB run; /* Current running task */ + P_TCB new_tsk; /* Scheduled task to run */ +} *P_TSK; + +typedef struct OS_ROBIN { /* Round Robin Control */ + P_TCB task; /* Round Robin task */ + U16 time; /* Round Robin switch time */ + U16 tout; /* Round Robin timeout */ +} *P_ROBIN; + +typedef struct OS_XCB { + U8 cb_type; /* Control Block Type */ + struct OS_TCB *p_lnk; /* Link pointer for ready/sem. wait list */ + struct OS_TCB *p_rlnk; /* Link pointer for sem./mbx lst backwards */ + struct OS_TCB *p_dlnk; /* Link pointer for delay list */ + struct OS_TCB *p_blnk; /* Link pointer for delay list backwards */ + U16 delta_time; /* Time until time out */ +} *P_XCB; + +typedef struct OS_MCB { + U8 cb_type; /* Control Block Type */ + U8 state; /* State flag variable */ + U8 isr_st; /* State flag variable for isr functions */ + struct OS_TCB *p_lnk; /* Chain of tasks waiting for message */ + U16 first; /* Index of the message list begin */ + U16 last; /* Index of the message list end */ + U16 count; /* Actual number of stored messages */ + U16 size; /* Maximum number of stored messages */ + void *msg[1]; /* FIFO for Message pointers 1st element */ +} *P_MCB; + +typedef struct OS_SCB { + U8 cb_type; /* Control Block Type */ + U8 mask; /* Semaphore token mask */ + U16 tokens; /* Semaphore tokens */ + struct OS_TCB *p_lnk; /* Chain of tasks waiting for tokens */ +} *P_SCB; + +typedef struct OS_MUCB { + U8 cb_type; /* Control Block Type */ + U8 prio; /* Owner task default priority */ + U16 level; /* Call nesting level */ + struct OS_TCB *p_lnk; /* Chain of tasks waiting for mutex */ + struct OS_TCB *owner; /* Mutex owner task */ +} *P_MUCB; + +typedef struct OS_XTMR { + struct OS_TMR *next; + U16 tcnt; +} *P_XTMR; + +typedef struct OS_TMR { + struct OS_TMR *next; /* Link pointer to Next timer */ + U16 tcnt; /* Timer delay count */ + U16 info; /* User defined call info */ +} *P_TMR; + +typedef struct OS_BM { + void *free; /* Pointer to first free memory block */ + void *end; /* Pointer to memory block end */ + U32 blk_size; /* Memory block size */ +} *P_BM; + +/* Definitions */ +#define __TRUE 1 +#define __FALSE 0 +#define NULL ((void *) 0) + +#endif |