i.MX53 GPIO 按键驱动

MPQ6533驱动程序 MPQ6533驱动程序详解 阅读详情

Freescale i.MX53 GPIO 按键驱动


硬件平台:IMX53-QSB
内核版本:LINUX-2.6.35.3
系统版本:ANDROID 2.3.4


一、GPIO 的使用 

按键的处理需要读取相应 IO 引脚的值,阅读 IMX53 处理器芯片手册,得知将 GPIO 读模式大的步骤如下:
1. 通过设置 IOMUX 将相应引脚配置为 GPIO 模式,控制的寄存器是 IOMUXC_SW_MUX_CTL_PAD_XXX
2. 配置 GPIO 的方向为输入,控制的寄存器是 GPIOx_GDIR ,0表示输入,1表示输出
3. 读取相应 GPIO 引脚的值,读取的寄存器为 GPIOx_PSR

第1步,配置为 gpio 模式(以 MX53_PAD_GPIO_2__GPIO1_2 为例)

在文件 arch/arm/mach-mx5/mx53_loco.c 中
板子初始化函数 mxc_board_init 中,调用了 io 初始化函数 mx53_loco_io_init :
static void __init mxc_board_init(void)
{
    mx53_loco_io_init();
}

mx53_loco_io_init 函数中调用 mxc_iomux_v3_setup_multiple_pads 函数配置引脚:
static void __init mx53_loco_io_init(void)
{
    mxc_iomux_v3_setup_multiple_pads(mx53_loco_pads,ARRAY_SIZE(mx53_loco_pads));
}

mx53_loco_pads 为一 u64 类型的数组:
static iomux_v3_cfg_t mx53_loco_pads[] = {
    MX53_PAD_GPIO_2__GPIO1_2, 
};

MX53_PAD_GPIO_2__GPIO1_2 定义在 arch/arm/plat-mxc/include/mach/iomux-mx53.h
#define MX53_PAD_GPIO_2__GPIO1_2  (_MX53_PAD_GPIO_2__GPIO1_2 | MUX_PAD_CTRL(NO_PAD_CTRL))

MX53_PAD_GPIO_2__GPIO1_2 由 _MX53_PAD_GPIO_2__GPIO1_2 与 MUX_PAD_CTRL(NO_PAD_CTRL) 按位或得到,
先来看 _MX53_PAD_GPIO_2__GPIO1_2 :
#define _MX53_PAD_GPIO_2__GPIO1_2  IOMUX_PAD(0x6B8, 0x328, 1, 0x0, 0, 0)

IOMUX_PAD 的定义在 arch/arm/plat-mxc/include/mach/iomux-v3.h
#define IOMUX_PAD(_pad_ctrl_ofs, _mux_ctrl_ofs, _mux_mode, _sel_input_ofs,_sel_input, _pad_ctrl)  \
 ( ((iomux_v3_cfg_t)(_mux_ctrl_ofs) << MUX_CTRL_OFS_SHIFT)|\
 ((iomux_v3_cfg_t)(_mux_mode) << MUX_MODE_SHIFT)|\
 ((iomux_v3_cfg_t)(_pad_ctrl_ofs) << MUX_PAD_CTRL_OFS_SHIFT)|\
 ((iomux_v3_cfg_t)(_pad_ctrl) << MUX_PAD_CTRL_SHIFT)|\
 ((iomux_v3_cfg_t)(_sel_input_ofs) << MUX_SEL_INPUT_OFS_SHIFT)|\
 ((iomux_v3_cfg_t)(_sel_input) << MUX_SEL_INPUT_SHIFT) )

#define MUX_CTRL_OFS_SHIFT 0
#define MUX_PAD_CTRL_OFS_SHIFT 12
#define MUX_SEL_INPUT_OFS_SHIFT 24
#define MUX_MODE_SHIFT 36
#define MUX_PAD_CTRL_SHIFT 41
#define MUX_SEL_INPUT_SHIFT 58

那么 IOMUX_PAD 是这个样子:
 __________
 |61|60|59|58|
 _sel_input  
 __________________________________________
 |57|56|55|54|53|52|51|50|49|48|47|46|45|44|43|42|41|
                                     _pad_ctrl                        
 _____________
 |40|39|38|37|36|
  _mux_mode   
 ______________________________
 |35|34|33|32|31|30|29|28|27|26|25|24|
               _sel_input_ofs                      
 ______________________________
 |23|22|21|20|19|18|17|16|15|14|13|12|
                   _pad_ctrl_ofs                    
 ________________________
 |11|10| 9| 8| 7| 6| 5| 4| 3| 2| 1| 0|
              _mux_ctrl_ofs         

