本帖最后由 小恩GG 于 2019-7-18 10:45 编辑
【经验分享】RT1050 LPSPI3 引脚daisy功能注意点
一文档简介
有网友在使用MIMXRT1050-EVKB板子,并且使用官方的SDK的代码运行lpspi驱动工程没有问题,但是由于客户的一些需求,需要将LPSPI3的引脚改为另外的引脚,从下面的表格可以知道RT1050 LPSPI3的相关引脚:
网友发现从GPIO_AD_B0口修改为GPIO_AD_B1口后不能工作的问题。修改点其实也只是在pin_mux.c中修改对应的LPSPI3引脚。
这里就以最新的RT1050SDK的代码,LPSPI工程:
SDK_2.6.1_EVKB-IMXRT1050\boards\evkbimxrt1050\driver_examples\lpspi\interrupt
为例,原代码的pin_mux.c配置的引脚为:
Master (LPSPI3) Slave (LPSPI1) PCS0: GPIO_AD_B0_03_LPSPI3_PCS0 GPIO_SD_B0_01_LPSPI1_PCS0 SCK : GPIO_AD_B0_00_LPSPI3_SCK GPIO_SD_B0_00_LPSPI1_SCK SDO: GPIO_AD_B0_01_LPSPI3_SDO GPIO_SD_B0_02_LPSPI1_SDO SDI : GPIO_AD_B0_02_LPSPI3_SDI GPIO_SD_B0_03_LPSPI1_SDI 现在网友想改代码的引脚为:
Master (LPSPI3) Slave (LPSPI1) PCS0: GPIO_AD_B1_12_LPSPI3_PCS0 GPIO_SD_B0_01_LPSPI1_PCS0 SCK : GPIO_AD_B1_15_LPSPI3_SCK GPIO_SD_B0_00_LPSPI1_SCK SDO: GPIO_AD_B1_14_LPSPI3_SDO GPIO_SD_B0_02_LPSPI1_SDO SDI : GPIO_AD_B1_13_LPSPI3_SDI GPIO_SD_B0_03_LPSPI1_SDI Pinmux.c 中 BOARD_InitPins 函数中关于SPI3的引脚代码修改为: IOMUXC_SetPinMux( IOMUXC_GPIO_AD_B1_15_LPSPI3_SCK, /* GPIO_AD_B1_15 is configured asLPSPI3_SCK */ 0U); /* SoftwareInput On Field: Input Path is determined by functionality */ IOMUXC_SetPinMux( IOMUXC_GPIO_AD_B1_14_LPSPI3_SDO, /* GPIO_AD_B1_14 is configured asLPSPI3_SDO */ 0U); /* SoftwareInput On Field: Input Path is determined by functionality */ IOMUXC_SetPinMux( IOMUXC_GPIO_AD_B1_13_LPSPI3_SDI, /* GPIO_AD_B1_13 is configured asLPSPI3_SDI */ 0U); /* Software Input On Field: InputPath is determined by functionality */ IOMUXC_SetPinMux( IOMUXC_GPIO_AD_B1_12_LPSPI3_PCS0, /* GPIO_AD_B1_12 is configured asLPSPI3_PCS0 */ 0U); /* SoftwareInput On Field: Input Path is determined by functionality */ IOMUXC_SetPinConfig( IOMUXC_GPIO_AD_B1_15_LPSPI3_SCK, /* GPIO_AD_B1_15 PAD functional properties : */ 0x10B0u); /* Slew Rate Field:Slow Slew Rate Drive Strength Field: R0/6 Speed Field: medium(100MHz) Open Drain Enable Field: Open DrainDisabled Pull / Keep Enable Field: Pull/Keeper Enabled Pull / Keep Select Field: Keeper Pull Up / Down Config.Field: 100K Ohm Pull Down Hyst. Enable Field: Hysteresis Disabled */ IOMUXC_SetPinConfig( IOMUXC_GPIO_AD_B1_14_LPSPI3_SDO, /* GPIO_AD_B1_14 PAD functionalproperties : */ 0x10B0u); /* Slew RateField: Slow Slew Rate Drive Strength Field: R0/6 Speed Field: medium(100MHz) Open Drain Enable Field: Open Drain Disabled Pull / Keep Enable Field: Pull/Keeper Enabled Pull / Keep Select Field: Keeper Pull Up / Down Config. Field: 100K Ohm Pull Down Hyst. Enable Field: Hysteresis Disabled */ IOMUXC_SetPinConfig( IOMUXC_GPIO_AD_B1_13_LPSPI3_SDI, /* GPIO_AD_B1_13 PAD functionalproperties : */ 0x10B0u); /* Slew RateField: Slow Slew Rate Drive Strength Field: R0/6 Speed Field: medium(100MHz) Open Drain Enable Field: Open Drain Disabled Pull / Keep Enable Field: Pull/Keeper Enabled Pull / Keep Select Field: Keeper Pull Up / Down Config. Field: 100K Ohm Pull Down Hyst. Enable Field: HysteresisDisabled */ IOMUXC_SetPinConfig( IOMUXC_GPIO_AD_B1_12_LPSPI3_PCS0, /* GPIO_AD_B1_12 PAD functionalproperties : */ 0x10B0u); /* Slew RateField: Slow Slew Rate Drive Strength Field: R0/6 Speed Field: medium(100MHz) Open Drain Enable Field: Open Drain Disabled Pull/ Keep Enable Field: Pull/Keeper Enabled Pull / Keep Select Field: Keeper Pull Up / Down Config. Field: 100K Ohm Pull Down Hyst. Enable Field: Hysteresis Disabled */代码修改之后,SPI通信失败,那么到底是什么原因导致这个问题呢?下面进行仔细分析。
二问题分析
首先从pin_mux.c代码分析, 可以看到每个SPI引脚调用两个API函数: IOMUXC_SetPinMux 和 IOMUXC_SetPinConfig 分析这两个函数具体功能: static inlinevoid IOMUXC_SetPinMux(uint32_t muxRegister, uint32_tmuxMode, uint32_tinputRegister, uint32_tinputDaisy, uint32_t configRegister, uint32_tinputOnfield) { *((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) =inputDaisy; } } static inlinevoid IOMUXC_SetPinConfig(uint32_t muxRegister, uint32_tmuxMode, uint32_tinputRegister, uint32_tinputDaisy, uint32_tconfigRegister, uint32_tconfigValue) { if (configRegister) { *((volatile uint32_t *)configRegister)= configValue; } } #defineIOMUXC_GPIO_AD_B1_15_LPSPI3_SCK 0x401F8138U, 0x2U, 0, 0, 0x401F8328U #defineIOMUXC_GPIO_AD_B1_14_LPSPI3_SDO 0x401F8134U, 0x2U, 0x401F8518U, 0x1U,0x401F8324U #defineIOMUXC_GPIO_AD_B1_13_LPSPI3_SDI 0x401F8130U, 0x2U, 0x401F8514U, 0x1U,0x401F8320U #define IOMUXC_GPIO_AD_B1_12_LPSPI3_PCS00x401F812CU, 0x2U, 0x401F850CU, 0x1U, 0x401F831CU这里以IOMUXC_GPIO_AD_B1_15_LPSPI3_SCK为例代入API分析。 IOMUXC_SetPinMux(IOMUXC_GPIO_AD_B1_15_LPSPI3_SCK, 0U); IOMUXC_SetPinMux( 0x401F8138U, 0x2U,0, 0, 0x401F8328U, 0U);
muxRegister = 0x401F8138U// 即SW_MUX_CTL_PAD_GPIO_AD_B1_15 SW MUX Control Register 地址 muxMode = 0x2U //MUX模式 inputRegister = 0 //输入寄存器地址,通常有daisy的为对于daisy寄存器的地址 inputDaisy = 0 //对应Daisy的数据 configRegister= 0x401F8328U//即SW_PAD_CTL_PAD_GPIO_AD_B1_15SW PAD Control Register地址 inputOnfield = 0U // 输入on是否使能, 输入回环功能 对于IOMUXC_SetPinMux代码:
*((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) = inputDaisy; }
可以知道,实际上是配置MUX控制寄存器数据,以及对应输入寄存器的daisy数据。 那么这里是以IOMUXC_GPIO_AD_B1_15_LPSPI3_SCK为例,对应的MUX控制寄存器情况如何?
IOMUXC_SetPinConfig(IOMUXC_GPIO_AD_B1_15_LPSPI3_SCK, 0x10B0u); IOMUXC_SetPinConfig( 0x401F8138U, 0x2U, 0, 0,0x401F8328U, 0x10B0u);
muxRegister = 0x401F8138U// 即SW_MUX_CTL_PAD_GPIO_AD_B1_15 SW MUX Control Register 地址 muxMode = 0x2U //MUX模式 inputRegister = 0 //输入寄存器地址,通常有daisy的为对于daisy寄存器的地址 inputDaisy = 0 //对应Daisy的数据 configRegister= 0x401F8328U//即SW_PAD_CTL_PAD_GPIO_AD_B1_15SW PAD Control Register地址 configValue = 0x10B0u//配置寄存器的值
if (configRegister) { *((volatile uint32_t *)configRegister)= configValue; } IOMUXC_SetPinConfig只用到配置寄存器,没有用MUX控制寄存器。 下面再来分析关于Daisy的功能,看看LPSPI3是否具有DAISY寄存器,通过查看RM,发现LPSPI3模块是有对应的DAISY寄存器的。
可以发现,LPSPI3的几个引脚都是具有DAISY功能的,DAISY功能主要用于一个模块对应多个引脚的情况,这个时候需要用DAISY寄存器去确定具体是哪个引脚接到对应的模块:
所以需要再次查看对应新引脚的定义,是否包含了DAISY寄存器,功能是否正确。
#defineIOMUXC_GPIO_AD_B1_15_LPSPI3_SCK 0x401F8138U, 0x2U, 0, 0, 0x401F8328U #defineIOMUXC_GPIO_AD_B1_14_LPSPI3_SDO 0x401F8134U, 0x2U, 0x401F8518U, 0x1U, 0x401F8324U #defineIOMUXC_GPIO_AD_B1_13_LPSPI3_SDI 0x401F8130U, 0x2U, 0x401F8514U, 0x1U,0x401F8320U #defineIOMUXC_GPIO_AD_B1_12_LPSPI3_PCS0 0x401F812CU, 0x2U, 0x401F850CU, 0x1U,0x401F831CU 可以发现,上述几个引脚,只有IOMUXC_GPIO_AD_B1_15_LPSPI3_SCK没有定义DAISY寄存器,那么看看具体对应的SPI3 SCK引脚DAISY寄存器到底如何?
看到这个位置,相信大家已经明白问题出在哪里了,SDK代码里面漏定义了SPI3 SCK的DAISY寄存器以及数据。
三修改内容
所以,根据第2章节的分析,可以知道,需要把SPI3 SCK的定义中添加DAISY寄存器以及数据的定义,把代码: #defineIOMUXC_GPIO_AD_B1_15_LPSPI3_SCK 0x401F8138U, 0x2U, 0, 0, 0x401F8328U
修改为:
#defineIOMUXC_GPIO_AD_B1_15_LPSPI3_SCK 0x401F8138U, 0x2U, 0X401F8510, 0x1U,0x401F8328U 修改后,再次运行修改后的新SPI3对应引脚,可以发现SPI3模块能够正常工作。
|