本文介绍如何应用infineon官方提供的免费ide开发环境aurix development studio和tc264开发板(龙邱科技提供)实现led的闪烁。
1. aurix development studio
aurix development studio(下简称ads), 是英飞凌推出在针对自家aurix芯片的免费编译环境,软件使用无需license,长期免费。该开发环境基于业内流行的eclipse打造而成,界面非常友好,对于刚刚接触英飞凌的朋友们而言更是易于上手。ads集成了编译器、调试器、illd底层开发库等必备组件,无需开发者四处寻找调试器和底层库代码。ads的编译器和调试器是基于tasking编译器、调试器打造而成,稳定性上无需额外担心,调试器比较难用,全当是一个高阶版的下载器吧。
2. 硬件环境
本次实现的硬件环境是用龙邱科技提供的tc264核心板+母版+下载器:

3.代码
3.1新建工程
打开adas,选择工作区(略)之后,在file→new,新建aurix工程
 
填写工程名称,选择next下一步:
 选择对应的芯片(tc26x b-step),点击finish:
 选择对应的芯片(tc26x b-step),点击finish:
 在产生的结构树中新建一个“src”文件夹,用于存放自己写的代码:
 在产生的结构树中新建一个“src”文件夹,用于存放自己写的代码:

建立以下代码文件:

3.2 关键代码
先说明下,以下为该开发板默认的led接口:
 led0p p10_6 龙邱tc母板核心板上led0 翠绿
 led1p p10_5 龙邱tc母板核心板上led1 蓝灯
 led2p p20_6 龙邱tc母板上led0
 led3p p20_7 龙邱tc母板上led1
3.2.1 lq_gpio
为了实现对gpio引脚的基本操作,先建立lq_gpio的头文件,lq_gpio主要目的是:
- 定义相关针脚枚举类gpio_name,如p10_5 = 0xb005(b005的前两位b0实际是module编号,05实际是pin的编号)
 该地址可参考英飞凌tc264用户手册第十四章《general purpose i/o ports and peripheral i/o lines (ports)

如上表,每个moudule的所有寄存器加起来需要的内存大小有256个字节(00-ff),以下为illd中ifxport_regdef.h中对port结构体的定义,可以看出共有256字节的相关的寄存器:
port结构体:
/** \brief  port object */
typedef volatile struct _ifx_p
{
    ifx_p_out out;                          /**< \brief 0, port output register */
    ifx_p_omr omr;                          /**< \brief 4, port output modification register */
    ifx_p_id id;                            /**< \brief 8, identification register */
    unsigned char reserved_c[4];            /**< \brief c, \internal reserved */
    ifx_p_iocr0 iocr0;                      /**< \brief 10, port input/output control register 0 */
    ifx_p_iocr4 iocr4;                      /**< \brief 14, port input/output control register 4 */
    ifx_p_iocr8 iocr8;                      /**< \brief 18, port input/output control register 8 */
    ifx_p_iocr12 iocr12;                    /**< \brief 1c, port input/output control register 12 */
    unsigned char reserved_20[4];           /**< \brief 20, \internal reserved */
    ifx_p_in in;                            /**< \brief 24, port input register */
    unsigned char reserved_28[24];          /**< \brief 28, \internal reserved */
    ifx_p_pdr0 pdr0;                        /**< \brief 40, port pad driver mode 0 register */
    ifx_p_pdr1 pdr1;                        /**< \brief 44, port pad driver mode 1 register */
    unsigned char reserved_48[8];           /**< \brief 48, \internal reserved */
    ifx_p_esr esr;                          /**< \brief 50, port emergency stop register */
    unsigned char reserved_54[12];          /**< \brief 54, \internal reserved */
    ifx_p_pdisc pdisc;                      /**< \brief 60, port pin function decision control register */
    ifx_p_pcsr pcsr;                        /**< \brief 64, port pin controller select register */
    unsigned char reserved_68[8];           /**< \brief 68, \internal reserved */
    ifx_p_omsr0 omsr0;                      /**< \brief 70, port output modification set register 0 */
    ifx_p_omsr4 omsr4;                      /**< \brief 74, port output modification set register 4 */
    ifx_p_omsr8 omsr8;                      /**< \brief 78, port output modification set register 8 */
    ifx_p_omsr12 omsr12;                    /**< \brief 7c, port output modification set register 12 */
    ifx_p_omcr0 omcr0;                      /**< \brief 80, port output modification clear register 0 */
    ifx_p_omcr4 omcr4;                      /**< \brief 84, port output modification clear register 4 */
    ifx_p_omcr8 omcr8;                      /**< \brief 88, port output modification clear register 8 */
    ifx_p_omcr12 omcr12;                    /**< \brief 8c, port output modification clear register 12 */
    ifx_p_omsr omsr;                        /**< \brief 90, port output modification set register */
    ifx_p_omcr omcr;                        /**< \brief 94, port output modification clear register */
    unsigned char reserved_98[8];           /**< \brief 98, \internal reserved */
    ifx_p_lpcr0 lpcr0;                      /**< \brief a0, port lvds pad control register 0 */
    ifx_p_lpcr1 lpcr1;                      /**< \brief a4, port lvds pad control register 1 */
    ifx_p_lpcr2 lpcr2;                      /**< \brief a8, port lvds pad control register 2 */
    unsigned char reserved_a4[76];          /**< \brief ac, \internal reserved */
    ifx_p_accen1 accen1;                    /**< \brief f8, port access enable register 1 */
    ifx_p_accen0 accen0;                    /**< \brief fc, port access enable register 0 */
} ifx_p;
定义gpio的模式,本例最终用的是推挽输出模式
 定义宏:根据gpio_name获取port的module首地址
 定义宏:根据gpio_name获取pin的编号
 声明gpio的pin初始化函数_void pin_initconfig(gpio_name_t pin,ifxport_mode mode, uint8 output);_
 声明gpio的pin的写入函数_void pin_write(gpio_name_t pin,uint8 output);_通过该函数来更新电平状态,(output为0则高电平,为1则低电平)
 声明gpio的pin电平翻转函数void pin_reverse(gpio_name_t pin);
 lq_gpio的头文件(.h文件)如下:
