ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

中科蓝讯RV32开发环境搭建:CodeBlocks 17.12与RV32-Toolchain配置指南

中科蓝讯RV32开发环境搭建:CodeBlocks 17.12与RV32-Toolchain配置指南 1. 中科蓝讯RV32开发环境搭建从选型到跑通的完整思路中科蓝讯的RV32系列芯片在蓝牙音频、TWS耳机、智能穿戴这些领域出货量非常大很多做嵌入式音频产品的团队都在用它。但第一次接触这套工具链的人十有八九会在环境搭建这一步卡住——不是编译器找不到就是CodeBlocks启动报错再不然就是编译出来的固件烧进去没反应。我自己前前后后搭过五六套中科蓝讯的开发环境从最早的纯命令行到后来配CodeBlocks做IDE踩过的坑基本能写一本小册子。这篇内容就是把这些经验整理出来给正在折腾RV32-Toolchain和CodeBlocks 17.12的朋友一个可以直接抄的作业。先说清楚这套环境到底解决什么问题。中科蓝讯的RV32内核用的是RISC-V 32位指令集官方提供的工具链是基于GCC的定制版本包含riscv32-unknown-elf-gcc、objcopy、objdump、gdb这些标准组件。CodeBlocks 17.12在这里的角色是一个轻量级的C/C IDE它本身不参与编译只是调用外部工具链来完成构建。所以整个环境的核心其实是两件事第一把RV32-Toolchain正确安装并让系统能找到它第二把CodeBlocks配置成能调用这套工具链的编辑器。听起来简单但实际操作中路径里的空格、中文目录、环境变量顺序、CodeBlocks自带的MinGW冲突每一个都能让你折腾半天。适合谁来参考这篇内容如果你是中科蓝讯方案开发的初学者或者从其他MCU平台比如STM32、ESP32转过来做RISC-V音频开发又或者你已经在用命令行编译但想换成IDE提高效率那这篇内容基本能覆盖你90%的需求。我假设你用的是Windows系统因为CodeBlocks 17.12在Windows下的坑最多Linux下反而简单很多。下面我会按照“先理清思路再拆解细节然后完整实操最后排查问题”的顺序来讲每一部分都尽量把“为什么这么做”说清楚而不是只给一堆步骤让你照抄。2. 工具链与IDE的选型逻辑为什么是CodeBlocks 17.12加RV32-Toolchain2.1 为什么不用官方推荐的IDE或者VS Code中科蓝讯官方其实提供过基于Eclipse的定制IDE但那个版本比较老界面卡顿不说有时候还会和Windows的杀毒软件打架。VS Code虽然现在很流行但配置RISC-V工具链需要装一堆插件对于只想快速编译烧录的音频方案开发者来说学习成本偏高。CodeBlocks 17.12的好处是它足够轻量安装包不到100MB启动速度快而且它的自定义编译器功能非常直接——你只需要告诉它编译器路径、编译参数、链接参数它就能干活。对于RV32这种需要频繁修改Makefile或者自定义编译选项的场景CodeBlocks的“自定义编译器”配置比VS Code的tasks.json要直观得多。还有一个很实际的原因很多中科蓝讯的方案商提供的SDK里示例工程就是基于CodeBlocks的.cbp文件组织的。你直接用CodeBlocks打开就能看到完整的工程结构编译按钮一点就出固件省去了自己写构建脚本的麻烦。当然如果你习惯用MakefileCodeBlocks也支持自定义Makefile构建灵活性是够的。2.2 RV32-Toolchain的版本选择与来源中科蓝讯的RV32-Toolchain通常随SDK一起提供文件名类似riscv32-unknown-elf-gcc-xxx-windows.zip。这里有一个关键点不要自己去RISC-V官网下载通用的工具链因为中科蓝讯的芯片在指令集扩展和链接脚本上有定制通用工具链编译出来的固件可能跑不起来。我试过一次用官方开源工具链编译结果链接阶段就报错提示找不到某些符号后来换回SDK自带的工具链才解决。工具链的版本号一般对应GCC的版本比如gcc version 8.3.0或者10.2.0。不同SDK版本可能要求不同的工具链版本这个在SDK的Release Note里通常会写。如果你拿到的工具链和SDK不匹配最常见的表现是编译通过但运行异常或者链接时提示relocation truncated to fit之类的错误。所以第一步一定是确认SDK文档里指定的工具链版本不要随意混用。2.3 CodeBlocks 17.12的安装包选择带不带MinGWCodeBlocks的下载页面会给你两个选项带MinGW的版本和不带MinGW的版本。这里我的建议非常明确下载不带MinGW的版本。原因很简单中科蓝讯的RV32-Toolchain本身就是一套完整的GCC工具链它包含了编译器、链接器、标准库。如果你装了带MinGW的CodeBlocks系统里就会有两套GCC环境变量一冲突CodeBlocks可能调用到MinGW的gcc而不是RV32的gcc编译出来的就是x86代码烧到芯片上肯定跑不了。不带MinGW的CodeBlocks安装包大概30MB左右安装过程也很干净不会往系统里塞一堆你不需要的东西。安装路径建议用纯英文比如C:\CodeBlocks不要放在Program Files下面因为路径里的空格有时候会让工具链的参数解析出问题。我遇到过有人装在C:\Program Files (x86)\CodeBlocks结果编译时提示找不到crt0.o折腾了一下午才发现是路径空格导致的。3. 安装过程中的核心细节与避坑要点3.1 RV32-Toolchain的解压与路径设置拿到工具链的压缩包后解压到一个纯英文、无空格的路径下比如C:\RV32-Toolchain。解压完成后目录结构通常是这样的C:\RV32-Toolchain\ ├── bin\ │ ├── riscv32-unknown-elf-gcc.exe │ ├── riscv32-unknown-elf-objcopy.exe │ ├── riscv32-unknown-elf-objdump.exe │ └── ... ├── lib\ ├── include\ └── ...接下来要把C:\RV32-Toolchain\bin添加到系统的PATH环境变量里。这一步的目的是让命令行和CodeBlocks都能直接找到riscv32-unknown-elf-gcc这个命令而不需要写完整路径。添加方法右键“此电脑”-属性-高级系统设置-环境变量-在“系统变量”里找到Path-编辑-新建-填入C:\RV32-Toolchain\bin-确定。注意添加PATH之后一定要重启CodeBlocks如果CodeBlocks已经打开它不会自动刷新环境变量。更稳妥的做法是添加完PATH后重启一次电脑确保所有进程都能读到新的环境变量。验证工具链是否安装成功打开命令提示符cmd输入riscv32-unknown-elf-gcc -v如果能看到GCC的版本信息说明PATH设置正确。如果提示“不是内部或外部命令”那就是PATH没生效检查路径是否写错或者有没有多余的空格。3.2 CodeBlocks 17.12的安装与首次启动配置CodeBlocks的安装基本是下一步下一步但有两个地方要注意。第一安装组件选择时只勾选“Code::Blocks主程序”和“中文语言包”如果需要汉化不要勾选任何编译器相关的组件。第二安装完成后首次启动CodeBlocks会弹出一个“编译器自动检测”的对话框它会扫描系统里的编译器。这时候你可能会看到它检测到了MinGW或者Visual Studio的编译器不要选这些直接点“Skip”跳过。因为我们后面要手动配置RV32的工具链自动检测的编译器对我们没用。跳过自动检测后进入CodeBlocks主界面。如果是英文界面可以通过Settings - Environment - View - Internationalization选择中文语言包来汉化。汉化包通常在安装目录的share\CodeBlocks\locale\zh_CN下如果没有可以去CodeBlocks的官方论坛找对应的语言包文件。3.3 那个烦人的“thesaurus files not found”报错怎么处理很多人第一次启动CodeBlocks 17.12时会看到一个弹窗提示thesaurus files \spellchecker\th_en_us.idx not found。这个报错不影响编译但每次启动都弹出来很烦人。它的原因是CodeBlocks的拼写检查插件找不到英语词库文件。解决方法有两个一是直接禁用拼写检查插件在Plugins - Manage plugins里找到SpellChecker把它禁用二是下载对应的词库文件放到指定目录。我一般直接用第一种方法因为写嵌入式代码根本用不到拼写检查禁用掉最省事。如果你不想禁用插件也可以去CodeBlocks的安装目录下找到share\CodeBlocks\SpellChecker文件夹把th_en_us.idx和th_en_us.dic两个文件放进去。这两个文件在网上可以找到但要注意版本匹配不然还是会报错。4. 在CodeBlocks中配置RV32自定义编译器的完整实操4.1 新建自定义编译器配置打开CodeBlocks进入Settings - Compiler在“Selected compiler”下拉框里选择GNU GCC Compiler然后点“Copy”按钮给它起个名字比如RV32-GCC。这一步的目的是基于GCC的默认配置创建一个副本我们在这个副本上修改不会影响原来的GCC配置。创建完成后切换到Toolchain executables标签页。这里是最关键的地方需要把每个工具的执行文件路径指向RV32-Toolchain的bin目录。具体配置如下配置项填写内容Compilers installation directoryC:\RV32-ToolchainC compilerriscv32-unknown-elf-gcc.exeC compilerriscv32-unknown-elf-g.exeLinker for dynamic libsriscv32-unknown-elf-g.exeLinker for static libsriscv32-unknown-elf-ar.exeDebuggerriscv32-unknown-elf-gdb.exeResource compiler留空Make programmingw32-make.exe如果SDK用Makefile构建注意“Compilers installation directory”只需要填到工具链的根目录CodeBlocks会自动去bin子目录下找对应的可执行文件。如果你填了C:\RV32-Toolchain\bin反而可能找不到因为CodeBlocks会再拼一次bin。4.2 编译选项与链接参数的设置切换到Compiler settings标签页这里需要根据中科蓝讯SDK的要求来设置。一般来说RV32的编译选项包括-marchrv32imc指定指令集架构rv32imc表示支持整数、乘除法、压缩指令-mabiilp32指定ABIilp32表示int、long、pointer都是32位-mcmodelmedany指定代码模型medany适合大多数嵌入式场景-Os优化等级音频方案通常用Os平衡性能和体积-ffunction-sections -fdata-sections把每个函数和数据放到独立的段方便链接器裁剪-Wall打开常用警告链接参数通常包括-T linker_script.ld指定链接脚本这个文件在SDK的工程目录里-Wl,--gc-sections回收未使用的段减小固件体积-nostartfiles不使用标准启动文件因为RV32的启动代码是SDK自己提供的-Wl,-Mapoutput.map生成map文件方便分析内存布局这些参数不是固定的具体要看SDK里的Makefile或者工程配置。我的建议是先把SDK自带的示例工程编译一遍看看它的编译命令是什么然后把这些参数原样填到CodeBlocks里。4.3 头文件与库文件的搜索路径在Search directories标签页里需要添加SDK的头文件路径和库文件路径。头文件路径通常包括SDK的include目录SDK的components目录下的各个子模块工程自身的inc目录库文件路径通常是SDK的lib目录里面会有libaudio.a、libbt.a之类的静态库。添加完路径后在Linker settings里把这些库文件按依赖顺序列出来。注意顺序很重要被依赖的库要放在后面比如libbt.a依赖libaudio.a那就要写成-lbt -laudio。5. 编译、烧录与调试的完整流程5.1 用CodeBlocks打开SDK示例工程中科蓝讯的SDK通常会提供一个.cbp文件这就是CodeBlocks的工程文件。直接双击打开CodeBlocks会自动加载工程结构。如果SDK没有提供.cbp文件你也可以新建一个空工程然后把源文件手动添加进去。新建工程时选择Empty project编译器选择刚才创建的RV32-GCC。工程打开后先别急着编译。检查一下Project - Build options里的编译器配置是否继承了我们刚才设置的RV32-GCC。有时候工程文件里会硬编码编译器名称如果和你设置的不一致需要手动改过来。5.2 编译过程中的常见报错与解决第一次编译大概率不会一帆风顺下面这几个报错是我遇到最多的报错1riscv32-unknown-elf-gcc: command not found这个说明CodeBlocks没找到编译器。检查Toolchain executables里的路径是否正确以及PATH环境变量是否生效。如果PATH没问题试试在CodeBlocks的Compiler settings - Other settings里把Compilers installation directory的路径手动写死不要用相对路径。报错2cannot find -lxxx链接阶段找不到某个库。检查Linker settings里的库文件名是否正确以及Search directories - Linker里的库路径是否包含了库文件所在的目录。注意库文件名要去掉lib前缀和.a后缀比如libaudio.a要写成-laudio。报错3relocation truncated to fit: R_RISCV_HI20 against symbol xxx这个通常是代码模型或者链接脚本的问题。试试把-mcmodelmedany改成-mcmodelmedlow或者检查链接脚本里的内存区域定义是否超出了芯片的实际地址范围。报错4undefined reference to _start链接器找不到入口点。检查链接脚本里是否定义了ENTRY(_start)以及启动文件start.S是否被正确编译和链接。有时候是因为-nostartfiles参数导致标准启动文件被排除但SDK的启动文件又没被加进来。5.3 烧录工具的使用与注意事项编译生成的固件通常是.bin或者.elf格式。中科蓝讯的烧录工具一般叫Downloader或者BurnTool具体名称看SDK版本。烧录时需要注意芯片要进入烧录模式通常是按住某个按键再上电或者通过串口发送特定命令烧录工具的串口号要选对波特率一般是115200或者921600烧录前最好先擦除芯片避免旧固件残留导致异常烧录完成后要复位芯片有些工具会自动复位有些需要手动断电再上电提示如果烧录后芯片没反应先用riscv32-unknown-elf-objdump -d output.elf反汇编一下看看入口地址的指令是否正确。有时候是链接脚本里的地址写错了导致固件被烧到了错误的Flash位置。6. 常见问题速查与独家避坑经验6.1 环境搭建阶段的高频问题速查表问题现象可能原因解决方法CodeBlocks启动报thesaurus文件缺失拼写检查插件找不到词库禁用SpellChecker插件或放入词库文件编译提示找不到riscv32-unknown-elf-gccPATH未生效或路径错误检查PATH重启CodeBlocks或电脑编译通过但烧录后无反应工具链版本不匹配或链接脚本错误换回SDK自带工具链检查链接脚本链接报relocation truncated to fit代码模型或内存地址范围问题改-mcmodel参数检查链接脚本找不到-lxxx库库路径或库名错误检查Linker settings和搜索路径CodeBlocks调用到了MinGW的gcc系统里有多个GCCPATH顺序问题把RV32的bin目录移到PATH最前面中文注释导致编译报错文件编码不是UTF-8把源文件保存为UTF-8无BOM格式工程打开后编译器显示为GNU GCC工程文件里硬编码了编译器名称在Project build options里改成RV32-GCC6.2 那些文档里不会写的实操心得第一个心得工具链路径千万不要有中文和空格。我见过有人把工具链解压到“D:\新建文件夹\RV32工具链”下面结果编译时各种奇怪的报错折腾了半天才发现是路径问题。Windows下虽然理论上支持中文路径但GCC的工具链对路径的处理有时候会出问题尤其是涉及到临时文件生成的时候。所以从一开始就用纯英文路径能省掉后面很多麻烦。第二个心得CodeBlocks的工程文件不要放在SDK的只读目录下。有些SDK是从压缩包里直接打开的目录属性是只读的。CodeBlocks在编译时会生成.o文件和.d依赖文件如果目录只读编译就会失败。把整个SDK复制到一个可读写的目录下再打开工程。第三个心得编译参数里的优化等级不要随便改。音频方案对实时性要求高-O0编译出来的代码体积大、运行慢可能导致音频卡顿。-O3又可能因为过度优化导致某些时序敏感的代码出问题。SDK默认给的-Os是经过验证的没有特殊需求不要动。第四个心得善用map文件分析内存占用。编译时加上-Wl,-Mapoutput.map然后打开map文件可以看到每个函数和变量占用了多少空间Flash和RAM的剩余量是多少。如果RAM快满了就要考虑优化数据结构或者把一些常量放到Flash里。第五个心得调试时优先用串口打印不要一上来就上GDB。RV32的GDB调试需要JTAG调试器而且配置起来比较麻烦。大多数情况下在代码里加几个printf通过串口输出调试信息效率反而更高。中科蓝讯的SDK通常已经封装好了串口打印函数直接调用就行。6.3 关于CodeBlocks汉化和插件的一些补充CodeBlocks 17.12的汉化包在网上有很多版本建议去官方论坛下载对应版本的汉化文件不要随便找个汉化包就用。版本不匹配的汉化包可能导致菜单显示不全或者CodeBlocks崩溃。汉化方法把zh_CN文件夹放到CodeBlocks安装目录\share\CodeBlocks\locale\下然后在Settings - Environment - View里选择中文。插件方面CodeBlocks自带的Code completion插件对RISC-V的头文件支持一般有时候补全不准。如果你需要更好的代码补全可以试试Clangd插件但配置起来稍微复杂一些。对于大多数嵌入式开发场景自带的补全够用了不用折腾。7. 从命令行到IDE两种构建方式的取舍与配合7.1 命令行构建的优势与适用场景虽然这篇内容主要讲CodeBlocks但我想说的是命令行构建在某些场景下反而更方便。比如你要做持续集成或者需要在多台机器上批量编译命令行一条make命令就能搞定不需要打开IDE。中科蓝讯的SDK通常都带Makefile直接在SDK根目录下执行make就能编译。命令行构建的另一个好处是错误信息更清晰。CodeBlocks的编译输出窗口有时候会把错误信息截断或者因为编码问题显示乱码。命令行下直接看gcc的输出什么问题一目了然。我一般是在CodeBlocks里写代码遇到编译错误时切到命令行跑一遍make看完整的错误信息。7.2 在CodeBlocks中调用外部Makefile如果你既想用CodeBlocks的编辑器又想用SDK自带的Makefile可以在CodeBlocks里配置“自定义Makefile”。具体做法Project - Properties - Build targets把Type改成Makefile然后在Make commands里填写make命令。这样点击编译按钮时CodeBlocks会调用外部make程序来构建而不是用它自己的构建系统。这种方式的优点是兼顾了IDE的编辑体验和Makefile的灵活性。缺点是CodeBlocks的语法检查和高亮可能不完全准确因为它不知道Makefile里定义的那些宏和包含路径。不过对于写代码来说影响不大。7.3 两种方式的配合使用建议我的习惯是日常开发用CodeBlocks因为编辑、跳转、补全方便发布版本或者排查编译问题时用命令行因为输出信息完整、可脚本化。具体来说在CodeBlocks里写好代码后按CtrlS保存然后切到命令行执行make clean make确认编译通过后再回到CodeBlocks里做其他操作。这样既享受了IDE的便利又保证了构建的可靠性。还有一个小技巧可以在CodeBlocks的Tools菜单里添加一个自定义工具命令填cmd /c cd /d $(PROJECT_DIR) make这样在CodeBlocks里点一下就能调用命令行编译输出会显示在CodeBlocks的日志窗口里。配置方法Settings - Tools - Add填好名称和命令即可。8. 环境验证与固件运行确认8.1 用最小工程验证工具链是否正常在正式开发之前建议先建一个最小工程验证工具链是否工作正常。这个工程只需要一个main.c和一个链接脚本main.c里写一个空循环int main(void) { volatile int i 0; while (1) { i; } return 0; }链接脚本里定义好Flash和RAM的地址范围入口点设为main。编译这个工程如果能在output目录下生成.elf和.bin文件说明工具链基本正常。然后用objdump反汇编一下看看main函数的指令是不是RISC-V指令指令编码以0x开头的32位或16位数据。如果反汇编出来是x86指令那说明CodeBlocks调用错了编译器。8.2 烧录后的运行确认方法固件烧录后怎么确认它真的在运行最直接的方法是看串口输出。在main函数开头加一句串口打印比如printf(RV32 boot ok\n)然后打开串口助手波特率设成和代码里一致复位芯片看能不能收到打印信息。如果收到了说明固件至少跑到了main函数。如果串口没输出先检查硬件连接TX和RX是不是接反了波特率是不是对串口助手是不是打开了正确的串口号。硬件没问题的话再检查软件时钟初始化是不是正确串口引脚配置是不是对打印函数是不是被优化掉了用volatile修饰或者降低优化等级试试。8.3 性能与资源占用的初步评估固件跑起来之后可以进一步评估资源占用。用riscv32-unknown-elf-size output.elf命令查看Flash和RAM的使用量text data bss dec hex filename 12345 678 9012 22035 5613 output.elftext是代码段大小data是已初始化数据段bss是未初始化数据段。Flash占用通常是text dataRAM占用是data bss。对比芯片的Flash和RAM容量看看还剩多少余量。如果余量不足10%后续加功能就要小心了。音频方案还要关注CPU占用率。中科蓝讯的SDK通常提供了CPU负载统计的接口可以在主循环里定期打印出来。如果CPU占用率长期超过80%音频播放可能会出现卡顿或断音需要优化代码或者降低采样率。9. 一些关于版本管理和团队协作的建议9.1 工具链和SDK的版本锁定团队开发时工具链和SDK的版本一定要统一。我见过因为两个人用的工具链版本不一样导致同一個工程一个人编译通过另一个人编译报错的情况。建议在项目文档里明确记录工具链的版本号、SDK的版本号、CodeBlocks的版本号最好把工具链的压缩包也放到版本控制里如果体积允许的话。如果工具链太大不方便入库至少要把版本号和下载链接记录下来。新成员加入时按照文档一步步装能避免很多“我这里怎么不行”的问题。9.2 CodeBlocks工程文件的版本控制CodeBlocks的.cbp文件和.layout文件是可以入库的但.depend和.o文件不要入库。.cbp文件里记录了工程的源文件列表、编译选项、搜索路径等信息入库后其他成员拉下来就能直接打开。.layout文件记录了窗口布局入不入库都行看团队习惯。需要注意的是.cbp文件里的路径如果是绝对路径换一台电脑可能就失效了。建议在CodeBlocks里把路径设置成相对路径具体做法Project - Properties - Build targets把Output filename和Objects output dir改成相对路径比如bin\output.elf和obj\。这样工程在不同电脑上都能正常编译。9.3 团队共享的编译脚本如果团队里有人用命令行、有人用IDE可以写一个统一的编译脚本比如build.bat里面封装好工具链路径和编译参数。CodeBlocks里配置调用这个脚本命令行下也执行这个脚本保证两边编译结果一致。脚本内容大概是这样echo off set TOOLCHAINC:\RV32-Toolchain\bin set PATH%TOOLCHAIN%;%PATH% riscv32-unknown-elf-gcc -marchrv32imc -mabiilp32 -Os -c main.c -o main.o riscv32-unknown-elf-gcc -T linker.ld main.o -o output.elf riscv32-unknown-elf-objcopy -O binary output.elf output.bin这个脚本虽然简单但能保证编译环境的一致性。新成员只需要改一下TOOLCHAIN变量指向自己的工具链路径就行。10. 后续扩展从环境搭建到量产固件环境搭好只是第一步后面还有很长的路要走。比如怎么优化音频算法的CPU占用怎么配置蓝牙协议栈的参数怎么做OTA升级这些都需要在稳定的开发环境基础上逐步深入。我的建议是环境搭建完成后先花时间把SDK里的示例工程都跑一遍理解每个模块的初始化和调用流程然后再动手改代码。不要一上来就大改那样出了问题很难定位是环境问题还是代码问题。另外中科蓝讯的芯片型号很多不同型号的RV32核配置可能略有差异比如有的带FPU有的不带有的Flash大有的Flash小。在搭建环境时要确认工具链的编译参数和芯片型号匹配。比如带FPU的型号需要加-marchrv32imfc不带FPU的就不能加f扩展否则编译出来的指令芯片不认。我在实际项目中的体会是环境搭建这件事第一次做最痛苦但只要把工具链路径、编译参数、链接脚本这三个东西搞清楚了后面换芯片型号或者换SDK版本基本就是改几个参数的事。所以第一次搭建时不要怕麻烦把每个配置项都弄明白为什么这么设后面会省很多时间。
返回列表