一、內核基礎組件
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、運行效果:
源碼鏈接:Git