问题/功能背景描述
提出此问题的背景:使用SD卡或者U盘烧写镜像时只能看着串口终端是否烧写完成,在批量烧写时不方便,所以通过led灯的闪烁来判断烧写是否完成。
1. 烧录led灯实现函数
int sprite_led_init(void)
{
user_gpio_set_t gpio_init;
int ret = 0;
int delay = 0;
sprite_led_status = 1;
//正常工作时,灯闪烁的时间
ret = script_parser_fetch("/soc/card_boot", "sprite_work_delay",
(void *)&delay, 0);
if (!delay) {
delay = 500;
}
pr_msg("try sprite_led_gpio config\n");
memset(&gpio_init, 0, sizeof(user_gpio_set_t));
//配置输出gpio口
ret = fdt_get_one_gpio(FDT_PATH_CARD_BOOT, "sprite_gpio0", &gpio_init);
if (!ret) {
if (gpio_init.port) {
sprite_led_hd = sunxi_gpio_request(&gpio_init, 1);
if (!sprite_led_hd) {
pr_err("reuqest gpio for led failed\n");
return 1;
}
TIMER0.data = (unsigned long)&TIMER0;
TIMER0.expires = delay;
TIMER0.function = sprite_timer_func;
//init_timer(&TIMER0);
add_timer(&TIMER0);
tick_printf("sprite_led_gpio start\n");
return 0;
}
}
return 0;
}
1.1. 代码解析
这段代码是一个函数 sprite_led_init,用于初始化一个 LED 灯的 GPIO 控制。
- 变量初始化和设置:
user_gpio_set_t gpio_init;
int ret = 0;
int delay = 0;
sprite_led_status = 1;
-
- gpio_init 是一个结构体类型 user_gpio_set_t,用于存储 GPIO 初始化的参数。
- ret 和 delay 是整型变量,ret 用于存储函数返回值,delay 用于存储灯闪烁的时间。
- sprite_led_status 被设置为 1,可能是用来记录 LED 灯的状态。
- 读取灯闪烁时间:
ret = script_parser_fetch("/soc/card_boot", "sprite_work_delay", (void *)&delay, 0);
-
- 从 /soc/card_boot 这个路径下的配置文件中读取 sprite_work_delay 的值,这个值用于设定 LED 灯闪烁的时间。如果读取失败或者值为 0,则将 delay 设置为默认值 500。
- GPIO 初始化和配置:
pr_msg("try sprite_led_gpio config\n");
memset(&gpio_init, 0, sizeof(user_gpio_set_t));
-
- 输出日志信息,表示正在尝试配置 LED 的 GPIO。
- 使用 memset 将 gpio_init 结构体清零,确保初始化时各字段的初始状态。
- 获取 GPIO 配置:
ret = fdt_get_one_gpio(FDT_PATH_CARD_BOOT, "sprite_gpio0", &gpio_init);
-
- 调用 fdt_get_one_gpio 函数从设备树中获取 sprite_gpio0 的配置信息,填充到 gpio_init 结构体中。
- GPIO 请求:
if (!ret) {
if (gpio_init.port) {
sprite_led_hd = sunxi_gpio_request(&gpio_init, 1);
if (!sprite_led_hd) {
pr_err("reuqest gpio for led failed\n");
return 1;
}
// 成功请求到 GPIO 后,设置定时器和回调函数
TIMER0.data = (unsigned long)&TIMER0;
TIMER0.expires = delay;
TIMER0.function = sprite_timer_func;
add_timer(&TIMER0); // 启动定时器
tick_printf("sprite_led_gpio start\n");
return 0;
}
}
-
- 如果成功获取了 GPIO 的配置信息 (ret 为 0),并且 gpio_init.port 不为 0,则表示获取到了有效的 GPIO 口。
- 调用 sunxi_gpio_request 函数请求这个 GPIO 口。如果请求失败 (sprite_led_hd 为 0),则打印错误信息并返回 1。
- 如果成功请求到 GPIO 口,则设置定时器 TIMER0:
- 将定时器的数据域、超时时间和回调函数设置好。
- 调用 add_timer 启动定时器。
- 输出日志信息表示 GPIO 初始化成功,并返回 0 表示初始化成功。
- 函数返回:
- 如果无法获取或配置 GPIO (ret 不为 0 或者 gpio_init.port 为 0),则直接返回 0,表示初始化失败或者无需进一步处理。
这段代码的主要功能是根据设备树中的配置,初始化一个 GPIO 控制的 LED 灯,并设置定时器来控制 LED 的闪烁频率。
2. 定时函数
static void sprite_timer_func(void *p)
{
gpio_write_one_pin_value(sprite_led_hd, sprite_led_status,
"sprite_gpio0");
sprite_led_status = (~sprite_led_status) & 0x01;
//printf("sprite_time_func\n");
del_timer(&TIMER0);
add_timer(&TIMER0);
return;
}
2.1. 代码解析
- 函数定义:
static void sprite_timer_func(void *p)
-
- sprite_timer_func 是一个静态函数,返回类型为 void,接受一个 void* 类型的参数 p,通常用于传递定时器的上下文信息,但在这段代码中没有使用该参数。
- GPIO 控制:
gpio_write_one_pin_value(sprite_led_hd, sprite_led_status, "sprite_gpio0");
-
- gpio_write_one_pin_value 函数用于控制一个 GPIO 引脚的输出电平。
- sprite_led_hd 是之前初始化时获取的 GPIO 控制句柄。
- sprite_led_status 是一个变量,用来记录当前 LED 灯的状态,通过该变量来控制 GPIO 引脚的输出状态。
- LED 状态切换:
sprite_led_status = (~sprite_led_status) & 0x01;
-
- 这行代码通过按位取反和按位与操作,实现 LED 状态的切换。如果 sprite_led_status 当前为 0,则取反后变为 1;如果当前为 1,则取反后变为 0。
- 定时器操作:
del_timer(&TIMER0);
add_timer(&TIMER0);
-
- del_timer(&TIMER0) 用于删除当前定时器 TIMER0,确保在重新添加之前没有冲突。
- add_timer(&TIMER0) 重新添加定时器 TIMER0,以便在下一次定时器超时后再次调用 sprite_timer_func 函数,从而实现周期性的 LED 灯闪烁效果。
- 函数返回:
return;
-
- 函数结束并返回,没有返回值。
这段代码的作用是在定时器超时时被调用,用于控制一个 GPIO 引脚,通过改变引脚的输出状态来实现 LED 灯的周期性闪烁。