我还记得当初学51单片机导师与我们说,当你点亮一盏灯,那么你已经学会了80%,就当个笑话吧,但也不是并无道理
源码路径esp-idf/examples/get-started/blink
#include
#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_GPIO
void blink_task(void *pvParameter)
{
/* Configure the IOMUX register for pad BLINK_GPIO (some pads are
muxed to GPIO on reset already, but some default to other
functions and need to be switched to GPIO. Consult the
Technical Reference for a list of pads and their default
functions.)
*/
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()函数内自动动态分配两个内存块。有兴趣可看以下网址https://www.freertos.org/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电平