HK32F030MF4P6的Linux GCC工具鏈開發環境

HK32F030MF4P6簡介

航順的 HK32F030MF4P6, TSSOP20封裝, Arm Cortex M0 內核, 內建32MHz時鐘, 16K Flash, 2K RAM(實際上可用的有4K).
這個型號的目的應該是硬體替換 STM8S003, 管腳和 STM8S003 兼容(和 STM32F030 兼容的型號是 HK32F030F4P6). HK32F030MF4P6 可能是當前市場上最便宜的 Cortex M0 晶片了, 單價0.9元不到. 一個32位的Arm M0晶片, 燒錄能用普通編程器, 參數也還可以, 常用的外設I2C, SPI, UART, PWM, ADC都有, 甚至還有I2S, 性價比相當不錯.

合宙也在放風要出1元的M0, 配置4K RAM, 256K Flash, M0這個級別很快就會進入一元的市場, 8bit系列按現在的價格, 如果不降到比M0低, 可能只剩下存量項目和教學用途了.

項目模板地址:

相關資料下載:

相關鏈接

HK32F030MF4P6 的外設庫

對比 HK32F030M 的外設庫和 STM32F0xx_StdPeriph_Lib_V1.5.0, 格式幾乎是照抄的, 定義前者比後者有一些縮水而已, 因為埠和功能上確實少一些. 所以熟悉 STM32F0 的人很容易上手. 相比較之前介紹的華大 HC32 系列, HC32 這個系列就有很明顯的 STC 暫存器風格, 和 STM 不是一條路線.

Linux GCC Arm Embedded 開發環境

Windows下的開發環境已經有很多資料了, 前面的資料下載里有很詳細的文檔. 這裡主要介紹一下 Linux (再準確點, Ubuntu) 下的開發環境. 以下介紹 HK32F030MF4P6 這個晶片使用 Linux GCC Arm Embedded 工具鏈的開發環境.

硬體環境

  • 帶 HK32F030MF4P6 的開發板. 這個晶片不需要外圍元件, 直接用 TSSOP20 轉接板接出即可
  • JLink OB, 最常見最便宜的那種 JLink 燒錄器

JLink接線

## JLINK
VCC -> #9  VCC
GND -> #7  GND
CLK -> #11 
SWD -> #2

軟體環境

JLink7.70 已經內建對 HK32F030M 系列的支援, 安裝後直接可用

GCC ARM工具鏈

在GCC ARM網站下載工具鏈接//developer.arm.com/downloads/-/arm-gnu-toolchain-downloads, 解壓到合適的目錄

tar xvf gcc-arm-11.2-2022.02-x86_64-arm-none-eabi.tar.xz
cd /opt/gcc-arm/
sudo mv ~/Backup/linux/gcc-arm-11.2-2022.02-x86_64-arm-none-eabi/ .
sudo chown -R root:root gcc-arm-11.2-2022.02-x86_64-arm-none-eabi/

檢查版本

/opt/gcc-arm/gcc-arm-11.2-2022.02-x86_64-arm-none-eabi/bin/arm-none-eabi-gcc --version
arm-none-eabi-gcc (GNU Toolchain for the Arm Architecture 11.2-2022.02 (arm-11.14)) 11.2.1 20220111
Copyright (C) 2021 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

HK32F030M外設庫

//bbs.21ic.com/icview-3236132-1-1.html 下載, 需要其中的外設庫.

示例項目導出和編譯

導出項目

git clone //github.com/IOsetting/hk32f030m-template.git

將下載的外設庫放到 Libraries/HK32F030M_Driver 目錄下

根據自己的環境參數修改 Makefile

PROJECT     ?= app
# path to gcc arm (or should be specified in PATH)
ARM_TOOCHAIN  ?= /opt/gcc-arm/gcc-arm-11.2-2022.02-x86_64-arm-none-eabi/bin
# path to JLinkExe (or should be specified in PATH)
JLINKEXE    ?= /opt/SEGGER/JLink/JLinkExe
# MCU type: HK32F030MD4P6, HK32F030MF4U6, HK32F030MF4P6 or HK32F030MJ4M6
DEVICE      ?= HK32F030MF4P6
# The path for generated files
BUILD_DIR     = Build

項目中帶了一個LED Blink的演示, 接線

## LED
LED1 -> #18 PD1
LED2 -> #17 PC7
LED3 -> #6  PA2

編譯

make clean
make

燒錄

make flash

項目模板目錄結構

項目模板結構

├── Build                       # 編譯結果文件目錄
├── Examples                    # 示例程式碼
├── flash.jlink                 # JLink 下載腳本
├── Libraries
│   ├── CMSIS
│   ├── Debug                   # SysTick 延時函數, printf 支援
│   ├── HK32F030M_Driver        # MCU 外設庫
│   └── LDScripts
├── LICENSE
├── Makefile                    # Make 配置
├── README.md
├── rules.mk                    # Makefile 預設的編譯規則
└── User                        # 用戶應用程式碼