这样 _MX53_PAD_GPIO_2__GPIO1_2 即 IOMUX_PAD(0x6B8, 0x328, 1, 0x0, 0, 0) 是这个样子:
 __________
 |61|60|59|58|
          0         
 __________________________________________
 |57|56|55|54|53|52|51|50|49|48|47|46|45|44|43|42|41|
                                                0                                        
 ____________
 |40|39|38|37|36|
            1            
 ______________________________
 |35|34|33|32|31|30|29|28|27|26|25|24|
                         0x0                              
 ______________________________
 |23|22|21|20|19|18|17|16|15|14|13|12|
                               0x6B8                    
 ________________________
 |11|10| 9| 8| 7| 6| 5| 4| 3| 2| 1| 0|
                  0x328                      

再来看看 MUX_PAD_CTRL(NO_PAD_CTRL)
#define MUX_PAD_CTRL(x)  ((iomux_v3_cfg_t)(x) << MUX_PAD_CTRL_SHIFT)
#define NO_PAD_CTRL  ((iomux_v3_cfg_t)1 << (MUX_PAD_CTRL_SHIFT + 16))
这 MUX_PAD_CTRL(NO_PAD_CTRL) 将 1 左移了 98 位,代表什么意思?
这样 MX53_PAD_GPIO_2__GPIO1_2 的值就确定了。

mxc_iomux_v3_setup_multiple_pads 定义在 arch/arm/plat-mxc/iomux-v3.c :
int mxc_iomux_v3_setup_multiple_pads(iomux_v3_cfg_t *pad_list, unsigned count)
{
    iomux_v3_cfg_t *p = pad_list;
    int i;

    /* 通过一个循环将 mx53_loco_pads 中的每个成员都使用 mxc_iomux_v3_get_pad 进行配置 */
    for (i = 0; i < count; i++) {
        mxc_iomux_v3_get_pad(p);
        p++;
    }
    return 0;
}

mxc_iomux_v3_setup_pad 函数定义:
int mxc_iomux_v3_setup_pad(iomux_v3_cfg_t pad)
{
    /* 这里的 pad 即是 mx53_loco_pads 数组中的 MX53_PAD_GPIO_2__GPIO1_2 
    * 以下 6 行即获得 MX53_PAD_GPIO_2__GPIO1_2 中的 
    * _pad_ctrl_ofs, _mux_ctrl_ofs, _mux_mode, _sel_input_ofs,_sel_input, _pad_ctrl
    */
    u32 mux_ctrl_ofs = (pad & MUX_CTRL_OFS_MASK) >> MUX_CTRL_OFS_SHIFT;       // 0x328
    u32 mux_mode = (pad & MUX_MODE_MASK) >> MUX_MODE_SHIFT;
    u32 sel_input_ofs = (pad & MUX_SEL_INPUT_OFS_MASK) >> MUX_SEL_INPUT_OFS_SHIFT;
    u32 sel_input = (pad & MUX_SEL_INPUT_MASK) >> MUX_SEL_INPUT_SHIFT;
    u32 pad_ctrl_ofs = (pad & MUX_PAD_CTRL_OFS_MASK) >> MUX_PAD_CTRL_OFS_SHIFT;
    u32 pad_ctrl = (pad & MUX_PAD_CTRL_MASK) >> MUX_PAD_CTRL_SHIFT;

    /* 将相关配置值写入相应的寄存器 */
    if (mux_ctrl_ofs)
    /* 地址偏移 0x328 的寄存器是 IOMUXC_SW_MUX_CTL_PAD_GPIO_2 ,mux_mode = 1 即为 gpio 模式 */
    __raw_writel(mux_mode, base + mux_ctrl_ofs);

    if (sel_input_ofs)
    /* 地址偏移 0x0 的寄存器是 IOMUXC_GPR0 */
    __raw_writel(sel_input, base + sel_input_ofs);

    if (!(pad_ctrl & NO_PAD_CTRL) && pad_ctrl_ofs)
    /* 地址偏移 0x6B8 的寄存器是 IOMUXC_SW_PAD_CTL_PAD_GPIO_2 */
    __raw_writel(pad_ctrl, base + pad_ctrl_ofs);

    return 0;
}

如果需要将某 IO 引脚 XXX_GPIO_XXX 设置为 GPIO 模式,将 XXX_GPIO_XXX 添加到 mx53_loco_pads 数组即可。

第2步,将 gpio 设置为输入

