五.NXP恩智浦官方SDK使用

恩智浦针对I.MX6ULL编写了一个SDK包,这个包类似STM32的标准库或者HAL库,这个SDK包含了Windows和Linux两种版本。下载链接可以点击下载,链接失效了还可以从这下:

https://pan.baidu.com/s/1L4OgqBiejZJFOmOxTVjtBw

提取码:slhm
我是用的Ubuntu20.04。修改完权限以后用./执行run文件即可,安装路径为主目录下。

定义数据类型

SDK包里会有很多数据类型,我们要先定义数据类型。

 

 

移植文件

SDK安装完成后,我们主要用到文件是

  • fsl_common.h——公共库文件
  • fsl_iomuxc.h
  • MCIMX6Y2.h

这几个文件的路径是在我们安装的SDK文件夹下。要对这三个文件做一些修改,过程不再赘述,把文件放在最后。这样就可以使用了。这里着重讲一个函数,先看下原来对GPIO进行初始化的方法

/*初始化LED*/
void led_init(void)
{   
    // 复用、电气属性寄存器初始化
    IOMUX_SW_MUX->GPIO1_IO03 = 0x5;
    IOMUX_SW_PAD->GPIO1_IO03 = 0x10B0;
    // GPIO1方向寄存器,
    GPIO1->GDIR = 0x8;
}

是通过指针直接对寄存器赋值,而NXP提供的方法是定义了个宏

void led_init(void)
{   
    // 复用、电气属性寄存器初始化
    IOMUXC_SetPinMux(IOMUXC_GPIO1_IO03_GPIO1_IO03,0);
    IOMUXC_SetPinConfig(IOMUXC_GPIO1_IO03_GPIO1_IO03,0x10B0);
    // GPIO1方向寄存器,
    GPIO1->GDIR = 0x8;

和原来的方法不一样,下面着重讲一下这两个函数,后面用到的概率比较大。

SetPinMux

我们先看下库文件对函数的定义

/*!
 * @brief Sets the IOMUXC pin mux mode.
 * @note The first five parameters can be filled with the pin function ID macros.
 *
 * This is an example to set the ENET1_RX_DATA0 Pad as FLEXCAN1_TX:
 * @code
 * IOMUXC_SetPinMux(IOMUXC_ENET1_RX_DATA0_FLEXCAN1_TX, 0);
 * @endcode
 *
 * This is an example to set the GPIO1_IO02 Pad as I2C1_SCL:
 * @code
 * IOMUXC_SetPinMux(IOMUXC_GPIO1_IO02_I2C1_SCL, 0);
 * @endcode
 *
 * @param muxRegister  The pin mux register.
 * @param muxMode      The pin mux mode.
 * @param inputRegister The select input register.
 * @param inputDaisy   The input daisy.
 * @param configRegister  The config register.
 * @param inputOnfield   Software input on field.
 */
static inline void IOMUXC_SetPinMux(uint32_t muxRegister,
                                    uint32_t muxMode,
                                    uint32_t inputRegister,
                                    uint32_t inputDaisy,
                                    uint32_t configRegister,
                                    uint32_t inputOnfield)
{
    *((volatile uint32_t *)muxRegister) =
        IOMUXC_SW_MUX_CTL_PAD_MUX_MODE(muxMode) | IOMUXC_SW_MUX_CTL_PAD_SION(inputOnfield);

    if (inputRegister)
    {
        *((volatile uint32_t *)inputRegister) = IOMUXC_SELECT_INPUT_DAISY(inputDaisy);
    }
}

注释很清楚,该函数是对IO引脚做复用设置的。函数形参有6个,看下传的参数IOMUXC_GPIO01_IO03_GFPIO1_IO03这个值。

#define IOMUXC_GPIO1_IO03_GPIO1_IO03                         0x020E0068U, 0x5U, 0x00000000U, 0x0U, 0x020E02F4U
IOMUXC_GPIO1_IO03_GPIO1_IO03  是一个被声明的宏,对应了5个参数,加上我们传的0刚好对应函数的6个形参。整个对应关系是这样的
muxRegister         0x020E0068U
muxMode             0x5U
inputRegister       0x00000000U
inputDaisy          0x0U
configRegister      0x020E02F4U
input Onfield       0

有三个寄存器,其中两个地址已经在宏里定义好了,查手册可以发现,muxRegister是复用设置,设置的值就是muxMode,和原先设置的值是一样的

所以下面的函数我们都不用看

 *((volatile uint32_t *)muxRegister) =
        IOMUXC_SW_MUX_CTL_PAD_MUX_MODE(muxMode) | IOMUXC_SW_MUX_CTL_PAD_SION(inputOnfield);

我们都知道他是将复用的模式设置给复用寄存器的。后面或了个inputOnfield是因为复用模式muxMode只是后3个bit,第4位还有个sion位,设置个0把他关闭掉。

 configRegister是电气属性设置

 

 这个参数在函数中实际是没有使用的。 原因下面会说到

IOMUXC_SetPinConfig

先看下函数的源代码

/*!
 * @brief Sets the IOMUXC pin configuration.
 * @note The previous five parameters can be filled with the pin function ID macros.
 *
 * This is an example to set pin configuration for IOMUXC_GPIO1_IO02_I2C1_SCL:
 * @code
 * IOMUXC_SetPinConfig(IOMUXC_GPIO1_IO02_I2C1_SCL, IOMUXC_SW_PAD_CTL_PAD_PUE_MASK | IOMUXC_SW_PAD_CTL_PAD_PUS(2U));
 * @endcode
 *
 * @param muxRegister  The pin mux register.
 * @param muxMode      The pin mux mode.
 * @param inputRegister The select input register.
 * @param inputDaisy   The input daisy.
 * @param configRegister  The config register.
 * @param configValue   The pin config value.
 */
static inline void IOMUXC_SetPinConfig(uint32_t muxRegister,
                                       uint32_t muxMode,
                                       uint32_t inputRegister,
                                       uint32_t inputDaisy,
                                       uint32_t configRegister,
                                       uint32_t configValue)
{
    if (configRegister)
    {
        *((volatile uint32_t *)configRegister) = configValue;
    }
}

我们会发现,函数的形参和前面讲复用配置的参数是一样的,并且我们传参的第一个宏也和前面一样。所以两个函数用到一个定义的宏。唯一的区别就是传入的第二个值(函数第6个形参)是0x10B0,看下函数里调用的方法,也是个传参,就是把configValue的值传递给configRegister寄存器里。和我们前面几张那个配置电气性能的赋值语句效果是一样的。

这两个方法要熟练掌握,后面我们做裸机驱动的时候回经常用到。用的多了就熟练了。

posted @ 2021-12-30 00:54  银色的音色  阅读(1037)  评论(0编辑  收藏  举报