如题:
1、使用的芯片为am4378,
2、目前在实现spi1功能,QNX操作系统下,采用地址映射的方式操作寄存器。
3、在配置SPI1外设的pin引脚复用功能时,通过读取手册发现需要配置以下几个寄存器:
CTRL_CONF_MCASP0_ACLKX Register
CTRL_CONF_MCASP0_FSX Register
CTRL_CONF_MCASP0_AXR0 Register
4、在用户手册中寄存器控制章节查到对应几个寄存器的配置:可以配置bit0-bit3为spi模式
CTRL_CONF_MCASP0_ACLKX Register —> 可以复用为:spi1_sclk —> bitr0-bit3为:mode3 即:b0011
CTRL_CONF_MCASP0_FSX Register —> 可以复用为:spi1_d0 —> bitr0-bit3为:mode3 即:b0011
CTRL_CONF_MCASP0_AXR0 Register —> 可以复用为:spi1_d1 —> bitr0-bit3为:mode3 即:b0011
如图:
5、然后问题出现了:
(1)读取默认值,发现bit0-bit3是b0111,也就是GPIO模式;
(2)写入b0011到bit0-bit3中,想要复用为SPI模式;
(3)再读取该寄存器,发现写入失败,寄存器的值还是以前的b0111,并未切换成功。
跪求指点,感激不尽!!
代码如下:(备注:为了看起来简洁,把判错以及一些不相关的log代码删除了)
/* GPIO MUX */ #define AM437X_PIN_MUX_SIZE0x1000 #define CONTROL_MODULE_BASE0x44E10000 #define CTRL_STS((CONTROL_MODULE_BASE) + (0x40)) #define CTRL_CONF_MCASP0_ACLKX((CONTROL_MODULE_BASE) + (0x990)) #define CTRL_CONF_MCASP0_FSX((CONTROL_MODULE_BASE) + (0x994)) #define CTRL_CONF_MCASP0_AXR0((CONTROL_MODULE_BASE) + (0x998)) typedef struct {am437x_reg sts;am437x_reg conf_mcasp0_aclkx;am437x_reg conf_mcasp0_fsx;am437x_reg conf_mcasp0_axr0; } am437x_pin_mux;
void spi_pin_mux_init(am437x_pin_mux *spi_pin) {/* pin mux io map */DEBUG_INFO("----pin mux iomap start.-----------\r\n");spi_pin->conf_mcasp0_aclkx.vaddr = mmap_device_io(AM437X_PIN_MUX_SIZE, CTRL_CONF_MCASP0_ACLKX);spi_pin->conf_mcasp0_fsx.vaddr= mmap_device_io(AM437X_PIN_MUX_SIZE, CTRL_CONF_MCASP0_FSX);spi_pin->conf_mcasp0_axr0.vaddr = mmap_device_io(AM437X_PIN_MUX_SIZE, CTRL_CONF_MCASP0_AXR0);/* pin mux *//* 1. spi1_sclk */DEBUG_INFO("reg value = 0x%8x\r\n", in32(spi_pin->conf_mcasp0_aclkx.vaddr));spi_pin->conf_mcasp0_aclkx.value.all = in32(spi_pin->conf_mcasp0_aclkx.vaddr);spi_pin->conf_mcasp0_aclkx.value.bit.bit0 = 1;spi_pin->conf_mcasp0_aclkx.value.bit.bit1 = 1;spi_pin->conf_mcasp0_aclkx.value.bit.bit2 = 0;spi_pin->conf_mcasp0_aclkx.value.bit.bit3 = 0;out32(spi_pin->conf_mcasp0_aclkx.vaddr, spi_pin->conf_mcasp0_aclkx.value.all);DEBUG_INFO("value= 0x%8x\r\n", spi_pin->conf_mcasp0_aclkx.value.all);DEBUG_INFO("reg value = 0x%8x\r\n", in32(spi_pin->conf_mcasp0_aclkx.vaddr));/* 2. spi1_d0 */DEBUG_INFO("reg value = 0x%8x\r\n", in32(spi_pin->conf_mcasp0_fsx.vaddr));spi_pin->conf_mcasp0_fsx.value.all = in32(spi_pin->conf_mcasp0_fsx.vaddr);spi_pin->conf_mcasp0_fsx.value.bit.bit0 = 1;spi_pin->conf_mcasp0_fsx.value.bit.bit1 = 1;spi_pin->conf_mcasp0_fsx.value.bit.bit2 = 0;spi_pin->conf_mcasp0_fsx.value.bit.bit3 = 0;out32(spi_pin->conf_mcasp0_fsx.vaddr, spi_pin->conf_mcasp0_fsx.value.all);DEBUG_INFO("value= 0x%8x\r\n", spi_pin->conf_mcasp0_fsx.value.all);DEBUG_INFO("reg value = 0x%8x\r\n", in32(spi_pin->conf_mcasp0_fsx.vaddr));/* 3. spi1_d1 */DEBUG_INFO("reg value = 0x%8x\r\n", in32(spi_pin->conf_mcasp0_axr0.vaddr));spi_pin->conf_mcasp0_axr0.value.all = in32(spi_pin->conf_mcasp0_axr0.vaddr);spi_pin->conf_mcasp0_axr0.value.bit.bit0 = 1;spi_pin->conf_mcasp0_axr0.value.bit.bit1 = 1;spi_pin->conf_mcasp0_axr0.value.bit.bit2 = 0;spi_pin->conf_mcasp0_axr0.value.bit.bit3 = 0;out32(spi_pin->conf_mcasp0_axr0.vaddr, spi_pin->conf_mcasp0_axr0.value.all);DEBUG_INFO("value= 0x%8x\r\n", spi_pin->conf_mcasp0_axr0.value.all);DEBUG_INFO("reg value = 0x%8x\r\n", in32(spi_pin->conf_mcasp0_axr0.vaddr)); }
打印结果如下:
reg value = 0x 8040007--->写入前先读取一下寄存器的值 value= 0x 8040003--->写入的变量的值 reg value = 0x 8040007--->写入以后再次读取寄存器的值 reg value = 0x 8040007 value= 0x 8040003 reg value = 0x 8040007 reg value = 0x 8040007 value= 0x 8040003 reg value = 0x 8040007
Nancy Wang:
请问代码是参考的哪个SDK?
有没有试过用pinmux工具直接生成相关配置。
www.ti.com/…/PINMUXTOOL
以下路径下的pinmux.c的源码也可以参考:
ti-processor-sdk-rtos-am437x\pdk_am437x_1_0_15\packages\ti\starterware\board\pinmux.c
PINMUXModuleConfig();
user6090244:
回复 Nancy Wang:
用pinmuxtool工具试了,生成的代码移植到我的项目中了,但是还是一样,目前情况是:复用功能寄存器写不进去,不知道为啥,写入以后,再读取,还是原始值。
是否复用寄存器也跟时钟有关系?需要配置复用功能时钟?
Nancy Wang:
回复 user6090244:
int32_t MCSPIAppInit(mcspiAppCfgObj_t *pCfgMcspi)
{
int32_t status = S_PASS;
/* Clock Configuration. */
status = PRCMModuleEnable(CHIPDB_MOD_ID_MCSPI, pCfgMcspi->instNum, 0U);
if (S_PASS != status)
{
CONSOLEUtilsPrintf("\n Clock Configuration failed !\n");
}
else
{
/* Perform the MCSPI pinmux. */
status = PINMUXModuleConfig(CHIPDB_MOD_ID_MCSPI, pCfgMcspi->instNum, NULL);
配置一下时钟看看。
ti-processor-sdk-rtos-am437xpdk_am437x_1_0_15\packages\ti\starterware\examples\mcspi
PRCMModuleEnable()请参考ti-processor-sdk-rtos-am437xpdk_am437x_1_0_15\packages\ti\starterware\soc\am43xx\am43xx_prcm.c
user6090244:
回复 Nancy Wang:
对了,昨天忘了说,我在第7章 Control Module的7.1 Introduction小节看到有这么一句描述:
Note: For writing to the control module registers, the MPU will need to be in privileged mode of operation and writes will not work from user mode.
意思是,我要写复用寄存器还需要先进入privileged mode吗?所以,这才是导致我写复用功能寄存器写不进去的原因吗?如果是的话,该怎么进特权模式呢?
如图:
Nancy Wang:
回复 user6090244:
是的,需要进入privileged mode 。
试试看调用void CPUSwitchToPrivilegedMode(void)
C:\ti-processor-sdk-rtos-am437x-evm-06.00.00.07-Windows\pdk_am437x_1_0_15\packages\ti\starterware\soc\armv7a\gcc\cpu.c
Cortex-A9技术手册也可以参考看一下。
developer.arm.com/…/h
Nancy Wang:
回复 user6090244:
CPUSwitchToPrivilegedMode()执行带有常量值1的SWI,但是SVC_Handler函数在切换到系统(特权)模式之前会查找常量458752。建议通过以下方法对此进行试验:
在代码中调用CPUSwitchToPrivilegedMode()
在exception vector table的SVC向量中打断点
查看SVC向量是否调用SVC_Handler
单步执行(asm单步执行)以查看是否跳过了切换到系统模式的操作
如果跳过了代码,则建议更新CPUSwitchToPrivilegedMode()以调用带有常量值458752的SWI。然后重复上面概述的相同实验。具体查看pdk_am437x_1_0_17\packages\ti\starterware\soc\armv7a\gcc\exceptionhandler.S: