AT32(一):vscode + EIDE + Cortex Debug环境搭建

前言

AT官方的教程 雅特力AT32 MCU在VSCode(Visual Studio Code)环境上进行开发 - - 21ic电子技术开发论坛

或官网雅特力科技 : 32位微控制器的创新领导者! (arterytek.com)

的AP Note:AN0130,提供了VScode上使用Cmake和Cotex Debug进行开发的方法。

本人更习惯用EIDE,可以提供方便的项目管理工具,所以这篇文章旨在用VScode的EIDE开发AT32F4单片机。

准备工作

硬件:

  • AT32F421C8T7 最小系统板(其他AT32F4系列同理)
  • ATLink(或者JLink,本文使用ATLink+OpenOCD)

软件:

  • OpenOCD (只能使用AT官网提供的发行版,github上开源的ArteryTek/openocd 似乎在Flash driver上有点问题,不能兼容FT2232器件的烧录器)

  • 适用于Arm的GCC工具链

  • MinGW

  • VScode :安装EIDE和Cortex Debug扩展。

代码:

  • 由AT官方 AN0130中的 project template 修改而来,以适用于最小系统(只含有一个8M HEXT,一个32.768用于RTC,一个LED和UserKey均连接PC13引脚,其余数字引脚全引出)

EIDE工程创建

新建工程,设置如图:

然后写一个控制PC13引脚的 blink LED 程序。用到最基础的外设CRM、systick,GPIO。

标准库文件都在 ./libraries/drivers 中,不需要改动。

startup.s文件,linker文件和svd文件在 ./project 中,不要改动。

