This commit is contained in:
2026-05-19 11:49:22 +08:00
commit add7af4222
96 changed files with 8635 additions and 0 deletions
+252
View File
@@ -0,0 +1,252 @@
#include <atomic.h>
#include "cmsis.h"
/*
* 注意:以下实现依赖于 CMSIS 提供的 CMSIS_LDREXW, CMSIS_STREXW, CMSIS_CLREX 等内建函数。
* 如果使用 ARMCC,请替换为 __ldrex, __strex, __clrex。
* 如果使用 IAR,请替换为 __LDREX, __STREX, CMSIS_CLREX。
*/
/* ======================================================================== */
/* 内部辅助宏:编译器屏障 */
/* ======================================================================== */
#if defined(__GNUC__)
#define COMPILER_BARRIER() __asm volatile ("" ::: "memory")
#elif defined(__CC_ARM)
#define COMPILER_BARRIER() __schedule_barrier()
#endif
/* ======================================================================== */
/* 32位 原子操作实现 */
/* ======================================================================== */
uint32_t atomic_load_32(const atomic_uint32_t *obj) {
// Cortex-M3 普通加载即为原子加载(对齐情况下),但为了语义明确和防止重排
uint32_t val;
do {
val = CMSIS_LDREXW((os_uint_t*)obj);
} while (CMSIS_STREXW(val, (os_uint_t*)obj)); // 实际上 load 不需要 STREX,直接读即可,但为了严格内存序可加屏障
// 更高效的 Load:
return *obj;
}
void atomic_store_32(atomic_uint32_t *obj, uint32_t desired) {
// 简单存储在某些情况下可能不是原子的(如果涉及中断上下文竞争且非位带),
// 但对于 M3,32位对齐写入是原子的。为了安全起见,使用独占序列确保完整性。
uint32_t status;
do {
CMSIS_LDREXW((os_uint_t*)obj);
status = CMSIS_STREXW(desired, (os_uint_t*)obj);
} while (status != 0);
}
uint32_t atomic_exchange_32(atomic_uint32_t *obj, uint32_t desired) {
uint32_t old_val;
uint32_t status;
do {
old_val = CMSIS_LDREXW((os_uint_t*)obj);
status = CMSIS_STREXW(desired, (os_uint_t*)obj);
} while (status != 0);
return old_val;
}
bool atomic_compare_exchange_strong_32(atomic_uint32_t *obj, uint32_t *expected, uint32_t desired) {
uint32_t current;
uint32_t status;
do {
current = CMSIS_LDREXW((os_uint_t*)obj);
if (current != *expected) {
CMSIS_CLREX(); // 清除独占标记,避免总线锁定
*expected = current; // 更新 expected 为当前实际值
return false;
}
status = CMSIS_STREXW(desired, (os_uint_t*)obj);
} while (status != 0);
return true;
}
bool atomic_compare_exchange_weak_32(atomic_uint32_t *obj, uint32_t *expected, uint32_t desired) {
// 在 Cortex-M3 上,Weak 和 Strong 区别不大,因为硬件不支持虚假失败的优化循环通常由软件处理
// 这里复用 Strong 逻辑,但在某些实现中 Weak 可能在第一次 STREX 失败时直接返回而不重试内部循环
// 为了标准兼容性,我们提供标准的 CAS 行为
return atomic_compare_exchange_strong_32(obj, expected, desired);
}
uint32_t atomic_fetch_add_32(atomic_uint32_t *obj, uint32_t operand) {
uint32_t old_val;
uint32_t new_val;
uint32_t status;
do {
old_val = CMSIS_LDREXW((os_uint_t*)obj);
new_val = old_val + operand;
status = CMSIS_STREXW(new_val, (os_uint_t*)obj);
} while (status != 0);
return old_val;
}
uint32_t atomic_fetch_sub_32(atomic_uint32_t *obj, uint32_t operand) {
uint32_t old_val;
uint32_t new_val;
uint32_t status;
do {
old_val = CMSIS_LDREXW((os_uint_t*)obj);
new_val = old_val - operand;
status = CMSIS_STREXW(new_val, (os_uint_t*)obj);
} while (status != 0);
return old_val;
}
uint32_t atomic_fetch_and_32(atomic_uint32_t *obj, uint32_t operand) {
uint32_t old_val;
uint32_t new_val;
uint32_t status;
do {
old_val = CMSIS_LDREXW((os_uint_t*)obj);
new_val = old_val & operand;
status = CMSIS_STREXW(new_val, (os_uint_t*)obj);
} while (status != 0);
return old_val;
}
uint32_t atomic_fetch_or_32(atomic_uint32_t *obj, uint32_t operand) {
uint32_t old_val;
uint32_t new_val;
uint32_t status;
do {
old_val = CMSIS_LDREXW((os_uint_t*)obj);
new_val = old_val | operand;
status = CMSIS_STREXW(new_val, (os_uint_t*)obj);
} while (status != 0);
return old_val;
}
uint32_t atomic_fetch_xor_32(atomic_uint32_t *obj, uint32_t operand) {
uint32_t old_val;
uint32_t new_val;
uint32_t status;
do {
old_val = CMSIS_LDREXW((os_uint_t*)obj);
new_val = old_val ^ operand;
status = CMSIS_STREXW(new_val, (os_uint_t*)obj);
} while (status != 0);
return old_val;
}
/* ======================================================================== */
/* 8位 原子操作实现 (基于 32位 LDREX/STREX + 掩码) */
/* ======================================================================== */
uint8_t atomic_load_8(const atomic_uint8_t *obj) {
return *obj;
}
void atomic_store_8(atomic_uint8_t *obj, uint8_t desired) {
// 需要读取包含该字节的整个32位字,修改后写回
volatile uint32_t *word_addr = (volatile uint32_t *)((uint32_t)obj & ~0x3);
uint32_t shift = ((uint32_t)obj & 0x3) * 8;
uint32_t mask = 0xFF << shift;
uint32_t old_word;
uint32_t new_word;
uint32_t status;
do {
old_word = CMSIS_LDREXW((os_uint_t*)word_addr);
new_word = (old_word & ~mask) | (((uint32_t)desired << shift) & mask);
status = CMSIS_STREXW(new_word, (os_uint_t*)word_addr);
} while (status != 0);
}
uint8_t atomic_fetch_add_8(atomic_uint8_t *obj, uint8_t operand) {
volatile uint32_t *word_addr = (volatile uint32_t *)((uint32_t)obj & ~0x3);
uint32_t shift = ((uint32_t)obj & 0x3) * 8;
uint32_t mask = 0xFF << shift;
uint32_t old_word;
uint32_t new_word;
uint32_t status;
uint8_t old_val;
do {
old_word = CMSIS_LDREXW((os_uint_t*)word_addr);
old_val = (old_word >> shift) & 0xFF;
uint8_t new_val = old_val + operand;
new_word = (old_word & ~mask) | (((uint32_t)new_val << shift) & mask);
status = CMSIS_STREXW(new_word, (os_uint_t*)word_addr);
} while (status != 0);
return old_val;
}
bool atomic_compare_exchange_strong_8(atomic_uint8_t *obj, uint8_t *expected, uint8_t desired) {
volatile uint32_t *word_addr = (volatile uint32_t *)((uint32_t)obj & ~0x3);
uint32_t shift = ((uint32_t)obj & 0x3) * 8;
uint32_t mask = 0xFF << shift;
uint32_t old_word;
uint32_t new_word;
uint32_t status;
uint8_t current_val;
do {
old_word = CMSIS_LDREXW((os_uint_t*)word_addr);
current_val = (old_word >> shift) & 0xFF;
if (current_val != *expected) {
CMSIS_CLREX();
*expected = current_val;
return false;
}
new_word = (old_word & ~mask) | (((uint32_t)desired << shift) & mask);
status = CMSIS_STREXW(new_word, (os_uint_t*)word_addr);
} while (status != 0);
return true;
}
/* ======================================================================== */
/* 位带操作实现 (绝对原子,无需 LDREX/STREX 循环) */
/* ======================================================================== */
void atomic_bit_set(volatile void *addr, uint32_t bit) {
// 向位带别名地址写入 1
*BITBAND_PTR(addr, bit) = 1;
}
void atomic_bit_clear(volatile void *addr, uint32_t bit) {
// 向位带别名地址写入 0
*BITBAND_PTR(addr, bit) = 0;
}
uint32_t atomic_bit_read(volatile void *addr, uint32_t bit) {
// 从位带别名地址读取,结果为 0 或 1
return *BITBAND_PTR(addr, bit);
}
void atomic_bit_toggle(volatile void *addr, uint32_t bit) {
// 位带不支持直接 toggle,需要读-改-写,但因为是单比特映射,可以这样实现:
// 读取当前位,然后写入相反值。由于读写的是不同的别名地址(如果是不同位)或同一地址,
// 对于同一位的 toggle,最安全的方式还是 LDREX/STREX 或者关中断。
// 但如果只是简单的 Set/Clear,位带是原子的。Toggle 通常不推荐在高位并发下使用位带,除非保证单线程访问该位。
// 这里提供一个基于位带的简单 Toggle(注意:这在多核或极高并发中断下可能不安全,但在 M3 单核中断模型中,
// 如果中断优先级管理得当,通常是安全的,或者更推荐使用 BSRR 寄存器进行 GPIO Toggle
// 更推荐的 GPIO Toggle 是使用 BSRR:
// 如果 addr 是 GPIO ODR,建议直接使用 BSRR 寄存器,而不是位带 Toggle。
// 此处仅为演示位带读写能力,实际 Toggle 建议:
uint32_t current = *BITBAND_PTR(addr, bit);
*BITBAND_PTR(addr, bit) = !current;
}
+134
View File
@@ -0,0 +1,134 @@
#ifndef INCLUDED_ATOMIC_H
#define INCLUDED_ATOMIC_H
#ifndef INCLUDED_OS_TYPES_H
#include <os_types.h>
#endif /*INCLUDED_OS_TYPES_H*/
#ifndef INCLUDED_OS_COMPILER_H
#include <os_compiler.h>
#endif /*INCLUDED_OS_COMPILER_H*/
#ifndef INCLUDED_CMSIS_H
#include <cmsis.h>
#endif /*INCLUDED_CMSIS_H*/
/* ------------------------------------------------------------------------------------------------------------------ */
/* */
#ifdef __cplusplus
extern "C" {
#endif
/* ======================================================================== */
/* 1. 内存序枚举 (简化版,适配 Cortex-M3 硬件特性) */
/* ======================================================================== */
typedef enum {
memory_order_relaxed = 0, /* Maps to simple atomic access (no barriers) */
memory_order_consume = 1,
memory_order_acquire = 2, /* Usually implemented with a DMB instruction to ensure memory operations do not cross a boundary */
memory_order_release = 3, /* Usually implemented with a DMB instruction to ensure memory operations do not cross a boundary */
memory_order_acq_rel = 4,
memory_order_seq_cst = 5 /* The default and safest; guarantees absolute ordering (uses DMB/DSB) */
} atomic_memory_order;
/* ======================================================================== */
/* 2. 原子类型定义 */
/* ======================================================================== */
typedef volatile os_uint_t atomic_uint_t;
typedef volatile os_int_t atomic_int_t;
typedef volatile uint32_t atomic_uint32_t;
typedef volatile int32_t atomic_int32_t;
typedef volatile uint16_t atomic_uint16_t;
typedef volatile int16_t atomic_int16_t;
typedef volatile uint8_t atomic_uint8_t;
typedef volatile int8_t atomic_int8_t;
typedef volatile bool atomic_bool;
/* 指针原子类型 (32位系统) */
typedef volatile void* atomic_ptr_t;
/* ======================================================================== */
/* 3. 位带操作宏 (仅适用于 SRAM 0x20000000-0x200FFFFF 和 PERIPH 0x40000000-0x400FFFFF) */
/* ======================================================================== */
#define BITBAND_SRAM_REF 0x20000000
#define BITBAND_SRAM_BASE 0x22000000
#define BITBAND_PERI_REF 0x40000000
#define BITBAND_PERI_BASE 0x42000000
// 计算位带别名地址的宏
// addr: 原始寄存器地址 (如 &GPIOA->ODR)
// bit: 位序号 (0-31)
#define BITBAND_ADDR(addr, bit) \
(((uint32_t)(addr) & 0xF0000000) == 0x20000000 ? \
(BITBAND_SRAM_BASE + ((uint32_t)(addr) - BITBAND_SRAM_REF) * 32 + (bit) * 4) : \
(BITBAND_PERI_BASE + ((uint32_t)(addr) - BITBAND_PERI_REF) * 32 + (bit) * 4))
// 访问位带地址的指针宏
#define BITBAND_PTR(addr, bit) ((volatile uint32_t *)BITBAND_ADDR(addr, bit))
// 示例:原子操作 GPIOA Pin 5 的输出
// 定义一个指向位带别名地址的指针
//#define PA5_OUT_BIT BITBAND_ADDR(&GPIOA->ODR, 5)
/* ======================================================================== */
/* 4. 核心原子操作函数声明 */
/* ======================================================================== */
/* --- 基础加载与存储 --- */
uint32_t atomic_load_32(const atomic_uint32_t *obj);
void atomic_store_32(atomic_uint32_t *obj, uint32_t desired);
/* --- 交换操作, 返回交换前的值 --- */
uint32_t atomic_exchange_32(atomic_uint32_t *obj, uint32_t desired);
/* --- 比较并交换 (CAS) --- */
/* 返回 true 如果交换成功,false 如果失败 (expected 会被更新为当前值) */
bool atomic_compare_exchange_strong_32(atomic_uint32_t *obj, uint32_t *expected, uint32_t desired);
bool atomic_compare_exchange_weak_32(atomic_uint32_t *obj, uint32_t *expected, uint32_t desired);
/* --- 算术与位运算 (Fetch-and-Op) --- */
/* 返回操作前的旧值 */
uint32_t atomic_fetch_add_32(atomic_uint32_t *obj, uint32_t operand);
uint32_t atomic_fetch_sub_32(atomic_uint32_t *obj, uint32_t operand);
uint32_t atomic_fetch_and_32(atomic_uint32_t *obj, uint32_t operand);
uint32_t atomic_fetch_or_32(atomic_uint32_t *obj, uint32_t operand);
uint32_t atomic_fetch_xor_32(atomic_uint32_t *obj, uint32_t operand);
/* --- 8位/16位支持 (通过掩码和LDREX/STREX实现) --- */
uint8_t atomic_load_8(const atomic_uint8_t *obj);
void atomic_store_8(atomic_uint8_t *obj, uint8_t desired);
uint8_t atomic_fetch_add_8(atomic_uint8_t *obj, uint8_t operand);
bool atomic_compare_exchange_strong_8(atomic_uint8_t *obj, uint8_t *expected, uint8_t desired);
/* --- 位带专用原子操作 (仅用于 GPIO 或支持位带的寄存器/SRAM) --- */
/* 设置指定位为 1 */
void atomic_bit_set(volatile void *addr, os_uint_t bit);
/* 清除指定位为 0 */
void atomic_bit_clear(volatile void *addr, os_uint_t bit);
/* 读取指定位的值 (0 或 1) */
os_uint_t atomic_bit_read(volatile void *addr, os_uint_t bit);
/* 翻转指定位 */
void atomic_bit_toggle(volatile void *addr, os_uint_t bit);
/* ------------------------------------------------------------------------------------------------------------------ */
/* */
#define atomic_load atomic_load_32
#define atomic_store atomic_store_32
#define atomic_exchange atomic_exchange_32
#define atomic_compare_exchange_strong atomic_compare_exchange_strong_32
#define atomic_compare_exchange_weak atomic_compare_exchange_weak_32
#define atomic_fetch_add atomic_fetch_add_32
#define atomic_fetch_sub atomic_fetch_sub_32
#define atomic_fetch_and atomic_fetch_and_32
#define atomic_fetch_or atomic_fetch_or_32
#define atomic_fetch_xor atomic_fetch_xor_32
#ifdef __cplusplus
}
#endif
#endif /*INCLUDED_ATOMIC_H*/
+760
View File
@@ -0,0 +1,760 @@
#include <cmsis.h>
/* ################### Compiler specific Intrinsics ########################### */
#if defined ( __CC_ARM ) /*------------------RealView Compiler -----------------*/
/* ARM armcc specific functions */
__ASM uint32_t CMSIS_get_IPSR(void)
{
mrs r0, ipsr
bx lr
}
/**
* @brief Return the Process Stack Pointer
*
* @return ProcessStackPointer
*
* Return the actual process stack pointer
*/
__ASM uint32_t CMSIS_get_PSP(void)
{
mrs r0, psp
bx lr
}
/**
* @brief Set the Process Stack Pointer
*
* @param topOfProcStack Process Stack Pointer
*
* Assign the value ProcessStackPointer to the MSP
* (process stack pointer) Cortex processor register
*/
__ASM void CMSIS_set_PSP(uint32_t topOfProcStack)
{
msr psp, r0
bx lr
}
/**
* @brief Return the Main Stack Pointer
*
* @return Main Stack Pointer
*
* Return the current value of the MSP (main stack pointer)
* Cortex processor register
*/
__ASM uint32_t CMSIS_get_MSP(void)
{
mrs r0, msp
bx lr
}
/**
* @brief Set the Main Stack Pointer
*
* @param topOfMainStack Main Stack Pointer
*
* Assign the value mainStackPointer to the MSP
* (main stack pointer) Cortex processor register
*/
__ASM void CMSIS_set_MSP(uint32_t mainStackPointer)
{
msr msp, r0
bx lr
}
/**
* @brief Reverse byte order in unsigned short value
*
* @param value value to reverse
* @return reversed value
*
* Reverse byte order in unsigned short value
*/
__ASM uint32_t CMSIS_REV16(uint16_t value)
{
rev16 r0, r0
bx lr
}
/**
* @brief Reverse byte order in signed short value with sign extension to integer
*
* @param value value to reverse
* @return reversed value
*
* Reverse byte order in signed short value with sign extension to integer
*/
__ASM int32_t CMSIS_REVSH(int16_t value)
{
revsh r0, r0
bx lr
}
#if (__ARMCC_VERSION < 400000)
/**
* @brief Remove the exclusive lock created by ldrex
*
* Removes the exclusive lock which is created by ldrex.
*/
__ASM void CMSIS_CLREX(void)
{
clrex
}
/**
* @brief Return the Base Priority value
*
* @return BasePriority
*
* Return the content of the base priority register
*/
__ASM uint32_t CMSIS_get_BASEPRI(void)
{
mrs r0, basepri
bx lr
}
/**
* @brief Set the Base Priority value
*
* @param basePri BasePriority
*
* Set the base priority register
*/
__ASM void CMSIS_set_BASEPRI(uint32_t basePri)
{
msr basepri, r0
bx lr
}
/**
* @brief Return the Priority Mask value
*
* @return PriMask
*
* Return state of the priority mask bit from the priority mask register
*/
__ASM uint32_t CMSIS_get_PRIMASK(void)
{
mrs r0, primask
bx lr
}
/**
* @brief Set the Priority Mask value
*
* @param priMask PriMask
*
* Set the priority mask bit in the priority mask register
*/
__ASM void CMSIS_set_PRIMASK(uint32_t priMask)
{
msr primask, r0
bx lr
}
/**
* @brief Return the Fault Mask value
*
* @return FaultMask
*
* Return the content of the fault mask register
*/
__ASM uint32_t CMSIS_get_FAULTMASK(void)
{
mrs r0, faultmask
bx lr
}
/**
* @brief Set the Fault Mask value
*
* @param faultMask faultMask value
*
* Set the fault mask register
*/
__ASM void CMSIS_set_FAULTMASK(uint32_t faultMask)
{
msr faultmask, r0
bx lr
}
/**
* @brief Return the Control Register value
*
* @return Control value
*
* Return the content of the control register
*/
__ASM uint32_t CMSIS_get_CONTROL(void)
{
mrs r0, control
bx lr
}
/**
* @brief Set the Control Register value
*
* @param control Control value
*
* Set the control register
*/
__ASM void CMSIS_set_CONTROL(uint32_t control)
{
msr control, r0
bx lr
}
#endif /* __ARMCC_VERSION */
#elif (defined (__ICCARM__)) /*------------------ ICC Compiler -------------------*/
/* IAR iccarm specific functions */
#pragma diag_suppress=Pe940
/**
* @brief Return the Process Stack Pointer
*
* @return ProcessStackPointer
*
* Return the actual process stack pointer
*/
uint32_t CMSIS_get_PSP(void)
{
__ASM("mrs r0, psp");
__ASM("bx lr");
}
/**
* @brief Set the Process Stack Pointer
*
* @param topOfProcStack Process Stack Pointer
*
* Assign the value ProcessStackPointer to the MSP
* (process stack pointer) Cortex processor register
*/
void CMSIS_set_PSP(uint32_t topOfProcStack)
{
__ASM("msr psp, r0");
__ASM("bx lr");
}
/**
* @brief Return the Main Stack Pointer
*
* @return Main Stack Pointer
*
* Return the current value of the MSP (main stack pointer)
* Cortex processor register
*/
uint32_t CMSIS_get_MSP(void)
{
__ASM("mrs r0, msp");
__ASM("bx lr");
}
/**
* @brief Set the Main Stack Pointer
*
* @param topOfMainStack Main Stack Pointer
*
* Assign the value mainStackPointer to the MSP
* (main stack pointer) Cortex processor register
*/
void CMSIS_set_MSP(uint32_t topOfMainStack)
{
__ASM("msr msp, r0");
__ASM("bx lr");
}
/**
* @brief Reverse byte order in unsigned short value
*
* @param value value to reverse
* @return reversed value
*
* Reverse byte order in unsigned short value
*/
uint32_t CMSIS_REV16(uint16_t value)
{
__ASM("rev16 r0, r0");
__ASM("bx lr");
}
/**
* @brief Reverse bit order of value
*
* @param value value to reverse
* @return reversed value
*
* Reverse bit order of value
*/
uint32_t CMSIS_RBIT(uint32_t value)
{
__ASM("rbit r0, r0");
__ASM("bx lr");
}
/**
* @brief LDR Exclusive (8 bit)
*
* @param *addr address pointer
* @return value of (*address)
*
* Exclusive LDR command for 8 bit values)
*/
uint8_t CMSIS_LDREXB(uint8_t *addr)
{
__ASM("ldrexb r0, [r0]");
__ASM("bx lr");
}
/**
* @brief LDR Exclusive (16 bit)
*
* @param *addr address pointer
* @return value of (*address)
*
* Exclusive LDR command for 16 bit values
*/
uint16_t CMSIS_LDREXH(uint16_t *addr)
{
__ASM("ldrexh r0, [r0]");
__ASM("bx lr");
}
/**
* @brief LDR Exclusive (32 bit)
*
* @param *addr address pointer
* @return value of (*address)
*
* Exclusive LDR command for 32 bit values
*/
uint32_t CMSIS_LDREXW(uint32_t *addr)
{
__ASM("ldrex r0, [r0]");
__ASM("bx lr");
}
/**
* @brief STR Exclusive (8 bit)
*
* @param value value to store
* @param *addr address pointer
* @return successful / failed
*
* Exclusive STR command for 8 bit values
*/
uint32_t CMSIS_STREXB(uint8_t value, uint8_t *addr)
{
__ASM("strexb r0, r0, [r1]");
__ASM("bx lr");
}
/**
* @brief STR Exclusive (16 bit)
*
* @param value value to store
* @param *addr address pointer
* @return successful / failed
*
* Exclusive STR command for 16 bit values
*/
uint32_t CMSIS_STREXH(uint16_t value, uint16_t *addr)
{
__ASM("strexh r0, r0, [r1]");
__ASM("bx lr");
}
/**
* @brief STR Exclusive (32 bit)
*
* @param value value to store
* @param *addr address pointer
* @return successful / failed
*
* Exclusive STR command for 32 bit values
*/
uint32_t CMSIS_STREXW(uint32_t value, uint32_t *addr)
{
__ASM("strex r0, r0, [r1]");
__ASM("bx lr");
}
uint32_t CMSIS_get_IPSR(void)
{
__ASM("mrs r0, ipsr");
__ASM("bx lr");
}
#pragma diag_default=Pe940
#elif (defined (__GNUC__)) /*------------------ GNU Compiler ---------------------*/
/* GNU gcc specific functions */
/**
* @brief Return the Process Stack Pointer
*
* @return ProcessStackPointer
*
* Return the actual process stack pointer
*/
uint32_t CMSIS_get_PSP(void) __attribute__( ( naked ) );
uint32_t CMSIS_get_PSP(void)
{
uint32_t result=0;
__ASM volatile ("MRS %0, psp\n\t"
"MOV r0, %0 \n\t"
"BX lr \n\t" : "=r" (result) );
return(result);
}
/**
* @brief Set the Process Stack Pointer
*
* @param topOfProcStack Process Stack Pointer
*
* Assign the value ProcessStackPointer to the MSP
* (process stack pointer) Cortex processor register
*/
void CMSIS_set_PSP(uint32_t topOfProcStack) __attribute__( ( naked ) );
void CMSIS_set_PSP(uint32_t topOfProcStack)
{
__ASM volatile ("MSR psp, %0\n\t"
"BX lr \n\t" : : "r" (topOfProcStack) );
}
/**
* @brief Return the Main Stack Pointer
*
* @return Main Stack Pointer
*
* Return the current value of the MSP (main stack pointer)
* Cortex processor register
*/
uint32_t CMSIS_get_MSP(void) __attribute__( ( naked ) );
uint32_t CMSIS_get_MSP(void)
{
uint32_t result=0;
__ASM volatile ("MRS %0, msp\n\t"
"MOV r0, %0 \n\t"
"BX lr \n\t" : "=r" (result) );
return(result);
}
/**
* @brief Set the Main Stack Pointer
*
* @param topOfMainStack Main Stack Pointer
*
* Assign the value mainStackPointer to the MSP
* (main stack pointer) Cortex processor register
*/
void CMSIS_set_MSP(uint32_t topOfMainStack) __attribute__( ( naked ) );
void CMSIS_set_MSP(uint32_t topOfMainStack)
{
__ASM volatile ("MSR msp, %0\n\t"
"BX lr \n\t" : : "r" (topOfMainStack) );
}
/**
* @brief Return the Base Priority value
*
* @return BasePriority
*
* Return the content of the base priority register
*/
uint32_t CMSIS_get_BASEPRI(void)
{
uint32_t result=0;
__ASM volatile ("MRS %0, basepri_max" : "=r" (result) );
return(result);
}
/**
* @brief Set the Base Priority value
*
* @param basePri BasePriority
*
* Set the base priority register
*/
void CMSIS_set_BASEPRI(uint32_t value)
{
__ASM volatile ("MSR basepri, %0" : : "r" (value) );
}
/**
* @brief Return the Priority Mask value
*
* @return PriMask
*
* Return state of the priority mask bit from the priority mask register
*/
uint32_t CMSIS_get_PRIMASK(void)
{
uint32_t result=0;
__ASM volatile ("MRS %0, primask" : "=r" (result) );
return(result);
}
/**
* @brief Set the Priority Mask value
*
* @param priMask PriMask
*
* Set the priority mask bit in the priority mask register
*/
void CMSIS_set_PRIMASK(uint32_t priMask)
{
__ASM volatile ("MSR primask, %0" : : "r" (priMask) );
}
/**
* @brief Return the Fault Mask value
*
* @return FaultMask
*
* Return the content of the fault mask register
*/
uint32_t CMSIS_get_FAULTMASK(void)
{
uint32_t result=0;
__ASM volatile ("MRS %0, faultmask" : "=r" (result) );
return(result);
}
/**
* @brief Set the Fault Mask value
*
* @param faultMask faultMask value
*
* Set the fault mask register
*/
void CMSIS_set_FAULTMASK(uint32_t faultMask)
{
__ASM volatile ("MSR faultmask, %0" : : "r" (faultMask) );
}
/**
* @brief Return the Control Register value
*
* @return Control value
*
* Return the content of the control register
*/
uint32_t CMSIS_get_CONTROL(void)
{
uint32_t result=0;
__ASM volatile ("MRS %0, control" : "=r" (result) );
return(result);
}
/**
* @brief Set the Control Register value
*
* @param control Control value
*
* Set the control register
*/
void CMSIS_set_CONTROL(uint32_t control)
{
__ASM volatile ("MSR control, %0" : : "r" (control) );
}
/**
* @brief Reverse byte order in integer value
*
* @param value value to reverse
* @return reversed value
*
* Reverse byte order in integer value
*/
uint32_t CMSIS_REV(uint32_t value)
{
uint32_t result=0;
__ASM volatile ("rev %0, %1" : "=r" (result) : "r" (value) );
return(result);
}
/**
* @brief Reverse byte order in unsigned short value
*
* @param value value to reverse
* @return reversed value
*
* Reverse byte order in unsigned short value
*/
uint32_t CMSIS_REV16(uint16_t value)
{
uint32_t result=0;
__ASM volatile ("rev16 %0, %1" : "=r" (result) : "r" (value) );
return(result);
}
/**
* @brief Reverse byte order in signed short value with sign extension to integer
*
* @param value value to reverse
* @return reversed value
*
* Reverse byte order in signed short value with sign extension to integer
*/
int32_t CMSIS_REVSH(int16_t value)
{
uint32_t result=0;
__ASM volatile ("revsh %0, %1" : "=r" (result) : "r" (value) );
return(result);
}
/**
* @brief Reverse bit order of value
*
* @param value value to reverse
* @return reversed value
*
* Reverse bit order of value
*/
uint32_t CMSIS_RBIT(uint32_t value)
{
uint32_t result=0;
__ASM volatile ("rbit %0, %1" : "=r" (result) : "r" (value) );
return(result);
}
/**
* @brief LDR Exclusive (8 bit)
*
* @param *addr address pointer
* @return value of (*address)
*
* Exclusive LDR command for 8 bit value
*/
uint8_t CMSIS_LDREXB(uint8_t *addr)
{
uint8_t result=0;
__ASM volatile ("ldrexb %0, [%1]" : "=r" (result) : "r" (addr) );
return(result);
}
/**
* @brief LDR Exclusive (16 bit)
*
* @param *addr address pointer
* @return value of (*address)
*
* Exclusive LDR command for 16 bit values
*/
uint16_t CMSIS_LDREXH(uint16_t *addr)
{
uint16_t result=0;
__ASM volatile ("ldrexh %0, [%1]" : "=r" (result) : "r" (addr) );
return(result);
}
/**
* @brief LDR Exclusive (32 bit)
*
* @param *addr address pointer
* @return value of (*address)
*
* Exclusive LDR command for 32 bit values
*/
uint32_t CMSIS_LDREXW(uint32_t *addr)
{
uint32_t result=0;
__ASM volatile ("ldrex %0, [%1]" : "=r" (result) : "r" (addr) );
return(result);
}
/**
* @brief STR Exclusive (8 bit)
*
* @param value value to store
* @param *addr address pointer
* @return successful / failed
*
* Exclusive STR command for 8 bit values
*/
uint32_t CMSIS_STREXB(uint8_t value, uint8_t *addr)
{
uint32_t result=0;
__ASM volatile ("strexb %0, %2, [%1]" : "=&r" (result) : "r" (addr), "r" (value) );
return(result);
}
/**
* @brief STR Exclusive (16 bit)
*
* @param value value to store
* @param *addr address pointer
* @return successful / failed
*
* Exclusive STR command for 16 bit values
*/
uint32_t CMSIS_STREXH(uint16_t value, uint16_t *addr)
{
uint32_t result=0;
__ASM volatile ("strexh %0, %2, [%1]" : "=&r" (result) : "r" (addr), "r" (value) );
return(result);
}
/**
* @brief STR Exclusive (32 bit)
*
* @param value value to store
* @param *addr address pointer
* @return successful / failed
*
* Exclusive STR command for 32 bit values
*/
uint32_t CMSIS_STREXW(uint32_t value, uint32_t *addr)
{
uint32_t result=0;
__ASM volatile ("strex %0, %2, [%1]" : "=&r" (result) : "r" (addr), "r" (value) );
return(result);
}
uint32_t CMSIS_get_IPSR(void)
{
uint32_t result=0;
__ASM volatile ("MRS %0, IPSR" : "=r" (result) );
return(result);
}
#elif (defined (__TASKING__)) /*------------------ TASKING Compiler ---------------------*/
/* TASKING carm specific functions */
/*
* The CMSIS functions have been implemented as intrinsics in the compiler.
* Please use "carm -?i" to get an up to date list of all instrinsics,
* Including the CMSIS ones.
*/
#endif
+739
View File
@@ -0,0 +1,739 @@
#ifndef INCLUDED_CMSIS_H
#define INCLUDED_CMSIS_H
#ifndef INCLUDED_STDINT_H
#define INCLUDED_STDINT_H
#include <stdint.h>
#endif /*INCLUDED_STDINT_H*/
/* ------------------------------------------------------------------------------------------------------------------ */
/* */
#define __CORTEX_M (0x03) /*!< Cortex core */
#if defined (__ICCARM__)
#include <intrinsics.h> /* IAR Intrinsics */
#endif
/**
* IO definitions
*
* define access restrictions to peripheral registers
*/
#ifdef __cplusplus
#define __I volatile /*!< defines 'read only' permissions */
#else
#define __I volatile const /*!< defines 'read only' permissions */
#endif /* __cplusplus */
#define __O volatile /*!< defines 'write only' permissions */
#define __IO volatile /*!< defines 'read / write' permissions */
/* ################### Compiler specific Intrinsics ########################### */
#if defined ( __CC_ARM )
#define __ASM __asm /*!< asm keyword for ARM Compiler */
#define __INLINE __inline /*!< inline keyword for ARM Compiler */
#elif defined ( __ICCARM__ )
#define __ASM __asm /*!< asm keyword for IAR Compiler */
#define __INLINE inline /*!< inline keyword for IAR Compiler. Only avaiable in High optimization mode! */
#elif defined ( __GNUC__ )
#define __ASM __asm /*!< asm keyword for GNU Compiler */
#define __INLINE inline /*!< inline keyword for GNU Compiler */
#elif defined ( __TASKING__ )
#define __ASM __asm /*!< asm keyword for TASKING Compiler */
#define __INLINE inline /*!< inline keyword for TASKING Compiler */
#endif
#if defined ( __CC_ARM ) /*------------------RealView Compiler -----------------*/
/* ARM armcc specific functions */
#define CMSIS_enable_fault_irq __enable_fiq
#define CMSIS_disable_fault_irq __disable_fiq
#define CMSIS_enable_irq __enable_irq
#define CMSIS_disable_irq __disable_irq
#define CMSIS_NOP __nop
#define CMSIS_WFI __wfi
#define CMSIS_WFE __wfe
#define CMSIS_SEV __sev
#define CMSIS_ISB() __isb(0)
#define CMSIS_DSB() __dsb(0)
#define CMSIS_DMB() __dmb(0)
#define CMSIS_REV __rev
#define CMSIS_RBIT __rbit
#define CMSIS_LDREXB(ptr) ((unsigned char ) __ldrex(ptr))
#define CMSIS_LDREXH(ptr) ((unsigned short) __ldrex(ptr))
#define CMSIS_LDREXW(ptr) ((unsigned int ) __ldrex(ptr))
#define CMSIS_STREXB(value, ptr) __strex(value, ptr)
#define CMSIS_STREXH(value, ptr) __strex(value, ptr)
#define CMSIS_STREXW(value, ptr) __strex(value, ptr)
/* intrinsic unsigned long long __ldrexd(volatile void *ptr) */
/* intrinsic int __strexd(unsigned long long val, volatile void *ptr) */
/* intrinsic void __enable_irq(); */
/* intrinsic void __disable_irq(); */
extern uint32_t CMSIS_get_IPSR(void);
/**
* @brief Return the Process Stack Pointer
*
* @return ProcessStackPointer
*
* Return the actual process stack pointer
*/
extern uint32_t CMSIS_get_PSP(void);
/**
* @brief Set the Process Stack Pointer
*
* @param topOfProcStack Process Stack Pointer
*
* Assign the value ProcessStackPointer to the MSP
* (process stack pointer) Cortex processor register
*/
extern void CMSIS_set_PSP(uint32_t topOfProcStack);
/**
* @brief Return the Main Stack Pointer
*
* @return Main Stack Pointer
*
* Return the current value of the MSP (main stack pointer)
* Cortex processor register
*/
extern uint32_t CMSIS_get_MSP(void);
/**
* @brief Set the Main Stack Pointer
*
* @param topOfMainStack Main Stack Pointer
*
* Assign the value mainStackPointer to the MSP
* (main stack pointer) Cortex processor register
*/
extern void CMSIS_set_MSP(uint32_t topOfMainStack);
/**
* @brief Reverse byte order in unsigned short value
*
* @param value value to reverse
* @return reversed value
*
* Reverse byte order in unsigned short value
*/
extern uint32_t CMSIS_REV16(uint16_t value);
/**
* @brief Reverse byte order in signed short value with sign extension to integer
*
* @param value value to reverse
* @return reversed value
*
* Reverse byte order in signed short value with sign extension to integer
*/
extern int32_t CMSIS_REVSH(int16_t value);
#if (__ARMCC_VERSION < 400000)
/**
* @brief Remove the exclusive lock created by ldrex
*
* Removes the exclusive lock which is created by ldrex.
*/
extern void CMSIS_CLREX(void);
/**
* @brief Return the Base Priority value
*
* @return BasePriority
*
* Return the content of the base priority register
*/
extern uint32_t CMSIS_get_BASEPRI(void);
/**
* @brief Set the Base Priority value
*
* @param basePri BasePriority
*
* Set the base priority register
*/
extern void CMSIS_set_BASEPRI(uint32_t basePri);
/**
* @brief Return the Priority Mask value
*
* @return PriMask
*
* Return state of the priority mask bit from the priority mask register
*/
extern uint32_t CMSIS_get_PRIMASK(void);
/**
* @brief Set the Priority Mask value
*
* @param priMask PriMask
*
* Set the priority mask bit in the priority mask register
*/
extern void CMSIS_set_PRIMASK(uint32_t priMask);
/**
* @brief Return the Fault Mask value
*
* @return FaultMask
*
* Return the content of the fault mask register
*/
extern uint32_t CMSIS_get_FAULTMASK(void);
/**
* @brief Set the Fault Mask value
*
* @param faultMask faultMask value
*
* Set the fault mask register
*/
extern void CMSIS_set_FAULTMASK(uint32_t faultMask);
/**
* @brief Return the Control Register value
*
* @return Control value
*
* Return the content of the control register
*/
extern uint32_t CMSIS_get_CONTROL(void);
/**
* @brief Set the Control Register value
*
* @param control Control value
*
* Set the control register
*/
extern void CMSIS_set_CONTROL(uint32_t control);
#else /* (__ARMCC_VERSION >= 400000) */
/**
* @brief Remove the exclusive lock created by ldrex
*
* Removes the exclusive lock which is created by ldrex.
*/
#define CMSIS_CLREX __clrex
/**
* @brief Return the Base Priority value
*
* @return BasePriority
*
* Return the content of the base priority register
*/
static __INLINE uint32_t CMSIS_get_BASEPRI(void)
{
register uint32_t __regBasePri __ASM("basepri");
return(__regBasePri);
}
/**
* @brief Set the Base Priority value
*
* @param basePri BasePriority
*
* Set the base priority register
*/
static __INLINE void CMSIS_set_BASEPRI(uint32_t basePri)
{
register uint32_t __regBasePri __ASM("basepri");
__regBasePri = (basePri & 0xff);
}
/**
* @brief Return the Priority Mask value
*
* @return PriMask
*
* Return state of the priority mask bit from the priority mask register
*/
static __INLINE uint32_t CMSIS_get_PRIMASK(void)
{
register uint32_t __regPriMask __ASM("primask");
return(__regPriMask);
}
/**
* @brief Set the Priority Mask value
*
* @param priMask PriMask
*
* Set the priority mask bit in the priority mask register
*/
static __INLINE void CMSIS_set_PRIMASK(uint32_t priMask)
{
register uint32_t __regPriMask __ASM("primask");
__regPriMask = (priMask);
}
/**
* @brief Return the Fault Mask value
*
* @return FaultMask
*
* Return the content of the fault mask register
*/
static __INLINE uint32_t CMSIS_get_FAULTMASK(void)
{
register uint32_t __regFaultMask __ASM("faultmask");
return(__regFaultMask);
}
/**
* @brief Set the Fault Mask value
*
* @param faultMask faultMask value
*
* Set the fault mask register
*/
static __INLINE void CMSIS_set_FAULTMASK(uint32_t faultMask)
{
register uint32_t __regFaultMask __ASM("faultmask");
__regFaultMask = (faultMask & 1);
}
/**
* @brief Return the Control Register value
*
* @return Control value
*
* Return the content of the control register
*/
static __INLINE uint32_t CMSIS_get_CONTROL(void)
{
register uint32_t __regControl __ASM("control");
return(__regControl);
}
/**
* @brief Set the Control Register value
*
* @param control Control value
*
* Set the control register
*/
static __INLINE void CMSIS_set_CONTROL(uint32_t control)
{
register uint32_t __regControl __ASM("control");
__regControl = control;
}
#endif /* __ARMCC_VERSION */
#elif (defined (__ICCARM__)) /*------------------ ICC Compiler -------------------*/
/* IAR iccarm specific functions */
#define CMSIS_enable_irq __enable_interrupt /*!< global Interrupt enable */
#define CMSIS_disable_irq __disable_interrupt /*!< global Interrupt disable */
static __INLINE void CMSIS_enable_fault_irq() { __ASM ("cpsie f"); }
static __INLINE void CMSIS_disable_fault_irq() { __ASM ("cpsid f"); }
#define CMSIS_NOP __no_operation /*!< no operation intrinsic in IAR Compiler */
static __INLINE void CMSIS_WFI() { __ASM ("wfi"); }
static __INLINE void CMSIS_WFE() { __ASM ("wfe"); }
static __INLINE void CMSIS_SEV() { __ASM ("sev"); }
static __INLINE void CMSIS_CLREX() { __ASM ("clrex"); }
/* intrinsic void CMSIS_ISB(void) */
/* intrinsic void CMSIS_DSB(void) */
/* intrinsic void CMSIS_DMB(void) */
/* intrinsic void CMSIS_set_PRIMASK(); */
/* intrinsic void CMSIS_get_PRIMASK(); */
/* intrinsic void CMSIS_set_FAULTMASK(); */
/* intrinsic void CMSIS_get_FAULTMASK(); */
/* intrinsic uint32_t CMSIS_REV(uint32_t value); */
/* intrinsic uint32_t CMSIS_REVSH(uint32_t value); */
/* intrinsic unsigned long __STREX(unsigned long, unsigned long); */
/* intrinsic unsigned long __LDREX(unsigned long *); */
/**
* @brief Return the Process Stack Pointer
*
* @return ProcessStackPointer
*
* Return the actual process stack pointer
*/
extern uint32_t CMSIS_get_PSP(void);
/**
* @brief Set the Process Stack Pointer
*
* @param topOfProcStack Process Stack Pointer
*
* Assign the value ProcessStackPointer to the MSP
* (process stack pointer) Cortex processor register
*/
extern void CMSIS_set_PSP(uint32_t topOfProcStack);
/**
* @brief Return the Main Stack Pointer
*
* @return Main Stack Pointer
*
* Return the current value of the MSP (main stack pointer)
* Cortex processor register
*/
extern uint32_t CMSIS_get_MSP(void);
/**
* @brief Set the Main Stack Pointer
*
* @param topOfMainStack Main Stack Pointer
*
* Assign the value mainStackPointer to the MSP
* (main stack pointer) Cortex processor register
*/
extern void CMSIS_set_MSP(uint32_t topOfMainStack);
/**
* @brief Reverse byte order in unsigned short value
*
* @param value value to reverse
* @return reversed value
*
* Reverse byte order in unsigned short value
*/
extern uint32_t CMSIS_REV16(uint16_t value);
/**
* @brief Reverse bit order of value
*
* @param value value to reverse
* @return reversed value
*
* Reverse bit order of value
*/
extern uint32_t CMSIS_RBIT(uint32_t value);
/**
* @brief LDR Exclusive (8 bit)
*
* @param *addr address pointer
* @return value of (*address)
*
* Exclusive LDR command for 8 bit values)
*/
extern uint8_t CMSIS_LDREXB(uint8_t *addr);
/**
* @brief LDR Exclusive (16 bit)
*
* @param *addr address pointer
* @return value of (*address)
*
* Exclusive LDR command for 16 bit values
*/
extern uint16_t CMSIS_LDREXH(uint16_t *addr);
/**
* @brief LDR Exclusive (32 bit)
*
* @param *addr address pointer
* @return value of (*address)
*
* Exclusive LDR command for 32 bit values
*/
extern uint32_t CMSIS_LDREXW(uint32_t *addr);
/**
* @brief STR Exclusive (8 bit)
*
* @param value value to store
* @param *addr address pointer
* @return successful / failed
*
* Exclusive STR command for 8 bit values
*/
extern uint32_t CMSIS_STREXB(uint8_t value, uint8_t *addr);
/**
* @brief STR Exclusive (16 bit)
*
* @param value value to store
* @param *addr address pointer
* @return successful / failed
*
* Exclusive STR command for 16 bit values
*/
extern uint32_t CMSIS_STREXH(uint16_t value, uint16_t *addr);
/**
* @brief STR Exclusive (32 bit)
*
* @param value value to store
* @param *addr address pointer
* @return successful / failed
*
* Exclusive STR command for 32 bit values
*/
extern uint32_t CMSIS_STREXW(uint32_t value, uint32_t *addr);
#elif (defined (__GNUC__)) /*------------------ GNU Compiler ---------------------*/
/* GNU gcc specific functions */
static __INLINE void CMSIS_enable_irq() { __ASM volatile ("cpsie i"); }
static __INLINE void CMSIS_disable_irq() { __ASM volatile ("cpsid i"); }
static __INLINE void CMSIS_enable_fault_irq() { __ASM volatile ("cpsie f"); }
static __INLINE void CMSIS_disable_fault_irq() { __ASM volatile ("cpsid f"); }
static __INLINE void CMSIS_NOP() { __ASM volatile ("nop"); }
static __INLINE void CMSIS_WFI() { __ASM volatile ("wfi"); }
static __INLINE void CMSIS_WFE() { __ASM volatile ("wfe"); }
static __INLINE void CMSIS_SEV() { __ASM volatile ("sev"); }
static __INLINE void CMSIS_ISB() { __ASM volatile ("isb"); }
static __INLINE void CMSIS_DSB() { __ASM volatile ("dsb"); }
static __INLINE void CMSIS_DMB() { __ASM volatile ("dmb"); }
static __INLINE void CMSIS_CLREX() { __ASM volatile ("clrex"); }
extern uint32_t CMSIS_get_IPSR(void);
/**
* @brief Return the Process Stack Pointer
*
* @return ProcessStackPointer
*
* Return the actual process stack pointer
*/
extern uint32_t CMSIS_get_PSP(void);
/**
* @brief Set the Process Stack Pointer
*
* @param topOfProcStack Process Stack Pointer
*
* Assign the value ProcessStackPointer to the MSP
* (process stack pointer) Cortex processor register
*/
extern void CMSIS_set_PSP(uint32_t topOfProcStack);
/**
* @brief Return the Main Stack Pointer
*
* @return Main Stack Pointer
*
* Return the current value of the MSP (main stack pointer)
* Cortex processor register
*/
extern uint32_t CMSIS_get_MSP(void);
/**
* @brief Set the Main Stack Pointer
*
* @param topOfMainStack Main Stack Pointer
*
* Assign the value mainStackPointer to the MSP
* (main stack pointer) Cortex processor register
*/
extern void CMSIS_set_MSP(uint32_t topOfMainStack);
/**
* @brief Return the Base Priority value
*
* @return BasePriority
*
* Return the content of the base priority register
*/
extern uint32_t CMSIS_get_BASEPRI(void);
/**
* @brief Set the Base Priority value
*
* @param basePri BasePriority
*
* Set the base priority register
*/
extern void CMSIS_set_BASEPRI(uint32_t basePri);
/**
* @brief Return the Priority Mask value
*
* @return PriMask
*
* Return state of the priority mask bit from the priority mask register
*/
extern uint32_t CMSIS_get_PRIMASK(void);
/**
* @brief Set the Priority Mask value
*
* @param priMask PriMask
*
* Set the priority mask bit in the priority mask register
*/
extern void CMSIS_set_PRIMASK(uint32_t priMask);
/**
* @brief Return the Fault Mask value
*
* @return FaultMask
*
* Return the content of the fault mask register
*/
extern uint32_t CMSIS_get_FAULTMASK(void);
/**
* @brief Set the Fault Mask value
*
* @param faultMask faultMask value
*
* Set the fault mask register
*/
extern void CMSIS_set_FAULTMASK(uint32_t faultMask);
/**
* @brief Return the Control Register value
*
* @return Control value
*
* Return the content of the control register
*/
extern uint32_t CMSIS_get_CONTROL(void);
/**
* @brief Set the Control Register value
*
* @param control Control value
*
* Set the control register
*/
extern void CMSIS_set_CONTROL(uint32_t control);
/**
* @brief Reverse byte order in integer value
*
* @param value value to reverse
* @return reversed value
*
* Reverse byte order in integer value
*/
extern uint32_t CMSIS_REV(uint32_t value);
/**
* @brief Reverse byte order in unsigned short value
*
* @param value value to reverse
* @return reversed value
*
* Reverse byte order in unsigned short value
*/
extern uint32_t CMSIS_REV16(uint16_t value);
/**
* @brief Reverse byte order in signed short value with sign extension to integer
*
* @param value value to reverse
* @return reversed value
*
* Reverse byte order in signed short value with sign extension to integer
*/
extern int32_t CMSIS_REVSH(int16_t value);
/**
* @brief Reverse bit order of value
*
* @param value value to reverse
* @return reversed value
*
* Reverse bit order of value
*/
extern uint32_t CMSIS_RBIT(uint32_t value);
/**
* @brief LDR Exclusive (8 bit)
*
* @param *addr address pointer
* @return value of (*address)
*
* Exclusive LDR command for 8 bit value
*/
extern uint8_t CMSIS_LDREXB(uint8_t *addr);
/**
* @brief LDR Exclusive (16 bit)
*
* @param *addr address pointer
* @return value of (*address)
*
* Exclusive LDR command for 16 bit values
*/
extern uint16_t CMSIS_LDREXH(uint16_t *addr);
/**
* @brief LDR Exclusive (32 bit)
*
* @param *addr address pointer
* @return value of (*address)
*
* Exclusive LDR command for 32 bit values
*/
extern uint32_t CMSIS_LDREXW(uint32_t *addr);
/**
* @brief STR Exclusive (8 bit)
*
* @param value value to store
* @param *addr address pointer
* @return successful / failed
*
* Exclusive STR command for 8 bit values
*/
extern uint32_t CMSIS_STREXB(uint8_t value, uint8_t *addr);
/**
* @brief STR Exclusive (16 bit)
*
* @param value value to store
* @param *addr address pointer
* @return successful / failed
*
* Exclusive STR command for 16 bit values
*/
extern uint32_t CMSIS_STREXH(uint16_t value, uint16_t *addr);
/**
* @brief STR Exclusive (32 bit)
*
* @param value value to store
* @param *addr address pointer
* @return successful / failed
*
* Exclusive STR command for 32 bit values
*/
extern uint32_t CMSIS_STREXW(uint32_t value, uint32_t *addr);
#elif (defined (__TASKING__)) /*------------------ TASKING Compiler ---------------------*/
/* TASKING carm specific functions */
/*
* The CMSIS functions have been implemented as intrinsics in the compiler.
* Please use "carm -?i" to get an up to date list of all instrinsics,
* Including the CMSIS ones.
*/
#endif
#endif /*INCLUDED_CMSIS_H*/
+63
View File
@@ -0,0 +1,63 @@
#include <dwt_delay.h>
extern uint32_t SystemCoreClock;
//定义需使能位
#define DEM_CR_TRCENA (1u<<24)
#define DWT_CR_CYCCNTENA (1u<<0)
//DWT init
void DWT_Init(void)
{
DEM_CR |= (uint32_t)DEM_CR_TRCENA;
DWT_CYCCNT = (uint32_t)0u;
DWT_CR |= (uint32_t)DWT_CR_CYCCNTENA;
}
void DWT_DelayUs(uint32_t us)
{
uint32_t start = DWT_CYCCNT;
uint32_t cycles = us * (SystemCoreClock / 1000000);
uint32_t elapsed;
while (1) {
uint32_t current = DWT_CYCCNT;
if (current >= start) {
elapsed = current - start;
} else {
elapsed = (0xFFFFFFFFu - start) + current; // 处理溢出
}
if (elapsed >= cycles) break;
}
}
void DWT_DelayMs(uint32_t ms)
{
for (uint32_t i = 0; i < ms; i++) {
DWT_DelayUs(1000);
}
}
//使用DWT测量函数运行时间
float DTW_Time_DiffMs(volatile uint32_t start, volatile uint32_t stop)
{
uint32_t diff;
if(stop > start)
diff = stop - start;
else
diff = stop + 0XFFFFFFFFu - start;
return (diff / (SystemCoreClock/1000));
}
float DTW_Time_DiffUs(volatile uint32_t start, volatile uint32_t stop)
{
uint32_t diff;
if(stop > start)
diff = stop - start;
else
diff = stop + 0XFFFFFFFFu - start;
return (diff / (SystemCoreClock/1000000));
}
+38
View File
@@ -0,0 +1,38 @@
#ifndef INCLUDED_DWT_DELAY_H
#define INCLUDED_DWT_DELAY_H
#ifndef INCLUDED_OS_TYPES_H
#include <os_types.h>
#endif /*INCLUDED_OS_TYPES_H*/
#ifndef INCLUDED_OS_COMPILER_H
#include <os_compiler.h>
#endif /*INCLUDED_OS_COMPILER_H*/
/* ------------------------------------------------------------------------------------------------------------------ */
/* */
//寄存器基地址
#define DWT_CR *(uint32_t*)0xE0001000
#define DWT_CYCCNT *(uint32_t*)0xE0001004
#define DEM_CR *(uint32_t*)0xE000EDFC
/* ------------------------------------------------------------------------------------------------------------------ */
/* */
OS_STATIC_FORCE_INLINE
uint32_t DWT_Get(void){
return ((uint32_t )DWT_CYCCNT);
}
void DWT_Init(void);
void DWT_DelayUs(uint32_t us);
void DWT_DelayMs(uint32_t ms);
float DTW_Time_DiffMs(volatile uint32_t start, volatile uint32_t stop);
float DTW_Time_DiffUs(volatile uint32_t start, volatile uint32_t stop);
#endif /*INCLUDED_DWT_DELAY_H*/
+25
View File
@@ -0,0 +1,25 @@
#include <os_loopdelay.h>
#if defined (__CC_ARM) /*!< ARM Compiler */
__asm void os_loop_delay(unsigned long ulCount)
{
subs r0, #1;
bne os_loop_delay;
bx lr;
}
#elif defined ( __ICCARM__ ) /*!< IAR Compiler */
void os_loop_delay(unsigned long ulCount)
{
__asm(" subs r0, #1 \n"
" bne.n os_loop_delay \n"
" bx lr");
}
#elif defined (__GNUC__) /*!< GNU Compiler */
__attribute__((naked))
void os_loop_delay(unsigned long ulCount){
__asm(" subs r0, #1 \n"
" bne os_loop_delay \n"
" bx lr");
}
#endif /* __CC_ARM */
+34
View File
@@ -0,0 +1,34 @@
#ifndef INCLUDED_OS_LOOPDELAY_H
#define INCLUDED_OS_LOOPDELAY_H
#ifndef INCLUDED_OS_TYPES_H
#include <os_types.h>
#endif /*INCLUDED_OS_TYPES_H*/
#define OS_LOOP_DELAY_US(n) (n * SystemCoreClock/3000000)
#define OS_LOOP_DELAY_MS(n) (n * SystemCoreClock/3000)
#define OS_LOOP_DELAY_S(n) (n * SystemCoreClock/3)
/*
72Mhz时钟时,当ulCount为1时,函数耗时3个时钟,延时=3*1/72us=1/24us
SystemCoreClock=72000000
us级延时,延时n微秒
LoopDelay(n*(SystemCoreClock/3000000));
ms级延时,延时n毫秒
LoopDelay(n*(SystemCoreClock/3000));
m级延时,延时n秒
LoopDelay(n*(SystemCoreClock/3));
*/
void os_loop_delay(unsigned long ulCount);
#define OS_LoopDelayUS(n) os_loop_delay(OS_LOOP_DELAY_US(n))
#define OS_LoopDelayMS(n) os_loop_delay(OS_LOOP_DELAY_MS(n))
#define OS_LoopDelayS(n) os_loop_delay(OS_LOOP_DELAY_S(n))
#endif /*INCLUDED_OS_LOOPDELAY_H*/
+1
View File
@@ -0,0 +1 @@
#include <os_mpu.h>
+250
View File
@@ -0,0 +1,250 @@
#ifndef INCLUDED_OS_MPU_H
#define INCLUDED_OS_MPU_H
#ifndef INCLUDED_OS_TYPES_H
#include <os_types.h>
#endif /*INCLUDED_OS_TYPES_H*/
#ifndef INCLUDED_OS_COMPILER_H
#include <os_compiler.h>
#endif /*INCLUDED_OS_COMPILER_H*/
#ifndef INCLUDED_CMSIS_H
#include <cmsis.h>
#endif /*INCLUDED_CMSIS_H*/
/* ------------------------------------------------------------------------------------------------------------------ */
/* */
typedef struct {
os_uintptr_t TYPE; /* 提供 MPU 信息 */
os_uintptr_t CTRL; /* MPU使能/禁止的背景区域控制 */
os_uintptr_t RNR; /* 选择待配置的MPU区域 */
os_uintptr_t RBAR; /* 定义MPU区域的基地址 */
os_uintptr_t RASR; /* 定义MPU区域的属性和大小 */
os_uintptr_t RBAR_A1; /* RBAR的别名 */
os_uintptr_t RBSR_A1; /* RASR的别名 */
os_uintptr_t RBAR_A2; /* RBAR的别名 */
os_uintptr_t RBSR_A2; /* RASR的别名 */
os_uintptr_t RBAR_A3; /* RBAR的别名 */
os_uintptr_t RBSR_A3; /* RASR的别名 */
}os_mpu_t;
#define OS_MPU ((os_mpu_t*)(0xE000ED90u))
OS_PACKED_STRUCT(os_mpu_type_t){
os_uint_t SEPARATE:1;
os_uint_t RESERVED_0:7;
os_uint_t DREGION:8;
os_uint_t IREGION:8;
os_uint_t RESERVED_1:8;
}os_mpu_type_t;
OS_PACKED_STRUCT(os_mpu_ctrl_t){
os_uint_t ENABLE:1;
os_uint_t HFNMIENA:1;
os_uint_t PRIVDEFENA:1;
os_uint_t RESERVED:29;
}os_mpu_ctrl_t;
OS_PACKED_STRUCT(os_mpu_rnr_t){
os_uint_t REGION:8;
os_uint_t RESERVED:24;
}os_mpu_rnr_t;
OS_PACKED_STRUCT(os_mpu_rbar_t){
os_uint_t REGION:4;
os_uint_t VALID:1;
os_uint_t ADDR:27;
}os_mpu_rbar_t;
OS_PACKED_STRUCT(os_mpu_rasr_t){
os_uint_t ENABLE:1; /* 区域使能 */
os_uint_t SIZE:5; /* MPU保护区域大小 */
os_uint_t RESERVED_0:2;
os_uint_t SRD:8; /* 子区域禁止 */
os_uint_t B:1; /* 可缓冲 */
os_uint_t C:1; /* 可缓存 */
os_uint_t S:1; /* 可共用 */
os_uint_t TEX:3; /* 类型展开域 */
os_uint_t RESERVED_1:2; /* 保留 */
os_uint_t AP:3; /* 数据访问允许域 */
os_uint_t RESERVED_2:1; /* 保留 */
os_uint_t XN:1; /* 指令访问禁止(1=禁止该区域的取值, 非要这么做会引发存储器管理错误) */
os_uint_t RESERVED_3:3; /* 保留 */
}os_mpu_rasr_t;
/* ------------------------------------------------------------------------------------------------------------------ */
/* */
#define OS_MPU_RASR_ENABLE_Pos 0
#define OS_MPU_RASR_SIZE_Pos 1
#define OS_MPU_RASR_SRD_Pos 8
#define OS_MPU_RASR_B_Pos 16
#define OS_MPU_RASR_C_Pos 17
#define OS_MPU_RASR_S_Pos 18
#define OS_MPU_RASR_TEX_Pos 19
#define OS_MPU_RASR_AP_Pos 24
#define OS_MPU_RASR_XN_Pos 28
#define OS_MPU_DEFS_RASR_SIZE_32B (0x04<<OS_MPU_RASR_SIZE_Pos)
#define OS_MPU_DEFS_RASR_SIZE_64B (0x05<<OS_MPU_RASR_SIZE_Pos)
#define OS_MPU_DEFS_RASR_SIZE_128B (0x06<<OS_MPU_RASR_SIZE_Pos)
#define OS_MPU_DEFS_RASR_SIZE_256B (0x07<<OS_MPU_RASR_SIZE_Pos)
#define OS_MPU_DEFS_RASR_SIZE_512B (0x08<<OS_MPU_RASR_SIZE_Pos)
#define OS_MPU_DEFS_RASR_SIZE_1KB (0x09<<OS_MPU_RASR_SIZE_Pos)
#define OS_MPU_DEFS_RASR_SIZE_2KB (0x0A<<OS_MPU_RASR_SIZE_Pos)
#define OS_MPU_DEFS_RASR_SIZE_4KB (0x0B<<OS_MPU_RASR_SIZE_Pos)
#define OS_MPU_DEFS_RASR_SIZE_8KB (0x0C<<OS_MPU_RASR_SIZE_Pos)
#define OS_MPU_DEFS_RASR_SIZE_16KB (0x0D<<OS_MPU_RASR_SIZE_Pos)
#define OS_MPU_DEFS_RASR_SIZE_32KB (0x0E<<OS_MPU_RASR_SIZE_Pos)
#define OS_MPU_DEFS_RASR_SIZE_64KB (0x0F<<OS_MPU_RASR_SIZE_Pos)
#define OS_MPU_DEFS_RASR_SIZE_128KB (0x10<<OS_MPU_RASR_SIZE_Pos)
#define OS_MPU_DEFS_RASR_SIZE_256KB (0x11<<OS_MPU_RASR_SIZE_Pos)
#define OS_MPU_DEFS_RASR_SIZE_512KB (0x12<<OS_MPU_RASR_SIZE_Pos)
#define OS_MPU_DEFS_RASR_SIZE_1MB (0x13<<OS_MPU_RASR_SIZE_Pos)
#define OS_MPU_DEFS_RASR_SIZE_2MB (0x14<<OS_MPU_RASR_SIZE_Pos)
#define OS_MPU_DEFS_RASR_SIZE_4MB (0x15<<OS_MPU_RASR_SIZE_Pos)
#define OS_MPU_DEFS_RASR_SIZE_8MB (0x16<<OS_MPU_RASR_SIZE_Pos)
#define OS_MPU_DEFS_RASR_SIZE_16MB (0x17<<OS_MPU_RASR_SIZE_Pos)
#define OS_MPU_DEFS_RASR_SIZE_32MB (0x18<<OS_MPU_RASR_SIZE_Pos)
#define OS_MPU_DEFS_RASR_SIZE_64MB (0x19<<OS_MPU_RASR_SIZE_Pos)
#define OS_MPU_DEFS_RASR_SIZE_128MB (0x1A<<OS_MPU_RASR_SIZE_Pos)
#define OS_MPU_DEFS_RASR_SIZE_256MB (0x1B<<OS_MPU_RASR_SIZE_Pos)
#define OS_MPU_DEFS_RASR_SIZE_512MB (0x1C<<OS_MPU_RASR_SIZE_Pos)
#define OS_MPU_DEFS_RASR_SIZE_1GB (0x1D<<OS_MPU_RASR_SIZE_Pos)
#define OS_MPU_DEFS_RASR_SIZE_2GB (0x1E<<OS_MPU_RASR_SIZE_Pos)
#define OS_MPU_DEFS_RASR_SIZE_4GB (0x1F<<OS_MPU_RASR_SIZE_Pos)
#define OS_MPU_DEFS_RASR_AP_NO_ACCESS (0x0 << OS_MPU_RASR_AP_Pos)
#define OS_MPU_DEFS_RASR_AP_PRIV_RW (0x1 << OS_MPU_RASR_AP_Pos)
#define OS_MPU_DEFS_RASR_AP_PRIV_RW_USER_RO (0x2 << OS_MPU_RASR_AP_Pos)
#define OS_MPU_DEFS_RASR_AP_PRIV_FULL_ACCESS (0x3 << OS_MPU_RASR_AP_Pos)
#define OS_MPU_DEFS_RASR_AP_PRIV_RO (0x5 << OS_MPU_RASR_AP_Pos)
#define OS_MPU_DEFS_RASR_AP_RO (0x6 << OS_MPU_RASR_AP_Pos)
#define OS_MPU_RASR_B_Msk (1<<OS_MPU_RASR_B_Pos)
#define OS_MPU_RASR_C_Msk (1<<OS_MPU_RASR_C_Pos)
#define OS_MPU_RASR_S_Msk (1<<OS_MPU_RASR_S_Pos)
#define OS_MPU_RASR_TEX_Msk (0x7<<OS_MPU_RASR_TEX_Pos)
#define OS_MPU_RASR_SIZE_Msk (0x1f<<OS_MPU_RASR_SIZE_Pos)
#define OS_MPU_RASR_ENABLE_Msk (0x1<<OS_MPU_RASR_ENABLE_Pos)
#define OS_MPU_RASR_XN_Msk (0x1<<OS_MPU_RASR_XN_Pos)
#define OS_MPU_RASR_SRD_Msk (0xff<<OS_MPU_RASR_SRD_Pos)
#define OS_MPU_DEFS_RASR_SRD_DISABLE (0x00 << OS_MPU_RASR_SRD_Pos)
#define OS_MPU_DEFS_RASR_TEX_LEVEL0 (0x0 << OS_MPU_RASR_TEX_Pos)
#define OS_MPU_DEFS_RASR_TEX_LEVEL1 (0x1 << OS_MPU_RASR_TEX_Pos)
#define OS_MPU_DEFS_RASR_TEX_LEVEL2 (0x2 << OS_MPU_RASR_TEX_Pos)
#define OS_MPU_DEFS_NORMAL_MEMORY_WT (OS_MPU_RASR_C_Msk)
#define OS_MPU_DEFS_NORMAL_MEMORY_WB (OS_MPU_RASR_C_Msk | OS_MPU_RASR_B_Msk)
#define OS_MPU_DEFS_NORMAL_MEMORY_SHARED_WT (OS_MPU_RASR_C_Msk | OS_MPU_RASR_S_Msk)
#define OS_MPU_DEFS_NORMAL_MEMORY_SHARED_WB (OS_MPU_DEFS_NORMAL_MEMORY_WB | OS_MPU_RASR_S_Msk)
#define OS_MPU_DEFS_SHARED_DEVICE (OS_MPU_RASR_B_Msk | OS_MPU_RASR_S_Msk)
#define OS_MPU_DEFS_EXTERNAL_MEMORY (OS_MPU_RASR_C_Msk | OS_MPU_RASR_B_Msk | OS_MPU_RASR_S_Msk)
#define OS_MPU_DEFS_STRONGLY_ORDERED_DEVICE (0x0)
#define OS_MPU_ACCESS_CACHEABLE (OS_MPU_RASR_C_Msk)
#define OS_MPU_ACCESS_BUFFERABLE (OS_MPU_RASR_B_Msk)
#define OS_MPU_ACCESS_SHAREABLE (OS_MPU_RASR_S_Msk)
#define OS_MPU_ACCESS_NOT_CACHEABLE (0x00 << OS_MPU_RASR_C_Pos)
#define OS_MPU_ACCESS_NOT_BUFFERABLE (0x00 << OS_MPU_RASR_B_Pos)
#define OS_MPU_ACCESS_NOT_SHAREABLE (0x00 << OS_MPU_RASR_S_Pos)
#define OS_MPU_CTRL_ENABLE_Pos (0)
#define OS_MPU_CTRL_HFNMIENA_Pos (1)
#define OS_MPU_CTRL_PRIVDEFENA_Pos (2)
#define OS_MPU_CTRL_ENABLE_Msk (1<<OS_MPU_CTRL_ENABLE_Pos)
#define OS_MPU_CTRL_HFNMIENA_Msk (1<<OS_MPU_CTRL_HFNMIENA_Pos)
#define OS_MPU_CTRL_PRIVDEFENA_Msk (1<<OS_MPU_CTRL_PRIVDEFENA_Pos)
#define OS_MPU_RBAR_REGION_Pos 0
#define OS_MPU_RBAR_VALID_Pos 4
#define OS_MPU_RBAR_VALID_Msk (1<<OS_MPU_RBAR_VALID_Pos)
#define OS_MPU_RBAR_REGION_Msk (0xf << OS_MPU_RBAR_REGION_Pos)
#define OS_MPU_DEFS_RBAR_VALID_DISABLE (0<<OS_MPU_RBAR_VALID_Pos)
/* ------------------------------------------------------------------------------------------------------------------ */
/* */
OS_STATIC_FORCE_INLINE
void os_mpu_enable(os_uint_t options){
OS_MPU->CTRL = OS_MPU_CTRL_ENABLE_Msk | options;
CMSIS_DSB();
CMSIS_ISB();
}
OS_STATIC_FORCE_INLINE
void os_mpu_disable(void){
CMSIS_DMB();
OS_MPU->CTRL = 0;
}
OS_STATIC_FORCE_INLINE
void os_mpu_region_disable(os_uint_t region_num){
OS_MPU->RNR = region_num;
OS_MPU->RBAR = 0;
OS_MPU->RASR = 0;
}
OS_STATIC_FORCE_INLINE
void os_mpu_region_config(os_uint_t region_num, os_uintptr_t addr, os_size_t size, os_uint_t attribute){
OS_MPU->RNR = region_num;
OS_MPU->RBAR = addr;
OS_MPU->RASR = ((size << OS_MPU_RASR_SIZE_Pos) & OS_MPU_RASR_SIZE_Msk) | attribute;
}
/* ------------------------------------------------------------------------------------------------------------------ */
/* Example */
#if 0
/* 以下是 MPU 配置示例 */
int mpu_setup(void){
if(OS_MPU->TYPE == 0){ return 1; /* 错误 */ }
os_mpu_disable();
/* 0 - Flash */
os_mpu_region_config(0
, 0x08000000
, OS_MPU_DEFS_RASR_SIZE_1MB
, OS_MPU_DEFS_NORMAL_MEMORY_WT | OS_MPU_DEFS_RASR_AP_PRIV_FULL_ACCESS | OS_MPU_RASR_ENABLE_Msk);
/* 1 - SRAM */
os_mpu_region_config(1
, 0x20000000
, OS_MPU_DEFS_RASR_SIZE_128KB
, OS_MPU_DEFS_NORMAL_MEMORY_WT | OS_MPU_DEFS_RASR_AP_PRIV_FULL_ACCESS | OS_MPU_RASR_ENABLE_Msk);
/* 2 - GPIOD */
os_mpu_region_config(2
, GPIOD_BASE
, OS_MPU_DEFS_RASR_SIZE_1KB
, OS_MPU_DEFS_SHARED_DEVICE | OS_MPU_DEFS_RASR_AP_PRIV_FULL_ACCESS | OS_MPU_RASR_ENABLE_Msk);
/* 3 - 复位时钟 */
os_mpu_region_config(3
, RCC_BASE
, OS_MPU_DEFS_RASR_SIZE_1KB
, OS_MPU_DEFS_SHARED_DEVICE | OS_MPU_DEFS_RASR_AP_PRIV_FULL_ACCESS | OS_MPU_RASR_ENABLE_Msk);
os_mpu_region_disable(4);
os_mpu_region_disable(5);
os_mpu_region_disable(6);
os_mpu_region_disable(7);
os_mpu_enable(0); /* 使能MPU,无需其它设置 */
return 0; /* 无错误 */
}
#endif /* 0 */
#endif /*INCLUDED_OS_MPU_H*/
+247
View File
@@ -0,0 +1,247 @@
#include "os_port.h"
#include "os_stack.h"
#include "os_macros.h"
#include "os_align.h"
#include "cmsis.h"
#include "os_compiler.h"
#include "os_systick.h"
#include "os_sched.h"
/* ------------------------------------------------------------------------------------------------------------------ */
/* */
#define OS_PORT_SYSCALL_ID 0x00
#define OS_PORT_SYSCALL_OP_SAVE_DISABLE_IRQ 0x00
#define OS_PORT_SYSCALL_OP_RESTORE_IRQ 0x01
#define OS_PORT_SYSCALL_OP_SCHED 0x02
/* ------------------------------------------------------------------------------------------------------------------ */
/* */
volatile os_uint_t svc_exc_return;
/* ------------------------------------------------------------------------------------------------------------------ */
/* */
OS_STATIC_FORCE_INLINE
int is_cpu_in_privilege(void){
// 1. 检查是否在中断/异常中 (IPSR != 0 表示 Handler 模式)
if ( CMSIS_get_IPSR() != 0) {
return 1;
}
// 2. 如果在 Thread 模式,检查 CONTROL 寄存器
return ((CMSIS_get_CONTROL() & 0x01) == 0)?1:0;
}
#if defined(__CC_ARM) /* armcc (AC5) */
#define SVC_CALL_ARGS0(num, type, name) \
__svc(num) type name(void);
#define SVC_CALL_ARGS1(num, type, name, a0) \
__svc(num) type name(os_uintptr_t a0);
#define SVC_CALL_ARGS2(num, type, name, a0, a1) \
__svc(num) type name(os_uintptr_t a0, os_uintptr_t a1);
#define SVC_CALL_ARGS3(num, type, name, a0, a1, a2) \
__svc(num) type name(os_uintptr_t a0, os_uintptr_t a1, os_uintptr_t a2);
#define SVC_CALL_ARGS4(num, type, name, a0, a1, a2, a3) \
__svc(num) type name(os_uintptr_t a0, os_uintptr_t a1, os_uintptr_t a2, os_uintptr_t a3);
#elif defined(__GNUC__) /* gcc */
#define SVC_CALL_ARGS0(num, type, name) \
static type name(void) { \
register os_uintptr_t r0 __asm__("r0")=0; \
__asm__ volatile ("svc " #num : : : "memory"); \
return (type)r0; \
}
#define SVC_CALL_ARGS1(num, type, name, a1) \
OS_STATIC_FORCE_INLINE type name(os_uintptr_t a1) { \
register os_uintptr_t r0 __asm__("r0") = a1; \
__asm__ volatile ("svc " #num :"=r"(r0):"r"(r0) : "memory"); \
return (type)r0; \
}
#define SVC_CALL_ARGS2(num, type, name, a1, a2) \
OS_STATIC_FORCE_INLINE type name(os_uintptr_t a1, os_uintptr_t a2) { \
register os_uintptr_t r0 __asm__("r0") = a1;\
register os_uintptr_t r1 __asm__("r1") = a2;\
__asm__ volatile ("svc " #num :"=r"(r0) :"r"(r0), "r"(r1) : "memory"); \
return (type)r0; \
}
#define SVC_CALL_ARGS3(num, type, name, a1, a2, a3) \
OS_STATIC_FORCE_INLINE type name(os_uintptr_t a1, os_uintptr_t a2, os_uintptr_t a3) { \
register os_uintptr_t r0 __asm__("r0") = a1; \
register os_uintptr_t r1 __asm__("r1") = a2; \
register os_uintptr_t r2 __asm__("r2") = a3; \
__asm__ volatile ("svc " #num :"=r"(r0) :"r"(r0), "r"(r1), "r"(r2) : "memory"); \
return (type)r0; \
}
#define SVC_CALL_ARGS4(num, type, name, a1, a2, a3, a4) \
OS_STATIC_FORCE_INLINE type name(os_uintptr_t a1, os_uintptr_t a2, os_uintptr_t a3, os_uintptr_t a4) { \
register os_uintptr_t r0 __asm__("r0") = a1; \
register os_uintptr_t r1 __asm__("r1") = a2; \
register os_uintptr_t r2 __asm__("r2") = a3; \
register os_uintptr_t r3 __asm__("r3") = a4; \
__asm__ volatile ("svc " #num :"=r"(r0) :"r"(r0), "r"(r1), "r"(r2), "r"(r3) : "memory"); \
return (type)r0; \
}
#endif
SVC_CALL_ARGS1(0, os_uint_t, os_port_svc0_args1, a1)
SVC_CALL_ARGS2(0, void, os_port_svc0_args2, a1, a2)
OS_STATIC_FORCE_INLINE
os_uint_t os_port_save_disable_irq_in_svc(void){
return os_port_svc0_args1(OS_PORT_SYSCALL_OP_SAVE_DISABLE_IRQ);
}
OS_STATIC_FORCE_INLINE
void os_port_restore_irq_in_svc(os_uint_t level){
os_port_svc0_args2(OS_PORT_SYSCALL_OP_RESTORE_IRQ, level);
}
OS_STATIC_FORCE_INLINE
void os_port_sched_in_svc(void){
os_port_svc0_args1(OS_PORT_SYSCALL_OP_SCHED);
}
/* ------------------------------------------------------------------------------------------------------------------ */
/* */
typedef struct {
/* ==== 以下为手动压栈部分 ==== */
os_uintptr_t exc_return; /* r2 - LR */ /* 这是地址最小的位置 */
os_uintptr_t control; /* r3 */
os_uintptr_t r4;
os_uintptr_t r5;
os_uintptr_t r6;
os_uintptr_t r7;
os_uintptr_t r8;
os_uintptr_t r9;
os_uintptr_t r10;
os_uintptr_t r11;
/* ==== 以下为自动压栈部分 ==== */
os_uintptr_t r0;
os_uintptr_t r1;
os_uintptr_t r2;
os_uintptr_t r3;
os_uintptr_t r12;
os_uintptr_t lr;
os_uintptr_t pc;
os_uintptr_t xPSR;
}os_stack_frame_t;
#define STACK_FRAME_SIZE sizeof(os_stack_frame_t)
os_stack_t os_port_cpu_stack_init(os_task_entry_t entry, void* param
, void* stack_base, os_size_t stack_size, void(*exit_entry)(void)){
os_uintptr_t stack_max = (os_uintptr_t)((uint8_t *) stack_base + stack_size);
os_uintptr_t real_max = OS_ALIGN_DOWN(stack_max, OS_ALIGN_SIZE); /* 实际栈顶的位置,对齐后的位置 */
stack_size -= (stack_max - real_max); /* 实际栈大小 */
os_stack_frame_t* p_frame = (os_stack_frame_t*)(real_max - STACK_FRAME_SIZE);
for(os_size_t i=0; i<STACK_FRAME_SIZE/sizeof(os_uintptr_t); i++){
((os_uintptr_t*)(p_frame))[i] = 0x5ac0ffee;
}
p_frame->r0 = (os_uintptr_t)param; /* 任务参数 */
p_frame->pc = (os_uintptr_t)entry; /* 任务入口 */
p_frame->lr = (os_uintptr_t)exit_entry; /* 退出地址 */
p_frame->xPSR = (1u << 24); /* THUMB */
p_frame->control = 0x03; /* 任务使用用户权限,栈使用 PSP */
p_frame->exc_return = 0xFFFFFFFDul; /* 任务在中断中切换,这里是退出中断的设置 */
os_stack_t stack;
stack.min = (os_uintptr_t)stack_base;
stack.max = (os_uintptr_t)real_max;
stack.type = kOsStackType_MaxToMin;
stack.sp = p_frame;
return stack;
}
void os_port_disable_irq(void){
CMSIS_disable_irq();
}
void os_port_enable_irq(void){
CMSIS_enable_irq();
}
os_uint_t os_port_save_disable_irq(void){
if(is_cpu_in_privilege()){
return os_port_save_disable_irq_in_isr();
}else{
return os_port_save_disable_irq_in_svc();
}
}
void os_port_restore_irq(os_uint_t level){
if(is_cpu_in_privilege()){
os_port_restore_irq_in_isr(level);
}else{
os_port_restore_irq_in_svc(level);
}
}
os_uint_t os_port_save_disable_irq_in_isr(void){
os_uint_t level = CMSIS_get_BASEPRI();
CMSIS_set_BASEPRI((OS_CFG_SYSCALL_PRIORITY+1) << 4);
return level;
}
void os_port_restore_irq_in_isr(os_uint_t level){
CMSIS_set_BASEPRI(level);
}
void os_sched(void){
if(is_cpu_in_privilege()){
os_sched_in_isr();
}else{
os_port_sched_in_svc();
}
}
void SVC_Handler_C(os_uintptr_t* svc_args){
// 读取系统调用号:它存储在原本的 PC 指令前两个字节
uint8_t svc_number = ((uint8_t *)svc_args[6])[-2];
switch (svc_number) {
case OS_PORT_SYSCALL_ID:{
os_uint_t op = svc_args[0];
switch (op) {
case OS_PORT_SYSCALL_OP_SAVE_DISABLE_IRQ:{
svc_args[0] = os_port_save_disable_irq_in_isr();
break;
}
case OS_PORT_SYSCALL_OP_RESTORE_IRQ:{
os_port_restore_irq_in_isr(svc_args[1]);
break;
}
case OS_PORT_SYSCALL_OP_SCHED:{
os_sched_in_isr();
break;
}
default:
break;
}
break;
}
default: break;
}
}
void SysTick_Handler(void){
os_systick_tick();
}
+70
View File
@@ -0,0 +1,70 @@
.syntax unified
.thumb
.section .text.PendSV_Handler,"ax",%progbits
.global g_os_port_switch_from_sp
.global g_os_port_switch_to_sp
.global PendSV_Handler
.thumb_func
PendSV_Handler:
mrs r1, primask //
cpsid i //
PUSH {R1}
LDR R1, =g_os_port_switch_from_sp //
LDR R1, [R1] // g_os_port_switch_from_sp
CBZ R1, __PendSV_SwitchTo
/* ---- 压栈 ---- */
MRS R0, PSP
MOV R2, LR
MRS R3, CONTROL
STMDB R0!, {R2-R11}
/* ---- sp值保存到变量中 ---- */
STR R0, [R1] // sp R0
__PendSV_SwitchTo:
BL os_port_on_switch_success //
/* ---- 加载目标栈 ---- */
LDR R2, =g_os_port_switch_to_sp //
LDR R2, [R2] //
LDR R0, [R2] // sp
LDMIA R0!, {R2-R11} // R2-R11
MOV LR, R2 // LR
MSR CONTROL, R3 // CONTROL , ISR 退 ISR
ISB // CONTROL
MSR PSP, R0 // PSP
POP {R1}
MSR PRIMASK, R1 //
BX LR
.section .text.SVC_Handler,"ax",%progbits
.global SVC_Handler
.global svc_exc_return
.global SVC_Handler_C
.type SVC_Handler, %function
SVC_Handler:
tst lr, #4 // EXC_RETURN (LR) 2
ite eq
mrseq r0, msp // 2 0 MSP
mrsne r0, psp // 2 1 PSP
ldr r1, =svc_exc_return
str lr, [r1]
bl SVC_Handler_C // C r0
ldr r1, =svc_exc_return
ldr lr, [r1]
bx lr
.section .text.cpu_clz,"ax",%progbits
.global cpu_clz
.thumb_func
cpu_clz:
CLZ R0, R0
BX LR
.align 4
.end