【RT-Thread】nxp rt10xx 设备驱动框架之--Pin搭建和使用

17 篇文章 1 订阅
13 篇文章 2 订阅

开发前准备

  • 硬件平台:nxp rt10xx单片机
  • IDE: Keil

1.Kconfig 修改和menuconfig配置

Kconfig中发现PIN 配置默认是选中状态(毕竟最常用的IO驱动设备)
RT-Thread Comonents -> Device Drivers
请添加图片描述
RT-Thread Components-> On-chip Peripheral Drivers

请添加图片描述

2.工程添加PIN驱动框架和BSP驱动接口

设备驱动框架:pin.c BSP接口:drv_gpio.c fsl_gpio.c fsl_iomuxc.c

请添加图片描述

3.添加或修改drv_gpio.c

笔者查阅了文件,该驱动很完善,几乎不用改什么,接下来先了解下基本框架吧

  • 定义rt_pin_ops结构
struct rt_pin_ops
{
    void (*pin_mode)(struct rt_device *device, rt_base_t pin, rt_base_t mode);
    void (*pin_write)(struct rt_device *device, rt_base_t pin, rt_base_t value);
    int (*pin_read)(struct rt_device *device, rt_base_t pin);
    rt_err_t (*pin_attach_irq)(struct rt_device *device, rt_int32_t pin,
                      rt_uint32_t mode, void (*hdr)(void *args), void *args);
    rt_err_t (*pin_detach_irq)(struct rt_device *device, rt_int32_t pin);
    rt_err_t (*pin_irq_enable)(struct rt_device *device, rt_base_t pin, rt_uint32_t enabled);
    rt_base_t (*pin_get)(const char *name);
};
  • 实现ops
const static struct rt_pin_ops imxrt_pin_ops =
{
    imxrt_pin_mode,
    imxrt_pin_write,
    imxrt_pin_read,
    imxrt_pin_attach_irq,
    imxrt_pin_detach_irq,
    imxrt_pin_irq_enable,
    RT_NULL,
};
  • 设备创建注册
int rt_hw_pin_init(void)
{
    int ret = RT_EOK;

    ret = rt_device_pin_register("pin", &imxrt_pin_ops, RT_NULL);

    return ret;
}
INIT_BOARD_EXPORT(rt_hw_pin_init);
  • ops相关函数

该bsp基本很完善了,没什么要改的,简单展示一下吧

static void imxrt_isr(rt_int16_t index_offset, rt_int8_t pin_start, GPIO_Type *base)
{
    rt_int32_t isr_status, index;
    rt_int8_t i, pin_end;

    pin_end = pin_start + 15;
    isr_status = GPIO_PortGetInterruptFlags(base) & base->IMR;

    for (i = pin_start; i <= pin_end ; i++)
    {
        if (isr_status & (1 << i))
        {
            GPIO_PortClearInterruptFlags(base, (1 << i));
            index = index_offset + i;
            if (hdr_tab[index].hdr != RT_NULL)
            {
                hdr_tab[index].hdr(hdr_tab[index].args);
            }
        }
    }
}

static void imxrt_pin_mode(rt_device_t dev, rt_base_t pin, rt_base_t mode)
{
    gpio_pin_config_t gpio;
    rt_uint32_t config_value = 0;
    rt_int8_t port, pin_num;

    port = pin >> 5;
    pin_num = pin & 31;

    if (PIN_INVALID_CHECK(port, pin_num))
    {
        LOG_D("invalid pin,rtt pin: %d,port: %d,pin: %d \n", pin,port + 1,pin_num);
        return;
    }

    gpio.outputLogic = 0;
    gpio.interruptMode = kGPIO_NoIntmode;

    switch (mode)
    {
    case PIN_MODE_OUTPUT:
    {
        gpio.direction = kGPIO_DigitalOutput;
        config_value = 0x0030U;    /* Drive Strength R0/6 */
    }
    break;

    case PIN_MODE_INPUT:
    {
        gpio.direction = kGPIO_DigitalInput;
        config_value = 0x0830U;    /* Open Drain Enable */
    }
    break;

    case PIN_MODE_INPUT_PULLDOWN:
    {
        gpio.direction = kGPIO_DigitalInput;
        config_value = 0x3030U;    /* 100K Ohm Pull Down */
    }
    break;

    case PIN_MODE_INPUT_PULLUP:
    {
        gpio.direction = kGPIO_DigitalInput;
        config_value = 0xB030U;    /* 100K Ohm Pull Up */
    }
    break;

    case PIN_MODE_OUTPUT_OD:
    {
        gpio.direction = kGPIO_DigitalOutput;
        config_value = 0x0830U;    /* Open Drain Enable */
    }
    break;
    }

    if (mask_tab[port].gpio != GPIO5)
    {
        CLOCK_EnableClock(kCLOCK_Iomuxc);
        IOMUXC_SetPinMux(MUX_BASE + reg_offset[pin] * 4, 0x5U, 0, 0, CONFIG_BASE + reg_offset[pin] * 4, 1);
        IOMUXC_SetPinConfig(MUX_BASE + reg_offset[pin] * 4, 0x5U, 0, 0, CONFIG_BASE + reg_offset[pin] * 4, config_value);
    }
    else
    {
        CLOCK_EnableClock(kCLOCK_IomuxcSnvs);
        IOMUXC_SetPinMux(GPIO5_MUX_BASE + pin_num * 4, 0x5U, 0, 0, GPIO5_CONFIG_BASE + pin_num * 4, 1);
        IOMUXC_SetPinConfig(GPIO5_MUX_BASE + pin_num * 4, 0x5U, 0, 0, GPIO5_CONFIG_BASE + pin_num * 4, config_value);
    }

    GPIO_PinInit(mask_tab[port].gpio, pin_num, &gpio);
}