需要自己改/写的,只有

  • main.c:配置SCKL和AHB(至systick和CPU core)时钟。使能APB(至GPIOC)外设时钟。初始化GPIOC。进入 blink LED 主循环。
    #include "at32f421_clock.h"
    #include "systick.h"
    
      /**
      * @brief  main function.
      * @param  none
      * @retval none
      */
    int main(void)
    {
        system_clock_config();
    
        gpio_init_type gpio_init_struct;
    
        /* enable the led clock */
        crm_periph_clock_enable(CRM_GPIOC_PERIPH_CLOCK, TRUE);
    
        /* set default parameter */
        gpio_default_para_init(&gpio_init_struct);
    
        /* configure the led gpio */
        gpio_init_struct.gpio_drive_strength = GPIO_DRIVE_STRENGTH_STRONGER;
        gpio_init_struct.gpio_out_type       = GPIO_OUTPUT_PUSH_PULL;
        gpio_init_struct.gpio_mode           = GPIO_MODE_OUTPUT;
        gpio_init_struct.gpio_pins           = GPIO_PINS_13;
        // gpio_init_struct.gpio_pull           = GPIO_PULL_NONE;
        gpio_init(GPIOC, &gpio_init_struct);
    
    	delay_init();
    	
        while (1)
        {
    		gpio_bits_set(GPIOC,GPIO_PINS_13);
    		delay_ms(400);
    		gpio_bits_reset(GPIOC,GPIO_PINS_13);
    		delay_ms(400);
        }
    }
  • systick.c:定义了 us, ms, s 的延时函数。特别注意,在使用延时函数前要配置systick CTRL寄存器(的bit 2),指定systick时钟来源是CPU FCLK还是它的8分频。
    #include "systick.h"
    
    #define STEP_DELAY_MS 50
    
    /* delay variable */
    static __IO uint32_t fac_us;
    static __IO uint32_t fac_ms;
    
    /**
     * @brief  initialize delay function
     * @param  none
     * @retval none
     */
    void delay_init()
    {
        /* configure systick */
        systick_clock_source_config(SYSTICK_CLOCK_SOURCE_AHBCLK_NODIV);
        fac_us = system_core_clock / (1000000U);
        fac_ms = fac_us * (1000U);
    }
    
    /**
     * @brief  inserts a delay time.
     * @param  nus: specifies the delay time length, in microsecond.
     * @retval none
     */
    void delay_us(uint32_t nus)
    {
        uint32_t temp = 0;
        SysTick->LOAD = (uint32_t)(nus * fac_us);
        SysTick->VAL  = 0x00;
        SysTick->CTRL |= SysTick_CTRL_ENABLE_Msk;
        do
        {
            temp = SysTick->CTRL;
        } while ((temp & 0x01) && !(temp & (1 << 16)));
    
        SysTick->CTRL &= ~SysTick_CTRL_ENABLE_Msk;
        SysTick->VAL = 0x00;
    }
    
    /**
     * @brief  inserts a delay time.
     * @param  nms: specifies the delay time length, in milliseconds.
     * @retval none
     */
    void delay_ms(uint16_t nms)
    {
        uint32_t temp = 0;
        while (nms)
        {
            if (nms > STEP_DELAY_MS)
            {
                SysTick->LOAD = (uint32_t)(STEP_DELAY_MS * fac_ms);
                nms -= STEP_DELAY_MS;
            }
            else
            {
                SysTick->LOAD = (uint32_t)(nms * fac_ms);
                nms           = 0;
            }
    
            SysTick->VAL = 0x00;
            SysTick->CTRL |= SysTick_CTRL_ENABLE_Msk;
            do
            {
                temp = SysTick->CTRL;
            } while ((temp & 0x01) && !(temp & (1 << 16)));
    
            SysTick->CTRL &= ~SysTick_CTRL_ENABLE_Msk;
            SysTick->VAL = 0x00;
        }
    }
    
    /**
     * @brief  inserts a delay time.
     * @param  sec: specifies the delay time, in seconds.
     * @retval none
     */
    void delay_sec(uint16_t sec)
    {
        uint16_t index;
        for (index = 0; index < sec; index++)
        {
            delay_ms(500);
            delay_ms(500);
        }
    }
  • at32f421_clock.c:当要改变时钟树时才需改动,此处不动。
    /**
      **************************************************************************
      * @file     at32f421_clock.c
      * @version  v2.0.5
      * @date     2022-04-02
      * @brief    system clock config program
      **************************************************************************
      *                       Copyright notice & Disclaimer
      *
      * The software Board Support Package (BSP) that is made available to
      * download from Artery official website is the copyrighted work of Artery.
      * Artery authorizes customers to use, copy, and distribute the BSP
      * software and its related documentation for the purpose of design and
      * development in conjunction with Artery microcontrollers. Use of the
      * software is governed by this copyright notice and the following disclaimer.
      *
      * THIS SOFTWARE IS PROVIDED ON "AS IS" BASIS WITHOUT WARRANTIES,
      * GUARANTEES OR REPRESENTATIONS OF ANY KIND. ARTERY EXPRESSLY DISCLAIMS,
      * TO THE FULLEST EXTENT PERMITTED BY LAW, ALL EXPRESS, IMPLIED OR
      * STATUTORY OR OTHER WARRANTIES, GUARANTEES OR REPRESENTATIONS,
      * INCLUDING BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY,
      * FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT.
      *
      **************************************************************************
      */
    
    /* includes ------------------------------------------------------------------*/
    #include "at32f421_clock.h"
    
    /** @addtogroup AT32F421_periph_template
      * @{
      */
    
    /** @addtogroup 421_System_clock_configuration System_clock_configuration
      * @{
      */
    
    /**
      * @brief  system clock config program
      * @note   the system clock is configured as follow:
      *         - system clock        = hext * pll_mult
      *         - system clock source = pll (hext)
      *         - hext                = 8000000
      *         - sclk                = 120000000
      *         - ahbdiv              = 1
      *         - ahbclk              = 120000000
      *         - apb2div             = 1
      *         - apb2clk             = 120000000
      *         - apb1div             = 1
      *         - apb1clk             = 120000000
      *         - pll_mult            = 15
      *         - flash_wtcyc         = 3 cycle
      * @param  none
      * @retval none
      */
    void system_clock_config(void)
    {
      /* config flash psr register */
      flash_psr_set(FLASH_WAIT_CYCLE_3);
    
      /* reset crm */
      crm_reset();
    
      crm_clock_source_enable(CRM_CLOCK_SOURCE_HEXT, TRUE);
    
       /* wait till hext is ready */
      while(crm_hext_stable_wait() == ERROR)
      {
      }
    
      /* config pll clock resource */
      crm_pll_config(CRM_PLL_SOURCE_HEXT, CRM_PLL_MULT_15);
    
      /* enable pll */
      crm_clock_source_enable(CRM_CLOCK_SOURCE_PLL, TRUE);
    
      /* wait till pll is ready */
      while(crm_flag_get(CRM_PLL_STABLE_FLAG) != SET)
      {
      }
    
      /* config ahbclk */
      crm_ahb_div_set(CRM_AHB_DIV_1);
    
      /* config apb2clk */
      crm_apb2_div_set(CRM_APB2_DIV_1);
    
      /* config apb1clk */
      crm_apb1_div_set(CRM_APB1_DIV_1);
    
      /* enable auto step mode */
      crm_auto_step_mode_enable(TRUE);
    
      /* select pll as system clock source */
      crm_sysclk_switch(CRM_SCLK_PLL);
    
      /* wait till pll is used as system clock source */
      while(crm_sysclk_switch_status_get() != CRM_SCLK_PLL)
      {
      }
    
      /* disable auto step mode */
      crm_auto_step_mode_enable(FALSE);
    
      /* update system_core_clock global variable */
      system_core_clock_update();
    }
    
    /**
      * @}
      */
    
    /**
      * @}
      */
    
    

  • at32f421_int.c:当需要自定义中断服务程序时才作改动,此处不动。

    /**
      **************************************************************************
      * @file     at32f421_int.c
      * @version  v2.0.5
      * @date     2022-04-02
      * @brief    main interrupt service routines.
      **************************************************************************
      *                       Copyright notice & Disclaimer
      *
      * The software Board Support Package (BSP) that is made available to
      * download from Artery official website is the copyrighted work of Artery.
      * Artery authorizes customers to use, copy, and distribute the BSP
      * software and its related documentation for the purpose of design and
      * development in conjunction with Artery microcontrollers. Use of the
      * software is governed by this copyright notice and the following disclaimer.
      *
      * THIS SOFTWARE IS PROVIDED ON "AS IS" BASIS WITHOUT WARRANTIES,
      * GUARANTEES OR REPRESENTATIONS OF ANY KIND. ARTERY EXPRESSLY DISCLAIMS,
      * TO THE FULLEST EXTENT PERMITTED BY LAW, ALL EXPRESS, IMPLIED OR
      * STATUTORY OR OTHER WARRANTIES, GUARANTEES OR REPRESENTATIONS,
      * INCLUDING BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY,
      * FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT.
      *
      **************************************************************************
      */
    
    /* includes ------------------------------------------------------------------*/
    #include "at32f421_int.h"
    
    /** @addtogroup AT32F421_periph_template
      * @{
      */
    
    /** @addtogroup 421_LED_toggle
      * @{
      */
    
    /**
      * @brief  this function handles nmi exception.
      * @param  none
      * @retval none
      */
    void NMI_Handler(void)
    {
    }
    
    /**
      * @brief  this function handles hard fault exception.
      * @param  none
      * @retval none
      */
    void HardFault_Handler(void)
    {
      /* go to infinite loop when hard fault exception occurs */
      while(1)
      {
      }
    }
    
    /**
      * @brief  this function handles memory manage exception.
      * @param  none
      * @retval none
      */
    void MemManage_Handler(void)
    {
      /* go to infinite loop when memory manage exception occurs */
      while(1)
      {
      }
    }
    
    /**
      * @brief  this function handles bus fault exception.
      * @param  none
      * @retval none
      */
    void BusFault_Handler(void)
    {
      /* go to infinite loop when bus fault exception occurs */
      while(1)
      {
      }
    }
    
    /**
      * @brief  this function handles usage fault exception.
      * @param  none
      * @retval none
      */
    void UsageFault_Handler(void)
    {
      /* go to infinite loop when usage fault exception occurs */
      while(1)
      {
      }
    }
    
    /**
      * @brief  this function handles svcall exception.
      * @param  none
      * @retval none
      */
    void SVC_Handler(void)
    {
    }
    
    /**
      * @brief  this function handles debug monitor exception.
      * @param  none
      * @retval none
      */
    void DebugMon_Handler(void)
    {
    }
    
    /**
      * @brief  this function handles pendsv_handler exception.
      * @param  none
      * @retval none
      */
    void PendSV_Handler(void)
    {
    }
    
    /**
      * @brief  this function handles systick handler.
      * @param  none
      * @retval none
      */
    void SysTick_Handler(void)
    {
    }
    
    /**
      * @}
      */
    
    /**
      * @}
      */
    

