一、了解SDK目录结构
安装完SDK后,首先了解下SDK工作路径下的文件结构:
比如,安装路径在D:\AGM_WORK\下的,首先看到工程路径:D:\AGM_WORK\AgRV_pio 如下图:
对上边的packages目录展开,可以看到:
再对platform展开,可以看到:
以上几个红色标圈的目录,是在后续编写代码时常用的几个目录。
其中:
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里配置对应引脚,没用到的不用配置。
这种方式下:
- 可以节省大量引脚(开发者只需要配置自己使用到的外设引脚即可)
- 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,以及硬件的JTAG/OSC/RTC/VDD/GND。
如果使用到这些外设,只能使用对应引脚。
如果不用这些外设,空闲出来的引脚可以被用于其他用途。
2. 在可配置的项中,注意相互间的少量冲突;
在《AGRV2K_逻辑设置.pdf》中有详细描述。
另外:不可配置的引脚(ADC、USB这些),在32pin/48pin/64pin/100pin上的对应是不同的。注意区分。
关于管脚配置和GPIO的更详细描述,请参考《AG32下驱动的使用.pdf》。
四、代码讲解
这里只是初步的讲解和描述。从main函数开始:
小技巧:Ctrl + 鼠标左键,点击函数名,可以跳转到函数定义中(相当于vs中的F12快捷键)
上图中:
board_init() 是芯片初始化入口,根据自己需求调整里边的内容即可。
plic_isr[BUT_GPIO_IRQ] = Button_isr; 这句代码,是设置按键的中断函数。(该Button在board_init里初始化过了,这里是开启中断。)
INT_EnableIRQ(BUT_GPIO_IRQ, PLIC_MAX_PRIORITY); 这句代码,是使能按键的中断。
INT_SetIRQThreshold(MIN_IRQ_PRIORITY); 这句代码,则是设置中断开启的阈值。当优先级大于这个参数时,才会触发中断。
最下边的框,则是各个驱动的测试样例入口。每个函数对应一个.c驱动文件。
接下来进入board_init函数:
在example样例中,使用的是外部8M时钟,pll后系统跑在100M主频。
看完board_init,再看后续对gpio测试样例的调用。(表现就是led灯的闪烁)
注意的是,这里使用的EXT_GPIO, EXT_GPIO_BITS,就是board_init()里初始化过的ext的gpio。GPIO_Toggle函数是对gpio进行翻转,也没什么难理解的。
这里比较难理解的,是宏定义 EXT_GPIO_BITS = 0b1110。意思就是同时对 bit1/bit2/bit3 进行操作。
gpio操作时,不仅支持对某个gpio的操作,也支持对一组(多个gpio)的操作。这里就是对一组内多个gpio操作的示例。
五、介绍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部分的详述。
关于gpio的使用的更多介绍,请进入AG32驱动介绍。
举例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中引用 时再拼接的。
第二种方式了解即可,不要使用。开发者使用第一种就够了。
.
这篇讲述了开发工程的配置,example代码。下篇将讲述如何在VScode下编译、调试、烧录。
.