使用的函数为 int gpio_direction_input(unsigned gpio) 
定义在 drivers/gpio/gpiolib.c
int gpio_direction_input(unsigned gpio)
{
    unsigned longflags;
    struct gpio_chip*chip;
    struct gpio_desc*desc = &gpio_desc[gpio];
    int status = -EINVAL;

    spin_lock_irqsave(&gpio_lock, flags);

    if (!gpio_is_valid(gpio))
        goto fail;
    chip = desc->chip;
    if (!chip || !chip->get || !chip->direction_input)
        goto fail;
    gpio -= chip->base;
    if (gpio >= chip->ngpio)
        goto fail;
    status = gpio_ensure_requested(desc, gpio);
    if (status < 0)
        goto fail;

    /* now we know the gpio is valid and chip won't vanish */
    spin_unlock_irqrestore(&gpio_lock, flags);

    might_sleep_if(extra_checks && chip->can_sleep);

    if (status) {
        status = chip->request(chip, gpio);
        if (status < 0) {
            pr_debug("GPIO-%d: chip request fail, %d\n",
            chip->base + gpio, status);
            /* and it's not available to anyone else ...
            * gpio_request() is the fully clean solution.
            */
            goto lose;
        }
    } 

    status = chip->direction_input(chip, gpio);
    if (status == 0)
        clear_bit(FLAG_IS_OUT, &desc->flags);
    lose:
    return status;
    fail:
    spin_unlock_irqrestore(&gpio_lock, flags);
    if (status)
        pr_debug("%s: gpio-%d status %d\n",
    __func__, gpio, status);
    return status;
}

该函数调用了 chip->direction_input(chip, gpio);
最终调用到的是 arch/arm/plat-mxc/gpio.c 文件中的函数 mxc_gpio_direction_input ,原型如下:
static int mxc_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
{
    /* 调用 _set_gpio_direction ,传递的第 3 个参数为 0 ,方向设置为输入 */
    _set_gpio_direction(chip, offset, 0);
    return 0;
}

_set_gpio_direction 函数原型:
static void _set_gpio_direction(struct gpio_chip *chip, unsigned offset,int dir)
{
    struct mxc_gpio_port *port =
        container_of(chip, struct mxc_gpio_port, chip);
    u32 l;
    unsigned long flags;

    spin_lock_irqsave(&port->lock, flags);
    l = __raw_readl(port->base + GPIO_GDIR);
    if (dir)
        l |= 1 << offset;
    else
        l &= ~(1 << offset);
    /* 传入的参数 dir=0,故向相应 GPIO 的 GDIR 寄存器写入 0  */
    __raw_writel(l, port->base + GPIO_GDIR);
    spin_unlock_irqrestore(&port->lock, flags);
}

第3步,获取 GPIO 引脚的值

使用的宏为 gpio_get_value
arch/arm/plat-mxc/include/mach/gpio.h
#define gpio_get_value      __gpio_get_value
__gpio_get_value 函数原型定义在 drivers/gpio/gpiolib.c
int __gpio_get_value(unsigned gpio)
{
    struct gpio_chip*chip;

    chip = gpio_to_chip(gpio);
    WARN_ON(extra_checks && chip->can_sleep);
    return chip->get ? chip->get(chip, gpio - chip->base) : 0;
}

__gpio_get_value 调用 chip->get ,实际调用到的是 arch/arm/plat-mxc/gpio.c 文件中 mxc_gpio_get 函数
static int mxc_gpio_get(struct gpio_chip *chip, unsigned offset)
{
    struct mxc_gpio_port *port =
container_of(chip, struct mxc_gpio_port, chip);

/* 读取相关寄存器的 PSR 寄存器 */
    return (__raw_readl(port->base + GPIO_PSR) >> offset) & 1;
}

二、PLATFORM DEVICE

GPIO按键作为系统的一种设备,挂载到platform总线上,相应的platform device定义在arch/arm/mach-mx5/mx53_loco.c:
static struct platform_device loco_button_device = {
    .name              = "gpio-keys",
    .id                = -1,
    .num_resources     = 0,
    .dev               = {
        .platform_data = &loco_button_data,
    }
};

loco_button_data 信息如下:  
static struct gpio_keys_platform_data loco_button_data = {
    .buttons    = loco_buttons,
    .nbuttons   = ARRAY_SIZE(loco_buttons),
};

loco_buttons 定义了5个按键:power、back、home、volumeup、volumedown和menu。
static struct gpio_keys_button loco_buttons[] = {
    GPIO_BUTTON(MX53_nONKEY, KEY_POWER,      1, "power",      0),
    GPIO_BUTTON(USER_UI1,    KEY_BACK,       1, "back",       0),
    GPIO_BUTTON(USER_UI2,    KEY_HOME,       1, "home",       0),
    GPIO_BUTTON(KEY_VOLUP,   KEY_VOLUMEUP,   1, "volumeup",   0),
    GPIO_BUTTON(KEY_VOLDOWN, KEY_VOLUMEDOWN, 1, "volumedown", 0),
    GPIO_BUTTON(KEY_SET,     KEY_MENU,       1, "menu",       0),
}; 

