我还记得当初学51单片机导师与我们说,当你点亮一盏灯,那么你已经学会了80%,就当个笑话吧,但也不是并无道理
源码路径esp-idf/examples/get-started/blink
#include <stdio.h>#include "freertos/FreeRTOS.h"#include "freertos/task.h"#include "driver/gpio.h"#include "sdkconfig.h"/* Can run 'make menuconfig' to choose the GPIO to blink,or you can edit the following line and set a number here.*/#define BLINK_GPIO CONFIG_BLINK_GPIOvoid blink_task(void *pvParameter){/* Configure the IOMUX register for pad BLINK_GPIO (some pads aremuxed to GPIO on reset already, but some default to otherfunctions and need to be switched to GPIO. Consult theTechnical Reference for a list of pads and their defaultfunctions.)*/gpio_pad_select_gpio(BLINK_GPIO);/* Set the GPIO as a push/pull output */gpio_set_direction(BLINK_GPIO, GPIO_MODE_OUTPUT);while(1) {/* Blink off (output low) */gpio_set_level(BLINK_GPIO, 0);vTaskDelay(1000 / portTICK_PERIOD_MS);/* Blink on (output high) */gpio_set_level(BLINK_GPIO, 1);vTaskDelay(1000 / portTICK_PERIOD_MS);}}void app_main(){xTaskCreate(&blink_task, "blink_task", configMINIMAL_STACK_SIZE, NULL, 5, NULL);}
分析代码:(可以看到乐鑫已经为我们写好了大量API,只需调用相应API就能够完成对芯片底层寄存器的操作)
1.入口函数app_main中创建了一个任务blink_task,下面来简单分析一下FreeRTOS的任务创建函数xTaskCreate:
原型:实质上是调用了xTaskCreatePinnedToCore
static inline IRAM_ATTR BaseType_t xTaskCreate(TaskFunction_t pvTaskCode,const char * const pcName,const uint32_t usStackDepth,void * const pvParameters,UBaseType_t uxPriority,TaskHandle_t * const pvCreatedTask){return xTaskCreatePinnedToCore( pvTaskCode, pcName, usStackDepth, pvParameters, uxPriority, pvCreatedTask, tskNO_AFFINITY );}BaseType_t xTaskCreatePinnedToCore(TaskFunction_t pvTaskCode,const char * const pcName,const uint32_t usStackDepth,void * const pvParameters,UBaseType_t uxPriority,TaskHandle_t * const pvCreatedTask,const BaseType_t xCoreID);
在内部,在FreeRTOS实现中,任务使用两块内存。第一个块用于保存任务的数据结构。任务将第二个块用作其堆栈。如果使用xTaskCreate()创建任务,则会在xTaskCreate()函数内自动动态分配两个内存块。有兴趣可看以下网址/a00111.html
pvTaskCode
:指向任务输入功能的指针。必须实现任务以永不返回(即连续循环)。pcName
:任务的描述性名称。这主要用于方便调试。由configMAX_TASK_NAME_LEN定义的最大长度 - 默认值为16。usStackDepth
:任务堆栈的大小指定为堆栈可以容纳的变量数 - 而不是字节数。例如,如果堆栈为16位宽且usStackDepth定义为100,则将为堆栈存储分配200个字节。pvParameters
:指针将用作正在创建的任务的参数。uxPriority
:任务应运行的优先级。包含MPU支持的系统可以选择通过设置优先级参数的位portPRIVILEGE_BIT以特权(系统)模式创建任务。例如,要以优先级2创建特权任务,应将uxPriority参数设置为(2 | portPRIVILEGE_BIT)。pvCreatedTask
:用于传回一个句柄,通过该句柄可以引用创建的任务。xCoreID
:如果值为tskNO_AFFINITY,则创建的任务不会固定到任何CPU,并且调度程序可以在任何可用的核心上运行它。其他值表示任务应固定到的CPU的索引号。指定大于(portNUM_PROCESSORS - 1)的值将导致函数失败。
2.分析blink_task函数是如何点亮一盏灯的:
void gpio_pad_select_gpio(uint8_t gpio_num); //选择某个引脚作为gpio功能,已封装成库,只能找到声明
esp_err_t gpio_set_direction(gpio_num_t gpio_num, gpio_mode_t mode); //设置gpio的模式,如输入输出
esp_err_t gpio_set_level(gpio_num_t gpio_num, uint32_t level); //设置gpio电平