static int imxrt_pin_read(rt_device_t dev, rt_base_t pin)
{
    int value;
    rt_int8_t port, pin_num;

    value = PIN_LOW;
    port = pin >> 5;
    pin_num = pin & 31;

    if (PIN_INVALID_CHECK(port, pin_num))
    {
        LOG_D("invalid pin,rtt pin: %d,port: %d,pin: %d \n", pin,port + 1,pin_num);
        return value;
    }

    return GPIO_PinReadPadStatus(mask_tab[port].gpio, pin_num);
}

static void imxrt_pin_write(rt_device_t dev, rt_base_t pin, rt_base_t value)
{
    rt_int8_t port, pin_num;

    port = pin >> 5;
    pin_num = pin & 31;

    if (PIN_INVALID_CHECK(port, pin_num))
    {
        LOG_D("invalid pin,rtt pin: %d,port: %d,pin: %d \n", pin,port + 1,pin_num);
        return;
    }

    GPIO_PinWrite(mask_tab[port].gpio, pin_num, value);
}

static rt_err_t imxrt_pin_attach_irq(struct rt_device *device, rt_int32_t pin,
                                     rt_uint32_t mode, void (*hdr)(void *args), void *args)
{
    rt_base_t level;
    rt_int8_t port, pin_num;

    port = pin >> 5;
    pin_num = pin & 31;

    if (PIN_INVALID_CHECK(port, pin_num))
    {
        LOG_D("invalid pin,rtt pin: %d,port: %d,pin: %d \n", pin,port + 1,pin_num);
        return RT_ENOSYS;
    }

    level = rt_hw_interrupt_disable();
    if (hdr_tab[pin].pin == pin &&
        hdr_tab[pin].hdr == hdr &&
        hdr_tab[pin].mode == mode &&
        hdr_tab[pin].args == args)
    {
        rt_hw_interrupt_enable(level);
        return RT_EOK;
    }

    hdr_tab[pin].pin  = pin;
    hdr_tab[pin].hdr  = hdr;
    hdr_tab[pin].mode = mode;
    hdr_tab[pin].args = args;
    rt_hw_interrupt_enable(level);

    return RT_EOK;
}

static rt_err_t imxrt_pin_detach_irq(struct rt_device *device, rt_int32_t pin)
{
    rt_base_t level;
    rt_int8_t port, pin_num;

    port = pin >> 5;
    pin_num = pin & 31;

    if (PIN_INVALID_CHECK(port, pin_num))
    {
        LOG_D("invalid pin,rtt pin: %d,port: %d,pin: %d \n", pin,port + 1,pin_num);
        return RT_ENOSYS;
    }

    level = rt_hw_interrupt_disable();
    if (hdr_tab[pin].pin == -1)
    {
        rt_hw_interrupt_enable(level);
        return RT_EOK;
    }
    hdr_tab[pin].pin = -1;
    hdr_tab[pin].hdr = RT_NULL;
    hdr_tab[pin].mode = 0;
    hdr_tab[pin].args = RT_NULL;
    rt_hw_interrupt_enable(level);

    return RT_EOK;
}

