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闪烁。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/60110.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Zmap+python脚本+burp实现自动化Fuzzing测试

声明 学习视频来自 B 站UP主泷羽sec&#xff0c;如涉及侵权马上删除文章。 笔记的只是方便各位师傅学习知识&#xff0c;以下网站只涉及学习内容&#xff0c;其他的都与本人无关&#xff0c;切莫逾越法律红线&#xff0c;否则后果自负。 ✍&#x1f3fb;作者简介&#xff1a;致…

红外相机和RGB相机外参标定 - 无需标定板方案

1. 动机 在之前的文章中红外相机和RGB相机标定&#xff1a;实现两种模态数据融合_红外相机标定-CSDN博客 &#xff0c;介绍了如何利用标定板实现外参标定&#xff1b;但实测下来发现2个问题&#xff1a; &#xff08;1&#xff09;红外标定板尺寸问题&#xff0c;由于标定板小…

android:taskAffinity 对Activity退出时跳转的影响

android:taskAffinity 对Activity跳转的影响 概述taskAffinity 的工作机制taskAffinity对 Activity 跳转的影响一个实际的开发问题总结参考 概述 在 Android 开发中&#xff0c;任务栈&#xff08;Task&#xff09;是一个核心概念。它决定了应用程序的 Activity 如何相互交互以…

Ubuntu常见命令

关于export LD_LIBRARY_PATHcmake默认地址CMakelists.txt知识扩充/home&#xff1a;挂载新磁盘到 /home 子目录 关于export LD_LIBRARY_PATH 程序运行时默认的依赖库的位置包括lib, /usr/lib ,/usr/local/lib 通过命令export LD_LIBRARY_PATHdesired_path:$LD_LIBRARY_PATH追加…

时间类的实现

在现实生活中&#xff0c;我们常常需要计算某一天的前/后xx天是哪一天&#xff0c;算起来十分麻烦&#xff0c;为此我们不妨写一个程序&#xff0c;来减少我们的思考时间。 1.基本实现过程 为了实现时间类&#xff0c;我们需要将代码写在3个文件中&#xff0c;以增强可读性&a…

php交友源码交友系统源码相亲交友系统源码php社交系统php婚恋源码php社区交友源码vue 仿交友社交语聊技术栈

关于PHP交友、相亲、婚恋、社区交友系统的源码以及Vue仿交友社交语聊技术栈&#xff0c;以下是一些详细信息和建议&#xff1a; 一、PHP交友系统源码 系统架构设计 前端展示层&#xff1a;负责向用户提供直观友好的界面&#xff0c;包括注册登录页面、个人资料页面、匹配页面、…

Java小技艺

