目录:
一、了解SDK目录结构
二、打开第一个工程:example
三、对工程进行配置
platformio.ini配置、ve配置
四、编译代码
五、烧录程序(和ve配置)
Daplink烧录、Jlink烧录、串口烧录
六、Daplink(或Jlink)仿真
七、进入开发
八、增加编译目录
九、脱机烧录
十、更多:flash的大小与两个bin
十一、更多:了解platformio插件
阅读本文前,请参照《AG32开发环境搭建.pdf》,先搭建好AG32运行环境。
通过本文,可以了解到怎么在VSCODE下的完成开发工作。
一、了解SDK目录结构:
安装完SDK后,首先了解下SDK工作路径下的文件结构:
以上几个红色标圈的目录,是在后续编写代码时常用的几个目录。
其中:
framework-agrv_sdk是整个SDK的基础支撑部分。包含全部的驱动代码、board代码、输出重定向代码。该framwork是开发者在创建自己工程时必须依赖的framwork(所有examples样例工程中都可以看到该项)
其中的ips/lwip/usb,是第三方的库,开发者根据自己需求决定是否使用它们。
目前支持的四个操作系统:ucos/rtthread/freertos/embos,也在这里可以看到。
点开framework-agrv_sdk目录,src中包含全部的驱动代码。
了解完依赖包,再看examples。
examples中包含了众多的样例工程:example(基础驱动)、各种OS使用、lwip使用、usb使用,...
其中的example工程,包含了基础驱动的举例:
【这个是最基础的工程,随后会展示和示范】
二、打开第一个工程:example
看完目录结构,再来打开第一个样例工程(examples/example样例工程)。
打开方式:Vscode (左上角)【文件】 -> 【打开文件夹】 -> 弹出框中选该工程。
VSCODE打开后如图:
上图的main()函数,是example工程的主入口。
然后,board_init函数中,会进行时钟初始化、GPIO初始化、log串口初始化;
INT_EnableIRQ是使能某种类型的中断;
再接下来,就是对各驱动的测试函数。需要测试时,放开对应项。
上边展示的环境,就是AG32芯片的开发环境。
在这个IDE中,开发者可以编写代码、修改配置、编译、调试、烧录。
事实上,在example工程中,除了上图的代码,还有两处重要的配置文件:
1.example_board.ve 管脚配置:
位于路径:AgRV_pioplatformsAgRVexamplesexample
该配置文件中,配置芯片主频及pin脚映射。
2.platformio.ini 工程配置:
位于路径:AgRV_pioplatformsAgRVexamplesexample
该文件是工程配置文件,里边定义IDE的编译/烧录/仿真及工程宏的选项。
三、工程配置:
接上述,了解工程配置。
两部分工程配置:platformio.ini 和 example_board.ve
注:不仅example工程需要这两个配置,所有的工程都需要这两个配置文件。
其中:
platformio.ini 配置 工程的编译、烧录、仿真的选项与IDE相关。
example_board.ve 配置 芯片系统时钟频率、芯片IO引脚映射等;
该文件中的配置是要被烧写到flash中的,做为该芯片独特的配置与用到的芯片有关。
A.platformio.ini配置项:
这里的配置项,就是配置项目如何进行编译、烧录、仿真,以及使用芯片型号、引用库等。
以下只对通用的几个配置项做简单的描述。
(更多的配置项,在随后其他模块中使用到时,会相应列出)
boards_dir = boards //指定board对应的工作路径(用于代码编译的path)
board = agrv2k_103 //使用boards_dir路径下的哪个硬件版本
//注:boards_dir和board共同组成了完整path。
//如:以上对应路径platformsAgRVboardsagrv2k_103。
//这个路径下的.c和.h会被编译到工程,这个路径下的资源被默认查找;
board_logic.ve = example_board.ve
//工程使用到的ve配置文件(每个工程必须指定自己的ve文件)
//如果用相对路径,是相对于platformio.ini所在的路径(即:工程路径)
framework = agrv_sdk, agrv_lwip //使用工程中的哪些库。SDK是必带的。
//工程中可添加的库,具体参考工程注释中的描述;
//使用多个库时名字中间加逗号隔开。
program = agm_example //工程名,可自定义,仅作用于生成的bin名称
src_dir = . //参与编译的c文件基目录(路径相对于工程路径)
include_dir = . //参与链接的h文件基目录(路径相对于工程路径)
//注意,如果工程内文件夹比较多,这里不要再使用./src(而是使用.)
build_src_filter = "-<*> +<*.c> +"
//参与编译的c文件路径列表
//*用于通配,+增加,-去除,**用于匹配所有子目录
//路径基于上边src_dir给出的路径
build_flags = -Isrc -Iuser -Iuser/print //头文件路径列表
//-I后边是一个个文件夹,各项之间用空格来分开
board_logic.device = AGRV2KL100 //芯片类型配置
//64脚的封装应配置为 AGRV2KL64
logger_if = UART0 //芯片输出log用的串口号(对应代码中printf函数)
//注意:UART0同时用于代码烧录,但烧录和log输出并不冲突
//如果用串口1输出log,这里设置为:UART1
monitor_speed = 115200 //芯片输出log用的波特率 (sdk1.5.0之后新增)
//注意:用宏BAUD_RATE=115200的方式也能设置波特率(1.5.0之前是用宏方式)
upload_protocol = jlink-openocd //烧录固件的方式
//可选方式:jlink、dap(官方烧录器)、serial,字段名称参考注释部分
debug_tool = jlink-openocd //仿真时使用的工具,同上
以上几个是常用配置项。
B.example_board.ve 配置项:
AG32芯片和其他芯片(比如ST、GD)在使用上有一个很大的差异点,是AG32的IO引脚并不是定死的,而是配置的。
比如,ST的gpio的PA1,是定死指定到某个PIN脚的;
但是,AG32的所有gpio,对应到哪个PIN脚是配置的。必须在VE里配置绑定后,程序里操作这个gpio(比如,置高置低)才会最终作用到PIN脚上。
除了gpio,其他的很多外设(如spi,iic,can,uart等)都是需要配置引脚的。
Mcu里用到哪个信号就在VE里配置对应引脚,没用到的不用配置。
这种方式下:
1.可以节省大量引脚(开发者只需要配置自己使用到的外设引脚即可)
2.PCB布线可以非常方便(引脚随意指定,不用再考虑走线时绕来绕去)
在引脚配置上,也有一些限制,参后续描述。
ve配置方式(以example_board.ve为例):
SYSCLK 100 #配置系统时钟频率,M为单位。407最高频率可到248M
HSECLK 8 #使用的外部晶振频率,M为单位,建议取值范围 4~16
UART0_UARTRXD PIN_69 #串口0的收引脚
UART0_UARTTXD PIN_68 #串口0的发引脚
GPIO6_2 PIN_23 #IO_Button1
GPIO6_4 PIN_24 #IO_xxxx
I2C0_SDA PIN_36 #I2C0
I2C0_SCL PIN_35 #I2C0
……
GPTIMER1_CH0 PIN_7 #配置GpTimer1的channal 0 输出到管脚7
……
在书写格式中,前边为信号量的名称,后边为PIN脚编号。
(如果用到mcu和cpld联合开发,cpld信号量也在ve配置,这里不做细述)
这里着重描述一下GPIO的使用:
AG32芯片内共有10组GPIO(GPIO0 – GPIO9),每组8个IO(0~7)。所以,可用的GPIO共有80个。(100pin/64pin/48pin只是外部封装的区别,不影响内部GPIO的定义和数量)
虽然总数有80个,但真正在VE里绑定了PIN脚的那些gpio才会“有效”。
GPIOx_y表示的是第x组第y个IO。
比如上图中,GPIO6_2表示的就是第6组的第2个IO。程序里操作GPIO6_2实际操作的就是PIN_23引脚。
VE里这些使用到的左列的信号名称,请从文档《AGRV2K_逻辑设置.pdf》中查找。
配置的限制:
1.只有少数几个外设不能配置引脚(芯片定死了引脚):
包括:ADC/DAC/CMP、USB、MAC。
如果使用到这些外设,只能使用对应引脚。
如果不用这些外设,空闲出来的引脚可以被用于其他用途。
2.在可配置的项中,注意相互间的少量冲突;
在《AGRV2K_逻辑设置.pdf》中有详细描述。
另外:不可配置的引脚(ADC、USB这些),在32pin/48pin/64pin/100pin上的对应是不同的。注意区分。
关于管脚配置和GPIO的更详细描述,请参考《AG32下驱动的使用.pdf》。
四、编译程序:
程序编译可以通过2种方式:pio左栏按钮、命令行;
1.Pio左栏按钮:
点下按钮编译后,会自动弹出终端窗口显示编译过程。
2.命令行方式:
在“终端”通过命令行进行的工程编译。命令:pio run -e debug -v
使用如图:
不管使用上边的哪种方式,编译和烧录成功时,会有success的提示如下:
五、烧录程序(和ve配置):
注意:AG32烧录程序和烧录VE配置是分开的。
程序有改动,就编译后烧录程序;VE有改动,就烧录VE。
两者相互独立,各烧各的。烧录没有先后顺序之分。两者的烧录接线都相同,只是按钮不同。
新开发板的第一次烧录,必须先烧录VE,再烧录程序。
烧录支持三种方式:daplink、jlink和串口。
daplink烧录:
daplink方式是官方推荐的烧录方式,官方提供的烧录工具属于这种类型。
1.配置烧录方式:
如果使用daplink来烧录,需要在platformio.ini中进行相应配置。
配置方法:
修改upload_protocol项,使:upload_protocol = cmsis-dap-openocd
(注,使用daplink烧录时,无需配置upload_port项)
2.烧录程序:
烧录方法和上边的编译相似,也是2种方式:下边按钮、命令方式。
如下图(二选一):
烧录命令:pio run -e release -t upload
3.烧录ve文件:
在烧录ve配置时,只支持两种方式:左边栏和命令方式。
如下图:(二选一)
烧录命令:pio run -e release -t logic
注:烧录到flash的ve配置,就是在platformio.ini中指定的board_logic_ve项。如样例中的:board_logic.ve = example_board.ve
4.烧录结果提示:
在烧录固件或者ve配置完成时,都会有SUCCESS提示。
如果烧录失败,会有红色Error信息给出对应的失败原因。
烧录中,最常见的报错是 “Error connecting DP: cannot read IDR”。
如果是新焊接的板子,需要检查:芯片是否有虚焊、芯片供电、link接线管脚是否正常,是否对应;
如果是正常使用中突然出现,可以Boot0拉高,重新上电芯片,重新插拔烧录器,再尝试。
Jlink烧录:
Jlink烧录和daplink烧录有两点差异,其他均完全相同。
1.在首次烧录前,需要先安装插件zadig-2.8.exe。
注:该插件是jlink正常驱动的插件。在安装该插件前,确保电脑上已经安装过jlink的驱动,并能正常使用jlink。
安装插件时,需要将jlink连接到电脑,然后再安装。
该插件位于SDK解压后的根目录下。
安装方式参下图:
注:开发中如重装过电脑,或重新安装过jlink驱动,需要再次安装该驱动插件。
2.在配置文件中修改烧录方式为:
upload_protocol = jlink-openocd
这里配置修改完后,烧录按钮(或命令),跟dap-link是完全一样的。
串口烧录:
1.串口烧录前,要先使芯片进入烧录模式;
进入烧录模式的方法:boot1接地, boot0 接高。
2.在platformio.ini的配置里,配置成串口烧录并指定PC使用的串口号;
配置方法:
修改upload_protocol项,使:upload_protocol = Serial
修改upload_port项,使:upload_port = COMx (x是编号)
烧录时的波特率可以在[env:serial] 中修改,如:upload_speed = 115200
(注:烧录时芯片端必须使用UART0)
3.烧录程序和烧录ve;
按钮方式,串口烧录和jlink烧录时相同(可参照上边jlink烧录的介绍)
命令方式,(把release换成serial)。
烧录程序的命令:pio run -e serial -t upload
烧录ve的命令:pio run -e serial -t logic
4.烧录成功后的反馈;
同jlink烧录相似,成功也会有SUCCESS提示;
烧录失败会有红色FAIL提示错误原因。
总结下几个常用命令(如果使用命令的话):
编译(debug):pio run -e dev -v
#串口烧录ve配置:pio run -e serial -t logic
#串口烧录code:pio run -e serial -t upload
jlink烧录ve配置: pio run -e release -t logic
jlink烧录code: pio run -e release -t upload
注:这里的烧录VE,其实是烧录logic。更多信息请参考后边描述。
六、daplink(或jlink)仿真:
烧录完成后,如果要仿真跟踪代码时,可通过daplink或jlink的方式。
使用时,需要在platformio.ini中指定:
用daplink时:debug_tool = cmsis-dap-openocd
用jlink时:debug_tool = jlink-openocd
在仿真的操作上,两种方式完全相同。
按以下步骤启动:
正常运行起来后,这个样子:
接下来就可以单步程序了。debug调试中的快捷键和VS一致。
注:从SDK1.5.0之后(安装包为 AgRV_pio-1.5.0-win64-release),debug调试除了当前的pio-debug外,还支持cortex-debug插件。具体使用方法,请参考网盘文档《AG32下使用cotex插件调试程序》
七、进入开发:
前边已经了解SDK工程的编译烧录,这里简单介绍gpio和串口的使用。
举例gpio的使用:
举例:用 pin3引脚接led灯,并控制亮灯(高为亮),则需要做:
1. ve文件中设置: GPIO4_5 PIN_3
2. 代码中定义三个宏:
#define LED_G_GPIO GPIO4
#define LED_G_GPIO_MASK APB_MASK_GPIO4
#define LED_G_GPIO_BITS GPIO_BIT5
3. 代码中调用:
SYS_EnableAPBClock(LED_G_GPIO_MASK);
GPIO_SetOutput(LED_G_GPIO, LED_G_GPIO_BITS);
GPIO_SetHigh(LED_G_GPIO, LED_G_GPIO_BITS);
4. 先烧录ve部分;
5. 再编译烧录代码部分;
以上代码的解释:
1.不管外部封装是多少pin(48pin/64pin/100pin),芯片内部可用gpio都有80个。
在使用gpio时,需要把使用到的gpio关联到外部pin脚。
(没被关联的gpio,即使在代码中操作它,也不会传导到外部pin脚)
这步关联动作是在ve文件中进行的。
ve文件里的配置,GPIOx_y PIN_z,就是关联的语句。
PIN_z,对应外部哪个引脚。z取值范围(48脚封装:0~47;64脚封装:0~63)
GPIOx_y,对应内部哪个GPIO。x取值范围(0~9),y取值范围(0~7);
80个gpio分为10组,每组8个。用GPIOx_y的格式来表达。如:
GPIO0_1对应第0组的第1个IO;
GPIO4_5 对应第4组的第5个IO;
GPIO9_7对应第9组的第7个IO…
2. 在代码中如何操作GPIO:
仍以GPIO4_5举例:
在代码里定义:
#define LED_G_GPIO GPIO4
#define LED_G_GPIO_BITS (1 << 5) (或用宏 GPIO_BIT5)
则意味着LED对应到了 GPIO4_5。
调用函数GPIO_SetOutput设置改IO为输出模式:
GPIO_SetOutput(LED_G_GPIO, LED_G_GPIO_BITS);
然后就可以通过 GPIO_SetHigh/GPIO_SetLow来置高置低IO口。
如果要设置上拉下拉,请参考文档《AG32驱动的使用.pdf》中对gpio部分的详述。
举例log输出:
通过串口烧录mcu程序时,是固定使用mcu的uart0。建议mcu在运行时也使用uart0来输出log。
在VE里设置后,代码中的printf函数将通过uart0来输出。
1. 在ve中配置输出Log的串口:
logger_if = UART0
build_flags = -DBAUD_RATE=115200 //增加系统宏 BAUD_RATE 为 115200
从SDK1.5.0之后,最好使用monitor_speed = 115200替代这种宏的用法。
2. 在ve中设置串口0的映射引脚,如:
UART0_UARTRXD PIN_69
UART0_UARTTXD PIN_68
3. 在程序的board_init()函数中,有UART0的初始化:
在该初始化中,会设置串口的波特率、位宽、停止位、奇偶位。
如果不想使用UART0输出log,要改用UART1。那么在ve配置中对应修改:
logger_if = UART1
UART1_UARTRXD PIN_xx
UART1_UARTTXD PIN_xx
即可。
关于系统的宏定义:
在代码中出现的宏,在VSCode中通过鼠标停留在上边,可以看到其定义值。
这些宏,除了代码中定义的外,还有“系统预制宏”也可以被代码中使用。
系统宏的两类:
1.定义在platformio.ini中的build_flags字段中;
如 上边定义的波特率:build_flags = -DBAUD_RATE=115200
在build_flags 后边用 -D 表示是系统宏。后边的紧跟的字符串BAUD_RATE=115200 (字符串中间不能有空格),则相当于C代码中的 #define BAUD_RATE 115200
如果有多个宏,则 -D与下个 -D之间用空格 隔开。
2.在platformio.ini中定义后再由main.py经过转换拼接,才最终使用的宏。
比如上边截图中的LOGGER_UART。
这个宏并没有在代码中定义,也没在build_flags中定义。但它是在agrv_sdk.py中引用 时再拼接的。
第二种方式了解即可,不要使用。开发者使用第一种就够了。
八、增加编译目录:
在开发中,新增了c文件和h文件,怎么编译进来?
1.如果新增文件在原有路径下,则会被自动关联进来编译;
2.如果新增一个文件夹,则要把该文件夹加入到编译选项中;
如果文件夹下存放C文件:在src_filter中增加该文件夹
如果文件夹下存放h文件:在src_build_flags中增加该文件夹
举例:
在example项目里,只有一个src文件夹(里边存放全部.c和.h)。编译设置为:
src_dir = .
include_dir = ./src
build_src_filter = "-<*> +<./src/**/*.c>"
其中:
src_dir定义“.c文件编译时,查找路径的基路径”
include_dir定义“.h文件编译时,查找路径的基路径”
build_src_filter 定义 “.c文件从哪些路径下搜索”,星号代表通配,双星代表子目录通 配,+表示增加一个搜索路径,-表示去除一个搜索路径
如果要新增一个文件夹print(跟src同级),里边也有.c和.h,可以设置如下:
src_dir = .
include_dir = .
build_src_filter = "-<*> +<./src/**/*.c> +<./print/**/*.c>"
src_build_flags = -Isrc -Iprint
其中:
include_dir路径也退回到根路径下;
build_src_filter 加入print文件夹的选项;
src_build_flags 是新增的“设置头文件查找路径”的选项。每个头文件路径用 -I 来加入, 多个-I之间加空格。
注意:在build_src_filter和src_build_flags中,都是使用相对路径。他们是从src_dir/include_dir定义的基路径上再开始的。
如果工程含有c++的文件,只需在build_src_filter的选项中增加cpp选项,如:
build_src_filter = "-<*> +<./src/**/*.c> +<./src/**/*.cpp>"
九、脱机烧录:
脱机烧录前需要先编译出最终bin(这个bin是code和ve整合后的bin)。
方式如下:
编译完成后,可以在工程路径下找到生成的 xxxx_release_batch.bin。
然后,运行PC下载工具(该工具在SDK安装路径下):
下载方式可选4种:
挑选对应的方式。
然后点左边“Query Device ID”按钮,如果连接正常的话,会显示正常ID:
(4种方式,连接正常的话,都能获取到设备ID)
(注意,如果选串口方式,要boot1接地, boot0 接高)
然后,点右下角“download”按钮下载程序。
如果成功,可以看到成功信息;
如果失败,会有红色报错信息。
十、更多:芯片flash的大小与两个bin:
关于芯片flash大小:
不管所选型号的flash是多大,请注意最后100K是留给fpga/cpld使用的。
如果使用的芯片是256K的flash,那么就是156K程序+100K fpga,用户程序不能超过156K。如果超过156K编译是可以通过的,但烧录后会冲掉ve配置部分。
ve配置被冲掉后,程序运行会表现出各种异常(通常是系统时钟初始化失败)。
如果程序使用的空间较大,fpga又刚好比较小,可以调整这个界限的值。调整方法如下:
board_logic.compress = true //(可选)对fpga部分进行压缩,更省空间
board_upload.logic_address = 0x80034000 //根据实际情况调整该边界值
flash的大小是在agrv2k_103.json 中定义的。
flash起始地址是0x80000000,ram是0x20000000。
关于2个bin的说明:
其他常用mcu(如ST、GD),工程编译后只有一个bin。
而AG32工程则会编译出来2个bin。一个是代码的bin,一个是逻辑的bin。称之为code.bin和logic.bin。
AG32芯片运行时,需要两个bin全部烧录下去。
code.bin容易理解,是软件代码的bin,等价于st编译后的那种bin。
Logic.bin是多出来的一个bin,这个bin是什么呢?
这个bin其实是fpga/cpld部分编译出来的bin。在上边第三章节里描述VE配置时,说到gpio/spi/iic等这些外设的引脚需要在VE文件里配置后,才能最终使用。里边提到的“烧录VE”,其实就是编译并烧录这个logic.bin。
这个bin并不是在mcu里运行的,而是在cpld模块里运行的。
拓展下:AG32的芯片并不止是传统意义的一颗mcu,而是 传统意义的mcu芯+cpld芯。而两部分各需一个bin。于是整颗芯片需要2个bin。
如果只使用mcu(没接触过cpld),不理解上述描述也没关系。只要知道,相比传统mcu,AG32需多做一个步骤:配置VE引脚并烧录VE。
这里的两个bin,在生产时烧录两次岂不是很不方便?上边第九章脱机烧录,描述的过程,就是把两个bin二合一,合并成一个bin的。
十一、更多:了解platformIO
这里描述下platformIO是什么。
在环境安装时,安装完VSCode后,首先下载的插件就是platformIO IDE。
它是VScode的一款第三方插件,这款插件本身就是一套IDE开发环境。
访问platformIO的官网就知道,它是一套开放的Iot集成环境平台,允许芯片厂商通过配置和对接,方便地搭建自己芯片的开发环境。
也就是说,VSCode + platformIO + 芯片厂商配置 = 该芯片的IDE编译环境。
在嵌入式开发中,大家比较熟悉的IDE会有 Keil、IAR。而上边构建出来的IDE环境就是类似Keil、IAR的一整套可开发仿真的环境。只是这套环境比Keil和IAR更强大。
既然AG32芯片是基于platformIO平台的开发环境,那么项目中的配置就是围绕platformIO展开的,上边章节描述的platformio.ini配置(配置编译、烧录、仿真等的配置项)就是用在这里的。
扩展信息:
查看platformIO的官网:platformIO的定位是新一代的IoT集成开发环境。它是基于VSCode的一款插件。VSCode这款强大的文本编辑器辅以PlatformIO插件就可以化身为一款强大的MCU开发环境,支持绝大多数流行的单片机平台。
我们知道,嵌入式Iot开发中,最让人不舒服的就是不同厂家的芯片要使用不同的集成开发环境。例如:STM32要使用Keil或IAR,Arduino默认使用自家Arduino开发环境,ESP32要使用linux环境或者在windows下部署eclipse再用交叉编译。那么,有没有一个IDE可以大一统起来,集成大多数常用的芯片和模块的开发任务,只要配置完成之后就一劳永逸的呢?没错,那就是 PlatformIO。PlatformIO 试图整合起目前所有主流的硬件平台:TI/ST/EspressIf/Intel/Silicon/… 等,并且提供更便利的接口和更友好的交互,以提高开发效率。
关于platformIO,有兴趣可以去官网获取更多的信息:https://platformio.org/
前边说到,每一款芯片在PlatformIO中需要配置,按照PlatformIO的格式配置后,才能被正常使用(platformio.ini有大量的标准的控制选项,可进入官网查看)。
官方配置:https://docs.platformio.org/en/latest/projectconf/index.html#projectconf
在实际使用中,除了官方标准配置(编译、烧录)外,芯片方也会在这个开放平台上自定义一些自己特有的配置项。
<