参考——CCS联合CLion调试__开发TI芯片

一、简介

        随着电赛临近,有些题必须指定使用TI芯片,那么就不得不学一下CCS。虽然CCS相较于Keil和IAR,显得更现代化一些,但还是没有代码样式代码格式化代码补全等功能。如果你用惯了CLion再用CCS,就会有些许一言难尽,总得来说就是智能了但又没完全智能,比如断点。因此想到了使用CLion来开发TI芯片.

        只不过过程很不顺,最主要的原因在于我使用的芯片是MSPM0G3507,且是launchpad,而OpenOCD上好像又没有相关的配置,最终导致调试TI开发板。想过直接使用GDB,或者换成可以使用JLink的开发板(有空再说),但由于时间有限就不得不找个次替方案,于是就想到了CCS联调CLion

        这里所谓的联调指的是在CLion里面编写代码(包括检测语法错误),在CCS里进行外设初始化、调试等,虽不如最初的构想,但也可以大大降低开发难度。同时,CLionCode with me这个功能,这意味着你和其他人可以联合开发同一个项目。下面配置中最难的步骤在于“删”和配置CMakelists,由于我们使用的TI芯片可能不同,所以这里主要讲方法。

二、联调配置

1,工程创建

①编译器选型

        前面提到,既然要想CCS联调CLion,那么就必须把CCS相关工程配好,在不影响CCS编译的情况下,联调CLion。CCS一共有两个编译工具链,其一为clang,其二为arm-gnu,不过后者需要的版本是9.82,这与CLion用的版本多半不同且CCS需要自己配置arm-gnu工具链。

        所以CCS的工程就选为clang,虽说与CLion用的编译器不同,语法、生成的代码会有些许差异,但是CLion在这里发挥的作用主要是编写,也就不用考虑了(有问题再说)。

②导入工程

        这里选用的是官方实例中的RTOS工程,首先要到官网下载相应的SDK,我使用的芯片是MSPM0G3507,所以就下载了MSPM0的SDKMSPM0-SDK 软件开发套件 (SDK) | 德州仪器 TI.com.cn

        在SDK里,我们需要找到对应工程,它就在【example-rtos-LP_MSPM0G3507-kernel】里。

我们选用最基础的闪灯工程。

         为了后续移植方便,把这个SDK复制到你准备创建的workplace里,我这里的workplace是TI这个目录,Furina是其工程名。

 在CCS里找到对应目录,直接导入即可

然后你就会得到以下目录

 2,准备CLion工程前置工作

①编写CMakelists

        前面提到这个工程名为Furina,那么在里面添加一个CMakelists.txt文件。这里面的编译器选项和链接器选项都是参照官方实例里gcc下的Makefile。这个嘛,就看个人选择,你可以直接使用官方这个makefile,配置相应的Makefile程序也是可以的,这样反而更快。不过由于我将来要尝试使用OpenOCD或者其他什么的调试程序,所以在此就用了最熟悉的cmake。

        如果你想使用makefile(本篇文章省去了具体配置过程,不过过程并不难),那么就而可以直接跳到【3,配置CLion工程】

        照着里面的CFLAGSLFLAGS里的参数(比如-mthumb)把对应的add_compile_optionsadd_link_options也改一下。同时要注意,CFLAGS里有个宏定义-D__MSPM0G3507__,需要添加至add_definitions里。

set(CMAKE_SYSTEM_NAME Generic)
set(CMAKE_SYSTEM_VERSION 1)
cmake_minimum_required(VERSION 3.28)

#
#set(toolsPath /usr/arm-gnu-toolchain/bin)
#set(CMAKE_C_COMPILER ${toolsPath}/arm-none-eabi-gcc)
#set(CMAKE_CXX_COMPILER ${toolsPath}/arm-none-eabi-g++)
#set(CMAKE_ASM_COMPILER ${toolsPath}/arm-none-eabi-gcc)
#set(CMAKE_AR  ${toolsPath}/arm-none-eabi-ar)
#set(CMAKE_OBJCOPY  ${toolsPath}/arm-none-eabi-objcopy)
#set(CMAKE_OBJDUMP  ${toolsPath}/arm-none-eabi-objdump)

