查看: 476|回复: 0

[项目提交] 《2023 DigiKey 汽车应用创意挑战赛》 PIN驱动适配

[复制链接]
  • TA的每日心情
    奋斗
    昨天 15:07
  • 签到天数: 121 天

    连续签到: 1 天

    [LV.7]常住居民III

    发表于 2024-1-11 22:13:12 | 显示全部楼层 |阅读模式
    分享到:
    本帖最后由 andeyqi 于 2024-1-12 09:52 编辑

    RT-thread 系统已经适配完成,我们的设计中涉及的CAN/软件模拟的I2C都依赖PIN驱动,我们按照RT-thread 的规范适配PIN 驱动。在RT-Thread中,PIN(引脚)驱动层主要负责对硬件引脚进行控制和管理。该层的设计旨在提供一种通用的、可移植的方式,使应用程序能够方便地与硬件引脚进行交互,而不需要关心底层硬件的具体细节。PIN 驱动提供了硬件抽象层,使得相同的应用程序代码可以在不同的硬件上运行。开发者在移植 RT-Thread 到新的硬件时,只需要实现相应的 PIN 驱动,而无需修改应用层的代码。右侧链接为官方文档对PIN驱动架构的详细描述(RT-thread PIN驱动介绍)。根据官方文档的介绍可以知道,RT-thread PIN 驱动框架通过如下几个接口和BSP芯片的GPIO对接,我们按照要求适配好这几个接口就完成了PIN 驱动框架和硬件的对接,接口如下:

    函数描述
    rt_pin_get()获取引脚编号
    rt_pin_mode()设置引脚模式
    rt_pin_write()设置引脚电平
    rt_pin_read()读取引脚电平
    rt_pin_attach_irq()绑定引脚中断回调函数
    rt_pin_irq_enable()使能引脚中断
    rt_pin_detach_irq()脱离引脚中断回调函数

    • rt_pin_get() 接口适配
    该接口通过传入pin 的name 获取pin 脚号,然后用户通过 pin number 完成GPIO 的输入、输出及中断控制。具体实现代码如下:
    1. static rt_base_t s32kxxx_pin_get(const char * name)
    2. {
    3.     int pin = 0;
    4.     int hw_port_num, hw_pin_num = 0;
    5.     int i, name_len;

    6.     name_len = strlen(name);

    7.     if ((name_len < 4) || (name_len >= 6))
    8.     {
    9.         return -1;
    10.     }

    11.     if ((name[0] != 'P') || (name[2] != '.'))
    12.     {
    13.         return -1;
    14.     }

    15.     if ((name[1] >= 'A') && (name[1] <= 'E'))
    16.     {
    17.         hw_port_num = (int)(name[1] - 'A');
    18.     }
    19.     else
    20.     {
    21.         return -1;
    22.     }

    23.     for (i = 3; i < name_len; i++)
    24.     {
    25.         hw_pin_num *= 10;
    26.         hw_pin_num += name[i] - '0';
    27.     }

    28.     pin = PIN_NUM(hw_port_num, hw_pin_num);

    29.     return pin;

    30. }
    复制代码
    使用的S32K146 芯片引脚是按照PTAx,我们对应成PA.x的形式,例如要获取PTA2 的pin number ,按照如下方式调用即可:

    1. pin_number = rt_pin_get("PA.2");
    复制代码
    • rt_mode()接口适配
    该接口使用rt_pin_get()接口返回的pin number 配置GPIO 的输入输出属性,及上下拉配置,在S32K146上适配代码如下:
    1. /**
    2.   * @brief  set pin mode
    3.   * @param  pin, mode
    4.   * @retval None
    5.   */
    6. static void s32kxxx_pin_mode(rt_device_t dev, rt_base_t pin, rt_uint8_t mode)
    7. {
    8.     const struct pin_index *index = NULL;

    9.     index = get_pin(pin);
    10.     if (index == NULL)
    11.     {
    12.         return;
    13.     }

    14.     PINS_DRV_SetMuxModeSel(index->port,index->pin,PORT_MUX_AS_GPIO);

    15.     switch(mode)
    16.     {
    17.     case PIN_MODE_OUTPUT:
    18.     case PIN_MODE_OUTPUT_OD:
    19.         PINS_DRV_SetPinDirection(index->gpio,index->pin,GPIO_OUTPUT_DIRECTION);
    20.         break;
    21.     case PIN_MODE_INPUT:
    22.         PINS_DRV_SetPullSel(index->port,index->pin,PORT_INTERNAL_PULL_NOT_ENABLED);
    23.         PINS_DRV_SetPinDirection(index->gpio,index->pin,GPIO_INPUT_DIRECTION);
    24.         break;
    25.     case PIN_MODE_INPUT_PULLUP:
    26.         PINS_DRV_SetPullSel(index->port,index->pin,PORT_INTERNAL_PULL_UP_ENABLED);
    27.         PINS_DRV_SetPinDirection(index->gpio,index->pin,GPIO_INPUT_DIRECTION);
    28.         break;
    29.     case PIN_MODE_INPUT_PULLDOWN:
    30.         PINS_DRV_SetPullSel(index->port,index->pin,PORT_INTERNAL_PULL_DOWN_ENABLED);
    31.         PINS_DRV_SetPinDirection(index->gpio,index->pin,GPIO_INPUT_DIRECTION);
    32.         break;
    33.     default:
    34.         break;
    35.     }
    36. }
    复制代码
    • rt_pin_write()接口适配:
    该接口使用rt_pin_get()接口返回的pin number 配置GPIO 的输出高低电平设置适配代码如下:

    1. /**
    2.   * @brief  pin write
    3.   * @param   pin, valuie
    4.   * @retval None
    5.   */
    6. static void s32kxxx_pin_write(rt_device_t dev, rt_base_t pin, rt_uint8_t value)
    7. {
    8.     const struct pin_index *index = NULL;

    9.     index = get_pin(pin);
    10.     if (index == NULL)
    11.     {
    12.         return;
    13.     }
    14.     PINS_DRV_WritePin(index->gpio,index->pin,value);
    15. }
    复制代码
    • rt_pin_read()接口适配
    该接口使用rt_pin_get()接口返回的pin number 读取 GPIO 的输入引脚状态,设置适配代码如下:
    1. <blockquote>/**
    复制代码
    • rt_irq_attach_irq 接口适配
    该接口绑定rt_pin_get()接口返回的pin number 对应的中断回调函数,设置适配代码如下:

    1. /**
    2.   * @brief  pin irq attach
    3.   * @param  device, pin, mode
    4.   * @retval None
    5.   */
    6. static rt_err_t s32kxxx_pin_attach_irq(struct rt_device *device, rt_base_t pin,
    7.                               rt_uint8_t mode, void (*hdr)(void *args), void *args)
    8. {
    9.     rt_base_t level;
    10.     rt_int32_t hdr_index = -1;

    11.     hdr_index = pin/32;
    12.     if (hdr_index < 0 || hdr_index >= 5)
    13.     {
    14.         return -RT_EINVAL;
    15.     }

    16.     level = rt_hw_interrupt_disable();
    17.     if (pin_irq_hdr_tab[hdr_index].pin == pin &&
    18.         pin_irq_hdr_tab[hdr_index].hdr == hdr &&
    19.         pin_irq_hdr_tab[hdr_index].mode == mode &&
    20.         pin_irq_hdr_tab[hdr_index].args == args)
    21.     {
    22.         rt_hw_interrupt_enable(level);
    23.         return RT_EOK;
    24.     }
    25.     if (pin_irq_hdr_tab[hdr_index].pin != -1)
    26.     {
    27.         rt_hw_interrupt_enable(level);
    28.         return -RT_EFULL;
    29.     }
    30.     pin_irq_hdr_tab[hdr_index].pin = pin;
    31.     pin_irq_hdr_tab[hdr_index].hdr = hdr;
    32.     pin_irq_hdr_tab[hdr_index].mode = mode;
    33.     pin_irq_hdr_tab[hdr_index].args = args;
    34.     rt_hw_interrupt_enable(level);

    35.     return RT_EOK;
    36. }
    复制代码
    • rt_pin_detach_irq接口适配
    该接口解除绑定rt_pin_get()接口返回的pin number 对应的中断回调函数,设置适配代码如下:

    1. /**
    2.   * @brief  pin irq detach
    3.   * @param  device, pin
    4.   * @retval None
    5.   */
    6. static rt_err_t s32kxxx_pin_detach_irq(struct rt_device *device, rt_base_t pin)
    7. {
    8.     rt_base_t level;
    9.     rt_int32_t hdr_index = -1;

    10.     hdr_index = pin/32;
    11.     if (hdr_index < 0 || hdr_index >= 5)
    12.     {
    13.         return -RT_EINVAL;
    14.     }

    15.     level = rt_hw_interrupt_disable();
    16.     if (pin_irq_hdr_tab[hdr_index].pin == -1)
    17.     {
    18.         rt_hw_interrupt_enable(level);
    19.         return RT_EOK;
    20.     }
    21.     pin_irq_hdr_tab[hdr_index].pin = -1;
    22.     pin_irq_hdr_tab[hdr_index].hdr = RT_NULL;
    23.     pin_irq_hdr_tab[hdr_index].mode = 0;
    24.     pin_irq_hdr_tab[hdr_index].args = RT_NULL;
    25.     rt_hw_interrupt_enable(level);

    26.     return RT_EOK;
    27. }
    复制代码
    • rt_pin_irq_enable接口适配
    该接口开启、关闭rt_pin_get()接口返回的pin number 对应的中断,设置适配代码如下:

    1. /**
    2.   * @brief  pin irq enable
    3.   * @param  device, pin, enabled
    4.   * @retval None
    5.   */
    6. static rt_err_t s32kxxx_pin_irq_enable(struct rt_device *device, rt_base_t pin, rt_uint8_t enabled)
    7. {
    8.     const struct pin_index *index;
    9.     rt_base_t level;
    10.     rt_int32_t hdr_index = -1;
    11.     port_interrupt_config_t trigger_mode;

    12.     index = get_pin(pin);
    13.     if (index == RT_NULL)
    14.     {
    15.         return -RT_EINVAL;
    16.     }

    17.     if (enabled == PIN_IRQ_ENABLE)
    18.     {
    19.         hdr_index = pin/32;
    20.         if (hdr_index < 0 || hdr_index >= 5)
    21.         {
    22.             return -RT_EINVAL;
    23.         }

    24.         level = rt_hw_interrupt_disable();
    25.         if (pin_irq_hdr_tab[hdr_index].pin == -1)
    26.         {
    27.             rt_hw_interrupt_enable(level);
    28.             return -RT_EINVAL;
    29.         }
    30.         switch (pin_irq_hdr_tab[hdr_index].mode)
    31.         {
    32.             case PIN_IRQ_MODE_RISING:
    33.                 trigger_mode = PORT_INT_RISING_EDGE;
    34.                 break;
    35.             case PIN_IRQ_MODE_FALLING:
    36.                 trigger_mode = PORT_INT_FALLING_EDGE;
    37.                 break;
    38.             case PIN_IRQ_MODE_RISING_FALLING:
    39.                 trigger_mode = PORT_INT_EITHER_EDGE;
    40.                 break;
    41.             case PIN_IRQ_MODE_HIGH_LEVEL:
    42.                 trigger_mode = PORT_INT_LOGIC_ONE;
    43.                 break;
    44.             case PIN_IRQ_MODE_LOW_LEVEL:
    45.                 trigger_mode = PORT_INT_LOGIC_ZERO;
    46.                 break;
    47.             default:
    48.                 rt_hw_interrupt_enable(level);
    49.                 return -RT_EINVAL;
    50.         }

    51.         PINS_DRV_SetPinIntSel(index->port,index->pin,trigger_mode);

    52.         INT_SYS_SetPriority(index->irq, 0);
    53.         INT_SYS_EnableIRQ(index->irq);

    54.         rt_hw_interrupt_enable(level);

    55.     }
    56.     else if (enabled == PIN_IRQ_DISABLE)
    57.     {
    58.         PINS_DRV_SetPinIntSel(index->port,index->pin,PORT_DMA_INT_DISABLED);
    59.         INT_SYS_DisableIRQ(index->irq);
    60.     }
    61.     else
    62.     {
    63.         return -RT_EINVAL;
    64.     }

    65.     return RT_EOK;
    66. }

    67. const static struct rt_pin_ops s32kxxx_pin_ops =
    68. {
    69.     .pin_mode = s32kxxx_pin_mode,
    70.     .pin_write = s32kxxx_pin_write,
    71.     .pin_read = s32kxxx_pin_read,
    72.     .pin_get = s32kxxx_pin_get,
    73.     .pin_attach_irq = s32kxxx_pin_attach_irq,
    74.     .pin_detach_irq= s32kxxx_pin_detach_irq,
    75.     .pin_irq_enable = s32kxxx_pin_irq_enable,
    76. };


    77. int rt_hw_pin_init(void)
    78. {
    79.     int result;

    80.     result = rt_device_pin_register("pin", &s32kxxx_pin_ops, RT_NULL);

    81.     return result;
    82. }

    83. INIT_BOARD_EXPORT(rt_hw_pin_init);
    复制代码
    至此已经适配好了PIN驱动。我们可以在此基础行控制GPIO完成CAN 收发器GPIO 模拟的I2C 接口的控制。

    回复

    使用道具 举报

    您需要登录后才可以回帖 注册/登录

    本版积分规则

    关闭

    站长推荐上一条 /2 下一条

    手机版|小黑屋|与非网

    GMT+8, 2024-5-7 05:07 , Processed in 0.124388 second(s), 16 queries , MemCache On.

    ICP经营许可证 苏B2-20140176  苏ICP备14012660号-2   苏州灵动帧格网络科技有限公司 版权所有.

    苏公网安备 32059002001037号

    Powered by Discuz! X3.4

    Copyright © 2001-2024, Tencent Cloud.