五.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
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寄存器里。和我们前面几张那个配置电气性能的赋值语句效果是一样的。
这两个方法要熟练掌握,后面我们做裸机驱动的时候回经常用到。用的多了就熟练了。