宏 GPIO_BUTTON 的内容为:
#define GPIO_BUTTON(gpio_num, ev_code, act_low, descr, wake)    \
{                                    \
    .gpio       = gpio_num,          \
    .type       = EV_KEY,            \
    .code       = ev_code,           \
    .active_low = act_low,           \
    .desc       = "btn " descr,      \
    .wakeup     = wake,              \
}
第一个参数为 gpio 引脚,第二个参数为按键的键值。

loco_buttons 使用的 gpio 定义如下:
#define MX53_nONKEY         (0*32 + 8)  /* GPIO_1_8  */
#define USER_UI1            (1*32 + 14) /* GPIO_2_14 */
#define USER_UI2            (1*32 + 15) /* GPIO_2_15 */
#define KEY_VOLUP           (6*32 + 13) /* GPIO_7_13 */
#define KEY_VOLDOWN         (0*32 + 4)  /* GPIO_1_4  */
#define KEY_SET             (0*32 + 2)  /* GPIO_1_2  */

键值定义在 include/linux/input.h 文件中:
#define KEY_HOME        102
#define KEY_VOLUMEDOWN  114
#define KEY_VOLUMEUP    115
#define KEY_POWER       116 /* SC System Power Down */
#define KEY_MENU        139 /* Menu (show menu) */
#define KEY_BACK        158 /* AC Back */

在板子初始化函数 static void __init mxc_board_init(void) 中
调用了 loco_add_device_buttons() 函数将loco_button_device加入到系统中,
这样驱动即可匹配 .name 找到我们的设备loco_button_device。

loco_add_device_buttons() 函数定义如下:
static void __init loco_add_device_buttons(void)
{
    platform_device_register(&loco_button_device);
}

三、PLATFORM DRIVER

GPIO按键的驱动文件为:drivers/input/keyboard/gpio_keys.c
通过 module_init ,在总线上注册 name 为 gpio-keys 的驱动,并通过 module_exit 相应的将其注销:
static int __init gpio_keys_init(void)
{
    return platform_driver_register(&gpio_keys_device_driver);
}

static void __exit gpio_keys_exit(void)
{
    platform_driver_unregister(&gpio_keys_device_driver);
}

module_init(gpio_keys_init);
module_exit(gpio_keys_exit);

platform driver - gpio_keys_device_driver 如下:
static struct platform_driver gpio_keys_device_driver = {
    .probe      = gpio_keys_probe,
    .remove     = __devexit_p(gpio_keys_remove),
    .driver     = {
        .name   = "gpio-keys",
        .owner  = THIS_MODULE,
#ifdef CONFIG_PM
        .pm     = &gpio_keys_pm_ops,
#endif
    }
};

在探测到 name 匹配的 device 之后,gpio_keys_probe 得以执行:

static int __devinit gpio_keys_probe(struct platform_device *pdev)
{
    struct gpio_keys_platform_data *pdata = pdev->dev.platform_data;
    struct gpio_keys_drvdata *ddata;
    struct device *dev = &pdev->dev;
    struct input_dev *input;
    int i, error;
    int wakeup = 0;

    /* 为ddata 分配空间 */
    ddata = kzalloc(sizeof(struct gpio_keys_drvdata) +
    pdata->nbuttons * sizeof(struct gpio_button_data),
        GFP_KERNEL);
    /* 分配一个输入设备 */
    input = input_allocate_device();
    if (!ddata || !input) {
        dev_err(dev, "failed to allocate state\n");
        error = -ENOMEM;
        goto fail1;
    }

    ddata->input = input;
    ddata->n_buttons = pdata->nbuttons;
    mutex_init(&ddata->disable_lock);

    /* 将 pdev 与 ddata 联系在一起,ddata 成为了 pdev 的平台data */
    platform_set_drvdata(pdev, ddata);
    input->name = pdev->name;
    input->phys = "gpio-keys/input0";
    input->dev.parent = &pdev->dev;

    input->id.bustype = BUS_HOST;
    input->id.vendor  = 0x0001;
    input->id.product = 0x0001;
    input->id.version = 0x0100;

    /* Enable auto repeat feature of Linux input subsystem */
    if (pdata->rep)
        __set_bit(EV_REP, input->evbit);

    /* 设置 loco_buttons 中各个 gpio 的中断及按键功能 */
    for (i = 0; i < pdata->nbuttons; i++) {
        struct gpio_keys_button *button = &pdata->buttons[i];
        struct gpio_button_data *bdata = &ddata->data[i];
        unsigned int type = button->type ?: EV_KEY;
   
        bdata->input = input;
        bdata->button = button;

        error = gpio_keys_setup_key(pdev, bdata, button);
        if (error)
            goto fail2;

        if (button->wakeup)
            wakeup = 1;

        input_set_capability(input, type, button->code);
    }

    /* 将我们的设备添加到 sys 文件系统 */
    error = sysfs_create_group(&pdev->dev.kobj, &gpio_keys_attr_group);
    if (error) {
        dev_err(dev, "Unable to export keys/switches, error: %d\n",
            error);
    goto fail2;
    }

    /* 将我们的设备注册到输入子系统 */
    error = input_register_device(input);
    if (error) {
        dev_err(dev, "Unable to register input device, error: %d\n",
            error);
        goto fail3;
    }

    /* get current state of buttons */
    for (i = 0; i < pdata->nbuttons; i++)
        /* 检测按键并上报 */
        gpio_keys_report_event(&ddata->data[i]);
    input_sync(input);

    device_init_wakeup(&pdev->dev, wakeup);

    return 0;

    fail3:
    sysfs_remove_group(&pdev->dev.kobj, &gpio_keys_attr_group);
    fail2:
    while (--i >= 0) {
        free_irq(gpio_to_irq(pdata->buttons[i].gpio), &ddata->data[i]);
        if (pdata->buttons[i].debounce_interval)
            del_timer_sync(&ddata->data[i].timer);
            cancel_work_sync(&ddata->data[i].work);
            gpio_free(pdata->buttons[i].gpio);
        }

    platform_set_drvdata(pdev, NULL);
    fail1:
    input_free_device(input);
    kfree(ddata);
    return error;
}

