本文适合有CCS使用经验的读者。
笔者使用的单片机是TM4C123GH6PM,硬件环境是EK-TM4C123GXL评估板,调试接口是ICDI。
笔者使用的CCS版本是11.1.0,安装时会自动安装两个编译器:armcl和tiarmclang,版本信息如下图,分别是:armcl 20.2.5,tiarmclang 1.3.0,读者可根据版本信息确认对应关系。
图中的LTS是LongTimeSupport的意思。
一、编译器简介
armcl:即TI Arm® C/C++ Compiler Tools,截止2022年5月,最新的版本是20.2.x,笔者使用的是20.2.5.LTS版本。
tiarmclang:即TI Arm® Clang Compiler Tools,截止2022年5月,最新的版本是2.0.0.STS。
tiarmclang是TI开发用来替换armcl的下一代编译器,衍生自开源的Clang编译器。其在兼容性和代码优化方面,比armcl和gcc更具优势。
二、编码模式
TM4C123GH6PM支持两种编码模式,分别是直接访问寄存器模式,和软件驱动模式。
其中软件驱动模式,依赖于TivaWare Peripheral Driver Library驱动库,截止2022年5月,最新版本是TivaWare_C_Series-2.2.0.295。
三、创建CCS工程
1、编译软件驱动库
如果使用直接访问寄存器模式,请跳过此步骤。
如果使用软件驱动模式开发,则需要先重新编译驱动库,建议先备份。
默认安装的驱动库,如下图所示,有一个已经编译好的driverlib.lib,但只适用于armcl编译器,所以需要重新编译适配tiarmclang的driverlib.lib。
(1)项目配置
File->Open Projects From File System,在弹出的窗口,将路径设置到TivaWare安装路径的driverlib/ccs目录即可。
之后,右键配置刚导入项目“driverlib”的属性,修改编译器为armcl,点击“Apply and Close”,如下图。
这一步非常关键,千万不能省略,一定先配置为armcl编译器,这样项目才会生成针对编译器的一些配置项。
然后继续右键,配置项目属性,将编译器配置为tiarmclang,点击“Apply and Close”,如下图。
弹出确认框,提示即将创建“Debug_TICLANG”的配置目录,点击OK即可。
接着又弹出提示框,提示project.log中,会显示一些需要完善的配置,点击OK即可。
然后继续右键修改项目属性,参考以下截图配置即可,不需要一一解释了。
(2)代码和文件适配
接下来,将epi_workaround_ccs.s文件的后缀,改成.asm。
因为这个项目默认只认识后缀是.asm的汇编文件。
把armcl安装目录下的stdbool.h,复制到tiarmclang目录下。
如果tiarmclang目录下已经有stdbool.h,那就不用复制了。
修改interrupt.c,如下图,因为tiarmclang不兼容”#pragma DATA_ALIGN”等语法。
修改sysctl.c里的SysCtlDelay函数。
之后重新编译driverlib项目,至此软件驱动库编译成功。
2、编译验证程序
新建ccs工程,新建时,编译器选择tiarmclang。
发现新建的工程没有startup_ccs.c和.cmd文件,从以前用过的armcl工程复制一份过来。
添加对driverlib.lib的依赖。
项目属性配置,和上一步编译driverlib时的属性配置一样。需要增加的配置参考下图:
如果报错“未初始化段名称”,则在.cmd文件里添加。
main.c中,写一段LED闪烁的代码验证一下。
#include <stdbool.h>
#include <stdint.h>
#include "inc/hw_memmap.h"
#include "driverlib/gpio.h"
#include "driverlib/rom.h"
#include "driverlib/sysctl.h"
int main(void)
{
// 外部16MHz的晶振
ROM_SysCtlClockSet(SYSCTL_SYSDIV_1 | SYSCTL_USE_OSC | SYSCTL_OSC_MAIN |
SYSCTL_XTAL_16MHZ);
ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF);
ROM_GPIOPinTypeGPIOOutput(GPIO_PORTF_BASE, GPIO_PIN_2);
while(1)
{
GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_2, 4);
SysCtlDelay(SysCtlClockGet() / 6); //大约500ms
GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_2, 0);
SysCtlDelay(SysCtlClockGet() / 6);
}
}
写进评估板中验证一下, LED闪烁符合预期。
写在最后
验证程序,如果用直接访问寄存器模式,则不受driverlib的限制,LED闪烁的代码如下:
#include <stdint.h>
#include "inc/tm4c123gh6pm.h"
int main(void)
{
volatile uint32_t ui32Loop;
//
// Enable the GPIO port that is used for the on-board LED.
//
SYSCTL_RCGC2_R = SYSCTL_RCGC2_GPIOF;
//
// Do a dummy read to insert a few cycles after enabling the peripheral.
//
ui32Loop = SYSCTL_RCGC2_R;
//
// Enable the GPIO pin for the LED (PF3). Set the direction as output, and
// enable the GPIO pin for digital function.
//
GPIO_PORTF_DIR_R = 0x08;
GPIO_PORTF_DEN_R = 0x08;
while(1)
{
//
// Turn on the LED.
//
GPIO_PORTF_DATA_R |= 0x08;
//
// Delay for a bit.
//
for(ui32Loop = 0; ui32Loop < 200000; ui32Loop++)
{
}
//
// Turn off the LED.
//
GPIO_PORTF_DATA_R &= ~(0x08);
//
// Delay for a bit.
//
for(ui32Loop = 0; ui32Loop < 200000; ui32Loop++)
{
}
}
}