AG32在VSCode下的使用入门
阅读本文前,请参照《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_pio\platforms\AgRV\examples\example
该配置文件中,配置芯片主频及pin 脚映射。
2. platformio.ini 工程配置:
位于路径:AgRV_pio\platforms\AgRV\examples\example
该文件是工程配置文件,里边定义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。
//如:以上对应路径\platforms\AgRV\boards\agrv2k_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> +<print/*.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
在实际使用中,除了官方标准配置(编译、烧录)外,芯片方也会在这个开放平台上自定
义一些自己特有的配置项。