gpio_keys_setup_key 函数内容 :

static int __devinit gpio_keys_setup_key(struct platform_device *pdev,
    struct gpio_button_data *bdata,
    struct gpio_keys_button *button)
{
    char *desc = button->desc ? button->desc : "gpio_keys";
    struct device *dev = &pdev->dev;
    unsigned long irqflags;
    int irq, error;

    setup_timer(&bdata->timer, gpio_keys_timer, (unsigned long)bdata);
    /* 初始化工作队列,当调度 &bdata->work 时,函数 gpio_keys_work_func 得以执行 */
    INIT_WORK(&bdata->work, gpio_keys_work_func);

    /* 请求 gpio */
    error = gpio_request(button->gpio, desc);
    if (error < 0) {
        dev_err(dev, "failed to request GPIO %d, error %d\n",
            button->gpio, error);
        goto fail2;
    }

    /* 设置 loco_buttons 中涉及的 gpio 为输入模式 */
    error = gpio_direction_input(button->gpio);
    if (error < 0) {
        dev_err(dev, "failed to configure"
            " direction for GPIO %d, error %d\n",
            button->gpio, error);
        goto fail3;
    }

    /* 获取 gpio 中断号 */
    irq = gpio_to_irq(button->gpio);
    if (irq < 0) {
        error = irq;
        dev_err(dev, "Unable to get irq number for GPIO %d, error %d\n",
            button->gpio, error);
        goto fail3;
    }

    irqflags = IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING;
    /*
    * If platform has specified that the button can be disabled,
    * we don't want it to share the interrupt line.
    */
    if (!button->can_disable)
        irqflags |= IRQF_SHARED;

    /* 请求中断,多个按键共用一个处理函数 */
    error = request_irq(irq, gpio_keys_isr, irqflags, desc, bdata);
    if (error) {
        dev_err(dev, "Unable to claim irq %d; error %d\n",
            irq, error);
    goto fail3;
    }

    return 0;

    fail3:
    gpio_free(button->gpio);
    fail2:
    return error;
}

中断处理函数 gpio_keys_isr 定义如下:
static irqreturn_t gpio_keys_isr(int irq, void *dev_id)
{
    /* 获取对应的按键信息 */
    struct gpio_button_data *bdata = dev_id;
    struct gpio_keys_button *button = bdata->button;

    BUG_ON(irq != gpio_to_irq(button->gpio));

    /* 这里 button->debounce_interval = 0 */
    if (button->debounce_interval)
        mod_timer(&bdata->timer,
            jiffies + msecs_to_jiffies(button->debounce_interval));
    else
        /* 调度 &bdata->work,gpio_keys_work_func 的以执行 */
        schedule_work(&bdata->work);

    return IRQ_HANDLED;
}

gpio_keys_work_func 的定义:
static void gpio_keys_work_func(struct work_struct *work)
{
    struct gpio_button_data *bdata =
        container_of(work, struct gpio_button_data, work);

    /* 获取按键状态并且上报 */

    gpio_keys_report_event(bdata);

}