#ifndef src_lq_gpio_h_
#define src_lq_gpio_h_
#include "platform_types.h"
#include "ifxport_regdef.h"
#include "ifxport.h"
// gpio port no.
typedef enum //
{
    p21_4 = 0xc104,
    p21_5 = 0xc105,
    p20_8 = 0xc008,
    p20_9 = 0xc009,
}gpio_name_t;
//gpio mode
#define pin_mode_output          ifxport_mode_outputpushpullgeneral    /*!< 推挽输出  */
#define pin_mode_output_od       ifxport_mode_outputopendraingeneral   /*!< 开漏输出  */
#define pin_mode_input           ifxport_mode_inputnopulldevice        /*!< 浮空输入  */
#define pin_mode_input_pullup    ifxport_mode_inputpullup              /*!< 上拉输入  */
#define pin_mode_input_pulldown  ifxport_mode_inputpulldown            /*!< 下拉输入  */
// get the gpio port module base address
#define pin_getmodule(gpio_name)    (ifx_p*)(0xf0030000u | (gpio_name & 0xff00))
// get the gpio port pin index
#define pin_getindex(gpio_name)    (uint8)(gpio_name & 0x000f)
void pin_initconfig(gpio_name_t pin,ifxport_mode mode, uint8 output);
void pin_write(gpio_name_t pin,uint8 output);
void pin_reverse(gpio_name_t pin);
#endif /* src_lq_gpio_h_ */
其中typedef enum中的地址为下图对应的地址

查看原理图,发现开发板的四个等分别是p21.4,p21.5,p20.8,p20.9所以0xc104,0xc105,0xc008,0xc009。这个根据自己开发板而定。

