赞
踩
导读:本节将以一个简单的 LED Demo 为例,详细介绍基于PGL22G 的 Cortex-M1 软核开发流程。
工欲善其事必先利其器,在正式开跑软核之前,还需要准备一下软件和Demo工程,清单如下:
钉钉群下载的两个文件解压后,放置到没有中文和空格的路径下,然后将pgr_ARM_Cortex_M1_PGL22_324_eval
文件夹放置到pgr_FPGA_Cortex-M1_eval
文件夹下的rtl_design
目录里,层级结构如下图所示:
注:下文若要对应到
pgr_ARM_Cortex_M1_PGL22_324_eval
所在目录,会直接写成:.\pgr_FPGA_Cortex-M1_eval\rtl_design\pgr_ARM_Cortex_M1_PGL22_324_eval
的形式。
LED应用程序对应的keil工程,位于:.\pgr_FPGA_Cortex-M1_eval\software_design\module_design\Cortex-M1_led
目录下。进入其子目录PROJECT
,双击cortex_M1_led.uvprojx
即可打开keil工程,如下图所示:
PGL22G Cortex-M1软核的ROM和RAM设置方式有两种:
ITCM
作为 ROM(起始地址为 0x00000000
), DTCM
作为 RAM(起始地址为 0x20000000
),大小根据用户实际需求进行设置。ICACHE
作为 ROM(起始地址为 0x10000000
), DCACHE
作为 RAM(起始地址为 0x30000000
),大小根据用户实际需求进行设置。我们使用CACHE
,故ROM和RAM地址设置为上述第二种,具体配置方式如下所示。
①、点击工具栏的魔术棒选项:
②、选择Target
,设置ROM和RAM起始地址和大小:
0x10000000
、大小:0x1000000
0x30000000
、大小:0x100000
注:
ICACHE
指令起始地址必须配置为:0x1000 0000
,DDR
颗粒映射范围0x0000 0000-0x00FF FFFF
(即最大:16MB - 0x100 0000
);DCACHE
数据起始地址必须配置为:0x3000 0000
,DDR
颗粒映射范围0x0100 0000-0x0FFF FFFF
(即最大:256MB - 0x10000 0000
)。- 不能超过这个映射范围,否者会出错。
Cortex-M1 软件编程设计通过:
Run #1
操作, 将 axf
文件转换为 bin
文件格式并输出;Run #2
操作, 使用 make_hex.exe
工具将 bin
文件转换为 4
个 ITCM
文件格式并输出。关于ITCM要说的几点:
Bootloader
工程产生的 itcm0
、itcm1
、 itcm2
、 itcm3
4个文件)才能将应用工程的指令(即由本节的LED工程编译生成的 BIN
文件) 装载到 DDR
颗粒中并实现地址跳转。Run #1
操作主要是为我们的LED
应用工程产生bin
文件,而Run #2
操作是为我们的Bootloader
引导工程产生4个ITCM
文件。为了让应用工程和引导工程可以复用同一个keil
模板,就没有在应用工程中特别地去掉Run #2
操作,同理也没有在引导工程中特别地去掉Run #1
操作。(后面做仿真会用在应用工程中修改 Run #2
)bin
文件,是不是下一节就是生成引导工程的4个ITCM
文件?不!4个ITCM
文件我们直接使用pgr_FPGA_Cortex_M1_PGL22_324_eval
这个PDS工程自带的即可!(自带的4个ITCM
文件位置:.\pgr_FPGA_Cortex-M1_eval\rtl_design\pgr_ARM_Cortex_M1_PGL22_324_eval\pnr
)继续回到正题,输出 bin 文件的具体配置方式如下所示。
①、点击工具栏的魔术棒选项:
②、选择User
,设置Run #1和Run #2的值:
D:\Keil_v5\ARM\ARMCC\bin\fromelf.exe --bin -o cortex_M1_led.bin .\Objects\cortex_M1_led.axf
(第一路径参数需要设置为自己的keil5
安装路径)make_hex.exe cortex_M1_led.bin
①、点击工具栏的全编译按钮,如下图所示:
②、全编译完成后如下图所示:
③、在keil工程目录下的Projet中,即可看到输出的cortex_M1_led.bin
文件,如下图所示:
将生成的cortex_M1_led.bin
文件拷贝到pgr_ARM_Cortex_M1_PGL22_324_eval
这个PDS工程的pnr\generate_bitstream
目录下,如下图所示:
①、双击.\pgr_FPGA_Cortex-M1_eval\rtl_design\pgr_ARM_Cortex_M1_PGL22_324_eval\pnr
路径下的ARM_M1_SoC_Top.pds
,打开官方提供的PDS工程。(第一次打开可能需要等待片刻~)
②、生成sbit文件
右击左侧Flow
栏中的Generate Bitstream
选项,选择Rerun All
,而后会弹出确认窗口,点击Yes
即可。
注:我的整个编译过程大概持续了
8min 50s
。
补充:使用带
CACHE
的Cortex M1 SoC
工程时,一定要将Bootloader
生成的itcm0
、itcm1
、itcm2
、itcm3
4个文件放入该PDS
工程的pnr
目录下,与RTL
工程一起编译生成sbit
文件,否则将不能实现应用程序的引导与地址跳转。(BootLoader
工程生成的itcm0~itcm3
4个文件,我们直接用官方提供在PDS
工程自带的即可,我们不需要太关心这个,应该把重点放在应用工程的bin
文件上!)
③、连接硬件,把 JTAG 下载器和开发板连接,然后开发板上电(下图为开发板的硬件连接图)。
④、单击界面中的“Configuration
”按钮,作用是下载程序。
⑤、在弹出的界面中的单击“Boundary Scan
”,然后在右侧空白区单击右键选择“Scan Device
”;
⑥、在扫描到 JTAG 设备后会弹出如下对话框,并按如下加载.sbit
文件即可,然后可以看到左侧显示了要加载的文件。
⑦、将sbit
文件转换为sfc
文件
对于PGL22G这款FPGA而言:
.sbit
,该种方式掉电会丢失!.sfc
,该种方式掉电不会丢失!但是我们肯定不能直接下载sbit
文件了,一方面是由于其程序掉电会丢失,另一方面是由于此时我们还没有将应用程序产生的bin
文件加载进来!而sfc
文件除了由sbit文件转换而成,还可以将sbit
与bin
文件拼接在一起转换成sfc
文件,转换方式如下所示:
选择菜单"Operations
“下”Convert File
"进行文件转换。
然后弹出如下界面,依次设置:
WINBOND
的 W25Q128Q
这款FLASH,Flash Read Mode
选择 SPI X4, 24-bit address
。sbit
文件起始地址和路径:起始地址为:0
,sbit文件在:.\pgr_FPGA_Cortex-M1_eval\rtl_design\pgr_ARM_Cortex_M1_PGL22_324_eval\pnr\generate_bitstream\m1_soc_top.sbit
。Load User Data File
选项,起始地址为:000C0000
,bin文件在:.\pgr_FPGA_Cortex-M1_eval\rtl_design\pgr_ARM_Cortex_M1_PGL22_324_eval\pnr\generate_bitstream\cortex_M1_led.bin
。设置完成后如下图所示,点击 OK 即可转换;
转换成功弹出如图所示对话框,点击OK即可。
⑧、下载sfc文件到FLASH中
选中右侧的PANGO方块,右击会弹出下拉菜单并选择"Scan outer Flash
"。
选择已生成的 sfc
文件,单击 Open;
可以看到界面中有了 flash
器件,选中“Outer Flash
”方块并右击选择菜单中“Program...
”
弹出正在编程的进度界面,flash 编程完成后进度界面自动消失。
至此,程序烧写完毕。
①、连接板载UART串口,如下图所示:
②、打开串口助手,选择合适的COM口,设置波特率115200
,重启开发板,观察打印信息
注:如找不到串口,注意查看
CP2102
驱动是否安装成功!
串口输出内容,如下图所示:
注意观察底板的LED2,间隔闪烁…
若与上述实验现象一致,则证明实验成功~
首先,先来了解下 M1_soc_top.v
中的信号绑定关系:
M1_soc_top.v
中的 gpio_in0
绑定了FPGA管脚P17
,对应底板按键 KEY3
M1_soc_top.v
中的 gpio_in1
绑定了FPGA管脚L12
对应底板按键 KEY4
M1_soc_top.v
中的 rst_key
绑定了FPGA管脚V12
对应底板按键 KEY2
M1_soc_top.v
中的 LED[3:0]
分别绑定FPGA管脚U10 V10 U11 V11
,对应底板LED[3:0]
另外需要知道,Cortex-M1软核的GPIO模块提供了一组 16 个 I/O 的通用输入输出:
M1_soc_top.v
中的verilog
代码为:.p0_in ({{14{1'b0}}, gpio_in1, gpio_in0}), // GPIO 0 inputs
M1_soc_top.v
中的verilog
代码为:.p0_out (p0_out), // GPIO 0 outputs
.p0_outen (p0_outen), // GPIO 0 output enables
...
assign LED[1:0] = p0_outen[1:0] & p0_out[1:0];
assign LED[2] = ddrc_init_done;
assign LED[3] = heart_beat_led;
...
打开LED应用工程中的main.c
文件,我们就从主函数来一点点分析。
...
#define LED_PIN GPIO_Pin_1
...
int main(void)
{
SystemInit();
GpioInit();
while(1)
{
GPIO_SetBit(GPIO0,LED_PIN);
Delay(DELAY_CNT);
GPIO_ResetBit(GPIO0,LED_PIN);
Delay(DELAY_CNT);
}
}
SystemInit
对GPIO寄存器进行初始化(赋0)操作,同时设置系统时钟为125M。GpioInit
对第0组GPIO的第1个管脚进行配置,设置为输出模式,且为普通IO,不设置中断。GPIO_SetBit
第0组GPIO的第1个管脚输出1。GPIO_ResetBit
第0组GPIO的第1个管脚输出0。Delay
是通过for循环计数的方法进行延时,具体时间未知。对第0组GPIO的第1个管脚输出控制,对应到 M1_soc_top.v
中的代码为:assign LED[1:0] = p0_outen[1:0] & p0_out[1:0];
。即当 GPIO_0_1
输出 0 时,p0_outen
的第1位为1,p0_out
的第1位为0,相与操作后LED
的第1位为0,对应的LED1会点亮(低电平点亮)。
怎么样,有没有茅塞顿开的感觉,这不是又回到了STM32的感觉了嘛!当你把LED_PIN
这个宏定义改为GPIO_Pin_0
时,你猜哪个灯会亮呢?
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。