函数 gpio_keys_report_event 内容:
static void gpio_keys_report_event(struct gpio_button_data *bdata)
{
    struct gpio_keys_button *button = bdata->button;
    struct input_dev *input = bdata->input;
    unsigned int type = button->type ?: EV_KEY;
    /* 获取按键状态 */
    int state = (gpio_get_value(button->gpio) ? 1 : 0) ^ button->active_low;

    /* 将相应功能按键的相应状态上报给 input 子系统 */
    input_event(input, type, button->code, !!state);
    /* 同步事件,通知事件的接收方,本次事件已完成 */
    input_sync(input);
}


如果要添加或是修改 android 的按键功能,需保证 device/fsl/imx53_loco/gpio-keys.kl 文件中有相应的键值,可以参考 qwerty.kl 文件修改。


以上内容为个人对 IMX53 GPIO 按键驱动的认识,如有不妥之处,还望批评指正。


飞思卡尔i.mx53x CPU对比 飞思卡尔i.mx53x CPU对比,包括内部各参数比较,及开发板介绍 立即下载

相关推荐

飞思卡尔i.MX53X数据手册

飞思卡尔i.MX53X数据手册,有详细的说明

freescale i.mx53 qt交叉编译环境安装

看上一篇文章,先编译ltib。

jupiter37的专栏 1883

Freescale IOMUX工具及使用说明

飞思卡尔公司的IMX系列工具,在设计阶段可通过工具实现模拟分配IO及复用关系

u-boot串口和stdio、console初始化及相关操作详解<二>