对应的实现源文件(.c文件)是:
#include "lq_gpio.h"
void pin_initconfig(gpio_name_t pin,ifxport_mode mode,uint8 output)
{
    ifx_p *port = pin_getmodule(pin);
    unsigned char pinindex = pin_getindex(pin);
    // 配置gpio模式
    ifxport_setpinmode(port, pinindex, mode);
    ifxport_setpinpaddriver(port, pinindex, ifxport_paddriver_cmosautomotivespeed2);
    /* gpio输出模式时 输出状态 */
    if (0 == output)
    {
        ifxport_setpinstate(port, pinindex, ifxport_state_low);
    }
    else
    {
        ifxport_setpinstate(port, pinindex, ifxport_state_high);
    }
}
void pin_write(gpio_name_t pin,unsigned char output)
{
    ifx_p *port = pin_getmodule(pin);
    unsigned char pinindex = pin_getindex(pin);
    // gpio output mode
    if (output == 0)
    {
        ifxport_setpinstate(port, pinindex, ifxport_state_low);
    }
    else
    {
        ifxport_setpinstate(port, pinindex, ifxport_state_high);
    }
}
void pin_reverse(gpio_name_t pin)
{
    ifx_p *port = pin_getmodule(pin);
    unsigned char pinindex = pin_getindex(pin);
    ifxport_togglepin(port, pinindex);
}
3.2.2 lq_gpio_led
建立led与gpio引脚的关系并定义相关操作,编写lq_gpio_led头文件,该头文件主要目的是:
定义led灯的编号枚举类ledn_e
 定义led灯的状态枚举类leds_e
 定义led灯编号与pin name的对应关系
 声明led初始化函数_void gpio_led_init(void);_
 声明led控制函数_void led_ctrl(ledn_e ledn,leds_e leds);_
 声明led测试函数void test_gpio_led(void);
 相关头文件(.h文件):
#ifndef src_lq_gpio_led_h_
#define src_lq_gpio_led_h_
#include "lq_gpio.h"
// define enum for led number
typedef enum
{
    led0 = 0,
    led1 = 1,
    led2 = 2,
    led3 = 3,
    led_all = 4
} ledn_e;
// define enum for led state
typedef enum
{
    on = 0,
    off = 1,
    rvs = 2 
}leds_e;
// led and pin
#define led0p   p20_8
#define led1p   p20_9
#define led2p   p21_4
#define led3p   p21_5
void gpio_led_init(void);
void led_ctrl(ledn_e ledn,leds_e leds);
void test_gpio_led(void);
#endif /* src_lq_gpio_led_h_ */
对应的源文件(.c文件):
#include "lq_gpio_led.h"
#include "lq_stm.h"
void gpio_led_init(void)
{
    // 初始化,输入口,高电平
    pin_initconfig(led0p, pin_mode_output, 0);
    pin_initconfig(led1p, pin_mode_output, 0);
    pin_initconfig(led2p, pin_mode_output, 0);
    pin_initconfig(led3p, pin_mode_output, 0);
}
void led_ctrl(ledn_e ledno,leds_e sta)
{
    switch(ledno)
    {
        case led0:
            if(sta==on)    pin_write(led0p, 0);
            else if(sta==off)    pin_write(led0p, 1);
            else if(sta==rvs)   pin_reverse(led0p);
        break;
        case led1:
          if(sta==on)        pin_write(led1p,0);
          else if(sta==off) pin_write(led1p,1);
          else if(sta==rvs) pin_reverse(led1p);
        break;
        case led2:
          if(sta==on)        pin_write(led2p,0);
          else if(sta==off) pin_write(led2p,1);
          else if(sta==rvs) pin_reverse(led2p);
        break;
        case led3:
          if(sta==on)        pin_write(led3p,0);
          else if(sta==off) pin_write(led3p,1);
          else if(sta==rvs) pin_reverse(led3p);
        break;
        case led_all:
          if(sta==on)
          {
              pin_write(led0p,0);
              pin_write(led1p,0);
              pin_write(led2p,0);
              pin_write(led3p,0);
          }
          else if(sta==off)
          {
              pin_write(led0p,1);
              pin_write(led1p,1);
              pin_write(led2p,1);
              pin_write(led3p,1);
          }
          else if(sta==rvs)
          {
              pin_reverse(led0p);
              pin_reverse(led1p);
              pin_reverse(led2p);
              pin_reverse(led3p);
          }
        break;
        default:
        break;
    }
}
void test_gpio_led(void)
{
    gpio_led_init();
    while(1)
    {
        led_ctrl(led_all, rvs);
        delayms(100);
    }
}
3.2.3 lq_stm
由于实现对led的翻转闪烁控制,需要实现计时功能,即要借助于tc264的系统定时器(stm),并实现自己的定时功能,lq_stm实现以下功能:
定义stm枚举类stm_t,包含stm0和stm1,其实这个对应于tc264两个cpu的时钟源,我们这里当然选stm0
 声明微妙级的延时函数_void stm_delayus(stm_t stm, unsigned long us);_
 声明毫秒级的延时函数_void delayms(unsigned short stmms);_
 声明两个延时函数:第一个是通过调用illd中的ifxstm_getticksfrommicroseconds函数实现精确的微妙级计时;第二个是调用汇编指令nop(无操作)实现不怎么精确的计时。
 本例中用#if条件汇编指令默认选用第一种方法