#下面代码是MinGW工具链下的
# specify cross-compilers and tools
set(CMAKE_C_COMPILER arm-none-eabi-gcc)
set(CMAKE_CXX_COMPILER arm-none-eabi-g++)
set(CMAKE_ASM_COMPILER arm-none-eabi-gcc)
set(CMAKE_AR arm-none-eabi-ar)
set(CMAKE_OBJCOPY arm-none-eabi-objcopy)
set(CMAKE_OBJDUMP arm-none-eabi-objdump)
set(SIZE arm-none-eabi-size)

set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY)

# project settings
project(blink_led C CXX ASM)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_C_STANDARD 11)

#如果是FreeRTOS,那么下面需要开启,如果是RT-Thread,则需要关闭
#Uncomment for hardware floating point
#add_compile_definitions(ARM_MATH_CM4;ARM_MATH_MATRIX_CHECK;ARM_MATH_ROUNDING)
#add_compile_options(-mfloat-abi=hard -mfpu=fpv4-sp-d16)
#add_link_options(-mfloat-abi=soft -mfpu=fpv4-sp-d16)

#Uncomment for software floating point,要注释
add_compile_options(-mfloat-abi=soft)

#add_compile_options(-mcpu=cortex-m0plus -mthumb -mthumb-interwork)
#add_compile_options(-ffunction-sections -fdata-sections -fno-common -fmessage-length=0)
add_compile_options(-mcpu=cortex-m0plus -march=armv6-m -mthumb -mthumb-interwork)
add_compile_options(-ffunction-sections -fdata-sections -fno-common -fmessage-length=0 -gstrict-dwarf)
# Enable assembler files preprocessing
add_compile_options($<$<COMPILE_LANGUAGE:ASM>:-x$<SEMICOLON>assembler-with-cpp>)


add_link_options(-Wl,-gc-sections,--print-memory-usage,-Map=${PROJECT_BINARY_DIR}/${PROJECT_NAME}.map)
add_link_options(-mcpu=cortex-m0plus -march=armv6-m -mthumb -mthumb-interwork)
add_link_options(-T ${LINKER_SCRIPT})

# uncomment to mitigate c++17 absolute addresses warnings
#set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-register")


if ("${CMAKE_BUILD_TYPE}" STREQUAL "Release")
    message(STATUS "Maximum optimization for speed")
    add_compile_options(-Ofast)
elseif ("${CMAKE_BUILD_TYPE}" STREQUAL "RelWithDebInfo")
    message(STATUS "Maximum optimization for speed, debug info included")
    add_compile_options(-Ofast -g)
elseif ("${CMAKE_BUILD_TYPE}" STREQUAL "MinSizeRel")
    message(STATUS "Maximum optimization for size")
    add_compile_options(-Os)
else ()
    message(STATUS "Minimal optimization, debug info included")
    add_compile_options(-Og -g)
endif ()

add_definitions(-DDEBUG -D__MSPM0G3507__)

include_directories(
        ticlang/Application
        ticlang/Debug

        kernel/freertos/builds/LP_MSPM0G3507/release
        source/third_party/CMSIS/Core/Include
        source/third_party/CMSIS/DSP/Include
        source/third_party/CMSIS/DSP/PrivateInclude
        kernel/freertos/Source/include
        source
        kernel/freertos/Source/portable/GCC/ARM_CM0
        source/ti/posix/gcc

        source/third_party/mcuboot/boot/bootutil/include
)

file(GLOB_RECURSE SOURCES
        "ticlang/Application/*.*"
        "ticlang/Debug/ti_msp_dl_config.c"
        "ticlang/Debug/ti_msp_dl_config.h"

        "kernel/freertos/builds/LP_MSPM0G3507/release/*.*"
        "kernel/freertos/Source/portable/GCC/ARM_CM0/*.*"
        "kernel/freertos/Source/include/*.*"
        "kernel/freertos/Source/*.*"
        "kernel/freertos/dpl/*.*"

        "source/*.*"
    "syscalls.c"
)
#下面是额外添加的,用于动态代码的分析
#set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address")

#set(LINKER_SCRIPT ${CMAKE_SOURCE_DIR}/STM32F407VETX_FLASH.ld)
set(LINKER_SCRIPT ${CMAKE_SOURCE_DIR}/mspm0g3507.lds)



