文章目录
- 一、原材料准备
- 二、编译应用程序的keil工程,得到bin文件
-
- 2.1、准备led应用程序对应的keil工程
- 2.2、设置ROM和RAM的起始地址和大小
- 2.3、配置输出 bin 文件
- 2.4、全编译工程,输出bin文件
- 2.5、下载程序到FLASH中
- 2.6、连接串口,查看打印信息
- 三、实验原理分析
-
- 3.1、知识储备
- 3.2、代码分析
- 四、仿真
-
- 4.1、重新编译仿真库
- 4.2、拷贝unsim文件夹至RTL工程的Simulation目录下
- 4.3、拷贝应用工程生成的三个文件`mem_xxx.dat`文件至RTL工程的Simulation文件夹
- 五、常见问题及解决方法
-
- 5.1、modelsim 仿真报错`** Error: (vish-42) Unsupported ModelSim library format…`
- 5.2、使用I2C 驱动 EEPROM 报错
- 5.3、网络相关设置
- 六、其他小知识
导读:本节将以一个简单的 LED Demo 为例,详细介绍基于PGL22G 的 Cortex-M1 软核开发流程。
一、原材料准备
工欲善其事必先利其器,在正式开跑软核之前,还需要准备一下软件和Demo工程,清单如下:
- Keil V5.15.0(建议与官方测试版本保持一致)
- ARM.CMSIS.5.6.0.pack(Cortex-M1的固件库)
- PDS 2020.3(建议与官方测试版本保持一致)
- pgr_FPGA_Cortex_M1_PGL22_324_eval.rar(钉钉群下载)
- pgr_FPGA_Cortex-M1_eval_v1_2.rar(钉钉群下载)
钉钉群下载的两个文件解压后,放置到没有中文和空格的路径下,然后将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
的形式。
二、编译应用程序的keil工程,得到bin文件
2.1、准备led应用程序对应的keil工程
LED应用程序对应的keil工程,位于:.\pgr_FPGA_Cortex-M1_eval\software_design\module_design\Cortex-M1_led
目录下。进入其子目录PROJECT
,双击cortex_M1_led.uvprojx
即可打开keil工程,如下图所示:
2.2、设置ROM和RAM的起始地址和大小
PGL22G Cortex-M1软核的ROM和RAM设置方式有两种:
- 在不使用 CACHE 的 Cortex M1 中,
ITCM
作为 ROM(起始地址为0x00000000
),DTCM
作为 RAM(起始地址为0x20000000
),大小根据用户实际需求进行设置。 - 在使用 CACHE 的 Cortex M1 中,
ICACHE
作为 ROM(起始地址为0x10000000
),DCACHE
作为 RAM(起始地址为0x30000000
),大小根据用户实际需求进行设置。
我们使用CACHE
,故ROM和RAM地址设置为上述第二种,具体配置方式如下所示。
②、选择Target
,设置ROM和RAM起始地址和大小:
- IROM1:起始地址:
0x10000000
、大小:0x1000000
- IRAM1:起始地址:
0x30000000
、大小:0x100000
注:
ICACHE
指令起始地址必须配置为:0x1000 0000
,DDR
颗粒映射范围0x0000 0000-0x00FF FFFF
(即最大:16MB - 0x100 0000
);DCACHE
数据起始地址必须配置为:0x3000 0000
,DDR
颗粒映射范围0x0100 0000-0x0FFF FFFF
(即最大:256MB - 0x10000 0000
)。- 不能超过这个映射范围,否者会出错。
2.3、配置输出 bin 文件
Cortex-M1 软件编程设计通过:
Run #1
操作, 将axf
文件转换为bin
文件格式并输出;Run #2
操作, 使用make_hex.exe
工具将bin
文件转换为4
个ITCM
文件格式并输出。
关于ITCM要说的几点:
- 使用 CACHE 的 Cortex M1 中,需要引导应用程序(即通过
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的值:
- Run #1:
D:\Keil_v5\ARM\ARMCC\bin\fromelf.exe --bin -o cortex_M1_led.bin .\Objects\cortex_M1_led.axf
(第一路径参数需要设置为自己的keil5
安装路径) - Run #2:
make_hex.exe cortex_M1_led.bin
2.4、全编译工程,输出bin文件
②、全编译完成后如下图所示:
③、在keil工程目录下的Projet中,即可看到输出的cortex_M1_led.bin
文件,如下图所示:
将生成的cortex_M1_led.bin
文件拷贝到pgr_ARM_Cortex_M1_PGL22_324_eval
这个PDS工程的pnr\generate_bitstream
目录下,如下图所示:
2.5、下载程序到FLASH中
①、双击.\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而言:
- 直接下载到FPGA的程序文件格式为:
.sbit
,该种方式掉电会丢失! - 间接下载到FLASH的程序文件格式为:
.sfc
,该种方式掉电不会丢失!
但是我们肯定不能直接下载sbit
文件了,一方面是由于其程序掉电会丢失,另一方面是由于此时我们还没有将应用程序产生的bin
文件加载进来!而sfc
文件除了由sbit文件转换而成,还可以将sbit
与bin
文件拼接在一起转换成sfc
文件,转换方式如下所示:
选择菜单"Operations
“下”Convert File
"进行文件转换。
- FLASH厂家、型号和读模式:黑金开发板用到的是
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
。- bin文件使能、起始地址和路径:勾选
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 即可转换;
⑧、下载sfc文件到FLASH中
选中右侧的PANGO方块,右击会弹出下拉菜单并选择"Scan outer Flash
"。
选择已生成的 sfc
文件,单击 Open;
可以看到界面中有了 flash
器件,选中“Outer Flash
”方块并右击选择菜单中“Program...
”
弹出正在编程的进度界面,flash 编程完成后进度界面自动消失。
2.6、连接串口,查看打印信息
②、打开串口助手,选择合适的COM口,设置波特率115200
,重启开发板,观察打印信息
注:如找不到串口,注意查看
CP2102
驱动是否安装成功!
串口输出内容,如下图所示:
注意观察底板的LED2,间隔闪烁…
若与上述实验现象一致,则证明实验成功~
三、实验原理分析
3.1、知识储备
首先,先来了解下 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;
...
3.2、代码分析
打开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
时,你猜哪个灯会亮呢? 😃 😃 😃 😃
四、仿真
Cortex M1 SoC 的硬件仿真平台采用的是无 Boot 的仿真方法,即跳过从 SPI-FLASH 中加载指令到 DDR 颗粒的过程,直接将所需指令初始化就进 DDR 颗粒的预定空间中,当系统初始化完成后就可进行指令与数据的加载。可实现指令与数据快速仿真,利于用户进行逻辑功能的快速验证与开发。
4.1、重新编译仿真库
打开 Tools -> Compile Simulation Libraries
设置Simulator Executable Path 为:
D:/modeltech64_10.6d/win64
然后点击Compile(大概需要2min),整个过程如下图所示。
编译成功,如下图所示:
4.2、拷贝unsim文件夹至RTL工程的Simulation目录下
将.\pgr_FPGA_Cortex-M1_eval\rtl_design\pgr_ARM_Cortex_M1_PGL22_324_eval\pnr\pango_sim_libraries
中的 usim
文件夹拷贝至 .\pgr_FPGA-Cortex_M1_eval\rtl_design\pgr_ARM_Cortex_M1_PGL22_324_eval\simulation
下,如下图所示。
4.3、拷贝应用工程生成的三个文件mem_xxx.dat
文件至RTL工程的Simulation文件夹
①、修改应用工程程序
要生成mem_xxx.dat
文件,首先需要修改好我们想要仿真的应用工程程序,打开.\pgr_FPGA_Cortex-M1_eval\software_design\boot
下的Cortex-M1_Icache_Dcache_Demo
工程,修改main.c
中的内容如下:
#define TEST_ADDR (*(__IO uint32_t*)(0x70001000))
int temp_cnt = 0;int main(void)
{SystemInit();GpioInit(); WatchDogInit(WATCH_DOG,2); DEBUG_P("PANGO Cortex-M1 Start Run......\r\n");DEBUG_P("JEDEC id = 0x%x\n",SFLASH_ReadJEDEC_ID());while(1){GPIO_SetBit(GPIO0,LED_PIN);GPIO_ResetBit(GPIO0,LED_PIN);TEST_ADDR = temp_cnt++;// temp_cnt++;
// TEST_ADDR = temp_cnt * 2;}
}
②、生成xxx.dat
文件
为了节约硬件仿真时间,就需要对 DDR 颗粒模型进行初始化赋值操作,即跳过引导过程(无boot),因此需要利用 make_hex128.exe
可执行文件,生成 DDR 颗粒模型初始化所需的xxx.dat
文件。
生成方法如下:
- i、打开应用程序的keil工程,点击魔术棒,选择
User
,将Run #2
原有的值:make_hex.exe cortex_M1_demo.bin
,设置为:make_hex128.exe cortex_M1_demo.bin
,如下图所示:
注:这里顺带提一下keil工程中的代码段和数据段设置,如下图所示:
哦对了,别忘了把 Run #1 中的keil路径修改为自己的keil路径,我的设置内容为:D:\Keil_v5\ARM\ARMCC\bin\fromelf.exe --bin -o cortex_M1_demo.bin .\Objects\cortex_M1_demo.axf
- ii、接着点击keil工程的全编译按钮,即可把
bin
文件转化为如下图所示的mem_addr.dat
、mem_data.dat
和mem_used.dat
3个文件
- iii、复制
mem_xxx.dat
文件至RTL工程的Simulation文件夹下
即将.\pgr_FPGA_Cortex-M1_eval\software_design\boot\Cortex-M1_Icache_Dcache_Demo\PROJECT
目录下的mem_xxx.dat
文件,拷贝至.\pgr_FPGA_Cortex-M1_eval\rtl_design\pgr_ARM_Cortex_M1_PGL22_324_eval\simulation
目录下,如下图所示:
③、运行仿真
双击.\pgr_FPGA_Cortex-M1_eval\rtl_design\pgr_ARM_Cortex_M1_PGL22_324_eval\simulation
目录下的sim.bat
批处理文件,开始仿真。
④、仿真分析
注:需要等待一段时间,等软核跑起来,才会运行到我们的main函数,我这里是仿了
600_000_000_000 fs
。
keil 应用工程实现的功能是将 0x7000_1000
这个地址的数据实现自加,我们通过波形验证一下是否是这样。
首先找到 HADDR
信号 和 HWDATA
信号。
将 HADDR
信号颜色设置为红色,方便观察波形,如下图所示:
接着将 HWDATA
信号数据格式设置为十进制,如下图所示:
找到任意一个0x7000_1000
出现的位置,如下图所示,此时HWDATA
的值为 221 。
继续寻找下一个0x7000_1000
出现的位置,如下图所示,可以看到HWDATA
的值为 222 。
不难得出,实验波形符合预期现象。
注:这里再顺便提一下,两个
0x7000_1000
地址出现的位置之间,0x3000_0028
地址处的数据也为222,这并非巧合,而是我们对应的temp_cnt
变量的地址,由于我们的keil设置数据段为0x3000_0000
,所以temp_cnt
变量的地址为0x3000_0000
开头!
五、常见问题及解决方法
5.1、modelsim 仿真报错** Error: (vish-42) Unsupported ModelSim library format...
# Error loading design
# Error: Error loading design
# Pausing macro execution
# MACRO ./sim.tcl PAUSED at line 11
# ** Error: (vish-42) Unsupported ModelSim library format for "E:/Linux Development/PGL22G-Board/1/pgr_FPGA_Cortex-M1_eval/rtl_design/pgr_ARM_Cortex_M1_PGL22_324_eval/simulation/usim". (Format: 4)
解决办法:
- 重新编译仿真库!
5.2、使用I2C 驱动 EEPROM 报错
解决办法:
PANGO_i2c_eeprom.h
中的I2C_PageSize
宏定义大小改为16
main.c
中的DATA_LEN
宏定义改为10
,小于16才可以
5.3、网络相关设置
板子IP:192.168.0.2
板子MAC:00-0A-35-01-FE-C0
电脑IP:192.168.0.3
电脑MAC:40-8D-5C-64-65-3B
#define MAC_ADDR0 0x00U
#define MAC_ADDR1 0x0AU
#define MAC_ADDR2 0x35U
#define MAC_ADDR3 0x01U
#define MAC_ADDR4 0xFEU
#define MAC_ADDR5 0xC0U#define DEST_IP_ADDR0 192
#define DEST_IP_ADDR1 168
#define DEST_IP_ADDR2 0
#define DEST_IP_ADDR3 3#define DEST_PORT 5001/*Static IP ADDRESS: IP_ADDR0.IP_ADDR1.IP_ADDR2.IP_ADDR3 */
#define IP_ADDR0 192
#define IP_ADDR1 168
#define IP_ADDR2 0
#define IP_ADDR3 2/*NETMASK*/
#define NETMASK_ADDR0 255
#define NETMASK_ADDR1 255
#define NETMASK_ADDR2 255
#define NETMASK_ADDR3 0/*Gateway Address*/
#define GW_ADDR0 192
#define GW_ADDR1 168
#define GW_ADDR2 1
#define GW_ADDR3 1
keil工程配置:
IROM1:0x10000000
、0x100000
IRAM1:0x30800000
、0x8000000
六、其他小知识
Cortex-M1软核包含较多宏文件,但CM1_OPTION_DEFS为关键宏文件,涉及系统参数与功能模块的使能配置。换句话说,要内核支持某个模块,需要在RTL代码中作相应的配置,即在cm1_option_defs.v
里的某些宏需要打开或关闭!
- 位置:
.\pgr_FPGA_Cortex-M1_eval\rtl_design\pgr_ARM_Cortex_M1_PGL22_324_eval\src\m1_core\cm1_option_defs.v
Cortex M1 SoC 的系统时钟为125Mhz,内置软复位功能以及使用 I/DCACHE 加载指令/数据方式,将所有外设全覆盖使用,包括Bootloader在线调试功能。
带有Cache的设计分为Bootloader部分和应用程序部分,其中Bootloader放置在片上ITCM中,即上电开始运行,而应用程序部分则通过Bootloader从Flash空间加载至DDR颗粒中, 当初始化完成后, CortexM 1软核配合I/DCACHE实现应用程序的执行。
注意:Bootloader程序无需用户编写,用户只需关心应用程序设计即可。通过PDS Configuration插件工具,将应用工程所编译的BIN文件(PGL22平台起始地址为0x000C0000) 与sbit数据流文件拼接,并利用同创cable直接下载到Flash芯片中。此后,板卡上电,当FPGA数据流文件加载完毕后, Bootloader将会自动将Flash空间的指令数据搬运至DDR颗粒中,完成指令初始化操作。
Cortex-M1 SoC的系统时钟默认是接在DDR的axi_clo0上的,如果不使用DDR设备,需要在cm1_option_defs.v
中取消注释'#define UNCACHE
将系统时钟切换到外部PLL时钟clkout0上。