# OSLIB
---
### 1.代码结构
```
├─can/
├─oslib_can // CAN发送接收管理
├─oslib_can_dispatch // CAN接收分发器
├─oslib_can_example // CAN接收任务范例
├─uart/
├─oslib_uart // UART发送接收管理
├─oslib_uart_cmd // UART命令行
├─utils/
├─oslib_hash // 通用哈希表
├─debug/
├─oslib_debug // 按调试等级区分输出内容
├─SEGGER_RTT // RTT调试
├─app/
├─cmd_func // [可修改]指定命令以及回调函数
├─can_func // [可修改]can消息接收处理
├─oslib // OSLIB初始化相关
└─oslib_config // [可修改]OSLIB功能裁剪
```
### 2.配置说明
##### 2.1 使用CubeMX进行配置
> OSLIB使用了HAL库, 推荐使用CubeMX进行配置。以下参数仅供参考。
- 基本配置
- *System Core\RCC\Mode*
- `HSE`: 自定
- `LSE`: 自定
- *System Core\SYS\Mode*:
- `Debug`: Serial Wire
- `Timebase Source`: **TIM1**(这里可以选择任意一个定时器)
- *..\Clock Configuration*:
- `HCLK(MHz)`: 自定
- FreeRTOS配置
- *Middleware\FREERTOS\Mode*:
- `Interface`: **CMSIS_V2**
- *Middleware\FREERTOS\Configuration\Config parameters*:
- `USE_STATS_FORMATTING_FUNCTIONS`: Enabled
- UART配置
- *Connectivity\USART1\Mode*:
- `Mode`: Asynchronous
- *Connectivity\USART1\Configuration\NVIC Settings*:
- `USART1 global interrupt`: ✔
- *Connectivity\USART1\Configuration\DMA Settings*:
- 点击`Add`添加 USART1_RX
- `Mode`: **Circular**
- 点击`Add`添加 USART1_TX
- CAN配置
- *Connectivity\CAN1\Mode*:
- `Master Mode`: ✔
- *Connectivity\CAN1\Configuration\Parameter Settings*:
- `Time Quanta in Bit Segment 2`: 4 Times
- (如果使用f103此处为2 Times)
- `Time Quanta in Bit Segment 1`: 9 Times
- `Prescaler(for Time Quantum)`: 3
- `Automatic Bus-Off Management`: Enable
- `Transmit Fifo Priority`: Enable
- *Connectivity\CAN1\Configuration\NVIC Settings*:
- `CAN1 TX interrupts`: ✔
- `CAN1 RX0 interrupts`: ✔
- `CAN1 RX1 interrupts`: ✔
##### 2.2 使用前的准备
- 将所需要的OSLIB代码和头文件添加到工程中
- 一个目录即为一个模块,其中头文件只需要添加oslib根目录即可
- 需要注意的是:
- 使用串口命令行模块, 需要额外添加app目录下的cmd_func系列文件和utils目录下的oslib_hash系列文件
- 使用CAN接收处理模块, 需要额外添加app目录下的can_func系列文件和utils目录下的oslib_hash系列文件
- 添加部分代码
- 文件*stm32f4xx_it.c*t添加: (上下注释用来定位)
```c
/* USER CODE BEGIN Includes */
#include "oslib.h"
/* USER CODE END Includes */
```
函数`void USART1_IRQHandler(void)`中添加: (上下两行注释用来定位)
```c
/* USER CODE BEGIN USART1_IRQn 0 */
if(__HAL_UART_GET_FLAG(&huart1, UART_FLAG_IDLE))
OSLIB_UART_RxIdleCallback(&huart1);
else
/* USER CODE END USART1_IRQn 0 */
```
- 文件*freertos.c*添加: (上下注释用来定位)
```c
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "oslib.h"
/* USER CODE END Includes */
```
函数 `void MX_FREERTOS_Init(void)`中添加: (上下两行注释用来定位)
```c
/* USER CODE BEGIN Init */
OSLIB_Init();
/* USER CODE END Init */
```
> 注意: CubeMX版本不同生成的代码可能有差别, 如果MX_FREERTOS_Init()函数内调用了osKernelInitialize()函数, 请把OSLIB_Init()放到osKernelInitialize()函数之后.
- 在oslib_config.h中进行配置
- OSLIB主要通过宏进行功能的选择, 宏的类型及其基本含义如下:
- `xxx_ENABLED`: 允许使用某模块/外设. 只需要将该宏注释掉即可表示不使用该模块.
- `USE_xxx`: 使用某功能. 主要针对OSLIB中各模块的子功能. 0或1表示是否使用功能.
- `SELECT_xxx`: 选择. 要求从允许的多个值中选择一个值作为该宏的值.
- 范例: 假设使用了CAN1, UART1, UART6. 将UART1作为命令行串口, 配置如下:
```c
#define OSLIB_DEBUG_MODULE_ENABLED // 调试输出功能
#define OSLIB_UART_MODULE_ENABLED // 串口功能
#define OSLIB_CAN_MODULE_ENABLED // CAN功能
/*------------------------------------------------------*/
#define UART1_ENABLED // 使用UART1
// #define UART2_ENABLED
// #define UART3_ENABLED
// #define UART4_ENABLED
// #define UART5_ENABLED
#define UART6_ENABLED
#define CAN1_ENABLED // 使用CAN1
// #define CAN2_ENABLED
/*------------------------------------------------------*/
#define SELECT_DEBUG_LEVEL DEBUG // 调试输出等级为DEBUG
#define USE_OSLIB_UART_CLI 1 // 使用串口命令行
#define SELECT_MAJOR_UART 1 // 主串口为1, 即命令行的串口为UART1
#define USE_OSLIB_CAN_CALLBACK 1 // 允许使用回调方式处理CAN报文
#define USE_OSLIB_CAN_EXAMPLE 1 // 使用CAN范例任务处理CAN报文
```
> 注意: oslib_config.h中有上下两个保留区域, 其中的内容不允许被修改.
##### 2.3 特别注意
- 禁止在中断中调用信号量等待函数(比如`osSemaphoreAcquire()`),以及调用该函数的函数(比如`OSLIB_Uart_Printf()`和`OSLIB_CAN_SendMessage()`)。
- 使用CubeMX生成的代码可能会颠倒DMA初始化`MX_DMA_Init()`和USART1初始化`MX_USART1_UART_Init()`, 需要手动调整。
- 使用较高版本(比如6.0.0)的CubeMX生成代码可能出现中断优先级默认为0的情况, 其他版本通常为5, 这时需要在NVIC配置中调低部分中断优先级。
- 当使用SRAM容量较小的芯片时, 可能出现默认的堆空间不足的情况, 需要在CubeMX里将FREERTOS选项中的堆空间调大。
### 3. 模块说明
##### 3.1 UART管理模块
- 模块目录: .\uart\
- 依赖模块: .\utils\oslib_hash
- 基本功能: ①多任务环境下避免串口发送冲突 ②缓存串口接收到的数据, 便于使用任务处理
- 发送接口: (\*表示衍生的宏, 本质上依赖于其他接口函数)
- `void OSLIB_Uart_Printf(huart, fmt, ...)` - **函数**, 通过指定串口发送格式化字符串
- `void OSLIB_Uart_SendData(huart, msg, size)` - **函数**, 通过指定串口发送任意数据
- \* `void uprintf(fmt, ...)` - **宏**, 通过主串口发送格式化字符串
- \* `void uprintf_to(huart, fmt, ...)` - **宏**, 通过指定串口发送格式化字符串
- DMA接收接口: (要求oslib_config.h中的宏`SELECT_UARTx_RXMODE`为0)
- `osSemaphoreId_t UARTx_RxSema` - **信号量**, 对应串口x接收情况
- `char UARTx_TaskBuffer[RxBufferSize]` - **缓冲区**, 得到信号量之后, 可以从缓冲区中取出数据进行处理
- `int UARTx_TaskBufferSize` - **接收数据的长度**, 得到信号量之后,可以通过该变量得到此次接收数据的长度
- IT接收接口: (要求oslib_config.h中的宏`SELECT_UARTx_RXMODE`为1)
- `osMessageQueueId_t UARTx_RxQueue` - **消息队列**, 存储串口x收到的字符
- 子功能: 创建命令行处理任务, 解析并执行主串口的接收到的命令.
- 功能裁剪: 宏`USE_OSLIB_UART_CLI`决定是否启用这一子功能, 宏`SELECT_MAJOR_UART`用于选择主串口, 即命令行所使用的串口.
- 命令格式: `<命令1> <参数表1>;<命令2> <参数表2>;<命令3> <参数表3>`
- 参数表可以为空. 如果不为空, 各参数之间用空格分隔, 一条命令的参数不能超过10个.
- 输入多条命令时, 两命令间用分号分割, 多条命令将会被依次执行. 一次输入的命令数不能超过5个, 第5条之后的命令不会被执行.
- 基本命令:
| 命令 | 说明 | 命令格式示例