头文件(.h文件):
#ifndef lq_stm_h_
#define lq_stm_h_
#include "platform_types.h"
#include "ifxstm_regdef.h"
#include "ifxstm.h"
#include "ifxstm_cfg.h"
// stm module enumerate
typedef enum{
    stm0 = 0,
    stm1 = 1
}stm_t;
void stm_delayus(stm_t stm, unsigned long us);
void delayms(unsigned short stmms);
# endif
对应的源文件(.c文件):
#include "lq_stm.h"
// stm delay
 void stm_delayus(stm_t stm, uint32 us)
 {
    ifx_stm * stm = ifxstm_getaddress((ifxstm_index)stm);
    uint32 tick = ifxstm_getticksfrommicroseconds(stm, us);
    ifxstm_waitticks(stm, tick);
 }
// delay function
void delayms(unsigned short stmms)
{
    #if 1
    // accurate delay
    while(stmms--){
        stm_delayus(stm0,1000);
    }
    #else 
    // not accurate delay
    volatile unsigned long i = 0;
    while(stmms--)
    {
        for(i=0;i<16580;++i){
            __asm("nop");
        }
    }
    #endif
}
3.2.4 cpu0_main.c
我们只利用cpu0进行led的控制,以下为源文件:
#include "lq_gpio_led.h"
#include "ifxcpu.h"
#include "ifxscuwdt.h"
#include "ifxscuccu.h"
#include "lq_stm.h"
ifxcpu_mutexlock mutexcpu0initisok = 1; // flag of cpu0 initialization
int core0_main(void)
{
    // close the cpu interrupt
    ifxcpu_disableinterrupts();
    // close the watch dog
    ifxscuwdt_disablecpuwatchdog(ifxscuwdt_getcpuwatchdogpassword());
    ifxscuwdt_disablesafetywatchdog(ifxscuwdt_getsafetywatchdogpassword());
    // initial led
    gpio_led_init();
    // open cpu interrupt
    ifxcpu_enableinterrupts();
    // tell cpu1, the cpu0 finished initialization
    ifxcpu_releasemutex(&mutexcpu0initisok);
    while(1)
    {
        led_ctrl(led_all,rvs);
        delayms(100);
    }
    return (1);
}
3.2.5 cpu1_main.c
对应的cpu1的源文件:
#include "ifx_types.h"
#include "ifxcpu.h"
#include "ifxscuwdt.h"
extern ifxcpu_mutexlock mutexcpu0initisok;
int core1_main(void)
{
    // 开启cpu总中断
    ifxcpu_enableinterrupts();
    // 关闭看门狗
    ifxscuwdt_disablecpuwatchdog (ifxscuwdt_getcpuwatchdogpassword ());
    // 等待cpu0 初始化完成
    while(!ifxcpu_acquiremutex(&mutexcpu0initisok));
    while(1)//主循环
    {
    }
}
4. build & debug
注意:在这一步的编译和debug中,如果提示“找不到ftd2××.dll”,都是因为开发板和电脑没有连接上,可以打开设备管理器,找到对应串口安装
4.1 编译
点击build按钮,对代码进行编译:

编译结束后,务必保证无error:
 同时,在debug文件夹下会产生.elf文件,用于debug和下载
 同时,在debug文件夹下会产生.elf文件,用于debug和下载

4.2 debug
点击debug按钮旁边的小三角,选择debug configurations

双击tasking c/c++ debugger:

① 选择出现的"lq_gpio_led",② 选择默认出现的file,③ 将其删除 ④ 选择add,在弹出的对话框中添加刚才的.elf文件 ⑤ 点击debug 弹出对话框,选择“switch”:
 弹出对话框,选择“switch”:

出现debug界面,可以进行debug:

4.3 烧录
 点击这个就能烧录了。
点击这个就能烧录了。
 
             我要评论
我要评论 
                                             
                                             
                                             
                                            
发表评论