static rt_err_t imxrt_pin_irq_enable(struct rt_device *device, rt_base_t pin, rt_uint32_t enabled)
{
    gpio_interrupt_mode_t int_mode;
    rt_int8_t port, pin_num, irq_index;

    port = pin >> 5;
    pin_num = pin & 31;

    if (PIN_INVALID_CHECK(port, pin_num))
    {
        LOG_D("invalid pin,rtt pin: %d,port: %d,pin: %d \n", pin,port + 1,pin_num);
        return RT_ENOSYS;
    }

    if (hdr_tab[pin].pin == -1)
    {
        LOG_D("rtt pin: %d callback function not initialized!\n", pin);
        return RT_ENOSYS;
    }

    if (enabled == PIN_IRQ_ENABLE)
    {
        switch (hdr_tab[pin].mode)
        {
        case PIN_IRQ_MODE_RISING:
            int_mode = kGPIO_IntRisingEdge;
            break;
        case PIN_IRQ_MODE_FALLING:
            int_mode = kGPIO_IntFallingEdge;
            break;
        case PIN_IRQ_MODE_RISING_FALLING:
            int_mode = kGPIO_IntRisingOrFallingEdge;
            break;
        case PIN_IRQ_MODE_HIGH_LEVEL:
            int_mode = kGPIO_IntHighLevel;
            break;
        case PIN_IRQ_MODE_LOW_LEVEL:
            int_mode = kGPIO_IntLowLevel;
            break;
        default:
            int_mode = kGPIO_IntRisingEdge;
            break;
        }
        irq_index = (port << 1) + (pin_num >> 4);
        GPIO_PinSetInterruptConfig(mask_tab[port].gpio, pin_num, int_mode);
        GPIO_PortEnableInterrupts(mask_tab[port].gpio, 1U << pin_num);
        NVIC_SetPriority(irq_tab[irq_index], NVIC_EncodePriority(NVIC_GetPriorityGrouping(), 5, 0));
        EnableIRQ(irq_tab[irq_index]);
    }
    else if (enabled == PIN_IRQ_DISABLE)
    {
        GPIO_PortDisableInterrupts(mask_tab[port].gpio, 1U << pin_num);
    }
    else
    {
        return RT_EINVAL;
    }

    return RT_EOK;
}

4.搭建应用层demo

基本功能LED0线程中闪烁,LED1通过KEY0按一次翻转一次IO

/**************************************************START OF FILE*****************************************************/






/*------------------------------------------------------------------------------------------------------------------
Includes
*/
#include <rtthread.h>
#include <rtdevice.h>
#include "drv_gpio.h"

/*------------------------------------------------------------------------------------------------------------------
Macros
*/
#define THREAD_GPIO_PRIORITY         24
#define THREAD_GPIO_STACK_SIZE       512
#define THREAD_GPIO_TIMESLICE        2

#define LED0_PIN  GET_PIN(1, 9)
#define LED1_PIN  GET_PIN(1, 24)
#define KEY0_PIN  GET_PIN(5, 0)    //IOMUXC_SNVS_WAKEUP_GPIO5_IO00

/*------------------------------------------------------------------------------------------------------------------
Variables
*/
static rt_thread_t h_thread_gpio = RT_NULL;

static uint8_t ledBlink;

/*------------------------------------------------------------------------------------------------------------------
Functions
*/

/* 中断回调函数 */
void key_irq(void *args)
{
    rt_kprintf("key push!\n");
    rt_pin_write(LED1_PIN, !rt_pin_read(LED1_PIN));
}

static void thread_gpio(void *parameter)
{
    rt_kprintf("thread gpio start\n");

    while(1)
    {
        rt_pin_write(LED0_PIN, PIN_HIGH);
        // rt_pin_write(LED1_PIN, PIN_HIGH);
        rt_thread_mdelay(500);
        rt_pin_write(LED0_PIN, PIN_LOW);
        // rt_pin_write(LED1_PIN, PIN_LOW);
        rt_thread_mdelay(500);
    }
}


void xAPP_GpioInit(void)
{
    rt_pin_mode(LED0_PIN, PIN_MODE_OUTPUT);
    rt_pin_mode(LED1_PIN, PIN_MODE_OUTPUT);
    rt_pin_write(LED1_PIN, PIN_HIGH);  

    rt_pin_mode(KEY0_PIN, PIN_MODE_INPUT_PULLUP);   
    rt_pin_attach_irq(KEY0_PIN, PIN_IRQ_MODE_FALLING, key_irq, RT_NULL);
    rt_pin_irq_enable(KEY0_PIN, PIN_IRQ_ENABLE);

    //创建Audio线程
    h_thread_gpio = rt_thread_create("t_gpio",thread_gpio,RT_NULL,THREAD_GPIO_STACK_SIZE,THREAD_GPIO_PRIORITY,THREAD_GPIO_TIMESLICE);
    if (h_thread_gpio != RT_NULL)
	{	
		rt_thread_startup(h_thread_gpio);
	}    
}


/****************************************************END OF FILE*****************************************************/

测试结果

请添加图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值