• LibOpenCM3(一) Linux下命令行开发环境配置


    目录

    本文默认使用 Linux 环境, 硬件为 STM32F103 系列开发板

    LibOpenCM3 介绍

    LibOpenCM3 是GPL协议(LGPL3)的Cortex-M系列的封装库, 支持stm32、atmel、nxp系列单片机. 这个固件库对标的是 CMSIS, 但是比 CMSIS 提供更多的方法接口, 实现度介于 CMSIS 和 SPL 之间. 对于常见的 STM32F1 系列, 代码已经基本稳定.

    开发环境

    硬件部分

    • STM32F103 开发板
    • ST-Link V2

    软件部分

    环境配置

    GNU Arm Embedded Toolchain 工具链

    通过前面的地址下载最新版本, 根据自己的系统架构选择合适的架构版本

    # 解压
    tar xjf gcc-arm-none-eabi-10.3-2021.10-x86_64-linux.tar.bz2
    # 放到/opt下并设置权限
    sudo mv gcc-arm-none-eabi-10.3-2021.10 /opt/gcc-arm/
    cd /opt/gcc-arm/
    sudo chown -R root:root gcc-arm-none-eabi-10.3-2021.10/
    

    加到PATH(可选)

    export PATH="/opt/gcc-arm/gcc-arm-none-eabi-10.3-2021.10/bin:$PATH"
    

    检查版本

    $ arm-none-eabi-gcc --version
    arm-none-eabi-gcc (GNU Arm Embedded Toolchain 10.3-2021.10) 10.3.1 20210824 (release)
    Copyright (C) 2020 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.
    

    stlink,st-flash,st-info

    需要先安装 libusb-1.0-0-dev

    sudo apt install libusb-1.0-0-dev
    

    编译安装

    git clone https://github.com/stlink-org/stlink.git
    cd stlink/
    make
    cd build/Release/
    sudo make install
    

    检查

    $ st-flash  --version
    v1.7.0-184-g468b1d2
    $ st-info --version
    Failed to parse flash type or unrecognized flash type
    v1.7.0-184-g468b1d2
    

    st-flash 使用说明 https://github.com/stlink-org/stlink/blob/develop/doc/tutorial.md

    • --flash=128k 参数可以指定flash大小, 例如覆盖 STM32F103C8T6 默认的 64k 大小设置. 取值可以使用 十进制(128k), 八进制 0200k, 或者十六进制 0x80k.
    • --reset 在写入结束后触发重置
    • --connect-under-reset 重置状态下连接. 使用这个选项可以在用户代码执行前连接MCU, 当目标MCU上的用户代码将MCU置于sleep状态, 或禁用了调试接口导致无法连接时特别有用.

    LibOpenCM3

    LibOpenCM3封装库文件结构

    libopencm3
    ├── COPYING.GPL3
    ├── COPYING.LGPL3
    ├── doc
    ├── HACKING
    ├── HACKING_COMMON_DOC
    ├── include                  # 头文件目录
    │     ├── libopencm3
    │     │     ├── cm3
    │     │     ├── dispatch
    │     │     ├── docmain.dox
    │     │     ├── efm32
    │     │     ├── ethernet
    │     │     ├── gd32
    │     │     ├── license.dox
    │     │     ├── lm3s
    │     │     ├── lm4f
    │     │     ├── lpc13xx
    │     │     ├── lpc17xx
    │     │     ├── lpc43xx
    │     │     ├── msp432
    │     │     ├── nrf
    │     │     ├── pac55xx
    │     │     ├── sam
    │     │     ├── stm32       # 按不同的型号分组的头文件, 定义中断向量表的 irq.json
    │     │     ├── swm050
    │     │     ├── usb
    │     │     └── vf6xx
    │     └── libopencmsis
    │         ├── core_cm3.h
    │         └── dispatch
    │             └── irqhandlers.h
    ├── ld
    │     ├── devices.data      # 芯片数据库, 各个芯片型号对应的flash和ram尺寸
    │     ├── linker.ld.S       # 连接器脚本模板, 不是汇编代码
    │     ├── README
    │     └── tests
    ├── lib                       # 链接库目录, 编译后生成的.a文件会放到对应芯片目录下
    │     ├── cm3
    │     │     ├── assert.c
    │     │     ├── dwt.c
    │     │     ├── nvic.c
    │     │     ├── scb.c
    │     │     ├── sync.c
    │     │     ├── systick.c
    │     │     └── vector.c      # startup代码
    │     ├── cortex-m-generic.ld
    │     ├── dispatch
    │     │     ├── vector_chipset.c
    │     │     └── vector_nvic.c
    │     ├── efm32
    │     ├── ethernet
    │     ├── gd32
    │     ├── lm3s
    │     ├── lm4f
    │     ├── lpc13xx
    │     ├── lpc17xx
    │     ├── lpc43xx
    │     ├── Makefile.include
    │     ├── msp432
    │     ├── nrf
    │     ├── pac55xx
    │     ├── sam
    │     ├── stm32
    │     ├── swm050
    │     ├── usb
    │     └── vf6xx
    ├── locm3.sublime-project
    ├── Makefile
    ├── mk                    # make 规则目录
    │     ├── gcc-config.mk
    │     ├── gcc-rules.mk
    │     ├── genlink-config.mk   # 用于配置生成ld需要的参数
    │     ├── genlink-rules.mk    # 用于生成ld文件
    │     └── README
    ├── README.md
    ├── scripts
    │     ├── checkpatch.pl
    │     ├── data
    │     ├── gendoxylayout.py
    │     ├── gendoxylist
    │     ├── genlink.py          # 芯片数据库文件搜索脚本
    │     ├── genlinktest.sh      # 芯片数据库文件搜索测试脚本
    │     ├── irq2nvic_h          # 读取irq.json, 填充IRQ_HANDLERS变量, 这个变量会被vector.c 的 vector_table 引用,
    │     └── lpcvtcksum
    └── tests
    

    LibOpenCM3 项目模板

    导出 libopencm3 可以单独编译, 但是配置为完整的项目还需要添加用户代码和Makefile, 因为 LibOpenCM3 已经提供了立即可用的项目模板, 可以直接用模板提供的环境进行开发

    导出模板

    git clone --recurse-submodules https://github.com/libopencm3/libopencm3-template.git
    cd libopencm3-template/
    # 这一步需要前面的 arm-none-eabi-gcc 工具链已经配置到 PATH
    # 编译
    make -C libopencm3
    

    这一步会编译 libopencm3

    • 在 libopencm3/lib 目录下生成全部型号的 .a 库文件
    • 在 libopencm3/lib/stm32 目录下, 对应 f0, f1, ..., f7 等各个目录下生成对应型号的 ld 文件

    如果前面没有将 arm-none-eabi-gcc 添加到PATH, 需要修改一下 libopencm3/Makefile, 将 PREFIX 修改为

    PREFIX		?= /opt/gcc-arm/gcc-arm-none-eabi-10.3-2021.10/bin/arm-none-eabi-
    

    如果只想编译当前使用的设备(STM32F103), 可以指定设备, 这样比较节省时间

    TARGETS=stm32/f1 make
    

    如果要输出完整命令, 可以加上 V=1 参数

    TARGETS=stm32/f1 make V=1
    

    注: 在当前的模板项目中, libopencm3不是最新版本, 版本号 cb0661f81de5b1cae52ca99c7b5985b678176db7 对应的是2020-02-16的版本, 这个版本在lib/stm32/fx 目录下依然有各个型号的ld文件, 而这些文件实际上在 2020-11-29 的提交 BREAKING: drop all part specific ld files中已经删除了. 具体的说明可以点开查看. 当前模板的Makefile实际上使用的是后者的编译方式生成项目的ld文件.

    编辑用户项目, 在编辑之前, 需要修改 my-project 目录下的 Makefile, 将 DEVICE 修改为自己的 STM32 型号

    # TODO - you will need to edit these two lines!
    DEVICE=stm32f103c6t6
    

    填入的型号如果正确, 会在编译时生成对应的ld文件, 例如对应上面的就是 generated.stm32f103c6t6.ld

    如果前面没有将 arm-none-eabi-gcc 添加到PATH, 需要修改一下 my-project/Makefile, 添加 PREFIX 定义

    PREFIX		?= /opt/gcc-arm/gcc-arm-none-eabi-10.3-2021.10/bin/arm-none-eabi-
    

    编译

    make -C my-project
    

    这时候在 my-project 目录下会产生以下文件

    total 172
    -rwxrwxr-x 1 milton milton   1492 Feb 20 23:55 awesomesauce.bin*
    -rwxrwxr-x 1 milton milton 276952 Feb 20 23:55 awesomesauce.elf*
    drwxrwxr-x 2 milton milton   4096 Feb 20 23:55 bin/
    -rw-rw-r-- 1 milton milton   1108 Feb 20 23:55 generated.stm32f103c6t6.ld
    -rw-rw-r-- 1 milton milton    493 Feb 20 23:38 Makefile
    -rw-rw-r-- 1 milton milton   2099 Feb 20 23:42 my-project.c
    

    其中 awesomesauce.bin 是用于烧录的文件

    通过 arm-none-eabi-size 查看编译结果的内存结构.

    $ arm-none-eabi-size awesomesauce.elf 
       text	   data	    bss	    dec	    hex	filename
       1480	     12	      0	   1492	    5d4	awesomesauce.elf
    

    其中

    • text 是占用的flash空间
    • data 初始化占用内存大小
    • bss 全局分配的内存大小
    • dec和hex 十进制和十六进制表示的总大小

    演示示例

    下面用一个闪灯的示例把开发环境跑一遍.

    用户代码

    将 my-project 目录下的 my-project.c 内容修改为

    #include <libopencm3/cm3/nvic.h>
    #include <libopencm3/stm32/rcc.h>
    #include <libopencm3/stm32/gpio.h>
    #include <libopencm3/stm32/timer.h>
    
    #ifndef ARRAY_LEN
    #define ARRAY_LEN(array) (sizeof((array))/sizeof((array)[0]))
    #endif
    
    #define LED1_PORT   GPIOC
    #define LED1_PIN    GPIO13
    
    static void gpio_setup(void)
    {
        /* Enable GPIO clock for leds. */
        rcc_periph_clock_enable(RCC_GPIOC);
        /* Enable led as output */
        gpio_set_mode(
            LED1_PORT,
            GPIO_MODE_OUTPUT_50_MHZ,
            GPIO_CNF_OUTPUT_PUSHPULL,
            LED1_PIN);
        gpio_set(LED1_PORT, LED1_PIN);
    }
    
    static void tim_setup(void)
    {
        /* Enable TIM2 clock. */
        rcc_periph_clock_enable(RCC_TIM2);
    
        /* Enable TIM2 interrupt. */
        nvic_enable_irq(NVIC_TIM2_IRQ);
    
        /* Reset TIM2 peripheral to defaults. */
        rcc_periph_reset_pulse(RST_TIM2);
    
        /* Timer global mode:
         * - No divider
         * - Alignment edge
         * - Direction up
         * (These are actually default values after reset above, so this call
         * is strictly unnecessary, but demos the api for alternative settings)
         */
        timer_set_mode(TIM2, TIM_CR1_CKD_CK_INT, TIM_CR1_CMS_EDGE, TIM_CR1_DIR_UP);
    
        /* Disable preload. */
        timer_disable_preload(TIM2);
        timer_continuous_mode(TIM2);
        timer_set_prescaler(TIM2, 36000); // Clock counts every 0.5 msec
        timer_set_period(TIM2, 2000); // 2000 * 0.5 msec => 1 sec
    
        /* Counter enable. */
        timer_enable_counter(TIM2);
    
        /* Enable Channel 1 compare interrupt to recalculate compare values */
        timer_enable_irq(TIM2, TIM_DIER_CC1IE);
    }
    
    /**
     * ISR method defined in libopencm3/include/libopencm3/stm32/f1/nvic.h
    */
    void tim2_isr(void)
    {
        if (timer_get_flag(TIM2, TIM_SR_CC1IF))
        {
            /* Clear compare interrupt flag. */
            timer_clear_flag(TIM2, TIM_SR_CC1IF);
            /* Toggle LED to indicate compare event. */
            gpio_toggle(LED1_PORT, LED1_PIN);
        }
    }
    
    int main(void)
    {
        // Setup main clock, using external 8MHz crystal 
        rcc_clock_setup_in_hse_8mhz_out_72mhz();
        // 如果用的libopencm3版本较高, 编译提示上面的函数已经废弃, 可以换成下面的代码
        //rcc_clock_setup_pll(&rcc_hse_configs[RCC_CLOCK_HSE8_72MHZ]);
    
        gpio_setup();
        tim_setup();
    
        while (1);
        return 0;
    }
    

    上面的代码, 用TIM2定时, 触发板载C13对应的LED每秒切换亮灭状态

    编译

    使用前面配置好的开发环境

    make -C my-project
    

    写入

    将开发板接上ST-Link接上PC

    写入, 0x800 0000 是 STM32F103 的Flash空间起始地址

    st-flash write ./awesomesauce.bin 0x8000000
    # 会看到包含如下文字的输出
    2022-02-21T00:00:42 INFO common.c: STM32F1xx_LD: 10 KiB SRAM, 32 KiB flash in at least 1 KiB pages.
    file ./awesomesauce.bin md5 checksum: 363668176fa21306a846725b7db2079, stlink checksum: 0x0001fe1e
    2022-02-21T00:00:42 INFO common_flash.c: Attempting to write 1492 (0x5d4) bytes to stm32 address: 134217728 (0x8000000)
    -> Flash page at 0x8000000 erased (size: 0x400)
    -> Flash page at 0x8000400 erased (size: 0x400)
    
    2022-02-21T00:00:42 INFO flashloader.c: Starting Flash write for VL/F0/F3/F1_XL
    2022-02-21T00:00:42 INFO flash_loader.c: Successfully loaded flash loader in sram
    2022-02-21T00:00:42 INFO flash_loader.c: Clear DFSR
    2022-02-21T00:00:42 INFO flash_loader.c: Clear CFSR
    2022-02-21T00:00:42 INFO flash_loader.c: Clear HFSR
      2/  2 pages written
    2022-02-21T00:00:42 INFO common_flash.c: Starting verification of write complete
    2022-02-21T00:00:42 INFO common_flash.c: Flash written and verified! jolly good!
    

    此时需要手动按一下开发板的 RESET 键, 程序才会开始执行, 如果需要自动重置, 使用下面的命令

    st-flash --reset write ./awesomesauce.bin 0x8000000
    

    其它命令

    查看开发板信息

    st-info --probe
    # 会看到包含如下文字的输出(当前这块测试用的是 stm32f103c6t6)
    Found 1 stlink programmers
      version:    V2J37S7
      serial:     56FF6B064966485627461667
      flash:      32768 (pagesize: 1024)
      sram:       10240
      chipid:     0x412
    

    擦除

    st-flash erase
    # 会看到包含如下文字的输出
    2022-02-21T00:00:12 INFO common.c: STM32F1xx_LD: 10 KiB SRAM, 32 KiB flash in at least 1 KiB pages.
    Mass erasing
    

    参考

  • 相关阅读:
    C++ VS2015安装教程,下载和安装(下载地址+图解+详细步骤)
    kubernetes集群之调度系统
    智云通CRM:客户说“别人家的便宜”,如何有效回应?
    解决transform带来的z-index失效问题
    手机银行体验性测试:如何获取用户真实感受
    自压缩llm 为 超长记忆
    HarmonyOS 学习记录
    C#界面里的AccessibleName、AccessibleDescription和AccessibleRole属性
    C++ Reference: Standard C++ Library reference: C Library: cwchar: mbrlen
    【JAVA】强引用、软引用、弱引用、幻象引用有什么区别?
  • 原文地址:https://www.cnblogs.com/milton/p/15917192.html