Linux第93步_Linux内核的LED灯驱动
Linux内核的LED灯驱动采用platfomm框架,因此我们只需要按照要求在“设备树文件”中添加相应的LED节点即可。
1 、通过“linux内核图形化配置界面”令“CONFIG_LEDS_GPIO=y”
1)、打开终端,输入“cd linux/atk-mp1/linux/my_linux/linux-5.4.31/回车”,切换到“linux/atk-mp1/linux/my_linux/linux-5.4.31/”目录;输入“make menuconfig回车”,打开linux内核图形化配置界面:
2)、移动“向下光标键”至“Device Drivers”,见下图:
3)、按“回车键”,得到下图:
4)、移动“向下光标键”至“LED Support”,见下图:
5)、按“回车键”,得到下图:
6)、移动“向下光标键”至“LED Support for GPIO connected LEDs”,见下图:
7)、按下“Y”键,使此选项前面变为“<*>”,即选中Linux内核自带的LED驱动。然后按“TAB键”至“Exit”,再按“回车”退出,直至到达下面这个界面:
8)、按“TAB键”至“Save”,按下“回车”,得到下面的界面。
9)、输入“./arch/arm/configs/stm32mp1_atk_defconfig”,移动“向下光标键”至“Ok”,得到下图:
10)、按“回车”,保存完成。得到下面的界面。
11)、按“回车”,退出。
12)、按两次“ESC键”,得到下图:
2、打开“./arch/arm/configs/stm32mp1_atk_defconfig”,查看“CONFIG_LEDS_GPIO=y”。
1)、输入“vi ./arch/arm/configs/stm32mp1_atk_defconfig回车”,打开“stm32mp1_atk_defconfig”文件,见下图:
2)、按“ESC键”,按下“/”,后,输入“CONFIG_LEDS_GPIO回车”,搜索“CONFIG_LEDS_GPIO”,见下图:
3)、发现“CONFIG_LEDS_GPIO=y”,按“ESC键”,按“:q!回车”,不保存退出;
3、查看LED灯驱动文件“/home/zgq/linux/atk-mp1/linux/my_linux/linux-5.4.31/drivers/leds/ leds-gpio.c”
1)、使用虚拟机中的VSCode打开文件夹“/home/zgq/linux/atk-mp1/linux/my_linux/linux-5.4.31/drivers/leds”,见下图:
2)、点击“确定”,然后打开“leds-gpio.c”和“Makefile”,并在“Makefile”中搜索“CONFIG_LEDS_GPIO”,见下图:
在前面的配置中,“CONFIG_LEDS_GPIO”被定义了,则输出“leds-gpio.o”。
3)、打开“leds-gpio.c”,找到“of_device_id of_gpio_leds_match[]”,见下图:
下面是驱动的匹配表:
static const struct of_device_id of_gpio_leds_match[] = {
{ .compatible = "gpio-leds", },/*这是驱动中的compatible属性*/
{}, /*这是一个空元素,在编写of_device_id时最后一个元素一定要为空*/
};
下面是platform driver驱动结构体变量
static struct platform_driver gpio_led_driver = {
.probe = gpio_led_probe,/*probe函数为gpio_led_probe()*/
.shutdown = gpio_led_shutdown,
.driver = {
.name = "leds-gpio",/*指定驱动名字为“leds-gpio”*/
.of_match_table = of_gpio_leds_match,
},
}
4)、打开“include/linux/platform_device.h”文件,查看“module_platform_driver”。见下图:
“module_platform_driver函数”用来向linux内核注册platform驱动,这是一个宏。
#define module_platform_driver(__platform_driver) \
module_driver(__platform_driver, platform_driver_register, \
platform_driver_unregister)
#define module_driver(__driver, __register, __unregister, ...) \
static int __init __driver##_init(void) \
{ \
return __register(&(__driver) , ##__VA_ARGS__); \
} \
module_init(__driver##_init); \
static void __exit __driver##_exit(void) \
{ \
__unregister(&(__driver) , ##__VA_ARGS__); \
} \
module_exit(__driver##_exit);
因此module_platform_driver(gpio_led_driver)展开后,就是:
static int __init gpio_led_driver_init(void)
{
return platform_driver_register (&(gpio_led_driver));
//向Linux内核注册一个platform驱动
}
module_init(gpio_led_driver_init);
static void __exit gpio_led_driver_exit(void)
{
platform_driver_unregister (&(gpio_led_driver) );
//卸载一个platform驱动
}
module_exit(gpio_led_driver_exit);
4、分析“leds-gpio.c”文件
// SPDX-License-Identifier: GPL-2.0-only
/*
* LEDs driver for GPIOs
*
* Copyright (C) 2007 8D Technologies inc.
* Raphael Assenat <raph@8d.com>
* Copyright (C) 2008 Freescale Semiconductor, Inc.
*/
#include <linux/err.h>
#include <linux/gpio.h>
#include <linux/gpio/consumer.h>
#include <linux/kernel.h>
#include <linux/leds.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/platform_device.h>
#include <linux/property.h>
#include <linux/slab.h>
struct gpio_led_data {
struct led_classdev cdev;
struct gpio_desc *gpiod;
u8 can_sleep;
u8 blinking;
gpio_blink_set_t platform_gpio_blink_set;
};
static inline struct gpio_led_data *
cdev_to_gpio_led_data(struct led_classdev *led_cdev)
{
return container_of(led_cdev, struct gpio_led_data, cdev);
}
static void gpio_led_set( struct led_classdev *led_cdev,
enum led_brightness value)
{
struct gpio_led_data *led_dat = cdev_to_gpio_led_data(led_cdev);
int level;
if (value == LED_OFF)
level = 0;
else
level = 1;
if (led_dat->blinking) {
led_dat->platform_gpio_blink_set(led_dat->gpiod, level,
NULL, NULL);
led_dat->blinking = 0;
} else {
if (led_dat->can_sleep)
gpiod_set_value_cansleep(led_dat->gpiod, level);
else
gpiod_set_value(led_dat->gpiod, level);
}
}
static int gpio_led_set_blocking(struct led_classdev *led_cdev,
enum led_brightness value)
{
gpio_led_set(led_cdev, value);
return 0;
}
static int gpio_blink_set(struct led_classdev *led_cdev,
unsigned long *delay_on, unsigned long *delay_off)
{
struct gpio_led_data *led_dat = cdev_to_gpio_led_data(led_cdev);
led_dat->blinking = 1;
return led_dat->platform_gpio_blink_set(led_dat->gpiod, GPIO_LED_BLINK,
delay_on, delay_off);
}
static int create_gpio_led(const struct gpio_led *template,
struct gpio_led_data *led_dat, struct device *parent,
struct fwnode_handle *fwnode, gpio_blink_set_t blink_set)
{
struct led_init_data init_data = {};
int ret, state;
led_dat->cdev.default_trigger = template->default_trigger;
led_dat->can_sleep = gpiod_cansleep(led_dat->gpiod);
if (!led_dat->can_sleep)
led_dat->cdev.brightness_set = gpio_led_set;
else
led_dat->cdev.brightness_set_blocking = gpio_led_set_blocking;
led_dat->blinking = 0;
if (blink_set) {
led_dat->platform_gpio_blink_set = blink_set;
led_dat->cdev.blink_set = gpio_blink_set;
}
if (template->default_state == LEDS_GPIO_DEFSTATE_KEEP) {
state = gpiod_get_value_cansleep(led_dat->gpiod);
if (state < 0)
return state;
} else {
state = (template->default_state == LEDS_GPIO_DEFSTATE_ON);
}
led_dat->cdev.brightness = state ? LED_FULL : LED_OFF;
if (!template->retain_state_suspended)
led_dat->cdev.flags |= LED_CORE_SUSPENDRESUME;
if (template->panic_indicator)
led_dat->cdev.flags |= LED_PANIC_INDICATOR;
if (template->retain_state_shutdown)
led_dat->cdev.flags |= LED_RETAIN_AT_SHUTDOWN;
ret = gpiod_direction_output(led_dat->gpiod, state);
if (ret < 0)
return ret;
if (template->name) {
led_dat->cdev.name = template->name;
ret = devm_led_classdev_register(parent, &led_dat->cdev);
} else {
init_data.fwnode = fwnode;
ret = devm_led_classdev_register_ext(parent, &led_dat->cdev,
&init_data);
}
return ret;
}
struct gpio_leds_priv {
int num_leds;
struct gpio_led_data leds[];
};
static inline int sizeof_gpio_leds_priv(int num_leds)
{
return sizeof(struct gpio_leds_priv) +
(sizeof(struct gpio_led_data) * num_leds);
}
static struct gpio_leds_priv *gpio_leds_create(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct fwnode_handle *child;
struct gpio_leds_priv *priv;
int count, ret;
count = device_get_child_node_count(dev);//统计子节点量
if (!count)
return ERR_PTR(-ENODEV);
priv = devm_kzalloc(dev, sizeof_gpio_leds_priv(count), GFP_KERNEL);
if (!priv)
return ERR_PTR(-ENOMEM);
device_for_each_child_node(dev, child) {
struct gpio_led_data *led_dat = &priv->leds[priv->num_leds];
struct gpio_led led = {};
const char *state = NULL;
/*
* Acquire gpiod from DT with uninitialized label, which
* will be updated after LED class device is registered,
* Only then the final LED name is known.
*/
led.gpiod = devm_fwnode_get_gpiod_from_child(dev, NULL, child,
GPIOD_ASIS,
NULL);
if (IS_ERR(led.gpiod)) {
fwnode_handle_put(child);
return ERR_CAST(led.gpiod);
}
led_dat->gpiod = led.gpiod;
fwnode_property_read_string(child, "linux,default-trigger",
&led.default_trigger);
if (!fwnode_property_read_string(child, "default-state",
&state)) {
if (!strcmp(state, "keep"))
led.default_state = LEDS_GPIO_DEFSTATE_KEEP;
else if (!strcmp(state, "on"))
led.default_state = LEDS_GPIO_DEFSTATE_ON;
else
led.default_state = LEDS_GPIO_DEFSTATE_OFF;
}
if (fwnode_property_present(child, "retain-state-suspended"))
led.retain_state_suspended = 1;
if (fwnode_property_present(child, "retain-state-shutdown"))
led.retain_state_shutdown = 1;
if (fwnode_property_present(child, "panic-indicator"))
led.panic_indicator = 1;
ret = create_gpio_led(&led, led_dat, dev, child, NULL);
if (ret < 0) {
fwnode_handle_put(child);
return ERR_PTR(ret);
}
/* Set gpiod label to match the corresponding LED name. */
gpiod_set_consumer_name(led_dat->gpiod,
led_dat->cdev.dev->kobj.name);
priv->num_leds++;
}
return priv;
}
static const struct of_device_id of_gpio_leds_match[] = {
{ .compatible = "gpio-leds", }, /*这是驱动中的compatible属性*/
{}, /*这是一个空元素,在编写of_device_id时最后一个元素一定要为空*/
};
MODULE_DEVICE_TABLE(of, of_gpio_leds_match);
static struct gpio_desc *gpio_led_get_gpiod(struct device *dev, int idx,
const struct gpio_led *template)
{
struct gpio_desc *gpiod;
unsigned long flags = GPIOF_OUT_INIT_LOW;
int ret;
/*
* This means the LED does not come from the device tree
* or ACPI, so let's try just getting it by index from the
* device, this will hit the board file, if any and get
* the GPIO from there.
*/
gpiod = devm_gpiod_get_index(dev, NULL, idx, flags);
if (!IS_ERR(gpiod)) {
gpiod_set_consumer_name(gpiod, template->name);
return gpiod;
}
if (PTR_ERR(gpiod) != -ENOENT)
return gpiod;
/*
* This is the legacy code path for platform code that
* still uses GPIO numbers. Ultimately we would like to get
* rid of this block completely.
*/
/* skip leds that aren't available */
if (!gpio_is_valid(template->gpio))
return ERR_PTR(-ENOENT);
if (template->active_low)
flags |= GPIOF_ACTIVE_LOW;
ret = devm_gpio_request_one(dev, template->gpio, flags,
template->name);
if (ret < 0)
return ERR_PTR(ret);
gpiod = gpio_to_desc(template->gpio);
if (!gpiod)
return ERR_PTR(-EINVAL);
return gpiod;
}
static int gpio_led_probe(struct platform_device *pdev)
{
struct gpio_led_platform_data *pdata = dev_get_platdata(&pdev->dev);
struct gpio_leds_priv *priv;
int i, ret = 0;
if (pdata && pdata->num_leds)/*非设备树方式*/
{
priv = devm_kzalloc(&pdev->dev,
sizeof_gpio_leds_priv(pdata->num_leds),
GFP_KERNEL);
if (!priv) return -ENOMEM;
priv->num_leds = pdata->num_leds;
for (i = 0; i < priv->num_leds; i++)
{
const struct gpio_led *template = &pdata->leds[i];
struct gpio_led_data *led_dat = &priv->leds[i];
if (template->gpiod)led_dat->gpiod = template->gpiod;
else
led_dat->gpiod = gpio_led_get_gpiod(&pdev->dev,i, template);
if (IS_ERR(led_dat->gpiod))
{
dev_info(&pdev->dev, "Skipping unavailable LED gpio %d (%s)\n",template->gpio, template->name);
continue;
}
ret=create_gpio_led(template, led_dat,&pdev->dev, NULL,pdata->gpio_blink_set);
if (ret < 0) return ret;
}
}
else/*采用设备树*/
{
priv = gpio_leds_create(pdev);
if (IS_ERR(priv)) return PTR_ERR(priv);
}
platform_set_drvdata(pdev, priv);
return 0;
}
static void gpio_led_shutdown(struct platform_device *pdev)
{
struct gpio_leds_priv *priv = platform_get_drvdata(pdev);
int i;
for (i = 0; i < priv->num_leds; i++) {
struct gpio_led_data *led = &priv->leds[i];
if (!(led->cdev.flags & LED_RETAIN_AT_SHUTDOWN))
gpio_led_set(&led->cdev, LED_OFF);
}
}
static struct platform_driver gpio_led_driver = {
.probe = gpio_led_probe,
.shutdown = gpio_led_shutdown,
.driver = {
.name = "leds-gpio",
.of_match_table = of_gpio_leds_match,
},
};
module_platform_driver(gpio_led_driver);
MODULE_AUTHOR("Raphael Assenat <raph@8d.com>, Trent Piepho <tpiepho@freescale.com>");
MODULE_DESCRIPTION("GPIO LED driver");
MODULE_LICENSE("GPL");
MODULE_ALIAS("platform:leds-gpio");
5、修改设备树
在“leds-gpio.c”中,驱动匹配表如下:
static const struct of_device_id of_gpio_leds_match[] = {
{ .compatible = "gpio-leds", },/*这是驱动中的compatible属性*/
{}, /*这是一个空元素,在编写of_device_id时最后一个元素一定要为空*/
};
1)、打开虚拟机上“VSCode”,点击“文件”,点击“打开文件夹”,点击“zgq”,点击“linux”,点击“atk-mp1”,点击“linux”,点击“my_linux”,点击“linux-5.4.31”,点击“确定”,见下图:
2)、点击“转到”,点击“转到文件”,输入“stm32mp15-pinctrl.dtsi回车”,打开设备树文件stm32mp15-pinctrl.dtsi。找到“pinctrl”节点,然后添加内容如下:
led_pins_a: gpioled-0 {/*"led_pins_a既是标号也是节点*/
pins {
pinmux = <STM32_PINMUX('I', 0, GPIO)>,/*设置PI0复用为GPIO功能*/
<STM32_PINMUX('F', 3, GPIO)>;/*设置PF3复用为GPIO功能*/
drive-push-pull;/*设置引脚为推挽输出*/
bias-pull-up;/*设置引脚内部上拉*/
output-high; /*输出高电平*/
slew-rate = <0>;/*设置引脚的速度为0档,0最慢,3 最高*/
};
};
key_pins_a: key_pins-0 {/*"led_pins_a既是标号也是节点*/
pins1 {
pinmux = <STM32_PINMUX('G', 3, GPIO)>, /* KEY0 */
<STM32_PINMUX('H', 7, GPIO)>; /* KEY1 */
bias-pull-up; /*设置引脚内部上拉*/
slew-rate = <0>;/*设置引脚的速度为0档,0最慢,3 最高*/
};
pins2 {
pinmux = <STM32_PINMUX('A', 0, GPIO)>; /* WK_UP */
bias-pull-down; /*内部下拉*/
slew-rate = <0>;/*设置引脚的速度为0档,0最慢,3 最高*/
};
};
电气属性 | 类型 | 作用 |
bias-disable | bootlean | 禁止使用内部偏置电压 |
bias-pull-down | bootlean | 内部下拉 |
bias-pull-up | bootlean | 内部上拉 |
drive-push-pull | bootlean | 推挽输出 |
drive-open-drain | bootlean | 开漏输出 |
output-low | bootlean | 输出低电平 |
output-high | bootlean | 输出高电平 |
slew-rate | enum | 引脚的速度,可设置:0~3,0最慢,3 最高 |
2)、点击“转到”,点击“转到文件”,输入“stm32mp157d-atk.dts回车”,打开设备树文件stm32mp157d-atk.dts。
3)、在根节点“/”下创建一个名为“dtsleds”的子节点,添加内容如下:
dtsleds{
compatible = "gpio-leds";/*设置属性compatible的值为"gpio-leds"*/
pinctrl-0 = <&led_pins_a>;
/*表示取led_pins_a标号所在子节点的硬件信息*/
led0 {
label = "red_led";
gpios = <&gpioi 0 GPIO_ACTIVE_LOW>;
/*“&gpioi”表示led-gpio引脚所使用的IO属于GPIOI组*/
/*“0’表示GPIOI组的第0号IO,即PI0引脚*/
/*“GPIO_ACTIVE_LOW”表示低电平有效,“GPIO_PULL_UP”表示上拉*/
default-state = "off";
};
led1 {
label = "green_led";
gpios = <&gpiof 3 GPIO_ACTIVE_LOW>;
/*“&gpiof”表示led-gpio引脚所使用的IO属于GPIOF组*/
/*“3’表示GPIOF组的第3号IO,即PF3引脚*/
/*“GPIO_ACTIVE_LOW”表示低电平有效,“GPIO_PULL_UP”表示上拉*/
default-state = "off";
};
};
gpio-keys {
compatible = "gpio-keys";
pinctrl-names = "default";
pinctrl-0 = <&key_pins_a>;
autorepeat;
key0 {
label = "GPIO Key L";
linux,code = <KEY_L>;
gpios = <&gpiog 3 GPIO_ACTIVE_LOW>;
};
key1 {
label = "GPIO Key S"; 15 linux,code = <KEY_S>;
gpios = <&gpioh 7 GPIO_ACTIVE_LOW>;
};
wkup {
label = "GPIO Key Enter";
linux,code = <KEY_ENTER>;
gpios = <&gpioa 0 GPIO_ACTIVE_HIGH>;
gpio-key,wakeup;
};
};
key0 {
compatible = "zgq,key";/*设置属性compatible的值为"zgq,led"*/
status = "okay";/*设置属性status的值为"okay"*/
pinctrl-names = "default";
pinctrl-0 = <&key_pins_a>;
key-gpio = <&gpiog 3 GPIO_ACTIVE_LOW>;
/*“&gpiog”表示key-gpio引脚所使用的IO属于GPIOG组*/
/*“3’表示GPIOG组的第3号IO,即PG3引脚*/
/*“GPIO_ACTIVE_LOW”表示低电平有效,“GPIO_PULL_UP”表示上拉*/
interrupt-parent = <&gpiog>;/*指定父中断器为&gpiog*/
/*通过interrupt-parent属性指定pinctrl所有子节点的中断父节点为 gpiog*/
interrupts = <3 IRQ_TYPE_EDGE_FALLING>;
/*“3’表示GPIOG组的第3号IO,即PG3引脚*/
/*IRQ_TYPE_EDGE_FALLING为下降沿触发*/
};
4)、编译设备树
①在VSCode终端,输入“make dtbs回车”,执行编译设备树
②输入“ls arch/arm/boot/uImage -l”
查看是否生成了新的“uImage”文件
③输入“ls arch/arm/boot/dts/stm32mp157d-atk.dtb -l”
查看是否生成了新的“stm32mp157d-atk.dtb”文件
5)、拷贝输出的文件:
①输入“cp arch/arm/boot/uImage /home/zgq/linux/atk-mp1/linux/bootfs/ -f回车”,执行文件拷贝,准备烧录到EMMC;
②输入“cp arch/arm/boot/dts/stm32mp157d-atk.dtb /home/zgq/linux/atk-mp1/linux/bootfs/ -f回车”,执行文件拷贝,准备烧录到EMMC
③输入“cp arch/arm/boot/uImage /home/zgq/linux/tftpboot/ -f回车”,执行文件拷贝,准备从tftp下载;
④输入“cp arch/arm/boot/dts/stm32mp157d-atk.dtb /home/zgq/linux/tftpboot/ -f回车”,执行文件拷贝,准备从tftp下载;
⑤输入“ls -l /home/zgq/linux/atk-mp1/linux/bootfs/回车”,查看“/home/zgq/linux/atk-mp1/linux/bootfs/”目录下的所有文件和文件夹
⑥输入“ls -l /home/zgq/linux/tftpboot/回车”,查看“/home/zgq/linux/tftpboot/”目录下的所有文件和文件夹
⑦输入“chmod 777 /home/zgq/linux/tftpboot/stm32mp157d-atk.dtb回车”
给“stm32mp157d-atk.dtb”文件赋予可执行权限
⑧输入“chmod 777 /home/zgq/linux/tftpboot/uImage回车” ,给“uImage”文件赋予可执行权限
⑨输入“ls /home/zgq/linux/tftpboot/回车”,查看“/home/zgq/linux/tftpboot/”目录下的所有文件和文件夹
5)、查看“/sys/bus/platform/devices/dtsleds”这个目录是否存在
我们在设备树文件stm32mp157d-atk.dts的根节点“/”下创建过“dtsleds”子节点,因此,需要给开发板上电,查看是否有“dtsleds”这个目录。
①用新的umage和stm32mpl57d-atk.dtb启动开发板。
②输入“root回车”。
③输入“cd /sys/bus/platform/devices/dtsleds”
切换到“/sys/bus/platform/devices/dtsleds”目录。若可以切换,说明有这个“dtsleds”这个目录。
④输入“ls回车”
⑤输入“cd /sys/devices/platform/dtsleds/leds”
切换到“/sys/devices/platform/dtsleds/leds”目录。
⑥输入“ls *led -l回车”。
⑦输入“echo 1 > /sys/class/leds/red_led/brightness”,打开LED0;
⑧输入“echo 1 > /sys/class/leds/green_led/brightness”,打开LED1;
⑨输入“echo 0 > /sys/class/leds/red_led/brightness”,关闭LED0;
⑩输入“echo 0 > /sys/class/leds/green_led/brightness”,关闭LED1;
5、将LEDO作为Linux系统心跳指示灯
5)、修改设备树
如果在“led1”里增加“linux,default-trigger = "heartbeat";”
dtsleds{
compatible = "gpio-leds";
/*设置属性compatible的值为"gpio-leds"*/
pinctrl-0 = <&led_pins_a>;
/*表示取led_pins_a标号所在子节点的硬件信息*/
led0 {
label = "red_led";
gpios = <&gpioi 0 GPIO_ACTIVE_LOW>;
/*“&gpioi”表示led-gpio引脚所使用的IO属于GPIOI组*/
/*“0’表示GPIOI组的第0号IO,即PI0引脚*/
/*“GPIO_ACTIVE_LOW”表示低电平有效,“GPIO_PULL_UP”表示上拉*/
default-state = "off";
};
led1 {
label = "green_led";
gpios = <&gpiof 3 GPIO_ACTIVE_LOW>;
/*“&gpiof”表示led-gpio引脚所使用的IO属于GPIOF组*/
/*“3’表示GPIOF组的第3号IO,即PF3引脚*/
/*“GPIO_ACTIVE_LOW”表示低电平有效,“GPIO_PULL_UP”表示上拉*/
linux,default-trigger = "heartbeat";
default-state = "off";
};
};
见下图:
重新编译“设备树”,使用新的设备树启动Linux系统,LEDO就会闪烁,作为系统心跳指示灯,表示系统正在运行。
①在VSCode终端,输入“make dtbs回车”,执行编译设备树
②输入“ls arch/arm/boot/uImage -l”
查看是否生成了新的“uImage”文件
③输入“ls arch/arm/boot/dts/stm32mp157d-atk.dtb -l”
查看是否生成了新的“stm32mp157d-atk.dtb”文件
5)、拷贝输出的文件:
①输入“cp arch/arm/boot/uImage /home/zgq/linux/atk-mp1/linux/bootfs/ -f回车”,执行文件拷贝,准备烧录到EMMC;
②输入“cp arch/arm/boot/dts/stm32mp157d-atk.dtb /home/zgq/linux/atk-mp1/linux/bootfs/ -f回车”,执行文件拷贝,准备烧录到EMMC
③输入“cp arch/arm/boot/uImage /home/zgq/linux/tftpboot/ -f回车”,执行文件拷贝,准备从tftp下载;
④输入“cp arch/arm/boot/dts/stm32mp157d-atk.dtb /home/zgq/linux/tftpboot/ -f回车”,执行文件拷贝,准备从tftp下载;
⑤输入“ls -l /home/zgq/linux/atk-mp1/linux/bootfs/回车”,查看“/home/zgq/linux/atk-mp1/linux/bootfs/”目录下的所有文件和文件夹
⑥输入“ls -l /home/zgq/linux/tftpboot/回车”,查看“/home/zgq/linux/tftpboot/”目录下的所有文件和文件夹
⑦输入“chmod 777 /home/zgq/linux/tftpboot/stm32mp157d-atk.dtb回车”
给“stm32mp157d-atk.dtb”文件赋予可执行权限
⑧输入“chmod 777 /home/zgq/linux/tftpboot/uImage回车” ,给“uImage”文件赋予可执行权限
⑨输入“ls /home/zgq/linux/tftpboot/回车”,查看“/home/zgq/linux/tftpboot/”目录下的所有文件和文件夹
给开发板重新上电,发现led1闪烁。