本文记录了复旦微fmql45t900 SPI裸核和linux系统下spi接口的调试步骤。
问题描述:
复旦微fmql45t900 SPI接口片选信号无法拉低控制。
原因分析:
为了排除硬件问题,创建spi裸核测试工程进行单步调试,spi发送数据时用示波器可以正常量到spi发送的数据和片选拉低信号,数据发送完后片选自动拉高。
当procise将相关MIO端口配置成spi功能时,对应的MIO30口默认配置为spi0的片选,当spi发送fifo非空时会自动拉低,无法作为通用GPIO口进行控制。
解决措施:修改spi测试工程中ps_init.c文件,将MIO30口配置成普通GPIO口,修改如下:
注意:在线调试时如果先加载了fsbl工程再加载的话,最好将fsbl工程和spi测试工程中的ps_init.c都进行修改,如果只修改fsbl工程后面再加载spi测试工程时再次初始化端口可能会覆盖之前的配置。
测试验证:
裸核测试验证
在spi测试工程fmsh_gpio_exampl.c中增加以下片选设置代码:
/*功能:片选设置
参数:
port:片选对应gpio口,共32个口,spi0片选对应端口30
value:gpio值,0拉低 1拉高
*/
u8 FGpioPs_cs_set(int port, int value)
{
FGpioPs_T gpioDevA;
FGpioPs_init(&gpioDevA, FGpioPs_LookupConfig(GPIO_DeviceID));
static unsigned int staus = 0xFFFFFFFF;
FGpioPs_setDirection(&gpioDevA, 0xFFFFFFFF); /*set gpio direction all output */
if(value)
{
staus |= (1 << port);
FGpioPs_writeData(&gpioDevA, staus); /*output high level to gpio pins*/
}
else
{
staus &= (~(1 << port));
FGpioPs_writeData(&gpioDevA, staus); /*output low level to gpio pins*/
}
return 0;
}
在spi测试工程fmsh_spi_exampl.c中修改spi测试函数FSpiPs_example如下:
int FSpiPs_example(void)
{
FSpiPs_T* spi0Ptr;
FSpiPs_T* spi1Ptr;
int status = FMSH_SUCCESS;
u32 data;
spi0Ptr = &spi0;
/* spi0 master, spi1 slaver */
FSpiPs_Initialize(spi0Ptr, FPS_SPI0_DEVICE_ID);
FSpiPs_Reset(spi0Ptr);
FSpiPs_Initialize_Master(spi0Ptr);
/*将spi0片选拉低*/
FGpioPs_cs_set(30, 0);
/*发送数据*/
FSpiPs_Send(spi0Ptr, 0xf3);
/*将spi0片选拉高*/
FGpioPs_cs_set(30, 1);
return status;
}
Linux系统下使用spi步骤:
a、将上述修改后的fsbl工程编译生成FSBL.out文件
b、修改dts设备树文件添加spi设备节点,修改如下:
spi@e0001000 {
//spi控制器名称,和spi主控制器驱动匹配
compatible = "fmsh,dw-apb-ssi", "snps,dw-apb-ssi";
#address-cells = <0x1>;
#size-cells = <0x0>;
reg = <0xe0001000 0x1000>; //spi控制器寄存器地址、长度
interrupts = <0x0 0x16 0x4>;
num-cs = <0x2>; //支持两个片选
clocks = <0x1 0x27 0x1 0x29>;
clock-names = "clk_ref", "pclk";
reg-io-width = <0x4>;
spi-max-frequency = <0xf4240>;
status = "okay";
//片选信号,0xb表示GPIO,对应porta,0x1e表示对应MIO30端口,0表示低电平有效
cs-gpios = <0xb 0x1e 0x0 0xb 0x1f 0x0>;
// spi控制器连接的设备0
spidev0:dh2228@0 {
compatible = "rohm,dh2228fv"; //设备名称,和spi设备驱动匹配
reg = <0x0>; //片选0
spi-max-frequency = <0x1000000>;
};
// spi控制器连接的设备1
spidev1:dh2228@1 {
compatible = "rohm,dh2228fv";
reg = <0x1>;//片选1
spi-max-frequency = <0x1000000>;
};
};
上述节点中的片选gpio设备树节点由procise将MIO配置成GPIO后自动生成,如下所示:
gpio@e0003000 {
compatible = "snps,dw-apb-gpio";
reg = <0xe0003000 0x100>;
#address-cells = <0x1>;
#size-cells = <0x0>;
clocks = <0x1 0x2d>;
status = "okay";
gpio-controller@0 {
compatible = "snps,dw-apb-gpio-port";
bank-name = "porta";
gpio-controller;
#gpio-cells = <0x2>;
snps,nr-gpios = <0x20>;
reg = <0x0>;
interrupt-controller;
#interrupt-cells = <0x2>;
interrupts = <0x0 0x11 0x4>;
linux,phandle = <0xb>;
phandle = <0xb>;
};
};
c、用dtc工具将步骤b修改后的dts编译成dtb, dtc工具使用命令如下(xxx表示对应dtb和dts文件名):
dtc -I dts -O dtb -o xxx.dtb xxx.dts
d、用dtb编译对应的uboot.elf文件,将uboot.elf和FSBL.out生成BOOT.bin
e、配置内核,增加spi驱动相关配置,重新编译内核(复旦微提供的内核默认已经配置相关项):
其中CONFIG_SPI_DW_FMSH对应复旦微spi主控制器驱动, CONFIG_SPI_SPIDEV对应spi外接设备驱动,其他为spi驱动框架涉及的核心和片选控制驱动代码。
完成上述步骤、进入系统后会在/dev目录下生成对应的spi设备文件,应用程序可以对设备文件进行读写操作。