add_executable(${PROJECT_NAME}.elf ${SOURCES} ${LINKER_SCRIPT})

set(HEX_FILE ${PROJECT_BINARY_DIR}/${PROJECT_NAME}.hex)
set(BIN_FILE ${PROJECT_BINARY_DIR}/${PROJECT_NAME}.bin)

add_custom_command(TARGET ${PROJECT_NAME}.elf POST_BUILD
        COMMAND ${CMAKE_OBJCOPY} -Oihex $<TARGET_FILE:${PROJECT_NAME}.elf> ${HEX_FILE}
        COMMAND ${CMAKE_OBJCOPY} -Obinary $<TARGET_FILE:${PROJECT_NAME}.elf> ${BIN_FILE}
        COMMENT "Building ${HEX_FILE}
Building ${BIN_FILE}")

②添加链接文件

        这个还是到gcc那个文件夹,把这个lds文件添加至Furina工程里。添加这个是为了可以在使用CLion构建时看到程序大致占用情况(clang编译器与gcc终归不一样,所以会和实际有些出入)

       

3,配置CLion工程

        接下来先导包,呃我的意思是向Furina这个工程SDK里的两个库,一个是source,另一个是kernel

        然后直接右键Furina这个文件夹用CLion打开,添加cmake项目之类的相信你已经炉火纯青了。

第一次编译的时候会报许多错,原因有三

        其一为“添加的这个sourcekernel库里有脏东西”,比如说下面这个目录里会有IAR、MemMang等不相关的东西。除了GCC都应该把它删掉,这个需要自己对应报错提示去修改,同时配合CMakelists里设置的包含目录和资源文件,过程比较繁琐耗时

需要的文件可以参考下面的release文件夹

        其二为 “缺少相关定义——unfined”,添加个syscalls.c就行了,代码如下(_sbrk可能需要你改,可参照lds链接脚本文件)。同时,不要直接放到Furina工程的ticlang(显示Active Debug的那个目录,我重命名过)里,不然CCS会自动编译它导致构建错误,这里推荐放在外面,

        再在链接脚本文件里添加了一句

_estack = ORIGIN(SRAM) + LENGTH(SRAM);

/**
 ******************************************************************************
 * @file      syscalls.c
 * @author    Auto-generated by STM32CubeIDE
 * @brief     STM32CubeIDE Minimal System calls file
 *
 *            For more information about which c-functions
 *            need which of these lowlevel functions
 *            please consult the Newlib libc-manual
 ******************************************************************************
 * @attention
 *
 * Copyright (c) 2020-2024 STMicroelectronics.
 * All rights reserved.
 *
 * This software is licensed under terms that can be found in the LICENSE file
 * in the root directory of this software component.
 * If no LICENSE file comes with this software, it is provided AS-IS.
 *
 ******************************************************************************
 */

/* Includes */
#include <sys/stat.h>
#include <stdlib.h>
#include <errno.h>
#include <stdio.h>
#include <signal.h>
#include <time.h>
#include <sys/time.h>
#include <sys/times.h>


/* Variables */
extern int __io_putchar(int ch) __attribute__((weak));
extern int __io_getchar(void) __attribute__((weak));


char *__env[1] = { 0 };
char **environ = __env;


/* Functions */
void initialise_monitor_handles()
{
}

int _getpid(void)
{
  return 1;
}

int _kill(int pid, int sig)
{
  (void)pid;
  (void)sig;
  errno = EINVAL;
  return -1;
}

void _exit (int status)
{
  _kill(status, -1);
  while (1) {}    /* Make sure we hang here */
}

__attribute__((weak)) int _read(int file, char *ptr, int len)
{
  (void)file;
  int DataIdx;

  for (DataIdx = 0; DataIdx < len; DataIdx++)
  {
    *ptr++ = __io_getchar();
  }

  return len;
}

__attribute__((weak)) int _write(int file, char *ptr, int len)
{
  (void)file;
  int DataIdx;

  for (DataIdx = 0; DataIdx < len; DataIdx++)
  {
    __io_putchar(*ptr++);
  }
  return len;
}

int _close(int file)
{
  (void)file;
  return -1;
}


int _fstat(int file, struct stat *st)
{
  (void)file;
  st->st_mode = S_IFCHR;
  return 0;
}

int _isatty(int file)
{
  (void)file;
  return 1;
}

int _lseek(int file, int ptr, int dir)
{
  (void)file;
  (void)ptr;
  (void)dir;
  return 0;
}

int _open(char *path, int flags, ...)
{
  (void)path;
  (void)flags;
  /* Pretend like we always fail */
  return -1;
}

int _wait(int *status)
{
  (void)status;
  errno = ECHILD;
  return -1;
}

int _unlink(char *name)
{
  (void)name;
  errno = ENOENT;
  return -1;
}

int _times(struct tms *buf)
{
  (void)buf;
  return -1;
}

int _stat(char *file, struct stat *st)
{
  (void)file;
  st->st_mode = S_IFCHR;
  return 0;
}

int _link(char *old, char *new)
{
  (void)old;
  (void)new;
  errno = EMLINK;
  return -1;
}

int _fork(void)
{
  errno = EAGAIN;
  return -1;
}

int _execve(char *name, char **argv, char **env)
{
  (void)name;
  (void)argv;
  (void)env;
  errno = ENOMEM;
  return -1;
}
static uint8_t *__sbrk_heap_end = NULL;

/**
 * @brief _sbrk() allocates memory to the newlib heap and is used by malloc
 *        and others from the C library
 *
 * @verbatim
 * ############################################################################
 * #  .data  #  .bss  #       newlib heap       #          MSP stack          #
 * #         #        #                         # Reserved by _Min_Stack_Size #
 * ############################################################################
 * ^-- RAM start      ^-- _end                             _estack, RAM end --^
 * @endverbatim
 *
 * This implementation starts allocating at the '_end' linker symbol
 * The '_Min_Stack_Size' linker symbol reserves a memory for the MSP stack
 * The implementation considers '_estack' linker symbol to be RAM end
 * NOTE: If the MSP stack, at any point during execution, grows larger than the
 * reserved size, please increase the '_Min_Stack_Size'.
 *
 * @param incr Memory size
 * @return Pointer to allocated memory
 */
void *_sbrk(ptrdiff_t incr)
{
    extern uint8_t _end; /* Symbol defined in the linker script */
    extern uint8_t _estack; /* Symbol defined in the linker script */
    extern uint32_t _Min_Stack_Size; /* Symbol defined in the linker script */
    const uint32_t stack_limit = (uint32_t)&_estack - (uint32_t)&_Min_Stack_Size;
    const uint8_t *max_heap = (uint8_t *)stack_limit;
    uint8_t *prev_heap_end;

    /* Initialize heap end at first call */
    if (NULL == __sbrk_heap_end)
    {
        __sbrk_heap_end = &_end;
    }

    /* Protect heap from growing into the reserved MSP stack */
    if (__sbrk_heap_end + incr > max_heap)
    {
        errno = ENOMEM;
        return (void *)-1;
    }

    prev_heap_end = __sbrk_heap_end;
    __sbrk_heap_end += incr;

    return (void *)prev_heap_end;
}

第三个为“缺少ti_msp_dl_config文件”,这个是CCS在Debug里产生的配置文件,复制到一个合适的位置就行(CMakelists要能找到)。或者直接把这个目录里的这两个文件包含进CMakelists里,后者这个更推荐,因为配置文件会经常改

        那么接下来除了一些小警告意外,就可以正常使用CLion来编写代码了,CLion这里可以检查语法错误,同时也不耽误CCS编译调试程序,开发体验也上去了,三赢零亏。

三,可能用到的文档 

1,TI的FFT官方文档

bing.com/ck/a?!&&p=88d3645f0a6dc0d5JmltdHM9MTcyMTAwMTYwMCZpZ3VpZD0yNTgzZDVmYi03NjJkLTY1MDktMGNkNS1jMTQwNzc1ZTY0NDUmaW5zaWQ9NTE4Nw&ptn=3&ver=2&hsh=3&fclid=2583d5fb-762d-6509-0cd5-c140775e6445&psq=TI+FFT&u=a1aHR0cHM6Ly93d3cudGkuY29tL2NuL2xpdC9wZGYvemhjYTQxNA&ntb=1

  • 15
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值