AG32 下 SPI 的扩展使用

1 min read CPLD

AG32

判别是否需要使用“扩展方式” :

SDK 中默认的 SPI 驱动,是封装给 flash 用的,不能像 ST 的通用 SPI 一样给普通外设使用。

如果要给其他外设使用,则设备必须满足一定的时序(参考 datasheet 中的详细描述)。

时序限制:

1. SPI 交互时第一段只能是 tx(不能是 rx);

2. 收和发不能同时进行(只能是发完再收);

3. rx 后边不能再有 tx(rx 位于一次交互的最后一段);

使用 SPI 前请确认(外设是否满足上述限制):

如果满足,则使用 example_spi_common.c的样例代码即可。

如果不满足,比如上来就是 spi 的收动作,则必须使用这里的 SPI 扩展方式。

(注:如果可以,请尽量使用 example_spi_common.c 的样例。这里的 spi 扩展方式是需要加

cpld 才能实现的,用起来比较费劲)

这里的功能是对应 SDK1.5.2 中\examples\spi\full_duplex_spi 样例。

“扩展方式”扩展出来的函数:

原 example_spi_common.c 中提供的函数:

1. Send:单纯发送数据,字节数不限制;

2. SendAndRecv:在一个片选周期内,发送一段数据,再接收一段数据;

其中发送长度最长 4byte,接收长度不限。

(如果发送长度要更长,请自行在 C 驱动中扩展。)

这里,会在以上基础上,扩展出来两个函数:

1. Recv:单纯收取数据,字节数长度小于 124 字节;

2. SendWithRecv:在发送数据的同时来收(双向传输),而不是发完后再收。

收取数据和发送数据的长度等长。

同时,新增了对 spi 的设置:极性、相位、大小端。“扩展方式”使用步骤:

1.这部分内容,可参考《AG32 下 fpga 和 cpld 的使用入门》,可以认为这里要开始 cpld

的编程了。

然后,从网盘当前路径下找到两个文件:

example_spi_advanced.c 和 full_duplex_spi.v。

C 文件是 SPI 调用的驱动实现;

V 文件是 SPI 在 cpld 中实现的逻辑补丁。

2.A. 修改 example 默认 VE 中对 SPI 引脚和信号量的定义:

VE 中对 SPI0 引脚原定义

对应修改为

文字粘贴如下:

# Connect these pins to logic to achieve full duplex transfer

SPI0_CSN

csn

SPI0_SCK

sck

SPI0_SI_IO0 si_io0:OUTPUT

csn

PIN_66:OUTPUT

sck

PIN_67:OUTPUT

si_io0

PIN_79:OUTPUT # MOSI

so_io1

PIN_80:INPUT # MISO

注意:这里的名字定义不要修改,因为在 full_duplex_spi.v 中使用的就是这组名字。

B. 放开 platformio.ini 中的 logic 选项:这里两项放开后,会出现下边的 prepare LOGIC 选项。(注意:这两行配置在放开

时,前边不要有空格,要顶格写。)

C. 生成 logic 出来(点 prepare LOGIC):

D. 复制上边准备好的 full_duplex_spi.v,覆盖掉 logic 下刚生成的 full_duplex_spi.v;

(以后,如果有自己的自定义 logic 代码,则这里是合并动作。)

此时 logic 文件夹如图所示:

3.用 Quartus II 打开刚新建的 logic 工程。

然后 Tool -> Tcl Scripts,在弹出画面中选择 af_quartus.tcl,再点【run】:成功后提示如下:

然后,再用 SDK 根路径下的 Supra.exe 工具,打开该 logic 工程:

点 Tool -> Compile,点【Run】:成功后提示如下:

此时,编译通过。

这个时候,logic 路径下的 bin,就是要下载到 flash 的逻辑 bin。

接下来,正常烧录该logicbin

4.把第一步中准备好的 example_spi_advanced.c 放到自己工程下。

在该 C 中,可以看到测试函数 TestSpiAdvanced 调用如下:

这里 4 个函数,可以在自己代码中使用,来实现自己的功能。

到这里,全部操作完毕

以下是拓展说明:

5.如果工程中还用到别的cpld,注意寄存器地址的更换:如果工程中还用到其他 cpld,比如 ADC,则需要将这里用到的 cpld 部分和 ADC 部分进

行合并。合并的思路,参考《AG32 下 fpga 和 cpld 的使用入门》

合并时,寄存器的偏移地址要和 ADC 区分开,这里不再是 0x60000000 的位置了,修改

ADDR_OFFSET_SPI0 的值来实现偏移。

同时,C 驱动里也要对应修改 SPI0_CTRL/SPI0_DATA 地址。

6.则 VE 里需要定义两份:spi0 和 spi1 各一份;

同时 cpld 里,也要处理两份。

并且注意两份的访问地址的区分。

在.c 里已经区分开来,需要 spi1 的两个地址映射过去即可。

这篇文档有帮助吗?