编译下载

按F7编译。

如果有报错,请检查EIDE项目设置。尤其是

  • 编译器配置,环境变量,路径问题等
  • 包含库目录
  • 预处理器宏定义

烧录

注意正确选择OpenOCD的 interface 和 target。

这里贴一下EIDE工程配置文件:

{
  "name": "AT32F421_eide_temp",
  "type": "ARM",
  "dependenceList": [],
  "srcDirs": [
    ".eide/deps",
    "libraries",
    "project"
  ],
  "virtualFolder": {
    "name": "<virtual_root>",
    "files": [],
    "folders": []
  },
  "outDir": "build",
  "deviceName": null,
  "packDir": null,
  "miscInfo": {
    "uid": "4d69a5f133c15cd63d6e4f3e0be364f3"
  },
  "targets": {
    "Debug": {
      "excludeList": [
        "libraries/cmsis/dsp",
        "libraries/cmsis/cm4/device_support/startup/iar",
        "libraries/cmsis/cm4/device_support/startup/mdk",
        "project/src/startup_at32f421.s"
      ],
      "toolchain": "GCC",
      "compileConfig": {
        "cpuType": "Cortex-M4",
        "floatingPointHardware": "none",
        "useCustomScatterFile": false,
        "scatterFilePath": "project/misc/AT32F421x8_FLASH.ld",
        "storageLayout": {
          "RAM": [
            {
              "tag": "IRAM",
              "id": 1,
              "mem": {
                "startAddr": "0x20000000",
                "size": "0x5000"
              },
              "isChecked": true,
              "noInit": false
            }
          ],
          "ROM": [
            {
              "tag": "IROM",
              "id": 1,
              "mem": {
                "startAddr": "0x08000000",
                "size": "0x10000"
              },
              "isChecked": true,
              "isStartup": true
            }
          ]
        },
        "options": "null"
      },
      "uploader": "OpenOCD",
      "uploadConfig": {
        "bin": "",
        "target": "at32f421xx",
        "interface": "atlink",
        "baseAddr": "0x08000000"
      },
      "uploadConfigMap": {
        "JLink": {
          "bin": "",
          "baseAddr": "",
          "cpuInfo": {
            "vendor": "null",
            "cpuName": "null"
          },
          "proType": 1,
          "speed": 8000,
          "otherCmds": ""
        }
      },
      "custom_dep": {
        "name": "default",
        "incList": [
          ".eide/deps",
          ".",
          "project/inc",
          "libraries/cmsis/cm4/core_support",
          "libraries/cmsis/cm4/device_support",
          "libraries/drivers/inc",
          "c:\\SysGCC\\arm-eabi\\arm-none-eabi\\include"
        ],
        "libList": [],
        "sourceDirList": [],
        "defineList": [
          "_DEBUG",
          "UNICODE",
          "_UNICODE",
          "AT32F421C8T7",
          "USE_STDPERIPH_DRIVER"
        ]
      }
    }
  },
  "version": "3.3"
}

