0
mirror of https://github.com/OneOfEleven/uv-k5-firmware-custom.git synced 2025-06-20 06:58:39 +03:00

Initial commit

This commit is contained in:
OneOfEleven
2023-09-09 08:03:56 +01:00
parent 92305117f1
commit 54441e27d9
3388 changed files with 582553 additions and 0 deletions

View File

@ -0,0 +1,558 @@
/*----------------------------------------------------------------------------
* CMSIS-RTOS - RTX
*----------------------------------------------------------------------------
* Name: RTX_CM_LIB.H
* Purpose: RTX Kernel System Configuration
* Rev.: V4.82
*----------------------------------------------------------------------------
*
* Copyright (c) 1999-2009 KEIL, 2009-2019 ARM Germany GmbH. All rights reserved.
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the License); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an AS IS BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*---------------------------------------------------------------------------*/
#if defined (__CC_ARM)
#pragma O3
#define __USED __attribute__((used))
#elif defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050)
#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 52
#define OS_TMR_SIZE 8
#if (( defined(__CC_ARM) || \
(defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050))) && \
!defined(__MICROLIB))
typedef void *OS_ID;
typedef uint32_t OS_TID;
typedef uint32_t OS_MUT[4];
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,0xFFFFU)
#define mutex_rel(m) os_mut_release(m)
extern uint8_t os_running;
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);
#if defined(__CC_ARM)
#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);
#else
__attribute__((always_inline))
static __inline OS_RESULT os_mut_release (OS_ID mutex) {
register uint32_t __rf __asm("r12") = (uint32_t)rt_mut_release;
register uint32_t __r0 __asm("r0") = (uint32_t)mutex;
__asm volatile \
( \
"svc 0" \
: "=r" (__r0) \
: "r" (__rf), "r" (__r0) \
: "r1", "r2" \
);
return (OS_RESULT)__r0;
}
__attribute__((always_inline))
static __inline OS_RESULT os_mut_wait (OS_ID mutex, uint16_t timeout) {
register uint32_t __rf __asm("r12") = (uint32_t)rt_mut_wait;
register uint32_t __r0 __asm("r0") = (uint32_t)mutex;
register uint32_t __r1 __asm("r1") = (uint32_t)timeout;
__asm volatile \
( \
"svc 0" \
: "=r" (__r0) \
: "r" (__rf), "r" (__r0), "r" (__r1) \
: "r2" \
);
return (OS_RESULT)__r0;
}
#endif
#endif
/*----------------------------------------------------------------------------
* Global Variables
*---------------------------------------------------------------------------*/
#if (OS_TASKCNT == 0)
#error "Invalid number of concurrent running threads!"
#endif
#if (OS_PRIVCNT >= OS_TASKCNT)
#error "Too many threads with user-provided stack size!"
#endif
#if (OS_TIMERS != 0)
#define OS_TASK_CNT (OS_TASKCNT + 1)
#define OS_PRIV_CNT (OS_PRIVCNT + 2)
#define OS_STACK_SZ (4*(OS_PRIVSTKSIZE+OS_MAINSTKSIZE+OS_TIMERSTKSZ))
#else
#define OS_TASK_CNT OS_TASKCNT
#define OS_PRIV_CNT (OS_PRIVCNT + 1)
#define OS_STACK_SZ (4*(OS_PRIVSTKSIZE+OS_MAINSTKSIZE))
#endif
#ifndef OS_STKINIT
#define OS_STKINIT 0
#endif
extern uint16_t const os_maxtaskrun;
extern uint32_t const os_stackinfo;
extern uint32_t const os_rrobin;
extern uint32_t const os_trv;
extern uint8_t const os_flags;
uint16_t const os_maxtaskrun = OS_TASK_CNT;
uint32_t const os_stackinfo = (OS_STKINIT<<28) | (OS_STKCHECK<<24) | (OS_PRIV_CNT<<16) | (OS_STKSIZE*4);
uint32_t const os_rrobin = (OS_ROBIN << 16) | OS_ROBINTOUT;
uint32_t const os_tickfreq = OS_CLOCK;
uint16_t const os_tickus_i = OS_CLOCK/1000000;
uint16_t const os_tickus_f = (((uint64_t)(OS_CLOCK-1000000*(OS_CLOCK/1000000)))<<16)/1000000;
uint32_t const os_trv = OS_TRV;
uint8_t const os_flags = OS_RUNPRIV;
/* Export following defines to uVision debugger. */
extern uint32_t const CMSIS_RTOS_API_Version;
__USED uint32_t const CMSIS_RTOS_API_Version = osCMSIS;
extern uint32_t const CMSIS_RTOS_RTX_Version;
__USED uint32_t const CMSIS_RTOS_RTX_Version = osCMSIS_RTX;
extern uint32_t const os_clockrate;
__USED uint32_t const os_clockrate = OS_TICK;
extern uint32_t const os_timernum;
__USED uint32_t const os_timernum = 0U;
/* Memory pool for TCB allocation */
extern
uint32_t mp_tcb[];
_declare_box (mp_tcb, OS_TCB_SIZE, OS_TASK_CNT);
extern
uint16_t const mp_tcb_size;
uint16_t const mp_tcb_size = sizeof(mp_tcb);
/* Memory pool for System stack allocation (+os_idle_demon). */
extern
uint64_t mp_stk[];
_declare_box8 (mp_stk, OS_STKSIZE*4, OS_TASK_CNT-OS_PRIV_CNT+1);
extern
uint32_t const mp_stk_size;
uint32_t const mp_stk_size = sizeof(mp_stk);
/* Memory pool for user specified stack allocation (+main, +timer) */
extern
uint64_t os_stack_mem[];
uint64_t os_stack_mem[2+OS_PRIV_CNT+(OS_STACK_SZ/8)];
extern
uint32_t const os_stack_sz;
uint32_t const os_stack_sz = sizeof(os_stack_mem);
#ifndef OS_FIFOSZ
#define OS_FIFOSZ 16
#endif
/* Fifo Queue buffer for ISR requests.*/
extern
uint32_t os_fifo[];
uint32_t os_fifo[OS_FIFOSZ*2+1];
extern
uint8_t const os_fifo_size;
uint8_t const os_fifo_size = OS_FIFOSZ;
/* An array of Active task pointers. */
extern
void *os_active_TCB[];
void *os_active_TCB[OS_TASK_CNT];
/* User Timers Resources */
#if (OS_TIMERS != 0)
extern void osTimerThread (void const *argument);
extern const osThreadDef_t os_thread_def_osTimerThread;
osThreadDef(osTimerThread, (osPriority)(OS_TIMERPRIO-3), 1, 4*OS_TIMERSTKSZ);
extern
osThreadId osThreadId_osTimerThread;
osThreadId osThreadId_osTimerThread;
extern uint32_t os_messageQ_q_osTimerMessageQ[];
extern const osMessageQDef_t os_messageQ_def_osTimerMessageQ;
osMessageQDef(osTimerMessageQ, OS_TIMERCBQS, void *);
extern
osMessageQId osMessageQId_osTimerMessageQ;
osMessageQId osMessageQId_osTimerMessageQ;
#else
extern
const osThreadDef_t os_thread_def_osTimerThread;
const osThreadDef_t os_thread_def_osTimerThread = { NULL, osPriorityNormal, 0U, 0U };
extern
osThreadId osThreadId_osTimerThread;
osThreadId osThreadId_osTimerThread;
extern uint32_t os_messageQ_q_osTimerMessageQ[];
extern const osMessageQDef_t os_messageQ_def_osTimerMessageQ;
osMessageQDef(osTimerMessageQ, 0U, void *);
extern
osMessageQId osMessageQId_osTimerMessageQ;
osMessageQId osMessageQId_osTimerMessageQ;
#endif
/* Legacy RTX User Timers not used */
extern
uint32_t os_tmr;
uint32_t os_tmr = 0U;
extern
uint32_t const *m_tmr;
uint32_t const *m_tmr = NULL;
extern
uint16_t const mp_tmr_size;
uint16_t const mp_tmr_size = 0U;
#if (( defined(__CC_ARM) || \
(defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050))) && \
!defined(__MICROLIB))
/* A memory space for arm standard library. */
static uint32_t std_libspace[OS_TASK_CNT][96/4];
static OS_MUT std_libmutex[OS_MUTEXCNT];
static uint32_t nr_mutex;
extern void *__libspace_start;
#endif
/*----------------------------------------------------------------------------
* RTX Optimizations (empty functions)
*---------------------------------------------------------------------------*/
#if OS_ROBIN == 0
extern
void rt_init_robin (void);
void rt_init_robin (void) {;}
extern
void rt_chk_robin (void);
void rt_chk_robin (void) {;}
#endif
#if OS_STKCHECK == 0
extern
void rt_stk_check (void);
void rt_stk_check (void) {;}
#endif
/*----------------------------------------------------------------------------
* Standard Library multithreading interface
*---------------------------------------------------------------------------*/
#if (( defined(__CC_ARM) || \
(defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050))) && \
!defined(__MICROLIB))
/*--------------------------- __user_perthread_libspace ---------------------*/
void *__user_perthread_libspace (void);
void *__user_perthread_libspace (void) {
/* Provide a separate libspace for each task. */
uint32_t idx;
idx = (os_running != 0U) ? runtask_id () : 0U;
if (idx == 0U) {
/* RTX not running yet. */
return (&__libspace_start);
}
return ((void *)&std_libspace[idx-1]);
}
/*--------------------------- _mutex_initialize -----------------------------*/
int _mutex_initialize (OS_ID *mutex);
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. */
for (;;);
}
*mutex = &std_libmutex[nr_mutex++];
mutex_init (*mutex);
return (1);
}
/*--------------------------- _mutex_acquire --------------------------------*/
__attribute__((used))
void _mutex_acquire (OS_ID *mutex);
void _mutex_acquire (OS_ID *mutex) {
/* Acquire a system mutex, lock stdlib resources. */
if (os_running) {
/* RTX running, acquire a mutex. */
mutex_wait (*mutex);
}
}
/*--------------------------- _mutex_release --------------------------------*/
__attribute__((used))
void _mutex_release (OS_ID *mutex);
void _mutex_release (OS_ID *mutex) {
/* Release a system mutex, unlock stdlib resources. */
if (os_running) {
/* RTX running, release a mutex. */
mutex_rel (*mutex);
}
}
#endif
/*----------------------------------------------------------------------------
* ARMCC6 Wrappers for ARMCC5 Binary
*---------------------------------------------------------------------------*/
#if defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050)
typedef uint32_t __attribute__((vector_size(8))) vect64_t;
#undef osSignalWait
__attribute__((pcs("aapcs")))
vect64_t osSignalWait (int32_t signals, uint32_t millisec);
osEvent __osSignalWait (int32_t signals, uint32_t millisec) {
vect64_t v;
osEvent e;
v = osSignalWait(signals, millisec);
e.status = v[0];
e.value.v = v[1];
return e;
}
#undef osMessageGet
__attribute__((pcs("aapcs")))
vect64_t osMessageGet (osMessageQId queue_id, uint32_t millisec);
osEvent __osMessageGet (osMessageQId queue_id, uint32_t millisec) {
vect64_t v;
osEvent e;
v = osMessageGet(queue_id, millisec);
e.status = v[0];
e.value.v = v[1];
return e;
}
#undef osMailGet
__attribute__((pcs("aapcs")))
vect64_t osMailGet (osMailQId queue_id, uint32_t millisec);
osEvent __osMailGet (osMailQId queue_id, uint32_t millisec) {
vect64_t v;
osEvent e;
v = osMailGet(queue_id, millisec);
e.status = v[0];
e.value.v = v[1];
return e;
}
#endif
/*----------------------------------------------------------------------------
* RTX Startup
*---------------------------------------------------------------------------*/
/* Main Thread definition */
extern int main (void);
extern
const osThreadDef_t os_thread_def_main;
const osThreadDef_t os_thread_def_main = {(os_pthread)main, osPriorityNormal, 1U, 4*OS_MAINSTKSIZE };
#if defined (__CC_ARM)
#ifdef __MICROLIB
__attribute__((section(".ARM.Collect$$$$000000FF")))
void _main_init (void);
void _main_init (void) {
osKernelInitialize();
osThreadCreate(&os_thread_def_main, NULL);
osKernelStart();
for (;;);
}
#else
__asm void _platform_post_lib_init (void) {
IMPORT os_thread_def_main
IMPORT osKernelInitialize
IMPORT osKernelStart
IMPORT osThreadCreate
IMPORT exit
ADD SP,#0x10
BL osKernelInitialize
LDR R0,=os_thread_def_main
MOVS R1,#0
BL osThreadCreate
BL osKernelStart
BL exit
ALIGN
}
#endif
#elif defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050)
#ifdef __MICROLIB
__attribute__((noreturn, section(".ARM.Collect$$$$000000FF")))
void _main_init (void);
void _main_init (void) {
#else
__asm(" .global __ARM_use_no_argv\n");
__attribute__((noreturn))
void _platform_post_lib_init (void);
void _platform_post_lib_init (void) {
#endif
osKernelInitialize();
osThreadCreate(&os_thread_def_main, NULL);
osKernelStart();
for (;;);
}
#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();
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"
"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 int __low_level_init(void);
extern void __iar_data_init3(void);
extern void exit(int arg);
__noreturn __stackless void __cmain(void) {
int a;
if (__low_level_init() != 0) {
__iar_data_init3();
}
osKernelInitialize();
osThreadCreate(&os_thread_def_main, NULL);
a = osKernelStart();
exit(a);
}
#endif
/*----------------------------------------------------------------------------
* end of file
*---------------------------------------------------------------------------*/

View File

@ -0,0 +1,677 @@
/* ----------------------------------------------------------------------
* $Date: 5. February 2013
* $Revision: V1.02
*
* 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
* Version 1.02
* Control functions for short timeouts in microsecond resolution:
* Added: osKernelSysTick, osKernelSysTickFrequency, osKernelSysTickMicroSec
* Removed: osSignalGet
*----------------------------------------------------------------------------
*
* Copyright (c) 2013-2017 ARM LIMITED. All rights reserved.
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the License); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an AS IS BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*---------------------------------------------------------------------------*/
#ifndef _CMSIS_OS_H
#define _CMSIS_OS_H
#define osCMSIS 0x10002U ///< CMSIS-RTOS API version (main [31:16] .sub [15:0])
#define osCMSIS_RTX ((4<<16)|82) ///< RTOS identification and version (main [31:16] .sub [15:0])
#define osKernelSystemId "RTX V4.82" ///< RTOS identification string
#define osFeature_MainThread 1 ///< main can be thread
#define osFeature_Pool 1 ///< Memory Pools available
#define osFeature_MailQ 1 ///< Mail Queues available
#define osFeature_MessageQ 1 ///< Message Queues available
#define osFeature_Signals 16 ///< 16 Signal Flags available per thread
#define osFeature_Semaphore 65535 ///< Maximum count for \ref osSemaphoreCreate function
#define osFeature_Wait 0 ///< osWait not available
#define osFeature_SysTick 1 ///< osKernelSysTick functions available
#if defined(__CC_ARM)
#define os_InRegs __value_in_regs // Compiler specific: force struct in registers
#else
#define os_InRegs
#endif
#if defined(__CC_ARM)
#define __NO_RETURN __declspec(noreturn)
#elif defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050)
#define __NO_RETURN __attribute__((noreturn))
#elif defined(__GNUC__)
#define __NO_RETURN __attribute__((noreturn))
#elif defined(__ICCARM__)
#define __NO_RETURN __noreturn
#else
#define __NO_RETURN
#endif
#include <stdint.h>
#include <stddef.h>
#ifdef __cplusplus
extern "C"
{
#endif
// ==== Enumeration, structures, defines ====
/// Priority used for thread control.
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
os_priority_reserved = 0x7FFFFFFF ///< prevent from enum down-size compiler optimization.
} osPriority;
/// Timeout value.
#define osWaitForever 0xFFFFFFFFU ///< wait forever timeout value
/// Status code values returned by CMSIS-RTOS functions.
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.
typedef enum {
osTimerOnce = 0, ///< one-shot timer
osTimerPeriodic = 1 ///< repeating timer
} os_timer_type;
/// Entry point of a thread.
typedef void (*os_pthread) (void const *argument);
/// Entry point of a timer call back function.
typedef void (*os_ptimer) (void const *argument);
// >>> the following data type definitions may shall adapted towards a specific RTOS
/// Thread ID identifies the thread (pointer to a thread control block).
typedef struct os_thread_cb *osThreadId;
/// Timer ID identifies the timer (pointer to a timer control block).
typedef struct os_timer_cb *osTimerId;
/// Mutex ID identifies the mutex (pointer to a mutex control block).
typedef struct os_mutex_cb *osMutexId;
/// Semaphore ID identifies the semaphore (pointer to a semaphore control block).
typedef struct os_semaphore_cb *osSemaphoreId;
/// Pool ID identifies the memory pool (pointer to a memory pool control block).
typedef struct os_pool_cb *osPoolId;
/// Message ID identifies the message queue (pointer to a message queue control block).
typedef struct os_messageQ_cb *osMessageQId;
/// Mail ID identifies the mail queue (pointer to a mail queue control block).
typedef struct os_mailQ_cb *osMailQId;
/// Thread Definition structure contains startup information of a thread.
typedef struct os_thread_def {
os_pthread pthread; ///< start address of thread function
osPriority tpriority; ///< initial thread priority
uint32_t instances; ///< maximum number of instances of that thread function
uint32_t stacksize; ///< stack size requirements in bytes; 0 is default stack size
} osThreadDef_t;
/// Timer Definition structure contains timer parameters.
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.
typedef struct os_mutex_def {
void *mutex; ///< pointer to internal data
} osMutexDef_t;
/// Semaphore Definition structure contains setup information for a semaphore.
typedef struct os_semaphore_def {
void *semaphore; ///< pointer to internal data
} osSemaphoreDef_t;
/// Definition structure for memory block allocation.
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.
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.
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.
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.
osStatus osKernelInitialize (void);
/// Start the RTOS Kernel.
/// \return status code that indicates the execution status of the function.
osStatus osKernelStart (void);
/// Check if the RTOS kernel is already started.
/// \return 0 RTOS is not started, 1 RTOS is started.
int32_t osKernelRunning(void);
#if (defined (osFeature_SysTick) && (osFeature_SysTick != 0)) // System Timer available
/// \cond INTERNAL_VARIABLES
extern uint32_t const os_tickfreq;
extern uint16_t const os_tickus_i;
extern uint16_t const os_tickus_f;
/// \endcond
/// Get the RTOS kernel system timer counter.
/// \return RTOS kernel system timer as 32-bit value
uint32_t osKernelSysTick (void);
/// The RTOS kernel system timer frequency in Hz.
/// \note Reflects the system timer setting and is typically defined in a configuration file.
#define osKernelSysTickFrequency os_tickfreq
/// Convert a microseconds value to a RTOS kernel system timer value.
/// \param microsec time value in microseconds.
/// \return time value normalized to the \ref osKernelSysTickFrequency
/*
#define osKernelSysTickMicroSec(microsec) (((uint64_t)microsec * (osKernelSysTickFrequency)) / 1000000)
*/
#define osKernelSysTickMicroSec(microsec) ((microsec * os_tickus_i) + ((microsec * os_tickus_f) >> 16))
#endif // System Timer available
// ==== Thread Management ====
/// Create a Thread Definition with function, priority, and stack requirements.
/// \param name name of the thread function.
/// \param priority initial priority of the thread function.
/// \param instances number of possible thread instances.
/// \param stacksz stack size (in bytes) requirements for the thread function.
/// macro body is implementation specific in every CMSIS-RTOS.
#if defined (osObjectsExternal) // object is external
#define osThreadDef(name, priority, instances, stacksz) \
extern const osThreadDef_t os_thread_def_##name
#else // define the object
#define osThreadDef(name, priority, instances, stacksz) \
const osThreadDef_t os_thread_def_##name = \
{ (name), (priority), (instances), (stacksz) }
#endif
/// Access a Thread definition.
/// \param name name of the thread definition object.
/// 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.
osThreadId osThreadCreate (const osThreadDef_t *thread_def, void *argument);
/// Return the thread ID of the current running thread.
/// \return thread ID for reference by other functions or NULL in case of error.
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.
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.
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.
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.
osPriority osThreadGetPriority (osThreadId thread_id);
// ==== Generic Wait Functions ====
/// Wait for Timeout (Time Delay).
/// \param[in] millisec \ref CMSIS_RTOS_TimeOutValue "Time delay" value
/// \return status code that indicates the execution status of the function.
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 \ref CMSIS_RTOS_TimeOutValue or 0 in case of no time-out
/// \return event that contains signal, message, or mail information or error code.
os_InRegs osEvent osWait (uint32_t millisec);
#endif // Generic Wait available
// ==== Timer Management Functions ====
/// Define a Timer object.
/// \param name name of the timer object.
/// \param function name of the timer call back function.
#if defined (osObjectsExternal) // object is external
#define osTimerDef(name, function) \
extern const osTimerDef_t os_timer_def_##name
#else // define the object
#define osTimerDef(name, function) \
uint32_t os_timer_cb_##name[6]; \
const osTimerDef_t os_timer_def_##name = \
{ (function), (os_timer_cb_##name) }
#endif
/// Access a Timer definition.
/// \param name name of the timer object.
#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.
osTimerId osTimerCreate (const osTimerDef_t *timer_def, os_timer_type type, void *argument);
/// Start or restart a timer.
/// \param[in] timer_id timer ID obtained by \ref osTimerCreate.
/// \param[in] millisec \ref CMSIS_RTOS_TimeOutValue "Time delay" value of the timer.
/// \return status code that indicates the execution status of the function.
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.
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.
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.
int32_t osSignalSet (osThreadId thread_id, int32_t signals);
/// Clear the specified Signal Flags of an active thread.
/// \param[in] thread_id thread ID obtained by \ref osThreadCreate or \ref osThreadGetId.
/// \param[in] signals specifies the signal flags of the thread that shall be cleared.
/// \return previous signal flags of the specified thread or 0x80000000 in case of incorrect parameters or call from ISR.
int32_t osSignalClear (osThreadId thread_id, int32_t signals);
/// Wait for one or more Signal Flags to become signaled for the current \b RUNNING thread.
/// \param[in] signals wait until all specified signal flags set or 0 for any single signal flag.
/// \param[in] millisec \ref CMSIS_RTOS_TimeOutValue or 0 in case of no time-out.
/// \return event flag information or error code.
#if defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050)
#define osSignalWait __osSignalWait
osEvent __osSignalWait (int32_t signals, uint32_t millisec);
#else
os_InRegs osEvent osSignalWait (int32_t signals, uint32_t millisec);
#endif
// ==== Mutex Management ====
/// Define a Mutex.
/// \param name name of the mutex object.
#if defined (osObjectsExternal) // object is external
#define osMutexDef(name) \
extern const osMutexDef_t os_mutex_def_##name
#else // define the object
#define osMutexDef(name) \
uint32_t os_mutex_cb_##name[4] = { 0 }; \
const osMutexDef_t os_mutex_def_##name = { (os_mutex_cb_##name) }
#endif
/// Access a Mutex definition.
/// \param name name of the mutex object.
#define osMutex(name) \
&os_mutex_def_##name
/// Create and Initialize a Mutex object.
/// \param[in] mutex_def mutex definition referenced with \ref osMutex.
/// \return mutex ID for reference by other functions or NULL in case of error.
osMutexId osMutexCreate (const osMutexDef_t *mutex_def);
/// Wait until a Mutex becomes available.
/// \param[in] mutex_id mutex ID obtained by \ref osMutexCreate.
/// \param[in] millisec \ref CMSIS_RTOS_TimeOutValue or 0 in case of no time-out.
/// \return status code that indicates the execution status of the function.
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.
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.
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.
#if defined (osObjectsExternal) // object is external
#define osSemaphoreDef(name) \
extern const osSemaphoreDef_t os_semaphore_def_##name
#else // define the object
#define osSemaphoreDef(name) \
uint32_t os_semaphore_cb_##name[2] = { 0 }; \
const osSemaphoreDef_t os_semaphore_def_##name = { (os_semaphore_cb_##name) }
#endif
/// Access a Semaphore definition.
/// \param name name of the semaphore object.
#define osSemaphore(name) \
&os_semaphore_def_##name
/// Create and Initialize a Semaphore object 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.
osSemaphoreId osSemaphoreCreate (const osSemaphoreDef_t *semaphore_def, int32_t count);
/// Wait until a Semaphore token becomes available.
/// \param[in] semaphore_id semaphore object referenced with \ref osSemaphoreCreate.
/// \param[in] millisec \ref CMSIS_RTOS_TimeOutValue or 0 in case of no time-out.
/// \return number of available tokens, or -1 in case of incorrect parameters.
int32_t osSemaphoreWait (osSemaphoreId semaphore_id, uint32_t millisec);
/// Release a Semaphore token.
/// \param[in] semaphore_id semaphore object referenced with \ref osSemaphoreCreate.
/// \return status code that indicates the execution status of the function.
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.
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).
#if defined (osObjectsExternal) // object is external
#define osPoolDef(name, no, type) \
extern const 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)]; \
const 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
#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.
osPoolId osPoolCreate (const osPoolDef_t *pool_def);
/// Allocate a memory block from a memory pool.
/// \param[in] pool_id memory pool ID obtain referenced with \ref osPoolCreate.
/// \return address of the allocated memory block or NULL in case of no memory available.
void *osPoolAlloc (osPoolId pool_id);
/// Allocate a memory block from a memory pool and set memory block to zero.
/// \param[in] pool_id memory pool ID obtain referenced with \ref osPoolCreate.
/// \return address of the allocated memory block or NULL in case of no memory available.
void *osPoolCAlloc (osPoolId pool_id);
/// Return an allocated memory block back to a 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.
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).
#if defined (osObjectsExternal) // object is external
#define osMessageQDef(name, queue_sz, type) \
extern const osMessageQDef_t os_messageQ_def_##name
#else // define the object
#define osMessageQDef(name, queue_sz, type) \
uint32_t os_messageQ_q_##name[4+(queue_sz)] = { 0 }; \
const 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
#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.
osMessageQId osMessageCreate (const osMessageQDef_t *queue_def, osThreadId thread_id);
/// Put a Message to a Queue.
/// \param[in] queue_id message queue ID obtained with \ref osMessageCreate.
/// \param[in] info message information.
/// \param[in] millisec \ref CMSIS_RTOS_TimeOutValue or 0 in case of no time-out.
/// \return status code that indicates the execution status of the function.
osStatus osMessagePut (osMessageQId queue_id, uint32_t info, uint32_t millisec);
/// Get a Message or Wait for a Message from a Queue.
/// \param[in] queue_id message queue ID obtained with \ref osMessageCreate.
/// \param[in] millisec \ref CMSIS_RTOS_TimeOutValue or 0 in case of no time-out.
/// \return event information that includes status code.
#if defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050)
#define osMessageGet __osMessageGet
osEvent __osMessageGet (osMessageQId queue_id, uint32_t millisec);
#else
os_InRegs osEvent osMessageGet (osMessageQId queue_id, uint32_t millisec);
#endif
#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
#if defined (osObjectsExternal) // object is external
#define osMailQDef(name, queue_sz, type) \
extern const osMailQDef_t os_mailQ_def_##name
#else // define the object
#define osMailQDef(name, queue_sz, type) \
uint32_t os_mailQ_q_##name[4+(queue_sz)] = { 0 }; \
uint32_t os_mailQ_m_##name[3+((sizeof(type)+3)/4)*(queue_sz)]; \
void * os_mailQ_p_##name[2] = { (os_mailQ_q_##name), os_mailQ_m_##name }; \
const osMailQDef_t os_mailQ_def_##name = \
{ (queue_sz), sizeof(type), (os_mailQ_p_##name) }
#endif
/// \brief Access a Mail Queue Definition.
/// \param name name of the queue
#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.
osMailQId osMailCreate (const 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 \ref CMSIS_RTOS_TimeOutValue or 0 in case of no time-out
/// \return pointer to memory block that can be filled with mail or NULL in case of error.
void *osMailAlloc (osMailQId queue_id, uint32_t millisec);
/// Allocate a memory block from a mail and set memory block to zero.
/// \param[in] queue_id mail queue ID obtained with \ref osMailCreate.
/// \param[in] millisec \ref CMSIS_RTOS_TimeOutValue or 0 in case of no time-out
/// \return pointer to memory block that can be filled with mail or NULL in case of error.
void *osMailCAlloc (osMailQId queue_id, uint32_t millisec);
/// Put a mail 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.
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 \ref CMSIS_RTOS_TimeOutValue or 0 in case of no time-out
/// \return event that contains mail information or error code.
#if defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050)
#define osMailGet __osMailGet
osEvent __osMailGet (osMailQId queue_id, uint32_t millisec);
#else
os_InRegs osEvent osMailGet (osMailQId queue_id, uint32_t millisec);
#endif
/// 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.
osStatus osMailFree (osMailQId queue_id, void *mail);
#endif // Mail Queues available
// ==== RTX Extensions ====
/// Suspend the RTX task scheduler.
/// \return number of ticks, for how long the system can sleep or power-down.
uint32_t os_suspend (void);
/// Resume the RTX task scheduler.
/// \param[in] sleep_time specifies how long the system was in sleep or power-down mode.
void os_resume (uint32_t sleep_time);
/// OS idle demon (running when no other thread is ready to run).
__NO_RETURN void os_idle_demon (void);
/// OS error callback (called when a runtime error is detected).
/// \param[in] error_code actual error code that has been detected.
__NO_RETURN void os_error (uint32_t error_code);
#ifdef __cplusplus
}
#endif
#endif // _CMSIS_OS_H

View File

@ -0,0 +1,80 @@
#!/bin/bash
VERSION=4.82.0
if [ -z "$JENKINS_FAMILY_ENV" ]; then
ARTIFACTORY_URL=https://artifactory.eu02.arm.com:443/artifactory/mcu.promoted
else
ARTIFACTORY_URL=https://eu-west-1.artifactory.aws.arm.com:443/artifactory/mcu.promoted
fi
if [ -z "$ARTIFACTORY_API_KEY" ]; then
echo "Please set your Artifactory in ARTIFACTORY_API_KEY"
echo ""
echo "1. Browse to $(dirname $(dirname $ARTIFACTORY_URL))/ui/admin/artifactory/user_profile"
echo "2. Copy the API Key"
echo "3. Add 'export ARTIFACTORY_API_KEY=\"<API Key>\"' to ~/.bashrc"
exit 1
fi
set -o pipefail
function usage {
echo "$(basename $0) [-h|--help] [-f|--force]"
echo ""
echo "Arguments:"
echo " -h|--help Print this usage message and exit."
echo " -f|--force Force (re)download."
echo ""
echo "Environment:"
echo " curl"
echo " sha256sum"
echo ""
}
POSITIONAL=()
while [[ $# -gt 0 ]]
do
key="$1"
case $key in
'-h'|'--help')
usage
exit 1
;;
'-f'|'--force')
FORCE=1
;;
*) # unknown option
POSITIONAL+=("$1") # save it in an array for later
;;
esac
shift # past argument
done
set -- "${POSITIONAL[@]}" # restore positional parameters
pushd $(dirname $0) > /dev/null
ARCHIVE_NAME="RTX-${VERSION}.zip"
ARCHIVE_URL="${ARTIFACTORY_URL}/CMSIS_5/Libraries/${ARCHIVE_NAME}"
echo "Fetching ${ARCHIVE_URL}..."
if [[ $FORCE == 1 ]]; then
rm ${ARCHIVE_NAME}
fi
if [[ -f ${ARCHIVE_NAME} ]]; then
sha256sum=$(curl -s -I -H "X-JFrog-Art-Api:${ARTIFACTORY_API_KEY}" "${ARCHIVE_URL}" | grep "X-Checksum-Sha256" | cut -d" " -f2)
if echo "${sha256sum} *${ARCHIVE_NAME}" | sha256sum -c --status; then
echo "Already up-to-date"
else
rm ${ARCHIVE_NAME}
fi
fi
if [[ ! -f ${ARCHIVE_NAME} ]]; then
curl -C - -H "X-JFrog-Art-Api:${ARTIFACTORY_API_KEY}" -O "${ARCHIVE_URL}"
fi
unzip -u ${ARCHIVE_NAME}
exit 0

View File

@ -0,0 +1,291 @@
/*----------------------------------------------------------------------------
* CMSIS-RTOS - RTX
*----------------------------------------------------------------------------
* Name: HAL_CM0.C
* Purpose: Hardware Abstraction Layer for Cortex-M0
* Rev.: V4.70
*----------------------------------------------------------------------------
*
* Copyright (c) 1999-2009 KEIL, 2009-2017 ARM Germany GmbH. All rights reserved.
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the License); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an AS IS BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*---------------------------------------------------------------------------*/
#include "rt_TypeDef.h"
#include "RTX_Config.h"
#include "rt_System.h"
#include "rt_HAL_CM.h"
#include "rt_Task.h"
#include "rt_MemBox.h"
/*----------------------------------------------------------------------------
* Functions
*---------------------------------------------------------------------------*/
/*--------------------------- rt_set_PSP ------------------------------------*/
__asm void rt_set_PSP (U32 stack) {
MSR PSP,R0
BX LR
}
/*--------------------------- rt_get_PSP ------------------------------------*/
__asm U32 rt_get_PSP (void) {
MRS R0,PSP
BX LR
}
/*--------------------------- os_set_env ------------------------------------*/
__asm void os_set_env (void) {
/* Switch to Unprivileged/Privileged Thread mode, use PSP. */
MOV R0,SP ; PSP = MSP
MSR PSP,R0
LDR R0,=__cpp(&os_flags)
LDRB R0,[R0]
LSLS R0,#31
BNE PrivilegedE
MOVS R0,#0x03 ; Unprivileged Thread mode, use PSP
MSR CONTROL,R0
BX LR
PrivilegedE
MOVS R0,#0x02 ; Privileged Thread mode, use PSP
MSR CONTROL,R0
BX LR
ALIGN
}
/*--------------------------- _alloc_box ------------------------------------*/
__asm void *_alloc_box (void *box_mem) {
/* Function wrapper for Unprivileged/Privileged mode. */
LDR R3,=__cpp(rt_alloc_box)
MOV R12,R3
MRS R3,IPSR
LSLS R3,#24
BNE PrivilegedA
MRS R3,CONTROL
LSLS R3,#31
BEQ PrivilegedA
SVC 0
BX LR
PrivilegedA
BX R12
ALIGN
}
/*--------------------------- _free_box -------------------------------------*/
__asm U32 _free_box (void *box_mem, void *box) {
/* Function wrapper for Unprivileged/Privileged mode. */
LDR R3,=__cpp(rt_free_box)
MOV R12,R3
MRS R3,IPSR
LSLS R3,#24
BNE PrivilegedF
MRS R3,CONTROL
LSLS R3,#31
BEQ PrivilegedF
SVC 0
BX LR
PrivilegedF
BX R12
ALIGN
}
/*-------------------------- SVC_Handler ------------------------------------*/
__asm void SVC_Handler (void) {
PRESERVE8
IMPORT SVC_Count
IMPORT SVC_Table
IMPORT rt_stk_check
MRS R0,PSP ; Read PSP
LDR R1,[R0,#24] ; Read Saved PC from Stack
SUBS R1,R1,#2 ; Point to SVC Instruction
LDRB R1,[R1] ; Load SVC Number
CMP R1,#0
BNE SVC_User ; User SVC Number > 0
MOV LR,R4
LDMIA R0,{R0-R3,R4} ; Read R0-R3,R12 from stack
MOV R12,R4
MOV R4,LR
BLX R12 ; Call SVC Function
MRS R3,PSP ; Read PSP
STMIA R3!,{R0-R2} ; Store return values
LDR R3,=__cpp(&os_tsk)
LDMIA R3!,{R1,R2} ; os_tsk.run, os_tsk.next
CMP R1,R2
BEQ SVC_Exit ; no task switch
SUBS R3,#8
CMP R1,#0 ; Runtask deleted?
BEQ SVC_Next
MRS R0,PSP ; Read PSP
SUBS R0,R0,#32 ; Adjust Start Address
STR R0,[R1,#TCB_TSTACK] ; Update os_tsk.run->tsk_stack
STMIA R0!,{R4-R7} ; Save old context (R4-R7)
MOV R4,R8
MOV R5,R9
MOV R6,R10
MOV R7,R11
STMIA R0!,{R4-R7} ; Save old context (R8-R11)
PUSH {R2,R3}
BL rt_stk_check ; Check for Stack overflow
POP {R2,R3}
SVC_Next
STR R2,[R3] ; os_tsk.run = os_tsk.next
LDR R0,[R2,#TCB_TSTACK] ; os_tsk.next->tsk_stack
ADDS R0,R0,#16 ; Adjust Start Address
LDMIA R0!,{R4-R7} ; Restore new Context (R8-R11)
MOV R8,R4
MOV R9,R5
MOV R10,R6
MOV R11,R7
MSR PSP,R0 ; Write PSP
SUBS R0,R0,#32 ; Adjust Start Address
LDMIA R0!,{R4-R7} ; Restore new Context (R4-R7)
SVC_Exit
MOVS R0,#:NOT:0xFFFFFFFD ; Set EXC_RETURN value
MVNS R0,R0
BX R0 ; RETI to Thread Mode, use PSP
/*------------------- 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
LSLS R1,R1,#2
LDR R4,[R4,R1] ; Load SVC Function Address
MOV LR,R4
LDMIA R0,{R0-R3,R4} ; Read R0-R3,R12 from stack
MOV R12,R4
BLX LR ; Call SVC Function
MRS R4,PSP ; Read PSP
STMIA R4!,{R0-R3} ; Function return values
SVC_Done
POP {R4,PC} ; RETI
ALIGN
}
/*-------------------------- PendSV_Handler ---------------------------------*/
__asm void PendSV_Handler (void) {
PRESERVE8
BL __cpp(rt_pop_req)
Sys_Switch
LDR R3,=__cpp(&os_tsk)
LDMIA R3!,{R1,R2} ; os_tsk.run, os_tsk.next
CMP R1,R2
BEQ Sys_Exit ; no task switch
SUBS R3,#8
MRS R0,PSP ; Read PSP
SUBS R0,R0,#32 ; Adjust Start Address
STR R0,[R1,#TCB_TSTACK] ; Update os_tsk.run->tsk_stack
STMIA R0!,{R4-R7} ; Save old context (R4-R7)
MOV R4,R8
MOV R5,R9
MOV R6,R10
MOV R7,R11
STMIA R0!,{R4-R7} ; Save old context (R8-R11)
PUSH {R2,R3}
BL rt_stk_check ; Check for Stack overflow
POP {R2,R3}
STR R2,[R3] ; os_tsk.run = os_tsk.next
LDR R0,[R2,#TCB_TSTACK] ; os_tsk.next->tsk_stack
ADDS R0,R0,#16 ; Adjust Start Address
LDMIA R0!,{R4-R7} ; Restore new Context (R8-R11)
MOV R8,R4
MOV R9,R5
MOV R10,R6
MOV R11,R7
MSR PSP,R0 ; Write PSP
SUBS R0,R0,#32 ; Adjust Start Address
LDMIA R0!,{R4-R7} ; Restore new Context (R4-R7)
Sys_Exit
MOVS R0,#:NOT:0xFFFFFFFD ; Set EXC_RETURN value
MVNS R0,R0
BX R0 ; RETI to Thread Mode, use PSP
ALIGN
}
/*-------------------------- SysTick_Handler --------------------------------*/
__asm void SysTick_Handler (void) {
PRESERVE8
BL __cpp(rt_systick)
B Sys_Switch
ALIGN
}
/*-------------------------- OS_Tick_Handler --------------------------------*/
__asm void OS_Tick_Handler (void) {
PRESERVE8
BL __cpp(os_tick_irqack)
BL __cpp(rt_systick)
B Sys_Switch
ALIGN
}
/*----------------------------------------------------------------------------
* end of file
*---------------------------------------------------------------------------*/

View File

@ -0,0 +1,264 @@
/*----------------------------------------------------------------------------
* CMSIS-RTOS - RTX
*----------------------------------------------------------------------------
* Name: HAL_CM3.C
* Purpose: Hardware Abstraction Layer for Cortex-M3
* Rev.: V4.70
*----------------------------------------------------------------------------
*
* Copyright (c) 1999-2009 KEIL, 2009-2017 ARM Germany GmbH. All rights reserved.
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the License); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an AS IS BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*---------------------------------------------------------------------------*/
#include "rt_TypeDef.h"
#include "RTX_Config.h"
#include "rt_System.h"
#include "rt_HAL_CM.h"
#include "rt_Task.h"
#include "rt_MemBox.h"
/*----------------------------------------------------------------------------
* Functions
*---------------------------------------------------------------------------*/
/*--------------------------- rt_set_PSP ------------------------------------*/
__asm void rt_set_PSP (U32 stack) {
MSR PSP,R0
BX LR
}
/*--------------------------- rt_get_PSP ------------------------------------*/
__asm U32 rt_get_PSP (void) {
MRS R0,PSP
BX LR
}
/*--------------------------- os_set_env ------------------------------------*/
__asm void os_set_env (void) {
/* Switch to Unprivileged/Privileged Thread mode, use PSP. */
MOV R0,SP ; PSP = MSP
MSR PSP,R0
LDR R0,=__cpp(&os_flags)
LDRB R0,[R0]
LSLS R0,#31
MOVNE R0,#0x02 ; Privileged Thread mode, use PSP
MOVEQ R0,#0x03 ; Unprivileged Thread mode, use PSP
MSR CONTROL,R0
BX LR
ALIGN
}
/*--------------------------- _alloc_box ------------------------------------*/
__asm void *_alloc_box (void *box_mem) {
/* Function wrapper for Unprivileged/Privileged mode. */
LDR R12,=__cpp(rt_alloc_box)
MRS R3,IPSR
LSLS R3,#24
BXNE R12
MRS R3,CONTROL
LSLS R3,#31
BXEQ R12
SVC 0
BX LR
ALIGN
}
/*--------------------------- _free_box -------------------------------------*/
__asm U32 _free_box (void *box_mem, void *box) {
/* Function wrapper for Unprivileged/Privileged mode. */
LDR R12,=__cpp(rt_free_box)
MRS R3,IPSR
LSLS R3,#24
BXNE R12
MRS R3,CONTROL
LSLS R3,#31
BXEQ R12
SVC 0
BX LR
ALIGN
}
/*-------------------------- SVC_Handler ------------------------------------*/
__asm void SVC_Handler (void) {
PRESERVE8
IMPORT SVC_Count
IMPORT SVC_Table
IMPORT rt_stk_check
#ifdef IFX_XMC4XXX
EXPORT SVC_Handler_Veneer
SVC_Handler_Veneer
#endif
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
BLX R12 ; Call SVC Function
MRS R12,PSP ; Read PSP
STM R12,{R0-R2} ; Store return values
LDR R3,=__cpp(&os_tsk)
LDM R3,{R1,R2} ; os_tsk.run, os_tsk.next
CMP R1,R2
BEQ SVC_Exit ; no task switch
CBZ R1,SVC_Next ; Runtask deleted?
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.next
LDR R12,[R2,#TCB_TSTACK] ; os_tsk.next->tsk_stack
LDMIA R12!,{R4-R11} ; Restore New Context
MSR PSP,R12 ; Write PSP
SVC_Exit
MVN LR,#:NOT:0xFFFFFFFD ; set EXC_RETURN value
#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
ALIGN
}
/*-------------------------- PendSV_Handler ---------------------------------*/
__asm void PendSV_Handler (void) {
PRESERVE8
#ifdef IFX_XMC4XXX
EXPORT PendSV_Handler_Veneer
PendSV_Handler_Veneer
#endif
BL __cpp(rt_pop_req)
Sys_Switch
LDR R3,=__cpp(&os_tsk)
LDM R3,{R1,R2} ; os_tsk.run, os_tsk.next
CMP R1,R2
BEQ Sys_Exit
MRS R12,PSP ; Read PSP
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.next
LDR R12,[R2,#TCB_TSTACK] ; os_tsk.next->tsk_stack
LDMIA R12!,{R4-R11} ; Restore New Context
MSR PSP,R12 ; Write PSP
Sys_Exit
MVN LR,#:NOT:0xFFFFFFFD ; set EXC_RETURN value
#ifdef IFX_XMC4XXX
PUSH {LR}
POP {PC}
#else
BX LR ; Return to Thread Mode
#endif
ALIGN
}
/*-------------------------- SysTick_Handler --------------------------------*/
__asm void SysTick_Handler (void) {
PRESERVE8
#ifdef IFX_XMC4XXX
EXPORT SysTick_Handler_Veneer
SysTick_Handler_Veneer
#endif
BL __cpp(rt_systick)
B Sys_Switch
ALIGN
}
/*-------------------------- OS_Tick_Handler --------------------------------*/
__asm void OS_Tick_Handler (void) {
PRESERVE8
BL __cpp(os_tick_irqack)
BL __cpp(rt_systick)
B Sys_Switch
ALIGN
}
/*----------------------------------------------------------------------------
* end of file
*---------------------------------------------------------------------------*/

View File

@ -0,0 +1,309 @@
/*----------------------------------------------------------------------------
* CMSIS-RTOS - RTX
*----------------------------------------------------------------------------
* Name: HAL_CM4.C
* Purpose: Hardware Abstraction Layer for Cortex-M4
* Rev.: V4.79
*----------------------------------------------------------------------------
*
* Copyright (c) 1999-2009 KEIL, 2009-2017 ARM Germany GmbH. All rights reserved.
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the License); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an AS IS BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*---------------------------------------------------------------------------*/
#include "rt_TypeDef.h"
#include "RTX_Config.h"
#include "rt_System.h"
#include "rt_HAL_CM.h"
#include "rt_Task.h"
#include "rt_MemBox.h"
/*----------------------------------------------------------------------------
* Functions
*---------------------------------------------------------------------------*/
/*--------------------------- rt_set_PSP ------------------------------------*/
__asm void rt_set_PSP (U32 stack) {
MSR PSP,R0
BX LR
}
/*--------------------------- rt_get_PSP ------------------------------------*/
__asm U32 rt_get_PSP (void) {
MRS R0,PSP
BX LR
}
/*--------------------------- os_set_env ------------------------------------*/
__asm void os_set_env (void) {
/* Switch to Unprivileged/Privileged Thread mode, use PSP. */
MOV R0,SP ; PSP = MSP
MSR PSP,R0
LDR R0,=__cpp(&os_flags)
LDRB R0,[R0]
LSLS R0,#31
MOVNE R0,#0x02 ; Privileged Thread mode, use PSP
MOVEQ R0,#0x03 ; Unprivileged Thread mode, use PSP
MSR CONTROL,R0
BX LR
ALIGN
}
/*--------------------------- _alloc_box ------------------------------------*/
__asm void *_alloc_box (void *box_mem) {
/* Function wrapper for Unprivileged/Privileged mode. */
LDR R12,=__cpp(rt_alloc_box)
MRS R3,IPSR
LSLS R3,#24
BXNE R12
MRS R3,CONTROL
LSLS R3,#31
BXEQ R12
SVC 0
BX LR
ALIGN
}
/*--------------------------- _free_box -------------------------------------*/
__asm U32 _free_box (void *box_mem, void *box) {
/* Function wrapper for Unprivileged/Privileged mode. */
LDR R12,=__cpp(rt_free_box)
MRS R3,IPSR
LSLS R3,#24
BXNE R12
MRS R3,CONTROL
LSLS R3,#31
BXEQ R12
SVC 0
BX LR
ALIGN
}
/*-------------------------- SVC_Handler ------------------------------------*/
__asm void SVC_Handler (void) {
PRESERVE8
IMPORT SVC_Count
IMPORT SVC_Table
IMPORT rt_stk_check
#ifdef IFX_XMC4XXX
EXPORT SVC_Handler_Veneer
SVC_Handler_Veneer
#endif
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,=__cpp(&os_tsk)
LDM R3,{R1,R2} ; os_tsk.run, os_tsk.next
CMP R1,R2
#ifdef IFX_XMC4XXX
PUSHEQ {LR}
POPEQ {PC}
#else
BXEQ LR ; RETI, no task switch
#endif
CBNZ R1,SVC_ContextSave ; Runtask not deleted?
TST LR,#0x10 ; is it extended frame?
BNE SVC_ContextRestore
LDR R1,=0xE000EF34
LDR R0,[R1] ; Load FPCCR
BIC R0,#1 ; Clear LSPACT (Lazy state)
STR R0,[R1] ; Store FPCCR
B SVC_ContextRestore
SVC_ContextSave
TST LR,#0x10 ; is it extended frame?
VSTMDBEQ R12!,{S16-S31} ; yes, stack also VFP hi-regs
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_ContextRestore
STR R2,[R3] ; os_tsk.run = os_tsk.next
LDR R12,[R2,#TCB_TSTACK] ; os_tsk.next->tsk_stack
LDMIA R12!,{R4-R11} ; Restore New Context
LDRB R0,[R2,#TCB_STACKF] ; Stack Frame
CMP R0,#0 ; Basic/Extended Stack Frame
MVNEQ LR,#:NOT:0xFFFFFFFD ; set EXC_RETURN value
MVNNE LR,#:NOT:0xFFFFFFED
VLDMIANE R12!,{S16-S31} ; restore VFP hi-registers
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
ALIGN
}
/*-------------------------- PendSV_Handler ---------------------------------*/
__asm void PendSV_Handler (void) {
PRESERVE8
#ifdef IFX_XMC4XXX
EXPORT PendSV_Handler_Veneer
PendSV_Handler_Veneer
#endif
PUSH {R4,LR} ; Save EXC_RETURN
BL __cpp(rt_pop_req)
Sys_Switch
POP {R4,LR} ; Restore EXC_RETURN
LDR R3,=__cpp(&os_tsk)
LDM R3,{R1,R2} ; os_tsk.run, os_tsk.next
CMP R1,R2
#ifdef IFX_XMC4XXX
PUSHEQ {LR}
POPEQ {PC}
#else
BXEQ LR ; RETI, no task switch
#endif
MRS R12,PSP ; Read PSP
TST LR,#0x10 ; is it extended frame?
VSTMDBEQ R12!,{S16-S31} ; yes, stack also VFP hi-regs
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.next
LDR R12,[R2,#TCB_TSTACK] ; os_tsk.next->tsk_stack
LDMIA R12!,{R4-R11} ; Restore New Context
LDRB R0,[R2,#TCB_STACKF] ; Stack Frame
CMP R0,#0 ; Basic/Extended Stack Frame
MVNEQ LR,#:NOT:0xFFFFFFFD ; set EXC_RETURN value
MVNNE LR,#:NOT:0xFFFFFFED
VLDMIANE R12!,{S16-S31} ; restore VFP hi-regs
MSR PSP,R12 ; Write PSP
Sys_Exit
#ifdef IFX_XMC4XXX
PUSH {LR}
POP {PC}
#else
BX LR ; Return to Thread Mode
#endif
ALIGN
}
/*-------------------------- SysTick_Handler --------------------------------*/
__asm void SysTick_Handler (void) {
PRESERVE8
#ifdef IFX_XMC4XXX
EXPORT SysTick_Handler_Veneer
SysTick_Handler_Veneer
#endif
PUSH {R4,LR} ; Save EXC_RETURN
BL __cpp(rt_systick)
B Sys_Switch
ALIGN
}
/*-------------------------- OS_Tick_Handler --------------------------------*/
__asm void OS_Tick_Handler (void) {
PRESERVE8
PUSH {R4,LR} ; Save EXC_RETURN
BL __cpp(os_tick_irqack)
BL __cpp(rt_systick)
B Sys_Switch
ALIGN
}
/*----------------------------------------------------------------------------
* end of file
*---------------------------------------------------------------------------*/

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,48 @@
;/*----------------------------------------------------------------------------
; * CMSIS-RTOS - RTX
; *----------------------------------------------------------------------------
; * Name: SVC_TABLE.S
; * Purpose: Pre-defined SVC Table for Cortex-M
; * Rev.: V4.70
; *----------------------------------------------------------------------------
; *
; * Copyright (c) 1999-2009 KEIL, 2009-2017 ARM Germany GmbH. All rights reserved.
; *
; * SPDX-License-Identifier: Apache-2.0
; *
; * Licensed under the Apache License, Version 2.0 (the License); you may
; * not use this file except in compliance with the License.
; * You may obtain a copy of the License at
; *
; * www.apache.org/licenses/LICENSE-2.0
; *
; * Unless required by applicable law or agreed to in writing, software
; * distributed under the License is distributed on an AS IS BASIS, WITHOUT
; * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
; * See the License for the specific language governing permissions and
; * limitations under the License.
; *---------------------------------------------------------------------------*/
AREA SVC_TABLE, CODE, READONLY
EXPORT SVC_Count
SVC_Cnt EQU (SVC_End-SVC_Table)/4
SVC_Count DCD SVC_Cnt
; Import user SVC functions here.
; IMPORT __SVC_1
EXPORT SVC_Table
SVC_Table
; Insert user SVC functions here. SVC 0 used by RTL Kernel.
; DCD __SVC_1 ; user SVC function
SVC_End
END
/*----------------------------------------------------------------------------
* end of file
*---------------------------------------------------------------------------*/

View File

@ -0,0 +1,360 @@
/*----------------------------------------------------------------------------
* CMSIS-RTOS - RTX
*----------------------------------------------------------------------------
* Name: HAL_CM0.S
* Purpose: Hardware Abstraction Layer for Cortex-M0
* Rev.: V4.70
*----------------------------------------------------------------------------
*
* Copyright (c) 1999-2009 KEIL, 2009-2017 ARM Germany GmbH. All rights reserved.
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the License); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an AS IS BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*---------------------------------------------------------------------------*/
.syntax unified
.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
BNE PrivilegedE
MOVS R0,#0x03 /* Unprivileged Thread mode, use PSP */
MSR CONTROL,R0
BX LR
PrivilegedE:
MOVS R0,#0x02 /* Privileged 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 R3,=rt_alloc_box
MOV R12,R3
MRS R3,IPSR
LSLS R3,#24
BNE PrivilegedA
MRS R3,CONTROL
LSLS R3,#31
BEQ PrivilegedA
SVC 0
BX LR
PrivilegedA:
BX R12
.fnend
.size _alloc_box, .-_alloc_box
/*--------------------------- _free_box -------------------------------------*/
# U32 _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 R3,=rt_free_box
MOV R12,R3
MRS R3,IPSR
LSLS R3,#24
BNE PrivilegedF
MRS R3,CONTROL
LSLS R3,#31
BEQ PrivilegedF
SVC 0
BX LR
PrivilegedF:
BX R12
.fnend
.size _free_box, .-_free_box
/*-------------------------- SVC_Handler ------------------------------------*/
# void SVC_Handler (void);
.thumb_func
.type SVC_Handler, %function
.global SVC_Handler
SVC_Handler:
.fnstart
.cantunwind
MRS R0,PSP /* Read PSP */
LDR R1,[R0,#24] /* Read Saved PC from Stack */
SUBS R1,R1,#2 /* Point to SVC Instruction */
LDRB R1,[R1] /* Load SVC Number */
CMP R1,#0
BNE SVC_User /* User SVC Number > 0 */
MOV LR,R4
LDMIA R0,{R0-R3,R4} /* Read R0-R3,R12 from stack */
MOV R12,R4
MOV R4,LR
BLX R12 /* Call SVC Function */
MRS R3,PSP /* Read PSP */
STMIA R3!,{R0-R2} /* Store return values */
LDR R3,=os_tsk
LDMIA R3!,{R1,R2} /* os_tsk.run, os_tsk.next */
CMP R1,R2
BEQ SVC_Exit /* no task switch */
SUBS R3,#8
CMP R1,#0 /* Runtask deleted? */
BEQ SVC_Next
MRS R0,PSP /* Read PSP */
SUBS R0,R0,#32 /* Adjust Start Address */
STR R0,[R1,#TCB_TSTACK] /* Update os_tsk.run->tsk_stack */
STMIA R0!,{R4-R7} /* Save old context (R4-R7) */
MOV R4,R8
MOV R5,R9
MOV R6,R10
MOV R7,R11
STMIA R0!,{R4-R7} /* Save old context (R8-R11) */
PUSH {R2,R3}
BL rt_stk_check /* Check for Stack overflow */
POP {R2,R3}
SVC_Next:
STR R2,[R3] /* os_tsk.run = os_tsk.next */
LDR R0,[R2,#TCB_TSTACK] /* os_tsk.next->tsk_stack */
ADDS R0,R0,#16 /* Adjust Start Address */
LDMIA R0!,{R4-R7} /* Restore new Context (R8-R11) */
MOV R8,R4
MOV R9,R5
MOV R10,R6
MOV R11,R7
MSR PSP,R0 /* Write PSP */
SUBS R0,R0,#32 /* Adjust Start Address */
LDMIA R0!,{R4-R7} /* Restore new Context (R4-R7) */
SVC_Exit:
MOVS R0,#~0xFFFFFFFD /* Set EXC_RETURN value */
MVNS R0,R0
BX R0 /* RETI to Thread Mode, use PSP */
/*------------------- 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
LSLS R1,R1,#2
LDR R4,[R4,R1] /* Load SVC Function Address */
MOV LR,R4
LDMIA R0,{R0-R3,R4} /* Read R0-R3,R12 from stack */
MOV R12,R4
BLX LR /* Call SVC Function */
MRS R4,PSP /* Read PSP */
STMIA R4!,{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:
.fnstart
.cantunwind
BL rt_pop_req
Sys_Switch:
LDR R3,=os_tsk
LDMIA R3!,{R1,R2} /* os_tsk.run, os_tsk.next */
CMP R1,R2
BEQ Sys_Exit /* no task switch */
SUBS R3,#8
MRS R0,PSP /* Read PSP */
SUBS R0,R0,#32 /* Adjust Start Address */
STR R0,[R1,#TCB_TSTACK] /* Update os_tsk.run->tsk_stack */
STMIA R0!,{R4-R7} /* Save old context (R4-R7) */
MOV R4,R8
MOV R5,R9
MOV R6,R10
MOV R7,R11
STMIA R0!,{R4-R7} /* Save old context (R8-R11) */
PUSH {R2,R3}
BL rt_stk_check /* Check for Stack overflow */
POP {R2,R3}
STR R2,[R3] /* os_tsk.run = os_tsk.next */
LDR R0,[R2,#TCB_TSTACK] /* os_tsk.next->tsk_stack */
ADDS R0,R0,#16 /* Adjust Start Address */
LDMIA R0!,{R4-R7} /* Restore new Context (R8-R11) */
MOV R8,R4
MOV R9,R5
MOV R10,R6
MOV R11,R7
MSR PSP,R0 /* Write PSP */
SUBS R0,R0,#32 /* Adjust Start Address */
LDMIA R0!,{R4-R7} /* Restore new Context (R4-R7) */
Sys_Exit:
MOVS R0,#~0xFFFFFFFD /* Set EXC_RETURN value */
MVNS R0,R0
BX R0 /* RETI to Thread Mode, use PSP */
.fnend
.size PendSV_Handler, .-PendSV_Handler
/*-------------------------- SysTick_Handler --------------------------------*/
# void SysTick_Handler (void);
.thumb_func
.type SysTick_Handler, %function
.global SysTick_Handler
SysTick_Handler:
.fnstart
.cantunwind
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
BL os_tick_irqack
BL rt_systick
B Sys_Switch
.fnend
.size OS_Tick_Handler, .-OS_Tick_Handler
.end
/*----------------------------------------------------------------------------
* end of file
*---------------------------------------------------------------------------*/

View File

@ -0,0 +1,335 @@
/*----------------------------------------------------------------------------
* CMSIS-RTOS - RTX
*----------------------------------------------------------------------------
* Name: HAL_CM3.S
* Purpose: Hardware Abstraction Layer for Cortex-M3
* Rev.: V4.70
*----------------------------------------------------------------------------
*
* Copyright (c) 1999-2009 KEIL, 2009-2017 ARM Germany GmbH. All rights reserved.
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the License); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an AS IS BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*---------------------------------------------------------------------------*/
.syntax unified
.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 -------------------------------------*/
# U32 _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 */
BLX R12 /* Call SVC Function */
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.next */
CMP R1,R2
BEQ SVC_Exit /* no task switch */
CBZ R1,SVC_Next /* Runtask deleted? */
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.next */
LDR R12,[R2,#TCB_TSTACK] /* os_tsk.next->tsk_stack */
LDMIA R12!,{R4-R11} /* Restore New Context */
MSR PSP,R12 /* Write PSP */
SVC_Exit:
MVN LR,#~0xFFFFFFFD /* set EXC_RETURN value */
.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
BL rt_pop_req
Sys_Switch:
LDR R3,=os_tsk
LDM R3,{R1,R2} /* os_tsk.run, os_tsk.next */
CMP R1,R2
BEQ Sys_Exit
MRS R12,PSP /* Read PSP */
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.next */
LDR R12,[R2,#TCB_TSTACK] /* os_tsk.next->tsk_stack */
LDMIA R12!,{R4-R11} /* Restore New Context */
MSR PSP,R12 /* Write PSP */
Sys_Exit:
MVN LR,#~0xFFFFFFFD /* set EXC_RETURN value */
.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
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
BL os_tick_irqack
BL rt_systick
B Sys_Switch
.fnend
.size OS_Tick_Handler, .-OS_Tick_Handler
.end
/*----------------------------------------------------------------------------
* end of file
*---------------------------------------------------------------------------*/

View File

@ -0,0 +1,389 @@
/*----------------------------------------------------------------------------
* CMSIS-RTOS - RTX
*----------------------------------------------------------------------------
* Name: HAL_CM4.S
* Purpose: Hardware Abstraction Layer for Cortex-M4
* Rev.: V4.79
*----------------------------------------------------------------------------
*
* Copyright (c) 1999-2009 KEIL, 2009-2017 ARM Germany GmbH. All rights reserved.
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the License); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an AS IS BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*---------------------------------------------------------------------------*/
.syntax unified
.equ TCB_STACKF, 37
.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 -------------------------------------*/
# U32 _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.next */
CMP R1,R2
.ifdef IFX_XMC4XXX
ITT EQ
PUSHEQ {LR}
POPEQ {PC}
.else
IT EQ
BXEQ LR /* RETI, no task switch */
.endif
CBNZ R1,SVC_ContextSave /* Runtask not deleted? */
TST LR,#0x10 /* is it extended frame? */
BNE SVC_ContextRestore
LDR R1,=0xE000EF34
LDR R0,[R1] /* Load FPCCR */
BIC R0,#1 /* Clear LSPACT (Lazy state) */
STR R0,[R1] /* Store FPCCR */
B SVC_ContextRestore
SVC_ContextSave:
TST LR,#0x10 /* is it extended frame? */
ITTE EQ
VSTMDBEQ R12!,{S16-S31} /* yes, stack also VFP hi-regs */
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_ContextRestore:
STR R2,[R3] /* os_tsk.run = os_tsk.next */
LDR R12,[R2,#TCB_TSTACK] /* os_tsk.next->tsk_stack */
LDMIA R12!,{R4-R11} /* Restore New Context */
LDRB R0,[R2,#TCB_STACKF] /* Stack Frame */
CMP R0,#0 /* Basic/Extended Stack Frame */
ITEE EQ
MVNEQ LR,#~0xFFFFFFFD /* set EXC_RETURN value */
MVNNE LR,#~0xFFFFFFED
VLDMIANE R12!,{S16-S31} /* restore VFP hi-registers */
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.next */
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? */
ITTE EQ
VSTMDBEQ R12!,{S16-S31} /* yes, stack also VFP hi-regs */
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.next */
LDR R12,[R2,#TCB_TSTACK] /* os_tsk.next->tsk_stack */
LDMIA R12!,{R4-R11} /* Restore New Context */
LDRB R0,[R2,#TCB_STACKF] /* Stack Frame */
CMP R0,#0 /* Basic/Extended Stack Frame */
ITEE EQ
MVNEQ LR,#~0xFFFFFFFD /* set EXC_RETURN value */
MVNNE LR,#~0xFFFFFFED
VLDMIANE R12!,{S16-S31} /* restore VFP hi-registers */
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
*---------------------------------------------------------------------------*/

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,44 @@
;/*----------------------------------------------------------------------------
; * CMSIS-RTOS - RTX
; *----------------------------------------------------------------------------
; * Name: SVC_TABLE.S
; * Purpose: Pre-defined SVC Table for Cortex-M
; * Rev.: V4.70
; *----------------------------------------------------------------------------
; *
; * Copyright (c) 1999-2009 KEIL, 2009-2017 ARM Germany GmbH. All rights reserved.
; *
; * SPDX-License-Identifier: Apache-2.0
; *
; * Licensed under the Apache License, Version 2.0 (the License); you may
; * not use this file except in compliance with the License.
; * You may obtain a copy of the License at
; *
; * www.apache.org/licenses/LICENSE-2.0
; *
; * Unless required by applicable law or agreed to in writing, software
; * distributed under the License is distributed on an AS IS BASIS, WITHOUT
; * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
; * See the License for the specific language governing permissions and
; * limitations under the License.
; *---------------------------------------------------------------------------*/
.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
*---------------------------------------------------------------------------*/

View File

@ -0,0 +1,171 @@
/*----------------------------------------------------------------------------
* CMSIS-RTOS - RTX
*----------------------------------------------------------------------------
* Name: HAL_CM.C
* Purpose: Hardware Abstraction Layer for Cortex-M
* Rev.: V4.79
*----------------------------------------------------------------------------
*
* Copyright (c) 1999-2009 KEIL, 2009-2017 ARM Germany GmbH. All rights reserved.
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the License); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an AS IS BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*---------------------------------------------------------------------------*/
#include "rt_TypeDef.h"
#include "RTX_Config.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;
if (size == 0U) {
size = (U16)os_stackinfo >> 2;
}
/* Write to the top of stack. */
stk = &p_TCB->stack[size];
/* Auto correct to 8-byte ARM stack alignment. */
if ((U32)stk & 0x04U) {
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 = 0U; i < 14U; i++) {
stk[i] = 0U;
}
/* 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;
/* Initialize stack with magic pattern. */
if (os_stackinfo & 0x10000000U) {
if (size > (16U+1U)) {
for (i = ((size - 16U)/2U) - 1U; i; i--) {
stk -= 2U;
stk[1] = MAGIC_PATTERN;
stk[0] = MAGIC_PATTERN;
}
if (--stk > p_TCB->stack) {
*stk = MAGIC_PATTERN;
}
}
}
/* Set a magic word for checking of stack overflow. */
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 defined(__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 + (8U*4U) + (16U*4U));
} else {
/* Basic Stack Frame: R4-R11,R0-R3,R12,LR,PC,xPSR */
return (U32 *)(p_TCB->tsk_stack + (8U*4U));
}
#else
/* Stack Frame: R4-R11,R0-R3,R12,LR,PC,xPSR */
return (U32 *)(p_TCB->tsk_stack + (8U*4U));
#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) != 0U) &&
((ITM_CONTROL & ITM_ITMENA) != 0U) &&
((ITM_ENABLE & (1UL << 31)) != 0U)) {
dbg_msg = __TRUE;
}
}
#endif
/*--------------------------- dbg_task_notify -------------------------------*/
#ifdef DBG_MSG
void dbg_task_notify (P_TCB p_tcb, BOOL create) {
while (ITM_PORT31_U32 == 0U);
ITM_PORT31_U32 = (U32)p_tcb->ptask;
while (ITM_PORT31_U32 == 0U);
ITM_PORT31_U16 = (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 == 0U);
ITM_PORT31_U8 = (U8)task_id;
}
#endif
/*----------------------------------------------------------------------------
* end of file
*---------------------------------------------------------------------------*/

View File

@ -0,0 +1,303 @@
/*----------------------------------------------------------------------------
* CMSIS-RTOS - RTX
*----------------------------------------------------------------------------
* Name: HAL_CM0.S
* Purpose: Hardware Abstraction Layer for Cortex-M0
* Rev.: V4.70
*----------------------------------------------------------------------------
*
* Copyright (c) 1999-2009 KEIL, 2009-2017 ARM Germany GmbH. All rights reserved.
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the License); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an AS IS BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*---------------------------------------------------------------------------*/
NAME HAL_CM0.S
#define TCB_TSTACK 40
EXTERN os_flags
EXTERN os_tsk
EXTERN rt_alloc_box
EXTERN rt_free_box
EXTERN rt_stk_check
EXTERN rt_pop_req
EXTERN rt_systick
EXTERN os_tick_irqack
EXTERN SVC_Table
EXTERN SVC_Count
/*----------------------------------------------------------------------------
* Functions
*---------------------------------------------------------------------------*/
SECTION .text:CODE:NOROOT(2)
THUMB
/*--------------------------- rt_set_PSP ------------------------------------*/
; void rt_set_PSP (U32 stack);
PUBLIC rt_set_PSP
rt_set_PSP:
MSR PSP,R0
BX LR
/*--------------------------- rt_get_PSP ------------------------------------*/
; U32 rt_get_PSP (void);
PUBLIC rt_get_PSP
rt_get_PSP:
MRS R0,PSP
BX LR
/*--------------------------- os_set_env ------------------------------------*/
; void os_set_env (void);
/* Switch to Unprivileged/Privileged Thread mode, use PSP. */
PUBLIC os_set_env
os_set_env:
MOV R0,SP /* PSP = MSP */
MSR PSP,R0
LDR R0,=os_flags
LDRB R0,[R0]
LSLS R0,#31
BNE PrivilegedE
MOVS R0,#0x03 /* Unprivileged Thread mode, use PSP */
MSR CONTROL,R0
BX LR
PrivilegedE:
MOVS R0,#0x02 /* Privileged Thread mode, use PSP */
MSR CONTROL,R0
BX LR
/*--------------------------- _alloc_box ------------------------------------*/
; void *_alloc_box (void *box_mem);
/* Function wrapper for Unprivileged/Privileged mode. */
PUBLIC _alloc_box
_alloc_box:
LDR R3,=rt_alloc_box
MOV R12,R3
MRS R3,IPSR
LSLS R3,#24
BNE PrivilegedA
MRS R3,CONTROL
LSLS R3,#31
BEQ PrivilegedA
SVC 0
BX LR
PrivilegedA:
BX R12
/*--------------------------- _free_box -------------------------------------*/
; U32 _free_box (void *box_mem, void *box);
/* Function wrapper for Unprivileged/Privileged mode. */
PUBLIC _free_box
_free_box:
LDR R3,=rt_free_box
MOV R12,R3
MRS R3,IPSR
LSLS R3,#24
BNE PrivilegedF
MRS R3,CONTROL
LSLS R3,#31
BEQ PrivilegedF
SVC 0
BX LR
PrivilegedF:
BX R12
/*-------------------------- SVC_Handler ------------------------------------*/
; void SVC_Handler (void);
PUBLIC SVC_Handler
SVC_Handler:
MRS R0,PSP /* Read PSP */
LDR R1,[R0,#24] /* Read Saved PC from Stack */
SUBS R1,R1,#2 /* Point to SVC Instruction */
LDRB R1,[R1] /* Load SVC Number */
CMP R1,#0
BNE SVC_User /* User SVC Number > 0 */
MOV LR,R4
LDMIA R0,{R0-R3,R4} /* Read R0-R3,R12 from stack */
MOV R12,R4
MOV R4,LR
BLX R12 /* Call SVC Function */
MRS R3,PSP /* Read PSP */
STMIA R3!,{R0-R2} /* Store return values */
LDR R3,=os_tsk
LDMIA R3!,{R1,R2} /* os_tsk.run, os_tsk.next */
CMP R1,R2
BEQ SVC_Exit /* no task switch */
SUBS R3,#8
CMP R1,#0 /* Runtask deleted? */
BEQ SVC_Next
MRS R0,PSP /* Read PSP */
SUBS R0,R0,#32 /* Adjust Start Address */
STR R0,[R1,#TCB_TSTACK] /* Update os_tsk.run->tsk_stack */
STMIA R0!,{R4-R7} /* Save old context (R4-R7) */
MOV R4,R8
MOV R5,R9
MOV R6,R10
MOV R7,R11
STMIA R0!,{R4-R7} /* Save old context (R8-R11) */
PUSH {R2,R3}
BL rt_stk_check /* Check for Stack overflow */
POP {R2,R3}
SVC_Next:
STR R2,[R3] /* os_tsk.run = os_tsk.next */
LDR R0,[R2,#TCB_TSTACK] /* os_tsk.next->tsk_stack */
ADDS R0,R0,#16 /* Adjust Start Address */
LDMIA R0!,{R4-R7} /* Restore new Context (R8-R11) */
MOV R8,R4
MOV R9,R5
MOV R10,R6
MOV R11,R7
MSR PSP,R0 /* Write PSP */
SUBS R0,R0,#32 /* Adjust Start Address */
LDMIA R0!,{R4-R7} /* Restore new Context (R4-R7) */
SVC_Exit:
MOVS R0,#~0xFFFFFFFD /* Set EXC_RETURN value */
MVNS R0,R0
BX R0 /* RETI to Thread Mode, use PSP */
/*------------------- 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
LSLS R1,R1,#2
LDR R4,[R4,R1] /* Load SVC Function Address */
MOV LR,R4
LDMIA R0,{R0-R3,R4} /* Read R0-R3,R12 from stack */
MOV R12,R4
BLX LR /* Call SVC Function */
MRS R4,PSP /* Read PSP */
STMIA R4!,{R0-R3} /* Function return values */
SVC_Done:
POP {R4,PC} /* RETI */
/*-------------------------- PendSV_Handler ---------------------------------*/
; void PendSV_Handler (void);
PUBLIC PendSV_Handler
PendSV_Handler:
BL rt_pop_req
Sys_Switch:
LDR R3,=os_tsk
LDMIA R3!,{R1,R2} /* os_tsk.run, os_tsk.next */
CMP R1,R2
BEQ Sys_Exit /* no task switch */
SUBS R3,#8
MRS R0,PSP /* Read PSP */
SUBS R0,R0,#32 /* Adjust Start Address */
STR R0,[R1,#TCB_TSTACK] /* Update os_tsk.run->tsk_stack */
STMIA R0!,{R4-R7} /* Save old context (R4-R7) */
MOV R4,R8
MOV R5,R9
MOV R6,R10
MOV R7,R11
STMIA R0!,{R4-R7} /* Save old context (R8-R11) */
PUSH {R2,R3}
BL rt_stk_check /* Check for Stack overflow */
POP {R2,R3}
STR R2,[R3] /* os_tsk.run = os_tsk.next */
LDR R0,[R2,#TCB_TSTACK] /* os_tsk.next->tsk_stack */
ADDS R0,R0,#16 /* Adjust Start Address */
LDMIA R0!,{R4-R7} /* Restore new Context (R8-R11) */
MOV R8,R4
MOV R9,R5
MOV R10,R6
MOV R11,R7
MSR PSP,R0 /* Write PSP */
SUBS R0,R0,#32 /* Adjust Start Address */
LDMIA R0!,{R4-R7} /* Restore new Context (R4-R7) */
Sys_Exit:
MOVS R0,#~0xFFFFFFFD /* Set EXC_RETURN value */
MVNS R0,R0
BX R0 /* RETI to Thread Mode, use PSP */
/*-------------------------- SysTick_Handler --------------------------------*/
; void SysTick_Handler (void);
PUBLIC SysTick_Handler
SysTick_Handler:
BL rt_systick
B Sys_Switch
/*-------------------------- OS_Tick_Handler --------------------------------*/
; void OS_Tick_Handler (void);
PUBLIC OS_Tick_Handler
OS_Tick_Handler:
BL os_tick_irqack
BL rt_systick
B Sys_Switch
END
/*----------------------------------------------------------------------------
* end of file
*---------------------------------------------------------------------------*/

View File

@ -0,0 +1,256 @@
/*----------------------------------------------------------------------------
* CMSIS-RTOS - RTX
*----------------------------------------------------------------------------
* Name: HAL_CM3.S
* Purpose: Hardware Abstraction Layer for Cortex-M3
* Rev.: V4.70
*----------------------------------------------------------------------------
*
* Copyright (c) 1999-2009 KEIL, 2009-2017 ARM Germany GmbH. All rights reserved.
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the License); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an AS IS BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*---------------------------------------------------------------------------*/
NAME HAL_CM3.S
#define TCB_TSTACK 40
EXTERN os_flags
EXTERN os_tsk
EXTERN rt_alloc_box
EXTERN rt_free_box
EXTERN rt_stk_check
EXTERN rt_pop_req
EXTERN rt_systick
EXTERN os_tick_irqack
EXTERN SVC_Table
EXTERN SVC_Count
/*----------------------------------------------------------------------------
* Functions
*---------------------------------------------------------------------------*/
SECTION .text:CODE:NOROOT(2)
THUMB
/*--------------------------- rt_set_PSP ------------------------------------*/
; void rt_set_PSP (U32 stack);
PUBLIC rt_set_PSP
rt_set_PSP:
MSR PSP,R0
BX LR
/*--------------------------- rt_get_PSP ------------------------------------*/
; U32 rt_get_PSP (void);
PUBLIC rt_get_PSP
rt_get_PSP:
MRS R0,PSP
BX LR
/*--------------------------- os_set_env ------------------------------------*/
; void os_set_env (void);
/* Switch to Unprivileged/Privileged Thread mode, use PSP. */
PUBLIC os_set_env
os_set_env:
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
/*--------------------------- _alloc_box ------------------------------------*/
; void *_alloc_box (void *box_mem);
/* Function wrapper for Unprivileged/Privileged mode. */
PUBLIC _alloc_box
_alloc_box:
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
/*--------------------------- _free_box -------------------------------------*/
; U32 _free_box (void *box_mem, void *box);
/* Function wrapper for Unprivileged/Privileged mode. */
PUBLIC _free_box
_free_box:
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
/*-------------------------- SVC_Handler ------------------------------------*/
; void SVC_Handler (void);
PUBLIC SVC_Handler
SVC_Handler:
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 */
BLX R12 /* Call SVC Function */
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.next */
CMP R1,R2
BEQ SVC_Exit /* no task switch */
CBZ R1,SVC_Next /* Runtask deleted? */
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.next */
LDR R12,[R2,#TCB_TSTACK] /* os_tsk.next->tsk_stack */
LDMIA R12!,{R4-R11} /* Restore New Context */
MSR PSP,R12 /* Write PSP */
SVC_Exit:
MVN LR,#~0xFFFFFFFD /* set EXC_RETURN value */
BX LR
/*------------------- 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 */
/*-------------------------- PendSV_Handler ---------------------------------*/
; void PendSV_Handler (void);
PUBLIC PendSV_Handler
PendSV_Handler:
BL rt_pop_req
Sys_Switch:
LDR R3,=os_tsk
LDM R3,{R1,R2} /* os_tsk.run, os_tsk.next */
CMP R1,R2
BEQ Sys_Exit
MRS R12,PSP /* Read PSP */
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.next */
LDR R12,[R2,#TCB_TSTACK] /* os_tsk.next->tsk_stack */
LDMIA R12!,{R4-R11} /* Restore New Context */
MSR PSP,R12 /* Write PSP */
Sys_Exit:
MVN LR,#~0xFFFFFFFD /* set EXC_RETURN value */
BX LR /* Return to Thread Mode */
/*-------------------------- SysTick_Handler --------------------------------*/
; void SysTick_Handler (void);
PUBLIC SysTick_Handler
SysTick_Handler:
BL rt_systick
B Sys_Switch
/*-------------------------- OS_Tick_Handler --------------------------------*/
; void OS_Tick_Handler (void);
PUBLIC OS_Tick_Handler
OS_Tick_Handler:
BL os_tick_irqack
BL rt_systick
B Sys_Switch
END
/*----------------------------------------------------------------------------
* end of file
*---------------------------------------------------------------------------*/

View File

@ -0,0 +1,298 @@
/*----------------------------------------------------------------------------
* CMSIS-RTOS - RTX
*----------------------------------------------------------------------------
* Name: HAL_CM4.S
* Purpose: Hardware Abstraction Layer for Cortex-M4
* Rev.: V4.79
*----------------------------------------------------------------------------
*
* Copyright (c) 1999-2009 KEIL, 2009-2017 ARM Germany GmbH. All rights reserved.
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the License); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an AS IS BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*---------------------------------------------------------------------------*/
NAME HAL_CM4.S
#define TCB_STACKF 37
#define TCB_TSTACK 40
EXTERN os_flags
EXTERN os_tsk
EXTERN rt_alloc_box
EXTERN rt_free_box
EXTERN rt_stk_check
EXTERN rt_pop_req
EXTERN rt_systick
EXTERN os_tick_irqack
EXTERN SVC_Table
EXTERN SVC_Count
/*----------------------------------------------------------------------------
* Functions
*---------------------------------------------------------------------------*/
SECTION .text:CODE:NOROOT(2)
THUMB
/*--------------------------- rt_set_PSP ------------------------------------*/
; void rt_set_PSP (U32 stack);
PUBLIC rt_set_PSP
rt_set_PSP:
MSR PSP,R0
BX LR
/*--------------------------- rt_get_PSP ------------------------------------*/
; U32 rt_get_PSP (void);
PUBLIC rt_get_PSP
rt_get_PSP:
MRS R0,PSP
BX LR
/*--------------------------- os_set_env ------------------------------------*/
; void os_set_env (void);
/* Switch to Unprivileged/Privileged Thread mode, use PSP. */
PUBLIC os_set_env
os_set_env:
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
/*--------------------------- _alloc_box ------------------------------------*/
; void *_alloc_box (void *box_mem);
/* Function wrapper for Unprivileged/Privileged mode. */
PUBLIC _alloc_box
_alloc_box:
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
/*--------------------------- _free_box -------------------------------------*/
; U32 _free_box (void *box_mem, void *box);
/* Function wrapper for Unprivileged/Privileged mode. */
PUBLIC _free_box
_free_box:
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
/*-------------------------- SVC_Handler ------------------------------------*/
; void SVC_Handler (void);
PUBLIC SVC_Handler
SVC_Handler:
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.next */
CMP R1,R2
IT EQ
BXEQ LR /* RETI, no task switch */
CBNZ R1,SVC_ContextSave /* Runtask not deleted? */
TST LR,#0x10 /* is it extended frame? */
BNE SVC_ContextRestore
LDR R1,=0xE000EF34
LDR R0,[R1] /* Load FPCCR */
BIC R0,R0,#1 /* Clear LSPACT (Lazy state) */
STR R0,[R1] /* Store FPCCR */
B SVC_ContextRestore
SVC_ContextSave:
TST LR,#0x10 /* is it extended frame? */
ITTE EQ
VSTMDBEQ R12!,{S16-S31} /* yes, stack also VFP hi-regs */
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_ContextRestore:
STR R2,[R3] /* os_tsk.run = os_tsk.next */
LDR R12,[R2,#TCB_TSTACK] /* os_tsk.next->tsk_stack */
LDMIA R12!,{R4-R11} /* Restore New Context */
LDRB R0,[R2,#TCB_STACKF] /* Stack Frame */
CMP R0,#0 /* Basic/Extended Stack Frame */
ITEE EQ
MVNEQ LR,#~0xFFFFFFFD /* set EXC_RETURN value */
MVNNE LR,#~0xFFFFFFED
VLDMIANE R12!,{S16-S31} /* restore VFP hi-registers */
MSR PSP,R12 /* Write PSP */
SVC_Exit:
BX LR
/*------------------- 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 */
/*-------------------------- PendSV_Handler ---------------------------------*/
; void PendSV_Handler (void);
PUBLIC PendSV_Handler
PendSV_Handler:
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.next */
CMP R1,R2
IT EQ
BXEQ LR /* RETI, no task switch */
MRS R12,PSP /* Read PSP */
TST LR,#0x10 /* is it extended frame? */
ITTE EQ
VSTMDBEQ R12!,{S16-S31} /* yes, stack also VFP hi-regs */
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.next */
LDR R12,[R2,#TCB_TSTACK] /* os_tsk.next->tsk_stack */
LDMIA R12!,{R4-R11} /* Restore New Context */
LDRB R0,[R2,#TCB_STACKF] /* Stack Frame */
CMP R0,#0 /* Basic/Extended Stack Frame */
ITEE EQ
MVNEQ LR,#~0xFFFFFFFD /* set EXC_RETURN value */
MVNNE LR,#~0xFFFFFFED
VLDMIANE R12!,{S16-S31} /* restore VFP hi-registers */
MSR PSP,R12 /* Write PSP */
Sys_Exit:
BX LR /* Return to Thread Mode */
/*-------------------------- SysTick_Handler --------------------------------*/
; void SysTick_Handler (void);
PUBLIC SysTick_Handler
SysTick_Handler:
PUSH {R4,LR} /* Save EXC_RETURN */
BL rt_systick
B Sys_Switch
/*-------------------------- OS_Tick_Handler --------------------------------*/
; void OS_Tick_Handler (void);
PUBLIC OS_Tick_Handler
OS_Tick_Handler:
PUSH {R4,LR} /* Save EXC_RETURN */
BL os_tick_irqack
BL rt_systick
B Sys_Switch
END
/*----------------------------------------------------------------------------
* end of file
*---------------------------------------------------------------------------*/

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,35 @@
<?xml version="1.0" encoding="UTF-8"?>
<workspace>
<project>
<path>$WS_DIR$\RTX_Lib_CM.ewp</path>
</project>
<batchBuild>
<batchDefinition>
<name>RTX_Lib_CM</name>
<member>
<project>RTX_Lib_CM</project>
<configuration>CM0_LE</configuration>
</member>
<member>
<project>RTX_Lib_CM</project>
<configuration>CM0_BE</configuration>
</member>
<member>
<project>RTX_Lib_CM</project>
<configuration>CM3_LE</configuration>
</member>
<member>
<project>RTX_Lib_CM</project>
<configuration>CM3_BE</configuration>
</member>
<member>
<project>RTX_Lib_CM</project>
<configuration>CM4F_LE</configuration>
</member>
<member>
<project>RTX_Lib_CM</project>
<configuration>CM4F_BE</configuration>
</member>
</batchDefinition>
</batchBuild>
</workspace>

View File

@ -0,0 +1,50 @@
;/*----------------------------------------------------------------------------
; * CMSIS-RTOS - RTX
; *----------------------------------------------------------------------------
; * Name: SVC_TABLE.S
; * Purpose: Pre-defined SVC Table for Cortex-M
; * Rev.: V4.70
; *----------------------------------------------------------------------------
; *
; * Copyright (c) 1999-2009 KEIL, 2009-2017 ARM Germany GmbH
; * All rights reserved.
; *
; * SPDX-License-Identifier: Apache-2.0
; *
; * Licensed under the Apache License, Version 2.0 (the License); you may
; * not use this file except in compliance with the License.
; * You may obtain a copy of the License at
; *
; * www.apache.org/licenses/LICENSE-2.0
; *
; * Unless required by applicable law or agreed to in writing, software
; * distributed under the License is distributed on an AS IS BASIS, WITHOUT
; * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
; * See the License for the specific language governing permissions and
; * limitations under the License.
; *---------------------------------------------------------------------------*/
NAME SVC_TABLE
SECTION .text:CONST (2)
PUBLIC SVC_Count
SVC_Cnt EQU (SVC_End-SVC_Table)/4
SVC_Count DCD SVC_Cnt
; Import user SVC functions here.
; IMPORT __SVC_1
PUBLIC SVC_Table
SVC_Table
; Insert user SVC functions here. SVC 0 used by RTL Kernel.
; DCD __SVC_1 ; user SVC function
SVC_End
END
/*----------------------------------------------------------------------------
* end of file
*---------------------------------------------------------------------------*/

View File

@ -0,0 +1,71 @@
/*----------------------------------------------------------------------------
* CMSIS-RTOS - RTX
*----------------------------------------------------------------------------
* Name: RTX_CONFIG.H
* Purpose: Exported functions of RTX_Config.c
* Rev.: V4.81
*----------------------------------------------------------------------------
*
* Copyright (c) 1999-2009 KEIL, 2009-2017 ARM Germany GmbH. All rights reserved.
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the License); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an AS IS BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*---------------------------------------------------------------------------*/
#include <stdint.h>
/* Error Codes */
#define OS_ERR_STK_OVF 1U
#define OS_ERR_FIFO_OVF 2U
#define OS_ERR_MBX_OVF 3U
#define OS_ERR_TIMER_OVF 4U
/* Definitions */
#define BOX_ALIGN_8 0x80000000U
#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 mp_tcb[];
extern U64 mp_stk[];
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_stackinfo;
extern U32 const os_rrobin;
extern U32 const os_clockrate;
extern U32 const os_timernum;
extern U16 const mp_tcb_size;
extern U32 const mp_stk_size;
extern U32 const *m_tmr;
extern U16 const mp_tmr_size;
extern U8 const os_fifo_size;
/* Functions */
extern void os_idle_demon (void);
extern S32 os_tick_init (void);
extern U32 os_tick_val (void);
extern U32 os_tick_ovf (void);
extern void os_tick_irqack (void);
extern void os_tmr_call (U16 info);
extern void os_error (uint32_t err_code);
/*----------------------------------------------------------------------------
* end of file
*---------------------------------------------------------------------------*/

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,181 @@
/*----------------------------------------------------------------------------
* CMSIS-RTOS - RTX
*----------------------------------------------------------------------------
* Name: RT_EVENT.C
* Purpose: Implements waits and wake-ups for event flags
* Rev.: V4.79
*----------------------------------------------------------------------------
*
* Copyright (c) 1999-2009 KEIL, 2009-2017 ARM Germany GmbH. All rights reserved.
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the License); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an AS IS BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*---------------------------------------------------------------------------*/
#include "rt_TypeDef.h"
#include "RTX_Config.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-1U];
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, 0x08U/*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-1U];
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-1U];
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, 0x08U/*osEventSignal*/, p_CB->waits);
#else
rt_ret_val (p_CB, OS_R_EVT);
#endif
rt_put_prio (&os_rdy, p_CB);
}
}
}
/*----------------------------------------------------------------------------
* end of file
*---------------------------------------------------------------------------*/

View File

@ -0,0 +1,36 @@
/*----------------------------------------------------------------------------
* CMSIS-RTOS - RTX
*----------------------------------------------------------------------------
* Name: RT_EVENT.H
* Purpose: Implements waits and wake-ups for event flags
* Rev.: V4.70
*----------------------------------------------------------------------------
*
* Copyright (c) 1999-2009 KEIL, 2009-2017 ARM Germany GmbH. All rights reserved.
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the License); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an AS IS BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*---------------------------------------------------------------------------*/
/* 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
*---------------------------------------------------------------------------*/

View File

@ -0,0 +1,280 @@
/*----------------------------------------------------------------------------
* CMSIS-RTOS - RTX
*----------------------------------------------------------------------------
* Name: RT_HAL_CM.H
* Purpose: Hardware Abstraction Layer for Cortex-M definitions
* Rev.: V4.79
*----------------------------------------------------------------------------
*
* Copyright (c) 1999-2009 KEIL, 2009-2017 ARM Germany GmbH. All rights reserved.
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the License); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an AS IS BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*---------------------------------------------------------------------------*/
/* Definitions */
#define INITIAL_xPSR 0x01000000U
#define DEMCR_TRCENA 0x01000000U
#define ITM_ITMENA 0x00000001U
#define MAGIC_WORD 0xE25A2EA5U
#define MAGIC_PATTERN 0xCCCCCCCCU
#if defined (__CC_ARM) /* ARM Compiler */
#if ((defined(__TARGET_ARCH_7_M) || defined(__TARGET_ARCH_7E_M)) && !defined(NO_EXCLUSIVE_ACCESS))
#define __USE_EXCLUSIVE_ACCESS
#else
#undef __USE_EXCLUSIVE_ACCESS
#endif
#ifndef __CMSIS_GENERIC
#define __DMB() do {\
__schedule_barrier();\
__dmb(0xF);\
__schedule_barrier();\
} while (0)
#endif
#elif defined (__GNUC__) /* GNU Compiler */
#undef __USE_EXCLUSIVE_ACCESS
#if defined (__CORTEX_M0)
#define __TARGET_ARCH_6S_M
#endif
#if defined (__VFP_FP__) && !defined(__SOFTFP__)
#define __TARGET_FPU_VFP
#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);
}
__attribute__((always_inline)) static inline void __DMB(void)
{
__asm volatile ("dmb 0xF":::"memory");
}
#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
#endif
#if defined __ARMVFP__
#define __TARGET_FPU_VFP 1
#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 *)0xE000E010U))
#define NVIC_ST_RELOAD (*((volatile U32 *)0xE000E014U))
#define NVIC_ST_CURRENT (*((volatile U32 *)0xE000E018U))
#define NVIC_ISER ((volatile U32 *)0xE000E100U)
#define NVIC_ICER ((volatile U32 *)0xE000E180U)
#if defined(__TARGET_ARCH_6S_M)
#define NVIC_IP ((volatile U32 *)0xE000E400U)
#else
#define NVIC_IP ((volatile U8 *)0xE000E400U)
#endif
#define NVIC_INT_CTRL (*((volatile U32 *)0xE000ED04U))
#define NVIC_AIR_CTRL (*((volatile U32 *)0xE000ED0CU))
#define NVIC_SYS_PRI2 (*((volatile U32 *)0xE000ED1CU))
#define NVIC_SYS_PRI3 (*((volatile U32 *)0xE000ED20U))
#define OS_PEND_IRQ() NVIC_INT_CTRL = (1UL<<28)
#define OS_PENDING ((NVIC_INT_CTRL >> 26) & 5U)
#define OS_UNPEND(fl) NVIC_INT_CTRL = (U32)(fl = (U8)OS_PENDING) << 25
#define OS_PEND(fl,p) NVIC_INT_CTRL = (U32)(fl | (U8)(p<<2)) << 26
#define OS_LOCK() NVIC_ST_CTRL = 0x0005U
#define OS_UNLOCK() NVIC_ST_CTRL = 0x0007U
#define OS_X_PENDING ((NVIC_INT_CTRL >> 28) & 1U)
#define OS_X_UNPEND(fl) NVIC_INT_CTRL = (U32)(fl = (U8)OS_X_PENDING) << 27
#define OS_X_PEND(fl,p) NVIC_INT_CTRL = (U32)(fl | p) << 28
#if defined(__TARGET_ARCH_6S_M)
#define OS_X_INIT(n) NVIC_IP[n>>2] |= (U32)0xFFU << ((n & 0x03U) << 3); \
NVIC_ISER[n>>5] = (U32)1U << (n & 0x1FU)
#else
#define OS_X_INIT(n) NVIC_IP[n] = 0xFFU; \
NVIC_ISER[n>>5] = (U32)1U << (n & 0x1FU)
#endif
#define OS_X_LOCK(n) NVIC_ICER[n>>5] = (U32)1U << (n & 0x1FU)
#define OS_X_UNLOCK(n) NVIC_ISER[n>>5] = (U32)1U << (n & 0x1FU)
/* Core Debug registers */
#define DEMCR (*((volatile U32 *)0xE000EDFCU))
/* ITM registers */
#define ITM_CONTROL (*((volatile U32 *)0xE0000E80U))
#define ITM_ENABLE (*((volatile U32 *)0xE0000E00U))
#define ITM_PORT30_U32 (*((volatile U32 *)0xE0000078U))
#define ITM_PORT31_U32 (*((volatile U32 *)0xE000007CU))
#define ITM_PORT31_U16 (*((volatile U16 *)0xE000007CU))
#define ITM_PORT31_U8 (*((volatile U8 *)0xE000007CU))
/* Variables */
extern BIT dbg_msg;
/* Functions */
#ifdef __USE_EXCLUSIVE_ACCESS
#define rt_inc(p) while(__strex((__ldrex(p)+1U),p))
#define rt_dec(p) while(__strex((__ldrex(p)-1U),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+1U, count));
do {
c2 = (cnt = __ldrex(first)) + 1U;
if (c2 == size) { c2 = 0U; }
} while (__strex(c2, first));
#else
__disable_irq();
if ((cnt = *count) < size) {
*count = (U8)(cnt+1U);
c2 = (cnt = *first) + 1U;
if (c2 == size) { c2 = 0U; }
*first = (U8)c2;
}
__enable_irq ();
#endif
return (cnt);
}
__inline static void rt_systick_init (void) {
NVIC_ST_RELOAD = os_trv;
NVIC_ST_CURRENT = 0U;
NVIC_ST_CTRL = 0x0007U;
NVIC_SYS_PRI3 |= 0xFF000000U;
}
__inline static U32 rt_systick_val (void) {
return (os_trv - NVIC_ST_CURRENT);
}
__inline static U32 rt_systick_ovf (void) {
return ((NVIC_INT_CTRL >> 26) & 1U);
}
__inline static void rt_svc_init (void) {
#if !defined(__TARGET_ARCH_6S_M)
U32 sh,prigroup;
#endif
NVIC_SYS_PRI3 |= 0x00FF0000U;
#if defined(__TARGET_ARCH_6S_M)
NVIC_SYS_PRI2 |= (NVIC_SYS_PRI3<<(8+1)) & 0xFC000000U;
#else
sh = 8U - __clz(~((NVIC_SYS_PRI3 << 8) & 0xFF000000U));
prigroup = ((NVIC_AIR_CTRL >> 8) & 0x07U);
if (prigroup >= sh) {
sh = prigroup + 1U;
}
NVIC_SYS_PRI2 = ((0xFEFFFFFFU << sh) & 0xFF000000U) | (NVIC_SYS_PRI2 & 0x00FFFFFFU);
#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 U32 _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.next!=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
*---------------------------------------------------------------------------*/

View File

@ -0,0 +1,309 @@
/*----------------------------------------------------------------------------
* CMSIS-RTOS - RTX
*----------------------------------------------------------------------------
* Name: RT_LIST.C
* Purpose: Functions for the management of different lists
* Rev.: V4.79
*----------------------------------------------------------------------------
*
* Copyright (c) 1999-2009 KEIL, 2009-2017 ARM Germany GmbH. All rights reserved.
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the License); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an AS IS BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*---------------------------------------------------------------------------*/
#include "rt_TypeDef.h"
#include "RTX_Config.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 = 0U;
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 = 0U;
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 == 0U) && (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 = 0U;
}
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
*---------------------------------------------------------------------------*/

View File

@ -0,0 +1,56 @@
/*----------------------------------------------------------------------------
* CMSIS-RTOS - RTX
*----------------------------------------------------------------------------
* Name: RT_LIST.H
* Purpose: Functions for the management of different lists
* Rev.: V4.79
*----------------------------------------------------------------------------
*
* Copyright (c) 1999-2009 KEIL, 2009-2017 ARM Germany GmbH. All rights reserved.
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the License); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an AS IS BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*---------------------------------------------------------------------------*/
/* Definitions */
/* Values for 'cb_type' */
#define TCB 0U
#define MCB 1U
#define SCB 2U
#define MUCB 3U
#define HCB 4U
/* 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
*---------------------------------------------------------------------------*/

View File

@ -0,0 +1,284 @@
/*----------------------------------------------------------------------------
* CMSIS-RTOS - RTX
*----------------------------------------------------------------------------
* Name: RT_MAILBOX.C
* Purpose: Implements waits and wake-ups for mailbox messages
* Rev.: V4.81
*----------------------------------------------------------------------------
*
* Copyright (c) 1999-2009 KEIL, 2009-2017 ARM Germany GmbH. All rights reserved.
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the License); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an AS IS BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*---------------------------------------------------------------------------*/
#include "rt_TypeDef.h"
#include "RTX_Config.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 = 0U;
p_MCB->isr_st = 0U;
p_MCB->p_lnk = NULL;
p_MCB->first = 0U;
p_MCB->last = 0U;
p_MCB->count = 0U;
p_MCB->size = (U16)((mbx_size - (sizeof(struct OS_MCB) - (sizeof(void *))))
/ 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 == 1U)) {
/* A task is waiting for message */
p_TCB = rt_get_first ((P_XCB)p_MCB);
#ifdef __CMSIS_RTOS
rt_ret_val2(p_TCB, 0x10U/*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 == 0U) {
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 = 2U;
}
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 = 0U;
}
}
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 = 0U;
}
if ((p_MCB->p_lnk != NULL) && (p_MCB->state == 2U)) {
/* A task is waiting to send message */
p_TCB = rt_get_first ((P_XCB)p_MCB);
#ifdef __CMSIS_RTOS
rt_ret_val(p_TCB, 0U/*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 = 0U;
}
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 == 0U) {
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 = 1U;
}
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 ((U32)(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->p_lnk != NULL) && (p_MCB->state == 2U)) {
/* A task is locked waiting to send message */
rt_psq_enq (p_MCB, 0U);
rt_psh_req ();
}
rt_dec (&p_MCB->count);
if (++p_MCB->last == p_MCB->size) {
p_MCB->last = 0U;
}
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, 0U/*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 = 0U;
}
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, 0x10U/*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;
default:
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 = 0U;
}
}
else {
os_error (OS_ERR_MBX_OVF);
}
}
}
/*----------------------------------------------------------------------------
* end of file
*---------------------------------------------------------------------------*/

View File

@ -0,0 +1,37 @@
/*----------------------------------------------------------------------------
* CMSIS-RTOS - RTX
*----------------------------------------------------------------------------
* Name: RT_MAILBOX.H
* Purpose: Implements waits and wake-ups for mailbox messages
* Rev.: V4.70
*----------------------------------------------------------------------------
*
* Copyright (c) 1999-2009 KEIL, 2009-2017 ARM Germany GmbH. All rights reserved.
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the License); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an AS IS BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*---------------------------------------------------------------------------*/
/* 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
*---------------------------------------------------------------------------*/

View File

@ -0,0 +1,159 @@
/*----------------------------------------------------------------------------
* CMSIS-RTOS - RTX
*----------------------------------------------------------------------------
* Name: RT_MEMBOX.C
* Purpose: Interface functions for fixed memory block management system
* Rev.: V4.79
*----------------------------------------------------------------------------
*
* Copyright (c) 1999-2009 KEIL, 2009-2017 ARM Germany GmbH. All rights reserved.
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the License); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an AS IS BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*---------------------------------------------------------------------------*/
#include "rt_TypeDef.h"
#include "RTX_Config.h"
#include "rt_System.h"
#include "rt_MemBox.h"
#include "rt_HAL_CM.h"
/*----------------------------------------------------------------------------
* Global Functions
*---------------------------------------------------------------------------*/
/*--------------------------- _init_box -------------------------------------*/
U32 _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) + 7U) & ~(U32)7U;
sizeof_bm = (sizeof (struct OS_BM) + 7U) & ~(U32)7U;
}
else {
/* Memory blocks 4-byte aligned. */
blk_size = (blk_size + 3U) & ~(U32)3U;
sizeof_bm = sizeof (struct OS_BM);
}
if (blk_size == 0U) {
return (1U);
}
if ((blk_size + sizeof_bm) > box_size) {
return (1U);
}
/* 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) = 0U;
return (0U);
}
/*--------------------------- rt_alloc_box ----------------------------------*/
void *rt_alloc_box (void *box_mem) {
/* Allocate a memory block and return start address. */
void **free;
#ifndef __USE_EXCLUSIVE_ACCESS
U32 irq_mask;
irq_mask = (U32)__disable_irq ();
free = ((P_BM) box_mem)->free;
if (free) {
((P_BM) box_mem)->free = *free;
}
if (irq_mask == 0U) { __enable_irq (); }
#else
do {
if ((free = (void **)__ldrex(&((P_BM) box_mem)->free)) == 0U) {
__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 -= 4U) {
*p = 0U;
p++;
}
}
return (free);
}
/*--------------------------- rt_free_box -----------------------------------*/
U32 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
U32 irq_mask;
#endif
if ((box < box_mem) || (box >= ((P_BM) box_mem)->end)) {
return (1U);
}
#ifndef __USE_EXCLUSIVE_ACCESS
irq_mask = (U32)__disable_irq ();
*((void **)box) = ((P_BM) box_mem)->free;
((P_BM) box_mem)->free = box;
if (irq_mask == 0U) { __enable_irq (); }
#else
do {
do {
*((void **)box) = ((P_BM) box_mem)->free;
__DMB();
} while (*(void**)box != (void *)__ldrex(&((P_BM) box_mem)->free));
} while (__strex ((U32)box, &((P_BM) box_mem)->free));
#endif
return (0U);
}
/*----------------------------------------------------------------------------
* end of file
*---------------------------------------------------------------------------*/

View File

@ -0,0 +1,36 @@
/*----------------------------------------------------------------------------
* CMSIS-RTOS - RTX
*----------------------------------------------------------------------------
* Name: RT_MEMBOX.H
* Purpose: Interface functions for fixed memory block management system
* Rev.: V4.79
*----------------------------------------------------------------------------
*
* Copyright (c) 1999-2009 KEIL, 2009-2017 ARM Germany GmbH. All rights reserved.
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the License); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an AS IS BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*---------------------------------------------------------------------------*/
/* Functions */
#define rt_init_box _init_box
#define rt_calloc_box _calloc_box
extern U32 _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 U32 rt_free_box (void *box_mem, void *box);
/*----------------------------------------------------------------------------
* end of file
*---------------------------------------------------------------------------*/

View File

@ -0,0 +1,131 @@
/*----------------------------------------------------------------------------
* CMSIS-RTOS - RTX
*----------------------------------------------------------------------------
* Name: RT_MEMORY.C
* Purpose: Interface functions for Dynamic Memory Management System
* Rev.: V4.79
*----------------------------------------------------------------------------
*
* Copyright (c) 1999-2009 KEIL, 2009-2017 ARM Germany GmbH. All rights reserved.
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the License); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an AS IS BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*---------------------------------------------------------------------------*/
#include "rt_TypeDef.h"
#include "rt_Memory.h"
/* Functions */
// Initialize Dynamic Memory pool
// Parameters:
// pool: Pointer to memory pool
// size: Size of memory pool in bytes
// Return: 0 - OK, 1 - Error
U32 rt_init_mem (void *pool, U32 size) {
MEMP *ptr;
if ((pool == NULL) || (size < sizeof(MEMP))) { return (1U); }
ptr = (MEMP *)pool;
ptr->next = (MEMP *)((U32)pool + size - sizeof(MEMP *));
ptr->next->next = NULL;
ptr->len = 0U;
return (0U);
}
// Allocate Memory from Memory pool
// Parameters:
// pool: Pointer to memory pool
// size: Size of memory in bytes to allocate
// Return: Pointer to allocated memory
void *rt_alloc_mem (void *pool, U32 size) {
MEMP *p, *p_search, *p_new;
U32 hole_size;
if ((pool == NULL) || (size == 0U)) { return NULL; }
/* Add header offset to 'size' */
size += sizeof(MEMP);
/* Make sure that block is 4-byte aligned */
size = (size + 3U) & ~(U32)3U;
p_search = (MEMP *)pool;
while (1) {
hole_size = (U32)p_search->next - (U32)p_search;
hole_size -= p_search->len;
/* Check if hole size is big enough */
if (hole_size >= size) { break; }
p_search = p_search->next;
if (p_search->next == NULL) {
/* Failed, we are at the end of the list */
return NULL;
}
}
if (p_search->len == 0U) {
/* No block is allocated, set the Length of the first element */
p_search->len = size;
p = (MEMP *)(((U32)p_search) + sizeof(MEMP));
} else {
/* Insert new list element into the memory list */
p_new = (MEMP *)((U32)p_search + p_search->len);
p_new->next = p_search->next;
p_new->len = size;
p_search->next = p_new;
p = (MEMP *)(((U32)p_new) + sizeof(MEMP));
}
return (p);
}
// Free Memory and return it to Memory pool
// Parameters:
// pool: Pointer to memory pool
// mem: Pointer to memory to free
// Return: 0 - OK, 1 - Error
U32 rt_free_mem (void *pool, void *mem) {
MEMP *p_search, *p_prev, *p_return;
if ((pool == NULL) || (mem == NULL)) { return (1U); }
p_return = (MEMP *)((U32)mem - sizeof(MEMP));
/* Set list header */
p_prev = NULL;
p_search = (MEMP *)pool;
while (p_search != p_return) {
p_prev = p_search;
p_search = p_search->next;
if (p_search == NULL) {
/* Valid Memory block not found */
return (1U);
}
}
if (p_prev == NULL) {
/* First block to be released, only set length to 0 */
p_search->len = 0U;
} else {
/* Discard block from chain list */
p_prev->next = p_search->next;
}
return (0U);
}

View File

@ -0,0 +1,35 @@
/*----------------------------------------------------------------------------
* CMSIS-RTOS - RTX
*----------------------------------------------------------------------------
* Name: RT_MEMORY.H
* Purpose: Interface functions for Dynamic Memory Management System
* Rev.: V4.79
*----------------------------------------------------------------------------
*
* Copyright (c) 1999-2009 KEIL, 2009-2017 ARM Germany GmbH. All rights reserved.
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the License); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an AS IS BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*---------------------------------------------------------------------------*/
/* Types */
typedef struct mem { /* << Memory Pool management struct >> */
struct mem *next; /* Next Memory Block in the list */
U32 len; /* Length of data block */
} MEMP;
/* Functions */
extern U32 rt_init_mem (void *pool, U32 size);
extern void *rt_alloc_mem (void *pool, U32 size);
extern U32 rt_free_mem (void *pool, void *mem);

View File

@ -0,0 +1,252 @@
/*----------------------------------------------------------------------------
* CMSIS-RTOS - RTX
*----------------------------------------------------------------------------
* Name: RT_MUTEX.C
* Purpose: Implements mutex synchronization objects
* Rev.: V4.82
*----------------------------------------------------------------------------
*
* Copyright (c) 1999-2009 KEIL, 2009-2017 ARM Germany GmbH. All rights reserved.
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the License); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an AS IS BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*---------------------------------------------------------------------------*/
#include "rt_TypeDef.h"
#include "RTX_Config.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->level = 0U;
p_MCB->p_lnk = NULL;
p_MCB->owner = NULL;
p_MCB->p_mlnk = 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;
P_MUCB p_mlnk;
U8 prio;
if (p_MCB->level != 0U) {
p_TCB = p_MCB->owner;
/* Remove mutex from task mutex owner list. */
p_mlnk = p_TCB->p_mlnk;
if (p_mlnk == p_MCB) {
p_TCB->p_mlnk = p_MCB->p_mlnk;
}
else {
while (p_mlnk) {
if (p_mlnk->p_mlnk == p_MCB) {
p_mlnk->p_mlnk = p_MCB->p_mlnk;
break;
}
p_mlnk = p_mlnk->p_mlnk;
}
}
/* Restore owner task's priority. */
prio = p_TCB->prio_base;
p_mlnk = p_TCB->p_mlnk;
while (p_mlnk) {
if ((p_mlnk->p_lnk != NULL) && (p_mlnk->p_lnk->prio > prio)) {
/* A task with higher priority is waiting for mutex. */
prio = p_mlnk->p_lnk->prio;
}
p_mlnk = p_mlnk->p_mlnk;
}
if (p_TCB->prio != prio) {
p_TCB->prio = prio;
if (p_TCB != os_tsk.run) {
rt_resort_prio (p_TCB);
}
}
}
while (p_MCB->p_lnk != NULL) {
/* A task is waiting for mutex. */
p_TCB = rt_get_first ((P_XCB)p_MCB);
rt_ret_val(p_TCB, 0U/*osOK*/);
rt_rmv_dly(p_TCB);
p_TCB->state = READY;
rt_put_prio (&os_rdy, p_TCB);
}
if ((os_rdy.p_lnk != NULL) && (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 = 0U;
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;
P_MUCB p_mlnk;
U8 prio;
if ((p_MCB->level == 0U) || (p_MCB->owner != os_tsk.run)) {
/* Unbalanced mutex release or task is not the owner */
return (OS_R_NOK);
}
if (--p_MCB->level != 0U) {
return (OS_R_OK);
}
/* Remove mutex from task mutex owner list. */
p_mlnk = os_tsk.run->p_mlnk;
if (p_mlnk == p_MCB) {
os_tsk.run->p_mlnk = p_MCB->p_mlnk;
}
else {
while (p_mlnk) {
if (p_mlnk->p_mlnk == p_MCB) {
p_mlnk->p_mlnk = p_MCB->p_mlnk;
break;
}
p_mlnk = p_mlnk->p_mlnk;
}
}
/* Restore owner task's priority. */
prio = os_tsk.run->prio_base;
p_mlnk = os_tsk.run->p_mlnk;
while (p_mlnk) {
if ((p_mlnk->p_lnk != NULL) && (p_mlnk->p_lnk->prio > prio)) {
/* A task with higher priority is waiting for mutex. */
prio = p_mlnk->p_lnk->prio;
}
p_mlnk = p_mlnk->p_mlnk;
}
os_tsk.run->prio = prio;
if (p_MCB->p_lnk != NULL) {
/* A task is waiting for mutex. */
p_TCB = rt_get_first ((P_XCB)p_MCB);
#ifdef __CMSIS_RTOS
rt_ret_val(p_TCB, 0U/*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 = 1U;
p_MCB->owner = p_TCB;
p_MCB->p_mlnk = p_TCB->p_mlnk;
p_TCB->p_mlnk = p_MCB;
/* Priority inversion, check which task continues. */
if (os_tsk.run->prio >= rt_rdy_prio()) {
rt_dispatch (p_TCB);
}
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 lowered by priority inversion. */
if (rt_rdy_prio() > os_tsk.run->prio) {
rt_put_prio (&os_rdy, os_tsk.run);
os_tsk.run->state = READY;
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 == 0U) {
p_MCB->owner = os_tsk.run;
p_MCB->p_mlnk = os_tsk.run->p_mlnk;
os_tsk.run->p_mlnk = p_MCB;
p_MCB->level = 1U;
return (OS_R_OK);
}
if (p_MCB->owner == os_tsk.run) {
/* OK, running task is the owner of this mutex. */
if (p_MCB->level == 0xFFFFU) {
return (OS_R_NOK);
}
p_MCB->level++;
return (OS_R_OK);
}
/* Mutex owned by another task, wait until released. */
if (timeout == 0U) {
return (OS_R_TMO);
}
/* Raise the owner task priority if lower than current priority. */
/* This priority inversion is called priority inheritance. */
if (p_MCB->owner->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
*---------------------------------------------------------------------------*/

View File

@ -0,0 +1,34 @@
/*----------------------------------------------------------------------------
* CMSIS-RTOS - RTX
*----------------------------------------------------------------------------
* Name: RT_MUTEX.H
* Purpose: Implements mutex synchronization objects
* Rev.: V4.70
*----------------------------------------------------------------------------
*
* Copyright (c) 1999-2009 KEIL, 2009-2017 ARM Germany GmbH. All rights reserved.
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the License); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an AS IS BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*---------------------------------------------------------------------------*/
/* 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
*---------------------------------------------------------------------------*/

View File

@ -0,0 +1,74 @@
/*----------------------------------------------------------------------------
* CMSIS-RTOS - RTX
*----------------------------------------------------------------------------
* Name: RT_ROBIN.C
* Purpose: Round Robin Task switching
* Rev.: V4.79
*----------------------------------------------------------------------------
*
* Copyright (c) 1999-2009 KEIL, 2009-2017 ARM Germany GmbH. All rights reserved.
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the License); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an AS IS BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*---------------------------------------------------------------------------*/
#include "rt_TypeDef.h"
#include "RTX_Config.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 - 1U;
}
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
*---------------------------------------------------------------------------*/

View File

@ -0,0 +1,35 @@
/*----------------------------------------------------------------------------
* CMSIS-RTOS - RTX
*----------------------------------------------------------------------------
* Name: RT_ROBIN.H
* Purpose: Round Robin Task switching definitions
* Rev.: V4.70
*----------------------------------------------------------------------------
*
* Copyright (c) 1999-2009 KEIL, 2009-2017 ARM Germany GmbH. All rights reserved.
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the License); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an AS IS BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*---------------------------------------------------------------------------*/
/* Variables */
extern struct OS_ROBIN os_robin;
/* Functions */
extern void rt_init_robin (void);
extern void rt_chk_robin (void);
/*----------------------------------------------------------------------------
* end of file
*---------------------------------------------------------------------------*/

View File

@ -0,0 +1,173 @@
/*----------------------------------------------------------------------------
* CMSIS-RTOS - RTX
*----------------------------------------------------------------------------
* Name: RT_SEMAPHORE.C
* Purpose: Implements binary and counting semaphores
* Rev.: V4.79
*----------------------------------------------------------------------------
*
* Copyright (c) 1999-2009 KEIL, 2009-2017 ARM Germany GmbH. All rights reserved.
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the License); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an AS IS BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*---------------------------------------------------------------------------*/
#include "rt_TypeDef.h"
#include "RTX_Config.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, 0U);
rt_rmv_dly(p_TCB);
p_TCB->state = READY;
rt_put_prio (&os_rdy, p_TCB);
}
if ((os_rdy.p_lnk != NULL) && (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 = 0U;
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, 1U);
#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 == 0U) {
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, 0U);
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, 1U);
#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
*---------------------------------------------------------------------------*/

View File

@ -0,0 +1,36 @@
/*----------------------------------------------------------------------------
* CMSIS-RTOS - RTX
*----------------------------------------------------------------------------
* Name: RT_SEMAPHORE.H
* Purpose: Implements binary and counting semaphores
* Rev.: V4.70
*----------------------------------------------------------------------------
*
* Copyright (c) 1999-2009 KEIL, 2009-2017 ARM Germany GmbH. All rights reserved.
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the License); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an AS IS BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*---------------------------------------------------------------------------*/
/* 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
*---------------------------------------------------------------------------*/

View File

@ -0,0 +1,316 @@
/*----------------------------------------------------------------------------
* CMSIS-RTOS - RTX
*----------------------------------------------------------------------------
* Name: RT_SYSTEM.C
* Purpose: System Task Manager
* Rev.: V4.82
*----------------------------------------------------------------------------
*
* Copyright (c) 1999-2009 KEIL, 2009-2017 ARM Germany GmbH. All rights reserved.
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the License); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an AS IS BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*---------------------------------------------------------------------------*/
#include "rt_TypeDef.h"
#include "RTX_Config.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_Timer.h"
#include "rt_Robin.h"
#include "rt_HAL_CM.h"
/*----------------------------------------------------------------------------
* Global Variables
*---------------------------------------------------------------------------*/
S32 os_tick_irqn;
/*----------------------------------------------------------------------------
* Local Variables
*---------------------------------------------------------------------------*/
static volatile BIT os_lock;
static volatile BIT os_psh_flag;
static U8 pend_flags;
/*----------------------------------------------------------------------------
* Global Functions
*---------------------------------------------------------------------------*/
#define RL_RTX_VER 0x482
#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 RL_RTX_VER
}
#endif
/*--------------------------- rt_suspend ------------------------------------*/
extern U32 sysUserTimerWakeupTime(void);
U32 rt_suspend (void) {
/* Suspend OS scheduler */
U32 delta = 0xFFFFU;
#ifdef __CMSIS_RTOS
U32 sleep;
#endif
rt_tsk_lock();
if (os_dly.p_dlnk) {
delta = os_dly.delta_time;
}
#ifdef __CMSIS_RTOS
sleep = sysUserTimerWakeupTime();
if (sleep < delta) { delta = sleep; }
#else
if (os_tmr.next) {
if (os_tmr.tcnt < delta) delta = os_tmr.tcnt;
}
#endif
return (delta);
}
/*--------------------------- rt_resume -------------------------------------*/
extern void sysUserTimerUpdate (U32 sleep_time);
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 = 1U;
while (os_dly.p_dlnk) {
rt_dec_dly();
if (delta == 0U) { break; }
delta--;
os_time++;
}
} else {
os_time += delta;
os_dly.delta_time -= (U16)delta;
}
} else {
os_time += sleep_time;
}
/* Check the user timers. */
#ifdef __CMSIS_RTOS
sysUserTimerUpdate(sleep_time);
#else
if (os_tmr.next) {
delta = sleep_time;
if (delta >= os_tmr.tcnt) {
delta -= os_tmr.tcnt;
os_tmr.tcnt = 1U;
while (os_tmr.next) {
rt_tmr_tick();
if (delta == 0U) { 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((U32)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((U32)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 = 0U; }
rt_dec (&os_psq->count);
}
os_psq->last = (U8)idx;
next = rt_get_first (&os_rdy);
rt_switch_req (next);
}
/*--------------------------- os_tick_init ----------------------------------*/
__weak S32 os_tick_init (void) {
/* Initialize SysTick timer as system tick timer. */
rt_systick_init();
return (-1); /* Return IRQ number of SysTick timer */
}
/*--------------------------- os_tick_val -----------------------------------*/
__weak U32 os_tick_val (void) {
/* Get SysTick timer current value (0 .. OS_TRV). */
return rt_systick_val();
}
/*--------------------------- os_tick_ovf -----------------------------------*/
__weak U32 os_tick_ovf (void) {
/* Get SysTick timer overflow flag */
return rt_systick_ovf();
}
/*--------------------------- os_tick_irqack --------------------------------*/
__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->tsk_stack < (U32)os_tsk.run->stack) ||
(os_tsk.run->stack[0] != MAGIC_WORD)) {
os_error (OS_ERR_STK_OVF);
}
}
/*----------------------------------------------------------------------------
* end of file
*---------------------------------------------------------------------------*/

View File

@ -0,0 +1,42 @@
/*----------------------------------------------------------------------------
* CMSIS-RTOS - RTX
*----------------------------------------------------------------------------
* Name: RT_SYSTEM.H
* Purpose: System Task Manager definitions
* Rev.: V4.79
*----------------------------------------------------------------------------
*
* Copyright (c) 1999-2009 KEIL, 2009-2017 ARM Germany GmbH. All rights reserved.
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the License); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an AS IS BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*---------------------------------------------------------------------------*/
/* Variables */
#define os_psq ((P_PSQ)&os_fifo)
extern S32 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
*---------------------------------------------------------------------------*/

View File

@ -0,0 +1,437 @@
/*----------------------------------------------------------------------------
* CMSIS-RTOS - RTX
*----------------------------------------------------------------------------
* Name: RT_TASK.C
* Purpose: Task functions and system start up.
* Rev.: V4.80
*----------------------------------------------------------------------------
*
* Copyright (c) 1999-2009 KEIL, 2009-2017 ARM Germany GmbH. All rights reserved.
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the License); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an AS IS BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*---------------------------------------------------------------------------*/
#include "rt_TypeDef.h"
#include "RTX_Config.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
*---------------------------------------------------------------------------*/
static OS_TID rt_get_TID (void) {
U32 tid;
for (tid = 1U; tid <= os_maxtaskrun; tid++) {
if (os_active_TCB[tid-1U] == NULL) {
return ((OS_TID)tid);
}
}
return (0U);
}
/*--------------------------- rt_init_context -------------------------------*/
static 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->prio_base = priority;
p_TCB->p_lnk = NULL;
p_TCB->p_rlnk = NULL;
p_TCB->p_dlnk = NULL;
p_TCB->p_blnk = NULL;
p_TCB->p_mlnk = NULL;
p_TCB->delta_time = 0U;
p_TCB->interval_time = 0U;
p_TCB->events = 0U;
p_TCB->waits = 0U;
p_TCB->stack_frame = 0U;
if (p_TCB->priv_stack == 0U) {
/* Allocate the memory space for the stack. */
p_TCB->stack = rt_alloc_box (mp_stk);
}
rt_init_stack (p_TCB, task_body);
}
/*--------------------------- rt_switch_req ---------------------------------*/
void rt_switch_req (P_TCB p_next) {
/* Switch to next task (identified by "p_next"). */
os_tsk.next = p_next;
p_next->state = RUNNING;
DBG_TASK_SWITCH(p_next->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 < 0xFFFFU) {
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 (0U);
}
return ((OS_TID)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 == 0U) {
/* Change execution priority of calling task. */
os_tsk.run->prio = new_prio;
os_tsk.run->prio_base = new_prio;
run:if (rt_rdy_prio() > new_prio) {
rt_put_prio (&os_rdy, os_tsk.run);
os_tsk.run->state = READY;
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-1U] == NULL)) {
/* Task with "task_id" not found or not started. */
return (OS_R_NOK);
}
p_task = os_active_TCB[task_id-1U];
p_task->prio = new_prio;
p_task->prio_base = 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_create ---------------------------------*/
OS_TID rt_tsk_create (FUNCP task, U32 prio_stksz, void *stk, void *argv) {
/* Start a new task declared with "task". */
P_TCB task_context;
U32 i;
/* Priority 0 is reserved for idle task! */
if ((prio_stksz & 0xFFU) == 0U) {
prio_stksz += 1U;
}
task_context = rt_alloc_box (mp_tcb);
if (task_context == NULL) {
return (0U);
}
/* If "size != 0" use a private user provided stack. */
task_context->stack = stk;
task_context->priv_stack = (U16)(prio_stksz >> 8);
/* Pass parameter 'argv' to 'rt_init_context' */
task_context->msg = argv;
/* For 'size == 0' system allocates the user stack from the memory pool. */
rt_init_context (task_context, (U8)(prio_stksz & 0xFFU), task);
/* Find a free entry in 'os_active_TCB' table. */
i = rt_get_TID ();
if (i == 0U) {
return (0U);
}
os_active_TCB[i-1U] = task_context;
task_context->task_id = (U8)i;
DBG_TASK_NOTIFY(task_context, __TRUE);
rt_dispatch (task_context);
return ((OS_TID)i);
}
/*--------------------------- rt_tsk_delete ---------------------------------*/
OS_RESULT rt_tsk_delete (OS_TID task_id) {
/* Terminate the task identified with "task_id". */
P_TCB task_context;
P_TCB p_TCB;
P_MUCB p_MCB, p_MCB0;
if ((task_id == 0U) || (task_id == os_tsk.run->task_id)) {
/* Terminate itself. */
os_tsk.run->state = INACTIVE;
os_tsk.run->tsk_stack = rt_get_PSP ();
rt_stk_check ();
p_MCB = os_tsk.run->p_mlnk;
while (p_MCB) {
/* Release mutexes owned by this task */
if (p_MCB->p_lnk) {
/* A task is waiting for mutex. */
p_TCB = rt_get_first ((P_XCB)p_MCB);
#ifdef __CMSIS_RTOS
rt_ret_val (p_TCB, 0U/*osOK*/);
#else
rt_ret_val (p_TCB, OS_R_MUT);
#endif
rt_rmv_dly (p_TCB);
p_TCB->state = READY;
rt_put_prio (&os_rdy, p_TCB);
/* A waiting task becomes the owner of this mutex. */
p_MCB0 = p_MCB->p_mlnk;
p_MCB->level = 1U;
p_MCB->owner = p_TCB;
p_MCB->p_mlnk = p_TCB->p_mlnk;
p_TCB->p_mlnk = p_MCB;
p_MCB = p_MCB0;
}
else {
p_MCB0 = p_MCB->p_mlnk;
p_MCB->level = 0U;
p_MCB->owner = NULL;
p_MCB->p_mlnk = NULL;
p_MCB = p_MCB0;
}
}
os_active_TCB[os_tsk.run->task_id-1U] = NULL;
rt_free_box (mp_stk, os_tsk.run->stack);
os_tsk.run->stack = NULL;
DBG_TASK_NOTIFY(os_tsk.run, __FALSE);
rt_free_box (mp_tcb, os_tsk.run);
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-1U] == NULL)) {
/* Task with "task_id" not found or not started. */
return (OS_R_NOK);
}
task_context = os_active_TCB[task_id-1U];
rt_rmv_list (task_context);
rt_rmv_dly (task_context);
p_MCB = task_context->p_mlnk;
while (p_MCB) {
/* Release mutexes owned by this task */
if (p_MCB->p_lnk) {
/* A task is waiting for mutex. */
p_TCB = rt_get_first ((P_XCB)p_MCB);
#ifdef __CMSIS_RTOS
rt_ret_val (p_TCB, 0U/*osOK*/);
#else
rt_ret_val (p_TCB, OS_R_MUT);
#endif
rt_rmv_dly (p_TCB);
p_TCB->state = READY;
rt_put_prio (&os_rdy, p_TCB);
/* A waiting task becomes the owner of this mutex. */
p_MCB0 = p_MCB->p_mlnk;
p_MCB->level = 1U;
p_MCB->owner = p_TCB;
p_MCB->p_mlnk = p_TCB->p_mlnk;
p_TCB->p_mlnk = p_MCB;
p_MCB = p_MCB0;
}
else {
p_MCB0 = p_MCB->p_mlnk;
p_MCB->level = 0U;
p_MCB->owner = NULL;
p_MCB->p_mlnk = NULL;
p_MCB = p_MCB0;
}
}
os_active_TCB[task_id-1U] = NULL;
rt_free_box (mp_stk, task_context->stack);
task_context->stack = NULL;
DBG_TASK_NOTIFY(task_context, __FALSE);
rt_free_box (mp_tcb, task_context);
if (rt_rdy_prio() > os_tsk.run->prio) {
/* Ready task has higher priority than running task. */
os_tsk.run->state = READY;
rt_put_prio (&os_rdy, os_tsk.run);
rt_dispatch (NULL);
}
}
return (OS_R_OK);
}
/*--------------------------- 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 = 0U; i < os_maxtaskrun; i++) {
os_active_TCB[i] = NULL;
}
rt_init_box (mp_tcb, (U32)mp_tcb_size, sizeof(struct OS_TCB));
rt_init_box (mp_stk, mp_stk_size, BOX_ALIGN_8 | (U16)(os_stackinfo));
rt_init_box ((U32 *)m_tmr, (U32)mp_tmr_size, sizeof(struct OS_TMR));
/* Set up TCB of idle demon */
os_idle_TCB.task_id = 255U;
os_idle_TCB.priv_stack = 0U;
rt_init_context (&os_idle_TCB, 0U, 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 = 0U;
/* Fix SP and system variables 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+32U);
#endif
os_tsk.run = &os_idle_TCB;
os_tsk.run->state = RUNNING;
/* Initialize ps queue */
os_psq->first = 0U;
os_psq->last = 0U;
os_psq->size = os_fifo_size;
rt_init_robin ();
#ifndef __CMSIS_RTOS
/* Initialize SVC and PendSV */
rt_svc_init ();
/* Initialize and start system clock timer */
os_tick_irqn = os_tick_init ();
if (os_tick_irqn >= 0) {
OS_X_INIT((U32)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 */
/* Initialize SVC and PendSV */
rt_svc_init ();
/* Initialize and start system clock timer */
os_tick_irqn = os_tick_init ();
if (os_tick_irqn >= 0) {
OS_X_INIT((U32)os_tick_irqn);
}
}
#endif
/*----------------------------------------------------------------------------
* end of file
*---------------------------------------------------------------------------*/

View File

@ -0,0 +1,72 @@
/*----------------------------------------------------------------------------
* CMSIS-RTOS - RTX
*----------------------------------------------------------------------------
* Name: RT_TASK.H
* Purpose: Task functions and system start up.
* Rev.: V4.79
*----------------------------------------------------------------------------
*
* Copyright (c) 1999-2009 KEIL, 2009-2017 ARM Germany GmbH. All rights reserved.
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the License); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an AS IS BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*---------------------------------------------------------------------------*/
/* Definitions */
/* Values for 'state' */
#define INACTIVE 0U
#define READY 1U
#define RUNNING 2U
#define WAIT_DLY 3U
#define WAIT_ITV 4U
#define WAIT_OR 5U
#define WAIT_AND 6U
#define WAIT_SEM 7U
#define WAIT_MBX 8U
#define WAIT_MUT 9U
/* Return codes */
#define OS_R_TMO 0x01U
#define OS_R_EVT 0x02U
#define OS_R_SEM 0x03U
#define OS_R_MBX 0x04U
#define OS_R_MUT 0x05U
#define OS_R_OK 0x00U
#define OS_R_NOK 0xFFU
/* Variables */
extern struct OS_TSK os_tsk;
extern struct OS_TCB os_idle_TCB;
/* Functions */
extern void rt_switch_req (P_TCB p_next);
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_TID rt_tsk_create (FUNCP task, U32 prio_stksz, void *stk, void *argv);
extern OS_RESULT rt_tsk_delete (OS_TID task_id);
#ifdef __CMSIS_RTOS
extern void rt_sys_init (void);
extern void rt_sys_start (void);
#else
extern void rt_sys_init (FUNCP first_task, U32 prio_stksz, void *stk);
#endif
/*----------------------------------------------------------------------------
* end of file
*---------------------------------------------------------------------------*/

View File

@ -0,0 +1,84 @@
/*----------------------------------------------------------------------------
* CMSIS-RTOS - RTX
*----------------------------------------------------------------------------
* Name: RT_TIME.C
* Purpose: Delay and interval wait functions
* Rev.: V4.79
*----------------------------------------------------------------------------
*
* Copyright (c) 1999-2009 KEIL, 2009-2017 ARM Germany GmbH. All rights reserved.
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the License); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an AS IS BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*---------------------------------------------------------------------------*/
#include "rt_TypeDef.h"
#include "RTX_Config.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 & 0x8000U) == 0U) {
rt_block (delta, WAIT_ITV);
}
}
/*----------------------------------------------------------------------------
* end of file
*---------------------------------------------------------------------------*/

View File

@ -0,0 +1,37 @@
/*----------------------------------------------------------------------------
* CMSIS-RTOS - RTX
*----------------------------------------------------------------------------
* Name: RT_TIME.H
* Purpose: Delay and interval wait functions definitions
* Rev.: V4.70
*----------------------------------------------------------------------------
*
* Copyright (c) 1999-2009 KEIL, 2009-2017 ARM Germany GmbH. All rights reserved.
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the License); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an AS IS BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*---------------------------------------------------------------------------*/
/* 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
*---------------------------------------------------------------------------*/

View File

@ -0,0 +1,125 @@
/*----------------------------------------------------------------------------
* CMSIS-RTOS - RTX
*----------------------------------------------------------------------------
* Name: RT_TIMER.C
* Purpose: User timer functions
* Rev.: V4.70
*----------------------------------------------------------------------------
*
* Copyright (c) 1999-2009 KEIL, 2009-2017 ARM Germany GmbH. All rights reserved.
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the License); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an AS IS BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*---------------------------------------------------------------------------*/
#include "rt_TypeDef.h"
#include "RTX_Config.h"
#include "rt_Timer.h"
#include "rt_MemBox.h"
#ifndef __CMSIS_RTOS
/*----------------------------------------------------------------------------
* Global Variables
*---------------------------------------------------------------------------*/
/* User Timer list pointer */
struct OS_XTMR os_tmr;
/*----------------------------------------------------------------------------
* Functions
*---------------------------------------------------------------------------*/
/*--------------------------- rt_tmr_tick -----------------------------------*/
void rt_tmr_tick (void) {
/* Decrement delta count of timer list head. Timers having the value of */
/* zero are removed from the list and the callback function is called. */
P_TMR p;
if (os_tmr.next == NULL) {
return;
}
os_tmr.tcnt--;
while ((os_tmr.tcnt == 0U) && ((p = os_tmr.next) != NULL)) {
/* Call a user provided function to handle an elapsed timer */
os_tmr_call (p->info);
os_tmr.tcnt = p->tcnt;
os_tmr.next = p->next;
rt_free_box ((U32 *)m_tmr, p);
}
}
/*--------------------------- rt_tmr_create ---------------------------------*/
OS_ID rt_tmr_create (U16 tcnt, U16 info) {
/* Create an user timer and put it into the chained timer list using */
/* a timeout count value of "tcnt". User parameter "info" is used as a */
/* parameter for the user provided callback function "os_tmr_call ()". */
P_TMR p_tmr, p;
U32 delta,itcnt = tcnt;
if ((tcnt == 0U) || (m_tmr == NULL)) {
return (NULL);
}
p_tmr = rt_alloc_box ((U32 *)m_tmr);
if (!p_tmr) {
return (NULL);
}
p_tmr->info = info;
p = (P_TMR)&os_tmr;
delta = p->tcnt;
while ((delta < itcnt) && (p->next != NULL)) {
p = p->next;
delta += p->tcnt;
}
/* Right place found, insert timer into the list */
p_tmr->next = p->next;
p_tmr->tcnt = (U16)(delta - itcnt);
p->next = p_tmr;
p->tcnt -= p_tmr->tcnt;
return (p_tmr);
}
/*--------------------------- rt_tmr_kill -----------------------------------*/
OS_ID rt_tmr_kill (OS_ID timer) {
/* Remove user timer from the chained timer list. */
P_TMR p, p_tmr;
p_tmr = (P_TMR)timer;
p = (P_TMR)&os_tmr;
/* Search timer list for requested timer */
while (p->next != p_tmr) {
if (p->next == NULL) {
/* Failed, "timer" is not in the timer list */
return (p_tmr);
}
p = p->next;
}
/* Timer was found, remove it from the list */
p->next = p_tmr->next;
p->tcnt += p_tmr->tcnt;
rt_free_box ((U32 *)m_tmr, p_tmr);
/* Timer killed */
return (NULL);
}
#endif
/*----------------------------------------------------------------------------
* end of file
*---------------------------------------------------------------------------*/

View File

@ -0,0 +1,36 @@
/*----------------------------------------------------------------------------
* CMSIS-RTOS - RTX
*----------------------------------------------------------------------------
* Name: RT_TIMER.H
* Purpose: User timer functions
* Rev.: V4.70
*----------------------------------------------------------------------------
*
* Copyright (c) 1999-2009 KEIL, 2009-2017 ARM Germany GmbH. All rights reserved.
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the License); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an AS IS BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*---------------------------------------------------------------------------*/
/* Variables */
extern struct OS_XTMR os_tmr;
/* Functions */
extern void rt_tmr_tick (void);
extern OS_ID rt_tmr_create (U16 tcnt, U16 info);
extern OS_ID rt_tmr_kill (OS_ID timer);
/*----------------------------------------------------------------------------
* end of file
*---------------------------------------------------------------------------*/

View File

@ -0,0 +1,158 @@
/*----------------------------------------------------------------------------
* CMSIS-RTOS - RTX
*----------------------------------------------------------------------------
* Name: RT_TYPEDEF.H
* Purpose: Type Definitions
* Rev.: V4.79
*----------------------------------------------------------------------------
*
* Copyright (c) 1999-2009 KEIL, 2009-2017 ARM Germany GmbH. All rights reserved.
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the License); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an AS IS BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*---------------------------------------------------------------------------*/
/* 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 U32 OS_TID;
typedef void *OS_ID;
typedef U32 OS_RESULT;
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 */
struct OS_MUCB *p_mlnk; /* Link pointer for mutex owner list */
U8 prio_base; /* Base priority */
/* Hardware dependant part: specific for CM processor */
U8 stack_frame; /* Stack frame: 0=Basic, 1=Extended, */
/* (2=VFP/D16 stacked, 4=NEON/D32 stacked) */
U16 priv_stack; /* Private stack size, 0= system assigned */
U32 tsk_stack; /* Current task Stack pointer (R13) */
U32 *stack; /* Pointer to Task Stack memory block */
/* Task entry point used for uVision debugger */
FUNCP ptask; /* Task entry address */
} *P_TCB;
#define TCB_STACKF 37 /* '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 next; /* 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 */
U16 level; /* Call nesting level */
struct OS_TCB *p_lnk; /* Chain of tasks waiting for mutex */
struct OS_TCB *owner; /* Mutex owner task */
struct OS_MUCB *p_mlnk; /* Chain of mutexes by owner task */
} *P_MUCB;
typedef struct OS_XTMR {
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 1U
#define __FALSE 0U
#define NULL ((void *) 0)
/*----------------------------------------------------------------------------
* end of file
*---------------------------------------------------------------------------*/

View File

@ -0,0 +1,304 @@
/*----------------------------------------------------------------------------
* CMSIS-RTOS - RTX
*----------------------------------------------------------------------------
* Name: RTX_Conf_CM.C
* Purpose: Configuration of CMSIS RTX Kernel for Cortex-M
* Rev.: V4.70.1
*----------------------------------------------------------------------------
*
* Copyright (c) 1999-2009 KEIL, 2009-2016 ARM Germany GmbH. All rights reserved.
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the License); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an AS IS BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*---------------------------------------------------------------------------*/
#include "cmsis_os.h"
/*----------------------------------------------------------------------------
* RTX User configuration part BEGIN
*---------------------------------------------------------------------------*/
//-------- <<< Use Configuration Wizard in Context Menu >>> -----------------
//
// <h>Thread Configuration
// =======================
//
// <o>Number of concurrent running user threads <1-250>
// <i> Defines max. number of user threads that will run at the same time.
// <i> Default: 6
#ifndef OS_TASKCNT
#define OS_TASKCNT 6
#endif
// <o>Default Thread stack size [bytes] <64-4096:8><#/4>
// <i> Defines default stack size for threads with osThreadDef stacksz = 0
// <i> Default: 200
#ifndef OS_STKSIZE
#define OS_STKSIZE 50 // this stack size value is in words
#endif
// <o>Main Thread stack size [bytes] <64-32768:8><#/4>
// <i> Defines stack size for main thread.
// <i> Default: 200
#ifndef OS_MAINSTKSIZE
#define OS_MAINSTKSIZE 50 // this stack size value is in words
#endif
// <o>Number of threads with user-provided stack size <0-250>
// <i> Defines the number of threads with user-provided stack size.
// <i> Default: 0
#ifndef OS_PRIVCNT
#define OS_PRIVCNT 0
#endif
// <o>Total stack size [bytes] for threads with user-provided stack size <0-1048576:8><#/4>
// <i> Defines the combined stack size for threads with user-provided stack size.
// <i> Default: 0
#ifndef OS_PRIVSTKSIZE
#define OS_PRIVSTKSIZE 0 // this stack size value is in words
#endif
// <q>Stack overflow checking
// <i> Enable stack overflow checks at thread switch.
// <i> Enabling this option increases slightly the execution time of a thread switch.
#ifndef OS_STKCHECK
#define OS_STKCHECK 1
#endif
// <q>Stack usage watermark
// <i> Initialize thread stack with watermark pattern for analyzing stack usage (current/maximum) in System and Thread Viewer.
// <i> Enabling this option increases significantly the execution time of osThreadCreate.
#ifndef OS_STKINIT
#define OS_STKINIT 0
#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>RTX Kernel Timer Tick Configuration
// ======================================
// <q> Use Cortex-M SysTick timer as RTX Kernel Timer
// <i> Cortex-M processors provide in most cases a SysTick timer that can be used as
// <i> as time-base for RTX.
#ifndef OS_SYSTICK
#define OS_SYSTICK 1
#endif
//
// <o>RTOS Kernel Timer input clock frequency [Hz] <1-1000000000>
// <i> Defines the input frequency of the RTOS Kernel Timer.
// <i> When the Cortex-M SysTick timer is used, the input clock
// <i> is on most systems identical with the core clock.
#ifndef OS_CLOCK
#define OS_CLOCK 12000000
#endif
// <o>RTX Timer tick interval value [us] <1-1000000>
// <i> The RTX Timer tick interval value is used to calculate timeout values.
// <i> When the Cortex-M SysTick timer is enabled, the value also configures the SysTick timer.
// <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 Thread stack size [bytes] <64-4096:8><#/4>
// <i> Defines stack size for Timer thread.
// <i> Default: 200
#ifndef OS_TIMERSTKSZ
#define OS_TIMERSTKSZ 50 // this stack size value is in words
#endif
// <o>Timer Callback Queue size <1-32>
// <i> Number of concurrent active timer callback functions.
// <i> Default: 4
#ifndef OS_TIMERCBQS
#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 8
#endif
/*----------------------------------------------------------------------------
* RTX User configuration part END
*---------------------------------------------------------------------------*/
#define OS_TRV ((uint32_t)(((double)OS_CLOCK*(double)OS_TICK)/1E6)-1)
/*----------------------------------------------------------------------------
* Global Functions
*---------------------------------------------------------------------------*/
/*--------------------------- os_idle_demon ---------------------------------*/
/// \brief The idle demon is running when no other thread is ready to run
void os_idle_demon (void) {
for (;;) {
/* HERE: include optional user code to be executed when no thread runs.*/
}
}
#if (OS_SYSTICK == 0) // Functions for alternative timer as RTX kernel timer
/*--------------------------- os_tick_init ----------------------------------*/
/// \brief Initializes an alternative hardware timer as RTX kernel timer
/// \return IRQ number of the alternative hardware timer
int os_tick_init (void) {
return (-1); /* Return IRQ number of timer (0..239) */
}
/*--------------------------- os_tick_val -----------------------------------*/
/// \brief Get alternative hardware timer's current value (0 .. OS_TRV)
/// \return Current value of the alternative hardware timer
uint32_t os_tick_val (void) {
return (0);
}
/*--------------------------- os_tick_ovf -----------------------------------*/
/// \brief Get alternative hardware timer's overflow flag
/// \return Overflow flag\n
/// - 1 : overflow
/// - 0 : no overflow
uint32_t os_tick_ovf (void) {
return (0);
}
/*--------------------------- os_tick_irqack --------------------------------*/
/// \brief Acknowledge alternative hardware timer interrupt
void os_tick_irqack (void) {
/* ... */
}
#endif // (OS_SYSTICK == 0)
/*--------------------------- os_error --------------------------------------*/
/* OS Error Codes */
#define OS_ERROR_STACK_OVF 1
#define OS_ERROR_FIFO_OVF 2
#define OS_ERROR_MBX_OVF 3
#define OS_ERROR_TIMER_OVF 4
extern osThreadId svcThreadGetId (void);
/// \brief Called when a runtime error is detected
/// \param[in] error_code actual error code that has been detected
void os_error (uint32_t error_code) {
/* HERE: include optional code to be executed on runtime error. */
switch (error_code) {
case OS_ERROR_STACK_OVF:
/* Stack overflow detected for the currently running task. */
/* Thread can be identified by calling svcThreadGetId(). */
break;
case OS_ERROR_FIFO_OVF:
/* ISR FIFO Queue buffer overflow detected. */
break;
case OS_ERROR_MBX_OVF:
/* Mailbox overflow detected. */
break;
case OS_ERROR_TIMER_OVF:
/* User Timer Callback Queue overflow detected. */
break;
default:
break;
}
for (;;);
}
/*----------------------------------------------------------------------------
* RTX Configuration Functions
*---------------------------------------------------------------------------*/
#include "RTX_CM_lib.h"
/*----------------------------------------------------------------------------
* end of file
*---------------------------------------------------------------------------*/

View File

@ -0,0 +1,71 @@
#include "cmsis_os.h" // CMSIS RTOS header file
/*----------------------------------------------------------------------------
* Mail Queue creation & usage
*---------------------------------------------------------------------------*/
void Thread_MailQueue1 (void const *argument); // thread function 1
void Thread_MailQueue2 (void const *argument); // thread function 2
osThreadId tid_Thread_MailQueue1; // thread id 1
osThreadId tid_Thread_MailQueue2; // thread id 2
osThreadDef (Thread_MailQueue1, osPriorityNormal, 1, 0); // thread object 1
osThreadDef (Thread_MailQueue2, osPriorityNormal, 1, 0); // thread object 2
#define MAILQUEUE_OBJECTS 16 // number of Message Queue Objects
typedef struct { // object data type
uint8_t Buf[32];
uint8_t Idx;
} MAILQUEUE_OBJ_t;
osMailQId qid_MailQueue; // mail queue id
osMailQDef (MailQueue, MAILQUEUE_OBJECTS, MAILQUEUE_OBJ_t); // mail queue object
int Init_MailQueue (void) {
qid_MailQueue = osMailCreate (osMailQ(MailQueue), NULL); // create mail queue
if (!qid_MailQueue) {
; // Mail Queue object not created, handle failure
}
tid_Thread_MailQueue1 = osThreadCreate (osThread(Thread_MailQueue1), NULL);
if (!tid_Thread_MailQueue1) return(-1);
tid_Thread_MailQueue2 = osThreadCreate (osThread(Thread_MailQueue2), NULL);
if (!tid_Thread_MailQueue2) return(-1);
return(0);
}
void Thread_MailQueue1 (void const *argument) {
MAILQUEUE_OBJ_t *pMail = 0;
while (1) {
; // Insert thread code here...
pMail = osMailAlloc (qid_MailQueue, osWaitForever); // Allocate memory
if (pMail) {
pMail->Buf[0] = 0xff; // Set the mail content
pMail->Idx = 0;
osMailPut (qid_MailQueue, pMail); // Send Mail
}
osThreadYield (); // suspend thread
}
}
void Thread_MailQueue2 (void const *argument) {
MAILQUEUE_OBJ_t *pMail = 0;
osEvent evt;
while (1) {
; // Insert thread code here...
evt = osMailGet (qid_MailQueue, osWaitForever); // wait for mail
if (evt.status == osEventMail) {
pMail = evt.value.p;
if (pMail) {
; // process data
osMailFree (qid_MailQueue, pMail); // free memory allocated for mail
}
}
}
}

View File

@ -0,0 +1,63 @@
#include "cmsis_os.h" // CMSIS RTOS header file
/*----------------------------------------------------------------------------
* Memory Pool creation & usage
*---------------------------------------------------------------------------*/
#define MEMPOOL_OBJECTS 16 // number of Memory Pool Objects
typedef struct { // object data type
uint8_t Buf[32];
uint8_t Idx;
} MEM_BLOCK_t;
void Thread_MemPool (void const *argument); // thread function
osThreadId tid_Thread_MemPool; // thread id
osThreadDef (Thread_MemPool, osPriorityNormal, 1, 0); // thread object
osPoolId mpid_MemPool; // memory pool id
osPoolDef (MemPool, MEMPOOL_OBJECTS, MEM_BLOCK_t); // memory pool object
int Init_MemPool (void) {
mpid_MemPool = osPoolCreate (osPool (MemPool)); // create Mem Pool
if (!mpid_MemPool) {
; // MemPool object not created, handle failure
}
tid_Thread_MemPool = osThreadCreate (osThread(Thread_MemPool), NULL);
if (!tid_Thread_MemPool) return(-1);
return(0);
}
void Thread_MemPool (void const *argument) {
osStatus status;
MEM_BLOCK_t *pMem = 0;
while (1) {
; // Insert thread code here...
pMem = (MEM_BLOCK_t *)osPoolCAlloc (mpid_MemPool); // get Mem Block
if (pMem) { // Mem Block was available
pMem->Buf[0] = 0x55; // do some work...
pMem->Idx = 0;
status = osPoolFree (mpid_MemPool, pMem); // free mem block
switch (status) {
case osOK:
break;
case osErrorParameter:
break;
case osErrorValue:
break;
default:
break;
}
}
osThreadYield (); // suspend thread
}
}

View File

@ -0,0 +1,85 @@
#include "cmsis_os.h" // CMSIS RTOS header file
/*----------------------------------------------------------------------------
* Message Queue creation & usage
*---------------------------------------------------------------------------*/
void Thread_MsgQueue1 (void const *argument); // thread function 1
void Thread_MsgQueue2 (void const *argument); // thread function 2
osThreadId tid_Thread_MsgQueue1; // thread id 1
osThreadId tid_Thread_MsgQueue2; // thread id 2
osThreadDef (Thread_MsgQueue1, osPriorityNormal, 1, 0); // thread object 1
osThreadDef (Thread_MsgQueue2, osPriorityNormal, 1, 0); // thread object 2
#define MSGQUEUE_OBJECTS 16 // number of Message Queue Objects
typedef struct { // object data type
uint8_t Buf[32];
uint8_t Idx;
} MEM_BLOCK_t;
typedef struct { // object data type
uint8_t Buf[32];
uint8_t Idx;
} MSGQUEUE_OBJ_t;
osPoolId mpid_MemPool2; // memory pool id
osPoolDef (MemPool2, MSGQUEUE_OBJECTS, MEM_BLOCK_t); // memory pool object
osMessageQId mid_MsgQueue; // message queue id
osMessageQDef (MsgQueue, MSGQUEUE_OBJECTS, MSGQUEUE_OBJ_t); // message queue object
int Init_MsgQueue (void) {
mpid_MemPool2 = osPoolCreate (osPool (MemPool2)); // create Mem Pool
if (!mpid_MemPool2) {
; // MemPool object not created, handle failure
}
mid_MsgQueue = osMessageCreate (osMessageQ(MsgQueue), NULL); // create msg queue
if (!mid_MsgQueue) {
; // Message Queue object not created, handle failure
}
tid_Thread_MsgQueue1 = osThreadCreate (osThread(Thread_MsgQueue1), NULL);
if (!tid_Thread_MsgQueue1) return(-1);
tid_Thread_MsgQueue2 = osThreadCreate (osThread(Thread_MsgQueue2), NULL);
if (!tid_Thread_MsgQueue2) return(-1);
return(0);
}
void Thread_MsgQueue1 (void const *argument) {
MEM_BLOCK_t *pMsg = 0;
while (1) {
; // Insert thread code here...
pMsg = (MEM_BLOCK_t *)osPoolCAlloc (mpid_MemPool2); // get Mem Block
if (pMsg) { // Mem Block was available
pMsg->Buf[0] = 0x55; // do some work...
pMsg->Idx = 0;
osMessagePut (mid_MsgQueue, (uint32_t)pMsg, osWaitForever); // Send Message
}
osThreadYield (); // suspend thread
}
}
void Thread_MsgQueue2 (void const *argument) {
osEvent evt;
MEM_BLOCK_t *pMsg = 0;
while (1) {
; // Insert thread code here...
evt = osMessageGet (mid_MsgQueue, osWaitForever); // wait for message
if (evt.status == osEventMessage) {
pMsg = evt.value.p;
if (pMsg) {
; // process data
osPoolFree (mpid_MemPool2, pMsg); // free memory allocated for message
}
}
}
}

View File

@ -0,0 +1,55 @@
#include "cmsis_os.h" // CMSIS RTOS header file
/*----------------------------------------------------------------------------
* Mutex creation & usage
*---------------------------------------------------------------------------*/
void Thread_Mutex (void const *argument); // thread function
osThreadId tid_Thread_Mutex; // thread id
osThreadDef (Thread_Mutex, osPriorityNormal, 1, 0); // thread object
osMutexId mid_Thread_Mutex; // mutex id
osMutexDef (SampleMutex); // mutex name definition
int Init_Mutex (void) {
mid_Thread_Mutex = osMutexCreate (osMutex (SampleMutex));
if (!tid_Thread_Mutex) {
; // Mutex object not created, handle failure
}
tid_Thread_Mutex = osThreadCreate (osThread(Thread_Mutex), NULL);
if (!tid_Thread_Mutex) return(-1);
return(0);
}
void Thread_Mutex (void const *argument) {
osStatus status;
while (1) {
; // Insert thread code here...
status = osMutexWait (mid_Thread_Mutex, NULL);
switch (status) {
case osOK:
; // Use protected code here...
osMutexRelease (mid_Thread_Mutex);
break;
case osErrorTimeoutResource:
break;
case osErrorResource:
break;
case osErrorParameter:
break;
case osErrorISR:
break;
default:
break;
}
osThreadYield (); // suspend thread
}
}

View File

@ -0,0 +1,51 @@
#include "cmsis_os.h" // CMSIS RTOS header file
/*----------------------------------------------------------------------------
* Semaphore creation & usage
*---------------------------------------------------------------------------*/
void Thread_Semaphore (void const *argument); // thread function
osThreadId tid_Thread_Semaphore; // thread id
osThreadDef (Thread_Semaphore, osPriorityNormal, 1, 0); // thread object
osSemaphoreId sid_Thread_Semaphore; // semaphore id
osSemaphoreDef (SampleSemaphore); // semaphore object
int Init_Semaphore (void) {
sid_Thread_Semaphore = osSemaphoreCreate (osSemaphore(SampleSemaphore), 1);
if (!sid_Thread_Semaphore) {
; // Semaphore object not created, handle failure
}
tid_Thread_Semaphore = osThreadCreate (osThread(Thread_Semaphore), NULL);
if (!tid_Thread_Semaphore) return(-1);
return(0);
}
void Thread_Semaphore (void const *argument) {
int32_t val;
while (1) {
; // Insert thread code here...
val = osSemaphoreWait (sid_Thread_Semaphore, 10); // wait 10 mSec
switch (val) {
case osOK:
; // Use protected code here...
osSemaphoreRelease (sid_Thread_Semaphore); // Return a token back to a semaphore
break;
case osErrorResource:
break;
case osErrorParameter:
break;
default:
break;
}
osThreadYield (); // suspend thread
}
}

View File

@ -0,0 +1,26 @@
#include "cmsis_os.h" // CMSIS RTOS header file
/*----------------------------------------------------------------------------
* Thread 1 'Thread_Name': Sample thread
*---------------------------------------------------------------------------*/
void Thread (void const *argument); // thread function
osThreadId tid_Thread; // thread id
osThreadDef (Thread, osPriorityNormal, 1, 0); // thread object
int Init_Thread (void) {
tid_Thread = osThreadCreate (osThread(Thread), NULL);
if (!tid_Thread) return(-1);
return(0);
}
void Thread (void const *argument) {
while (1) {
; // Insert thread code here...
osThreadYield (); // suspend thread
}
}

View File

@ -0,0 +1,60 @@
#include "cmsis_os.h" // CMSIS RTOS header file
/*----------------------------------------------------------------------------
* Timer: Sample timer functions
*---------------------------------------------------------------------------*/
/*----- One-Shoot Timer Example -----*/
static void Timer1_Callback (void const *arg); // prototype for timer callback function
static osTimerId id1; // timer id
static uint32_t exec1; // argument for the timer call back function
static osTimerDef (Timer1, Timer1_Callback); // define timers
// One-Shoot Timer Function
static void Timer1_Callback (void const *arg) {
// add user code here
}
/*----- Periodic Timer Example -----*/
static void Timer2_Callback (void const *arg); // prototype for timer callback function
static osTimerId id2; // timer id
static uint32_t exec2; // argument for the timer call back function
static osTimerDef (Timer2, Timer2_Callback);
// Periodic Timer Example
static void Timer2_Callback (void const *arg) {
// add user code here
}
// Example: Create and Start timers
void Init_Timers (void) {
osStatus status; // function return status
// Create one-shoot timer
exec1 = 1;
id1 = osTimerCreate (osTimer(Timer1), osTimerOnce, &exec1);
if (id1 != NULL) { // One-shot timer created
// start timer with delay 100ms
status = osTimerStart (id1, 100);
if (status != osOK) {
// Timer could not be started
}
}
// Create periodic timer
exec2 = 2;
id2 = osTimerCreate (osTimer(Timer2), osTimerPeriodic, &exec2);
if (id2 != NULL) { // Periodic timer created
// start timer with periodic 1000ms interval
status = osTimerStart (id2, 1000);
if (status != osOK) {
// Timer could not be started
}
}
}

View File

@ -0,0 +1,21 @@
/*----------------------------------------------------------------------------
* CMSIS-RTOS 'main' function template
*---------------------------------------------------------------------------*/
#define osObjectsPublic // define objects in main module
#include "osObjects.h" // RTOS object definitions
/*
* main: initialize and start the system
*/
int main (void) {
osKernelInitialize (); // initialize CMSIS-RTOS
// initialize peripherals here
// create 'thread' functions that start executing,
// example: tid_name = osThreadCreate (osThread(name), NULL);
osKernelStart (); // start thread execution
}

View File

@ -0,0 +1,70 @@
/*----------------------------------------------------------------------------
* osObjects.h: CMSIS-RTOS global object definitions for an application
*----------------------------------------------------------------------------
*
* This header file defines global RTOS objects used throughout a project
*
* #define osObjectsPublic indicates that objects are defined; without that
* definition the objects are defined as external symbols.
*
*--------------------------------------------------------------------------*/
#ifndef __osObjects
#define __osObjects
#if (!defined (osObjectsPublic))
#define osObjectsExternal // define RTOS objects with extern attribute
#endif
#include "cmsis_os.h" // CMSIS RTOS header file
// global 'thread' functions ---------------------------------------------------
/*
Example:
extern void sample_name (void const *argument); // thread function
osThreadId tid_sample_name; // thread id
osThreadDef (sample_name, osPriorityNormal, 1, 0); // thread object
*/
// global 'semaphores' ----------------------------------------------------------
/*
Example:
osSemaphoreId sid_sample_name; // semaphore id
osSemaphoreDef (sample_name); // semaphore object
*/
// global 'memory pools' --------------------------------------------------------
/*
Example:
typedef struct sample_name type_sample_name; // object data type
osPoolId mpid_sample_name; // memory pool id
osPoolDef (sample_name, 16, type_sample_name); // memory pool object
*/
// global 'message queues' -------------------------------------------------------
/*
Example:
typedef struct sample_name type_sample_name; // object data type
osMessageQId mid_sample_name; // message queue id
osMessageQDef (sample_name, 16, type_sample_name); // message queue object
*/
// global 'mail queues' ----------------------------------------------------------
/*
Example:
typedef struct sample_name type_sample_name; // object data type
osMailQId qid_sample_name; // mail queue id
osMailQDef (sample_name, 16, type_sample_name); // mail queue object
*/
#endif // __osObjects