RTOS技术:实时处理、缓冲技术与功能安全
立即解锁
发布时间: 2025-08-16 01:19:42 阅读量: 1 订阅数: 4 


Cortex-M处理器系列的设计与开发指南
### RTOS 技术:实时处理、缓冲技术与功能安全
#### 1. 计数器与看门狗管理
计数器 0 会开始递增。当达到最大线程停滞计数(即 5)时,会触发断点。再次启动代码运行后,`ThreadIsStalled` 变量会被设置,这会使监控线程停止喂狗,微控制器将被复位,从而导致应用程序重启。这种 RTOS 中的电源和看门狗管理方法具有简单的优点,适用于大多数低功耗应用。所有代码都包含在两个文件中,便于在多个项目中复用。
#### 2. 启动屏障
在开始使用新的微控制器或添加低功耗代码时,在代码中添加“启动屏障”是个不错的做法。在开发早期,配置系统外设时,可能会意外使微控制器进入异常状态,导致难以或无法通过 CoreSight 调试端口进行连接。也可能添加的代码会使芯片进入掉电状态,同样无法连接调试器。若出现这种情况,就无法擦除闪存并对内存进行编程。“启动屏障”是一个小函数,只有当特定的模式出现在特定的 RAM 内存位置时,代码才能继续执行。
以下是相关代码:
```c
volatile uint32_t debuggerAttached __attribute__((at(0x2000FFFC)));
void startupBarrier (void)
{
if(debuggerAttached != 0x55555555){
__BKPT(0);
}
}
```
这个函数在 `system_init()` 的第一行调用,在可能影响 Cortex - M 处理器的代码执行之前。若构建带有“启动屏障”的程序并下载到闪存中,程序会开始执行,然后陷入屏障函数,这样就能保证可以擦除和重新编程闪存。要越过“启动屏障”,可以向调试器添加一个脚本文件,将屏障模式编程到 RAM 中。
#### 3. 实时设计与缓冲技术
##### 3.1 双缓冲或循环缓冲
开发第一个实时 DSP 应用时,首先要决定如何缓冲来自 ADC 的输入数据块和发送到 DAC 的输出数据块。典型的解决方案是使用双缓冲。当 Ping 缓冲区被 ADC 数据填充时,DSP 算法处理 Pong 缓冲区中的数据。当 ADC 填充完 Ping 缓冲区后,会开始向 Pong 缓冲区存储数据,Ping 缓冲区中的新数据则可以被处理。类似的乒乓结构也可用于缓冲输出到 DAC 的数据。
双缓冲的优点是信号延迟最小,但要求 DSP 算法频繁运行,在执行其他软件例程时难以保持实时性能。
##### 3.2 FIFO 内存池
可以使用由一组事件标志控制访问的内存池对象来实现输入和输出双缓冲。使用 RTX RTOS 可以创建一个线程来运行 DSP 算法,该线程的输入和输出是一对内存池数据块。以所需采样率运行的定时器中断触发 ADC 转换,结果用于填充数据块。当块满时,DSP 线程处理该块,同时第二个块被新的 ADC 数据填充。DSP 线程使用 CMSIS DSP 库处理 ADC 数据块,并生成输出块,在每个定时器中断时将一个样本发送到 DAC。
以下是相关代码示例:
```c
typedef struct _DSP_DataType {
q15_t Sample[DSP_BLOCKSIZE];
} DSP_DataType;
DSP_MemPool = osMemoryPoolNew (4, sizeof(DSP_DataType), NULL);
pDataTimIrqOut = osMemoryPoolAlloc(DSP_MemPool, 0);
pDataSigModOut = osMemoryPoolAlloc(DSP_MemPool, 0);
dataTimIrqOutIdx = 0;
dataTimIrqInIdx = 0;
DSP_Event = osEventFlagsNew(NULL);
```
定时器中断可分为两部分:第一部分采样 ADC 并填充活动内存池,第二部分将过滤后的样本从输出内存池块写入 DAC。
以下是 ADC 处理部分的简化代码:
```c
void TIMER2_IRQHandler(void) {
uint32_t adGdr; int32_t flags; osStatus_t status; q15_t tmp;
adGdr = LPC_ADC->ADGDR;
//get ADC sample
arm_float_to_q15(&adGdr, &tmp, 1);
// Convert to Q15
pDataTimIrqOut->Sample[dataTimIrqOutIdx+1] = tmp;
//Write to the memory pool block
//and increment index
if (dataTimIrqOutIdx >= DSP_BLOCKSIZE){
//if the memory pool block is full
pDataSigModIn = pDataTimIrqOut;
//Hand over to the DSP pointer
flags = osEventFlagsSet(DSP_Event, EVENT_DATA_TIM_OUT_SIG_IN);
//Signal DSP Thread
pDataTimIrqOut = osMemoryPoolAlloc(DSP_MemPool, 0);
//Allocate a new block
dataTimIrqOutIdx = 0;
//Reset the block index
}
}
```
主 DSP 线程等待 `EVENT_DATA_TIM_OUT_SIG_IN` 事件标志被设置,标志被设置后,处理 ADC 数据块并生成输出块,然后设置 `EVENT_DATA_TIM_IN_SIG_OUT` 事件标志通知定时器中断有输出数据块可用。
以下是 DSP 线程的代码:
```c
void SigMod (void __attrib
```
0
0
复制全文
相关推荐