调试

配置好launch.json后,按F5直接开启调试。

{
    "version": "0.2.0",
    "configurations": [
        {
            "cwd": "${workspaceRoot}",
            "type": "cortex-debug",
            "request": "launch",
            "name": "openocd-launch",
            "armToolchainPath": "C:/Users/hyq/.eide/tools/gcc_arm/10 2021.10/bin",
            "gdbPath": "C:/Users/hyq/.eide/tools/gcc_arm/10 2021.10/bin/arm-none-eabi-gdb.exe",
            "interface": "swd",
            "servertype": "openocd",
            "configFiles": [
                "D:/OpenHardware/AT32/Tool/vscode/Tool/OpenOCD_V2.0.2/scripts/interface/atlink.cfg",
                "D:/OpenHardware/AT32/Tool/vscode/Tool/OpenOCD_V2.0.2/scripts/target/at32f421xx.cfg"
            ],
            "executable": "build/Debug/AT32F421_eide_temp.elf",
            "runToMain": true,
            "svdFile": "./project/misc/AT32F421xx_v2.svd",
        }
    ]
}

Cortex Debug扩展需要依赖于launch.json文件,并且会使用系统环境变量Path里的openocd.exe路径作为默认的OpenOCD,所以这里有一个坑,因为本人电脑的系统上装有多个OpenOCD,并且配置地比较乱(EIDE上也填写过OpenOCD路径),所以如果不给Cortex Debug指定你希望使用的OpenOCD版本,很可能会出错。

因此最好在settings.json中指定扩展使用的OpenOCD路径:

"cortex-debug.openocdPath": "D:\\OpenHardware\\AT32\\Tool\\vscode\\Tool\\OpenOCD_V2.0.2\\bin\\openocd.exe",

输出EIDE模板

 生成的 EIDE template 文件(.ept) 会在项目的根目录下。

之后再新建AT32F4的项目时,导入模板即可。

  • 2
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值