使用bat文件启动jar包 平时在工作中运行jar包一般是导出后命令行窗口运行 jar -jar xxx.jar 这个其实是很不方便的。可以在win上编写bat脚本去运行jar包的。 1 编写bat脚本 start jre8/bin/javaw -jar xxxx.jar2 将jre和待执行的jar包存放到一个目录下(和bat文件在同一目录…

蓝桥杯第22场小白入门赛2~5题

这场比赛开打第二题就理解错意思了&#xff0c;还以为只能用3个消除和5个消除其中一种呢&#xff0c;结果就是死活a不过去&#xff0c;第三题根本读不懂题意&#xff0c;这蓝桥杯的题面我只能说出的是一言难尽啊。。第四题写出来一点但是后来知道是错了&#xff0c;不会正解&am…

‘视’不可挡:OAK相机助力无人机智控飞行!

南京邮电大学通达学院的刘同学用我们的oak-d-lite实现精确打击无人机的避障和目标识别定位功能&#xff0c;取得了比赛冠军。我们盼望着更多的朋友们能够加入到我们OAK的队伍中来&#xff0c;参与到各式各样的比赛中去。我们相信&#xff0c;有了我们相机的助力&#xff0c;大家…

最小生成树——Kruskal、Prim算法

图的存储&#xff1a; 高阶数据结构——图 文章目录 目录 文章目录 一、kruskal算法 二、Prim算法 前言 连通图中的每一棵生成树&#xff0c;都是原图的一个极大无环子图&#xff0c;即&#xff1a;从其中删去任何一条边&#xff0c;生成树 就不在连通&#xff1b;反之&#xf…

集群聊天服务器(9)一对一聊天功能

目录 一对一聊天离线消息服务器异常处理 一对一聊天 先新添一个消息码 在业务层增加该业务 没有绑定事件处理器的话消息会派发不出去 聊天其实是服务器做一个中转 现在同时登录两个账号 收到了聊天信息 再回复一下 离线消息 声明中提供接口和方法 张三对离线的李…

华为再掀技术革新!超薄膜天线设计路由器首发!

随着Wi-Fi技术的不断进步&#xff0c;新一代的Wi-Fi 7路由器凭借其高速率、低延迟、更稳定的性能受到了广泛关注。它能够更好地满足现代家庭对网络性能的高要求&#xff0c;带来更加流畅、高效的网络体验。9月24日&#xff0c;华为在其秋季全场景新品发布会上推出了全新Wi-Fi 7…

【阅读记录-章节2】Build a Large Language Model (From Scratch)

目录 2.Working with text data2.1 Understanding word embeddings2.2 Tokenizing text通过一个简单的实验来理解文本的词元化概念关键概念 2.3 Converting tokens into token IDs实现分词器类&#xff08;Tokenizer Class&#xff09;应用分词器测试文本的编码与解码通过分词器…

SDF,一个从1978年运行至今的公共Unix Shell

关于SDF 最近发现了一个很古老的公共Unix Shell服务器&#xff0c;这个项目从1978年运行至今&#xff0c;如果对操作系统&#xff0c;对Unix感兴趣&#xff0c;可以进去玩一玩体验一下 SDF Public Access UNIX System - Free Shell Account and Shell Access 注册方式 我一…

关于Qt C++中connect的几种写法

目录 1. 传统的槽函数写法 2. 使用函数指针的connect写法&#xff08;5.0&#xff09; 3. Lambda表达式作为槽函数&#xff08;C11&#xff09; 4.使用QOverload选择重载信号的写法 这connect函数就像是编程世界里的“茴”字&#xff0c;千变万化&#xff0c;各有千秋。咱们…

反向代理模块

1 概念 1.1 反向代理概念 反向代理是指以代理服务器来接收客户端的请求&#xff0c;然后将请求转发给内部网络上的服务器&#xff0c;将从服务器上得到的结果返回给客户端&#xff0c;此时代理服务器对外表现为一个反向代理服务器。 对于客户端来说&#xff0c;反向代理就相当于…

用jquery做一个websocket客户端

先看效果图&#xff1a; 功能很简单&#xff0c;就是作为客户端连接websocket&#xff0c;并实现接受和发送消息。具体代码如下&#xff1a; <!DOCTYPE html> <html lang"zh-cn"> <head><meta charset"UTF-8"><meta name"…

抽象java入门1.5.3.2——类的进阶(中)

前期回顾&#xff1a;抽象java入门1.5.3.1——类的进阶https://blog.csdn.net/c_yanxin_ru/article/details/140858898?spm1001.2014.3001.5501 总结&#xff1a; 在代码溯源中&#xff0c;我发现了一个奇怪的东西&#xff0c;就是OUT不是类中类&#xff08;不是常规类的写法…

蓝桥杯每日真题 - 第17天

题目&#xff1a;&#xff08;最大数字&#xff09; 题目描述&#xff08;13届 C&C B组D题&#xff09; 题目分析&#xff1a; 操作规则&#xff1a; 1号操作&#xff1a;将数字加1&#xff08;如果该数字为9&#xff0c;变为0&#xff09;。 2号操作&#xff1a;将数字…