二.board_r阶段串口操作和stdio初始化 该阶段包括3个函数:stdio_init_tables、 initr_serial、stdio_add_devices。下面逐一对其进行详细说明。 1. stdio_init_tablesint stdio_init_tables(void) { /* Initialize the list */ INIT_LIST_HEA

metersun的专栏 2504

Freescale 的IMX53平台使用手册

使用手册,关于飞思卡尔公司的一款基于imx53 cpu的嵌入式操作系统平台,OS是windows Embedded compact 7;

实战!在 AMD RX 9070 XT (16G) 上使用原生 Windows ROCm 7.1 部署 ComfyUI + Z-Image-Turbo

本文详细介绍了如何在Windows系统下为AMD Radeon RX 9070 XT显卡配置Z-Image-Turbo AI绘图环境。主要内容包括:安装VS Build Tools和最新显卡驱动,配置Conda Python 3.12环境,安装ROCm 7.1.1 SDK及PyTorch适配版本,部署ComfyUI可视化界面。重点解决了AMD显卡在AI绘图中的适配问题,通过--use-split-cross-attention参数优化显存使用,最终成功搭建了可在消费级16G显存设备上运行的AI绘图环境

qq_33614778的博客 4696

u-boot串口和stdio、console初始化及相关操作详解<一>

当u-boot的启动执行到_main函数处,将在_main函数中执行板级的前初始化和后初始化操作,即函数board_init_f和board_init_r。 串口的初始化以及相关stdio、console操作穿插在这两个函数的执行过程中。下面将分别详细讨论这两阶段中涉及的串口及stdio、 console设备操作。 这里所使用的u-boot版本为2015.7,硬件为I.MX6 boundar

metersun的专栏 5362

从零开始:手把手教你规划与部署华为FusionCompute虚拟化平台(含网络规划避坑指南)

本文详细介绍了华为FusionCompute虚拟化平台的规划与部署流程,特别针对网络规划中的常见问题提供了避坑指南。从硬件软件清单检查、网络平面配置到VRM部署方案选择,帮助用户高效完成部署并优化性能,适用于云计算环境中的虚拟化平台搭建。

weixin_28693447的博客 243

Linux串口驱动(1) - serial层

1. serial 层的初始化 以IMX6的串口驱动为例,文件在drivers/tty/serial/imx.c,初始化概述如下: module_init(imx_serial_init) -->uart_register_driver(&imx_reg); -->tty_set_operations(normal, &uart_ops); -->driver->ops = op; -->tty_register_...

四季帆的博客 1809

车载导航测试,面试常见问题

车载导航测试是汽车软件测试的重要组成部分,涉及验证导航系统的功能、性能、可靠性和用户体验。在面试中,面试官通常会考察候选人的测试思维、问题解决能力和实际经验。以下我将从常见问题类别入手,逐步介绍面试中的高频问题,并提供结构化分析。通过以上结构化准备,你能在面试中自信应对车载导航测试相关问题。用户体验测试关注界面友好性和交互流畅性,安全测试则涉及功能安全和数据隐私。功能测试聚焦于导航核心功能的正确性,如路线规划、位置定位和地图显示。面试官会考察你如何识别、报告和跟踪缺陷,以及熟悉测试工具。

m0_69889939的博客 527

C#实战:如何用Chart控件打造专业级数据可视化报表(附完整代码)

本文详细介绍了如何使用C#的Chart控件创建专业级数据可视化报表,涵盖柱状图、饼图和雷达图等多种图表类型的高级定制与交互增强。通过完整的代码示例,展示了从环境配置到动态数据绑定的全流程,助力开发者提升企业级应用的数据可视化能力。

ipfs8storage的博客 420

linux mx53注册串口驱动,(转)i.MX53 GPIO 按键驱动

Freescale i.MX53 GPIO 按键驱动硬件平台:IMX53-QSB内核版本:LINUX-2.6.35.3系统版本:ANDROID 2.3.4一、GPIO的使用按键的处理需要读取相应IO 引脚的值,阅读 IMX53 处理器芯片手册,得知将 GPIO 读模式大的步骤如下:1. 通过设置 IOMUX 将相应引脚配置为 GPIO 模式,控制的寄存器是IOMUXC_SW_MUX_CTL_PAD...

weixin_34171095的博客 283

【2025华为OD机考真题】- 简易内存池(B卷-200分)(C版)

🔔本文收录于「最新最全华为OD机试真题(C版)」专栏,手把手带你零基础教学华为OD机试。本题集提供最优题解思路,解题步骤,代码解析,复杂度分析及最优题解源码等,支持多语言题解,助你轻松拿捏OD机考,一举上岸!安利大家关注&&收藏&&订阅!题库正在疯狂收录中,up!up!up!! 🚫提醒:拒绝一切代考/替考,违法必究!专栏所写题库均精心搜集于互联网,经过精心筛选和整理,结合数位十多年大厂实战经验资深大佬经验所撰,欢迎订阅。    💗订阅福利:一次订阅,可永久免费阅读,提供在线答疑解惑,后续题库更新皆可阅

**My Coding Family** 962

linux mx53注册串口驱动,i.MX53 GPIO 按键驱动

硬件平台:IMX53-QSB内核版本:LINUX-2.6.35.3系统版本:ANDROID 2.3.4一、GPIO 的使用按键的处理需要读取相应 IO 引脚的值,阅读 IMX53 处理器芯片手册,得知将 GPIO 读模式大的步骤如下:1. 通过设置 IOMUX 将相应引脚配置为 GPIO 模式,控制的寄存器是 IOMUXC_SW_MUX_CTL_PAD_XXX2. 配置 GPIO 的方向为输入,控...

weixin_39577052的博客 193

第25节:cesium 地形开挖综合实例-地下管网(含源码+视频)

地图开挖综合示例,包括底图切换,绘制开挖区域,移除开挖区域,影藏地图等等。

qq_29384639的博客 1782

静态时序分析—门控时钟检查(clock gating check)

clock gating check的条件与类型

m0_61544122的博客 9609

Freescale i.MX53 GPIO 按键驱动

硬件平台:IMX53-QSB 内核版本:LINUX-2.6.35.3 系统版本:ANDROID 2.3.4 一、GPIO 的使用  按键的处理需要读取相应 IO 引脚的值,阅读 IMX53 处理器芯片手册,得知将 GPIO 读模式大的步骤如下: 1. 通过设置 IOMUX 将相应引脚配置为 GPIO 模式,控制的寄存器是 IOMUXC_SW_MUX_CTL_PAD_XXX 2. 配

lyf666888的博客 1224

华为OD新系统机试真题 4.26 -最大化游戏试玩资格分发

华为OD机试新系统真题【最大化游戏试玩资格分发】,提供C语言、Java、C++、Python、Go、JavaScript源码实现,并提供完整思路讲解,以及在线OJ模拟做题。华为OD新系统机试 4月26号真题【最大化游戏试玩资格分发】。

qq_45776114的博客 827

【北京迅为】《i.MX8MM嵌入式Linux开发指南》-第三篇 嵌入式Linux驱动开发篇-第六十二章 定时器按键消抖实验

在上图中,t1 时刻按键被按下,但是由于抖动的原因,直到 t2 时刻才稳定下来,t1 到t2 这段时间就是抖动。我们可以借助定时器来实现消抖,按键采用中断驱动方式,当按键按下以后触发按键中断,在按键中断中开启一个定时器,定时周期为 10ms,当定时时间到了以后就会触发定时器中断,最后在定时器中断处理函数中读取按键的值,如果按键值还是按下状态那就表示这是一次有效的按键。在上图中,按键没有按下的时候按键值为 1,当按键在 t1 时刻按键被按下以后按键值就变为 0,这是最理想的状态。程序源码在网盘资料“

BeiJingXunWei的博客 1310

华为的C语言编程规范.pdf

华为技术有限公司内部技术规范。本规范制定了编写C语言程序的基本原则、规则和建议。从代码的清晰、简洁、可测试、安全、程序效率、可移植各个方面对C语言编程作出了具体指导。

lwip-2.0.3

lwip是瑞典计算机科学院(SICS)的Adam Dunkels 开发的一个小型开源的TCP/IP协议栈。实现的重点是在保持TCP协议主要功能的基础上减少对RAM 的占用。

Linux之ARM(IMX6U)裸机按键输入实验(GPIO的输出与输入)

Linux之ARM(MX6U)裸机按键输入实验(GPIO读取)1、按键输入简介2、硬件原理图分析3、实验程序的编写3.1、bsp_gpio.h3.2、bsp_gpio.c3.3、gpio_key.h3.4、gpio_key.c3.5、main.c4、编译下载验证4.1、连接脚本的编写4.2、Makefile的编写4.3、编译下载 前面几篇文章试验都是讲解如何使用 I.MX6U 的 GPIO 输出控制功能, I.MX6U 的 IO 不仅能作为输出,而且也可以作为输入。 I.MX6U-ALPHA 开发板上有一个

一只青木呀 1909

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

Linux之ARM(MX6U)裸机之按键输入实验(GPIO的输入、输出)

Linux之ARM(MX6U)裸机之按键输入实验(GPIO的输入、输出)1.按键输入简介2. 硬件原理分析3.实验程序编写3.1编写bsp_gpio.h3.2编写bsp_gpio.c3.3编写bsp_key.h3.4编写bsp_key.c3.5修改main.c4. 编译下载验证4.1编写 Makefile4.2链接脚本编写4.3 编译下载 前面几章试验都是讲解如何使用 I.MX6U 的 GPIO 输出控制功能,I.MX6U 的 IO 不仅能作 为输出,而且也可以作为输入。I.MX6U-ALPHA 开发板上

weixin_47932709的博客 982

IEM模型,地表粗糙度模拟

利用微波反演土壤水分时候,利用IEM模型可以实现对随机地表的模拟

【i.MX6ULL】驱动开发7——按键输入捕获

前面几篇文章,从最基础的寄存器点灯,到设备树点灯,再到GPIO子系统点灯,一步步了解嵌入式Linux开发的各种点灯原理。 点灯用到的都是GPIO的输出功能,这篇,通过按键的使用,来学习GPIO输入功能的使用。 1 硬件介绍 1.1 板子上按键原理图 先来看原理图,我板子上有4个按键sw1~sw4: 1.1.1 SW1 SW1是板子的系统复位按键,不可编程使用 1.1.2 SW2、SW3 SW2:SNVS_TAMPER1,GPIO5_1 平时是低电平,按下去是高电平。 SW3:ONOFF 它也是系统

码农爱学习的博客 1222

从轮询到中断:i.MX6ULL GPIO按键处理机制深度解析

1. 初始化 4 大步① 复用 IOMUXC_SW_MUX_CTL_PAD_UART1_CTS_B代码:IOMUXC_SetPinMux(IOMUXC_UART1_CTS_B_GPIO1_IO18, 0);② 电气 IOMUXC_SW_PAD_CTL_PAD_UART1_CTS_BHYS=0 PUS=11b(22 kΩ上拉) PUE=1 PKE=1 ODE=0 SPEED=10b(100 MHz) DSE=000(输出禁用) SRE=0。

kkkkkingw的博客 958

i.MX6ULL终结者Linux按键输入实验按键驱动程序

本实验例程路径:i.MX6UL终结者光盘资料/06_Linux驱动例程/08_key 在设备树文件中添加好按键的硬件信息后,创建key.c文件,编写驱动程序,具体内容如下: 1 #include <linux/types.h> 2 #include <linux/kernel.h> 3 #include <linux/delay.h> 4 #include <linux/ide.h> 5 #include <linux/init.h&gt

weixin_46635880的博客 185

iMX6ULL —按键输入捕获与GPIO输入配置与高低电平读取

i.MX6ULL 按键输入捕获与GPIO输入配置与高低电平读取

yaningli的博客 1995

i.MX6ULL终结者GPIO中断例程编译及运行

首先使用命令“vi Makefile”打开Makefile。如图 1所示: 图 1 添加内容如下: 1 CROSS_COMPILE ?= arm-linux-gnueabihf- 2 TARGET ?= int 3 4 CC := $(CROSS_COMPILE)gcc 5 LD := $(CROSS_COMPILE)ld 6 O

weixin_46635880的博客 966
上一篇: S5PV210 LCD 驱动
下一篇: 问题总结
mxl_mxl
博客等级 码龄15年 7粉丝 7原创
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值