其中並未包含外設庫, 和STM32的太像了, 放上去感覺不妥, 怕有版權問題, 還是刪掉了. 自己下載也很方便.

編譯參數

rules.mk 中, 預設的包含文件和目錄為

# C source folders
CDIRS := User \
    Libraries/CMSIS/HK32F030M/Source \
    Libraries/HK32F030M_Driver/src \
    Libraries/Debug
# C source files (if there are any single ones)
CFILES := 

# ASM source folders
ADIRS := User
# ASM single files
AFILES  := Libraries/CMSIS/HK32F030M/Source/startup_hk32f030mf4p6.s

# Include paths
INCLUDES  := Libraries/CMSIS/CM0/Core \
      Libraries/CMSIS/HK32F030M/Include \
      Libraries/HK32F030M_Driver/inc \
      Libraries/Debug \
      User

其中 CDIRS, ADIRS, INCLUDES 對應的都是目錄, CFILES 和 AFILES 對應的是單獨的源文件.
如果引入其它的庫或者源文件, 對應修改這部分即可.

編譯參數如下所示

# Global compile flags
CFLAGS    = -Wall -ggdb -ffunction-sections -fdata-sections
ASFLAGS   = -g -Wa,--warn

# Arch and target specified flags
OPT     ?= -Os
CSTD    ?= -std=c99
ARCH_FLAGS  := -fno-common -mcpu=cortex-m0 -mthumb

### c flags ###
TGT_CFLAGS  += $(ARCH_FLAGS) $(addprefix -D, $(LIB_FLAGS))

### asm flags ###
TGT_ASFLAGS += $(ARCH_FLAGS)

### ld flags ###
TGT_LDFLAGS += --specs=nosys.specs -mcpu=cortex-m0 -mthumb -Wl,--gc-sections -Wl,-Map=$(BDIR)/$(PROJECT).map -Wl,--print-memory-usage
 # Use newlib-nano instead of newlib for smaller flash size
TGT_LDFLAGS += --specs=nano.specs
 # Exclude standard initialization actions, when __libc_init_array exists, this should be omit, \
   otherwise it will generate "undefined reference to `_init'" error. \
   **Remove** `bl __libc_init_array` from startup.s if you want to enable this.
# TGT_LDFLAGS += -nostartfiles

因為使用了__libc_init_array, 默認不使用-nostartfiles, 如果取消注釋, 需要到 startup_hk32f030mf4p6.s 中刪除這行, 否則會報錯.

bl __libc_init_array

Startup 和 LD 程式碼

startup_hk32f030mf4p6.s 移植自 STM32F0 的 startup 程式碼, 沒有什麼特別的, 中斷向量和手冊是一致的. LD文件中

MEMORY
{
  RAM (xrw)      : ORIGIN = 0x20000000, LENGTH = 4K
  FLASH (rx)     : ORIGIN = 0x08000000, LENGTH = 16K
}

記憶體大小在手冊上寫的是2KB, 但是實際可用的有4KB, 這裡根據實際的記憶體大小將記憶體設成了 4K. 如果實際的規格有變化, 需要將其改回2K.

預聲明的堆棧

_Min_Heap_Size = 0x200;   /* required amount of heap: 512 bytes */
_Min_Stack_Size = 0x400;  /* required amount of stack: 1024 bytes */

...

/* User_heap_stack section, used to check that there is enough RAM left */
._user_heap_stack :
{
  . = ALIGN(8);
  PROVIDE ( end = . );
  PROVIDE ( _end = . );
  . = . + _Min_Heap_Size;
  . = . + _Min_Stack_Size;
  . = ALIGN(8);
} >RAM

這裡預聲明了 512 Byte的堆和 1024 Byte的棧, 所以編譯的結果, 顯示的記憶體佔用是一定大於1.5KB的, 如果希望增加或縮小, 在這裡調整

示例程式碼

模板中 Examples 目錄下面是一些示例程式碼

├── ADC
│     ├── ADC_Interrupt_Continous
│     └── ADC_Single
├── GPIO
│     └── LED_Blink
├── I2S
│     └── I2S_Audio_TX
├── SPI
│     └── MAX7219_8x8LED
├── TIM
│     ├── Advanced_Timer
│     ├── Basic_Timer
│     └── PWM_Complementary_Output
└── USART
    └── UART_TxRx

除了 I2S 的程式碼, 其它都移植自官方的參考示例. 使用時, 將 User 目錄下的程式碼刪除, 將示例下的程式碼複製到 User 目錄, 編譯燒錄即可.

I2S 音頻輸出演示

B站影片”航順HK32F030MF4P6 I2S驅動MAX98357播放8k 8bit語音效果演示”, 地址 //www.bilibili.com/video/BV1AP411G7kf