一、内核基础组件
1、字符流先入先出队列
概述
字符流先入先出队列,提供的是一个面向字符操作的环形队列实现,提供了基本的字符流入队出队操作。本质上就是环形队列中元素为字符(单字节长度)时的特例,实际上字符流先出先出队列底层的实现就是环形队列。
API讲解
编程实例
1、编写main.c示例代码:
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "usart.h"
#include "gpio.h"
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "cmsis_os.h"
#include "stdio.h"
#include "tos_k.h"
/* USER CODE END Includes */
/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */
#define STK_SIZE_TASK_DEMO 512
#define PRIO_TASK_DEMO 4
k_stack_t stack_task_demo[STK_SIZE_TASK_DEMO];
k_task_t task_demo;
#define FIFO_BUFFER_SIZE 5
uint8_t fifo_buffer[FIFO_BUFFER_SIZE];
k_chr_fifo_t fifo;
extern void entry_task_demo(void *arg);
/* USER CODE END PTD */
/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
/* USER CODE END PD */
/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */
void char_push(void)
{
k_err_t err;
int i = 0;
uint8_t data;
// 往fifo中压入FIFO_BUFFER_SIZE个字符,分别是a、b、c、d、e
for (i = 0; i < FIFO_BUFFER_SIZE; ++i) {
printf("char pushed: %c\n", 'a' + i);
err = tos_chr_fifo_push(&fifo, 'a' + i);
if (err != K_ERR_NONE) {
printf("should never happen\n");
}
}
// fifo最多包含FIFO_BUFFER_SIZE个字符,上文逻辑中已经压入了最大的字符量,此时继续压入字符会返回K_ERR_FIFO_FULL(fifo已满)
err = tos_chr_fifo_push(&fifo, 'z');
if (err == K_ERR_RING_Q_FULL) {
printf("fifo is full: %s\n", tos_chr_fifo_is_full(&fifo) ? "TRUE" : "FALSE");
} else {
printf("should never happen\n");
}
// 从fifo中把所有的字符都弹出来
for (i = 0; i < FIFO_BUFFER_SIZE; ++i) {
err = tos_chr_fifo_pop(&fifo, &data);
if (err == K_ERR_NONE) {
printf("%d pop: %c\n", i, data);
} else {
printf("should never happen\n");
}
}
// 此时继续弹出字符,会返回K_ERR_FIFO_EMPTY(fifo已空)
err = tos_chr_fifo_pop(&fifo, &data);
if (err == K_ERR_RING_Q_EMPTY) {
printf("fifo is empty: %s\n", tos_chr_fifo_is_empty(&fifo) ? "TRUE" : "FALSE");
} else {
printf("should never happen\n");
}
}
void stream_push(void)
{
int count = 0, i = 0;
uint8_t stream[FIFO_BUFFER_SIZE] = { 'a', 'b', 'c', 'd', 'e' };
uint8_t stream_dummy[1] = { 'z' };
uint8_t stream_pop[FIFO_BUFFER_SIZE];
// 压入字符流,字符流的长度是5,不超过fifo的最大长度FIFO_BUFFER_SIZE,会压入成功,并返回压入字符流的长度5
count = tos_chr_fifo_push_stream(&fifo, &stream[0], FIFO_BUFFER_SIZE);
if (count != FIFO_BUFFER_SIZE) {
printf("should never happen\n");
}
// 继续压入字符流(即使是长度为1的字符流),因fifo已满无法继续压入,返回长度0(压入失败)
count = tos_chr_fifo_push_stream(&fifo, &stream_dummy[0], 1);
if (count == 0) {
printf("fifo is full: %s\n", tos_chr_fifo_is_full(&fifo) ? "TRUE" : "FALSE");
} else {
printf("should never happen\n");
}
// 将前文中压入的字符流全部弹出,返回前文压入的字符流长度5(弹出的字符流长度)
count = tos_chr_fifo_pop_stream(&fifo, &stream_pop[0], FIFO_BUFFER_SIZE);
if (count == FIFO_BUFFER_SIZE) {
printf("stream popped:\n");
for (i = 0; i < FIFO_BUFFER_SIZE; ++i) {
printf("%c", stream_pop[i]);
}
printf("\n");
} else {
printf("should never happen\n");
}
// 继续弹出,因fifo已空,返回0
count = tos_chr_fifo_pop_stream(&fifo, &stream_pop[0], 1);
if (count == 0) {
printf("fifo is empty: %s\n", tos_chr_fifo_is_empty(&fifo) ? "TRUE" : "FALSE");
} else {
printf("should never happen\n");
}
}
void entry_task_demo(void *arg)
{
// 创建了一个最多包含FIFO_BUFFER_SIZE个字符的fifo
tos_chr_fifo_create(&fifo, &fifo_buffer[0], FIFO_BUFFER_SIZE);
printf("fifo, dealing with char\n");
char_push();
printf("fifo, dealing with stream\n");
stream_push();
}
/* USER CODE END PM */
/* Private variables ---------------------------------------------------------*/
/* USER CODE BEGIN PV */
/* USER CODE END PV */
/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
/* USER CODE BEGIN PFP */
/* USER CODE END PFP */
/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
/* USER CODE END 0 */
/**
* @brief The application entry point.
* @retval int
*/
int main(void)
{
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */
/* MCU Configuration--------------------------------------------------------*/
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* USER CODE BEGIN Init */
/* USER CODE END Init */
/* Configure the system clock */
SystemClock_Config();
/* USER CODE BEGIN SysInit */
/* USER CODE END SysInit */
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_USART1_UART_Init();
/* USER CODE BEGIN 2 */
tos_knl_init();
(void)tos_task_create(&task_demo, "demo", entry_task_demo, NULL,
PRIO_TASK_DEMO, stack_task_demo, STK_SIZE_TASK_DEMO, 0);
tos_knl_start();
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
}
2、运行效果:
源码链接