AT32 Development Record: vscode + EIDE + Cortex Debug Environment Setup

Preface

AT Official Tutorial AT32 MCU is being developed in the VSCode (Visual Studio Code) environment - 21ic Electronic Technology Development Forum

Or the official website Yateli Technology: 32 innovative leaders in microcontrollers! (arterytek.com)

APNote:AN0130, which provides a way to develop VScode using Cmake and Notex Debug.

I am more used to EIDE and can provide convenient project management tools, so this article aims to develop AT32F4 single-chip computer with EIDE of VScode.

Dead work

Hardware:

  • AT32F421C8T7 Minimum System Board (same as other AT32F4 series)
  • ATLink (or JLink, this article uses ATLink+OpenOCD)

Software:

  • OpenOCD (only available with AT's official distribution, open source on github) ArteryTek/openocd It seems that there is a problem with Flash driver and it is not compatible with the burner of FT2232 device)

  • GCC Tool Chain for Arm

  • MinGW

  • VScode: Install the EIDE and Cortex Debug extensions.

Code:

  • Modified from the project template in AT's official AN0130 to work with the smallest system (with only one 8M HEXT, one 32.768 for RTC, one LED and UserKey connected to PC13 pins, all remaining digital pins coming out)

EIDE Project Creation

Create a new project with settings as shown in the diagram:

 

Then write a blink LED program to control the pin of PC13. Use the most basic external CRM, systick, GPIO.

The standard library files are in. /libraries/drivers and do not need to be changed.

startup.s file, linker file and svd file are in. /project, do not change.

Need to change/write by yourself, only

  • main.c: Configure SCKL and AHB (to systick and CPU core) clocks. Enables APB (to GPIOC) peripheral clock. Initialize GPIOC. Enter the blink LED main cycle.
    #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: Defines the delay function of us, ms, s. It is important to configure the systick CTRL register (bit 2) before using the delay function to specify whether the systick clock source is CPU FCLK or its 8-crossover frequency.
    #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: You need to change the clock tree when you want to change it. It doesn't change here.
    /**
      **************************************************************************
      * @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: Change when a custom interrupt service program is required, not here.

    /**
      **************************************************************************
      * @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)
    {
    }
    
    /**
      * @}
      */
    
    /**
      * @}
      */
    

Compile and Download

Compile as F7.

If there is an error, check the EIDE project settings. In especial

  • Compiler configuration, environment variables, path problems, etc.
  • Include library directories
  • Preprocessor Macro Definition

Burning

Note that the interface and target of OpenOCD are selected correctly.

Here is the EIDE project configuration file:

{
  "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"
}

debugging

Once launch.json is configured, press F5 to start debugging directly.

{
    "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",
        }
    ]
}

The Cortex Debug extension relies on the launch.json file and uses openocd in the system environment variable Path. The exe path is the default OpenOCD, so here's a pit because my computer has multiple OpenOCDs installed on it and is not configured properly (OpenOCD paths are also filled in on the EIDE), so if you don't specify the version of OpenOCD you want to use for Cortex Debug, you'll probably make a mistake.

Therefore, it is best to specify the OpenOCD path used by the extension in settings.json:

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

Output EIDE Template

The resulting EIDE template file (.ept) is located in the project's root directory.

When you create a new AT32F4 project later, you can import the template.

Tags: Single-Chip Microcomputer Visual Studio Code OpenOCD

Posted by jjacquay712 on Sun, 11 Sep 2022 21:07:05 +0300