電子產(chǎn)業(yè)一站式賦能平臺(tái)

PCB聯(lián)盟網(wǎng)

搜索
查看: 2001|回復(fù): 0
收起左側(cè)

移植鴻蒙系統(tǒng)到STM32L476RG_NUCLEO開(kāi)發(fā)板的一點(diǎn)小經(jīng)驗(yàn)

[復(fù)制鏈接]

2607

主題

2607

帖子

7472

積分

高級(jí)會(huì)員

Rank: 5Rank: 5

積分
7472
跳轉(zhuǎn)到指定樓層
樓主
發(fā)表于 2020-11-12 15:56:35 | 只看該作者 回帖獎(jiǎng)勵(lì) |倒序?yàn)g覽 |閱讀模式
移植鴻蒙系統(tǒng)到STM32L476RG_NUCLEO開(kāi)發(fā)板的一點(diǎn)小經(jīng)驗(yàn),   
本帖最后由 死龍 于 2020-11-12 14:51 編輯





  • https://gitee.com/walker2048/hmos_iot

復(fù)制代碼 目前移植STM32L476的相關(guān)代碼已上傳在gitee,有興趣的同學(xué)可以自行下載研究。

編譯命令為 python build.py stm32l476rg_nucleo



移植鴻蒙的建議:

一步一步來(lái),別想一口吃成胖子,給自己定計(jì)劃。   

多看源碼以及編譯日志,多想,多動(dòng)手 。

源碼既是文檔,別想著百度或者google能幫你直接解決問(wèn)題。

修改完代碼后,完成了小部分功能的,也要及時(shí)提交git。



1、第一步肯定是創(chuàng)建廠商文件夾

      首先按移植LiteOS教程里的說(shuō)明,使用CubeMX工具生成makefile格式的項(xiàng)目(包含了stm32l4xx標(biāo)準(zhǔn)hal庫(kù)和ll庫(kù)實(shí)現(xiàn)代碼及makefile),并把項(xiàng)目文件復(fù)制到vendor/st/stm32l4xx目錄里。

這就是2020-11-06日  dbbaf5f  這個(gè)提交所包含的內(nèi)容

然后在該目錄執(zhí)行命令  make > build.log,這樣一是測(cè)試代碼是否能正常編譯,二是可以把stm官方提供的makefile實(shí)際執(zhí)行指令信息存儲(chǔ)到build.log文件里,方便以后修改gn系統(tǒng)的編譯配置時(shí)做參考用。



2、第二步,配置編譯環(huán)境及組件。

       根據(jù)以往閱讀makefile和嵌入式開(kāi)發(fā)經(jīng)驗(yàn),應(yīng)該先確定編譯工具鏈。不同硬件架構(gòu),需要的編譯工具鏈并不一樣,哪怕是一個(gè)最簡(jiǎn)單的helloworld,也沒(méi)辦法實(shí)現(xiàn)同一個(gè)bin文件,能在不同架構(gòu)的硬件上直接運(yùn)行。目前鴻蒙2.0配置好的兩套編譯工具(主要是gcc),并不能完成stm32的編譯工作。

      打開(kāi)build/lite/toolchain/目錄,復(fù)制gcc.gni文件的內(nèi)容到arm_none_eabi_gcc.gni,并將第14行的ohos_kernel_type (內(nèi)核類(lèi)型) 修改成liteos_m,并將15行的ohos_build_compiler_prefix 設(shè)置為正確的gcc工具前綴arm-none-eabi。其他內(nèi)容暫時(shí)沒(méi)動(dòng),然后根據(jù)其他開(kāi)發(fā)板的設(shè)置,又復(fù)制粘貼了一遍各種配置,例如



  • build/lite/config/boards/stm32l476rg_nucleo.gni
      


復(fù)制代碼 等等配置先抄一遍hi3861的,期間各種嘗試使用編譯命令python build.py stm32l476rg_nucleo,直到不再提示找不到stm32l476rg_nucleo目標(biāo)板,進(jìn)入下一個(gè)確認(rèn)工具鏈環(huán)節(jié)為止。

這一環(huán)節(jié)中,比較重要的應(yīng)該是build/lite/product/stm32l476rg_nucleo.json文件,該文件定義了目標(biāo)板名稱,編譯工具鏈,內(nèi)核等等重要信息。



當(dāng)編譯命令提示arm-none-eabi-gcc不是OHOS的編譯器時(shí),我也楞了一會(huì)兒。翻了build目錄下各種配置也找不到對(duì)應(yīng)配置時(shí),我就放棄找配置了。直接在VScode中全局搜索包含not OHOS compiler字段的文件,最終在build/lite/config.py的124行和158行找到了對(duì)應(yīng)判斷語(yǔ)句,并增加了arm-none-eabi-gcc的判斷語(yǔ)句。



隨后測(cè)試編譯時(shí),又發(fā)現(xiàn)編譯腳本會(huì)針對(duì)ohos_kernel_type 進(jìn)行各種優(yōu)化和設(shè)置。沒(méi)辦法,就只能搜索ohos_kernel_type == “l(fā)iteos_riscv“,并將對(duì)應(yīng)腳本一一修改

。涉及到的文件也很多,詳細(xì)請(qǐng)看gitee上的變更記錄。



最終各組件的配置判斷語(yǔ)句沒(méi)問(wèn)題了,能順利進(jìn)入到編譯狀態(tài),出現(xiàn)類(lèi)似以下信息了




  •   
  • === start build ===
      

  •   
  • Done. Made 39 targets from 41 files in 648ms
      
  • ninja: Entering directory `/mnt/out/stm32l476rg_nucleo\“
      
  • [1/112] cross compiler obj/applications/sample/wifi-iot/app/demolink/helloworld.o
      
  • [2/112] AR libs/libdemolink.a

復(fù)制代碼 也就是說(shuō)能出現(xiàn)[1/112]之類(lèi)的,恭喜你,編譯配置已經(jīng)完成了80%了。期間還刪除了大量容易出現(xiàn)問(wèn)題的組件,例如wifi功能等等一堆組件。



3、調(diào)整頭文件配置

     為了減少以后找文件找目錄頭疼,我在源碼目錄新建了一個(gè)include文件夾,并將疑似應(yīng)該從廠商目錄中提取出來(lái)的頭文件放在該目錄的hal目錄下,并將難以解決的頭文件錯(cuò)誤組件去掉,不編譯對(duì)應(yīng)組件。

      最終編譯命令都順利通過(guò)了,只差最后一步生成elf和bin文件了。



4、根據(jù)原廠makefile修改和調(diào)整編譯細(xì)節(jié)

      重頭戲是此文件build/lite/toolchain/arm_none_eabi_gcc.gni

      查看原廠makefile的build.log文件,可以看出編譯過(guò)程為

      .c文件=>.o文件,然后.S文件=>.o文件,然后將所有的.o文件以及

STM32L476RGTx_FLASH.ld文件一起鏈接成elf文件。最后再由elf文件生成bin和hex。

      多次嘗試修改后,最終調(diào)整為以下內(nèi)容



  • template(“gcc_toolchain“) {
      
  •     toolchain(target_name) {
      
  •         assert(defined(invoker.cc), “gcc toolchain must specify a \“cc\“ value“)
      
  •         assert(defined(invoker.cxx), “gcc toolchain must specify a \“cxx\“ value“)
      
  •         assert(defined(invoker.ld), “gcc toolchain must specify a \“l(fā)d\“ value“)
      
  •         assert(defined(invoker.ar), “gcc toolchain must specify a \“ar\“ value“)
      
  •         assert(defined(invoker.as), “clang toolchain must specify a \“as\“ value“)
      
  •         assert(defined(invoker.cp), “clang toolchain must specify a \“cp\“ value“)
      
  •         
      
  •         ar = invoker.ar
      
  •         as = invoker.as
      
  •         cc = invoker.cc
      
  •         cxx = invoker.cxx
      
  •         ld = invoker.ld
      
  •         cp = invoker.cp
      

  •   
  •         need_strip = false
      
  •         if(defined(invoker.strip)) {
      
  •             strip = invoker.strip
      
  •             need_strip = true
      
  •         }
      

  •   
  •         if (defined(invoker.extra_ldflags) && invoker.extra_ldflags != ““) {
      
  •           extra_ldflags = ““
      
  •         } else {
      
  •           extra_ldflags = ““
      
  •         }
      

  •   
  •         tool(“cc“) {
      
  •             command = “$cc -c {{cflags}} {{defines}} {{include_dirs}} {{cflags_c}} “ +
      
  •                      # “-MMD -MP -MF‘{{source_out_dir}}/{{source_name_part}}.d’ “ +
      
  •                      # “-Wa,-a,-ad,-alms={{source_out_dir}}/{{source_name_part}}.lst “ +
      
  •                       “{{source}} -o {{output}}“
      
  •             depsformat = “gcc“
      
  •             description = “cross compiler {{output}}“
      
  •             outputs = [
      
  •                 “{{source_out_dir}}/{{source_name_part}}.o“,
      
  •             ]
      
  •         }
      
  •         tool(“cxx“) {
      
  •             depfile = “{{output}}.d“
      
  •             command = “$cxx -c {{cflags}} {{defines}} {{include_dirs}} {{cflags_c}} “ +
      
  •                      # “-MMD -MP -MF‘{{source_out_dir}}/{{source_name_part}}.d’ “ +
      
  •                      # “-Wa,-a,-ad,-alms={{source_out_dir}}/{{source_name_part}}.lst “ +
      
  •                       “{{source}} -o {{output}}“
      
  •             depsformat = “gcc“
      
  •             description = “CXX {{output}}“
      
  •             outputs = [
      
  •                 “{{source_out_dir}}/{{target_output_name}}.{{source_name_part}}.o“,
      
  •             ]
      
  •         }
      
  •         tool(“asm“) {
      
  •             depfile = “{{output}}.d“
      
  •             command = “$as -c {{cflags}} {{defines}} {{include_dirs}} {{asmflags}} {{source}} {{cflags_c}} “ +
      
  •                       “-o {{output}}“
      
  •             depsformat = “gcc“
      
  •             description = “cross compiler {{output}}“
      
  •             outputs = [
      
  •                 “{{source_out_dir}}/{{source_name_part}}.o“
      
  •             ]
      
  •         }
      
  •         tool(“alink“) {
      
  •             outfile = “{{output_dir}}/{{target_output_name}}{{output_extension}}“
      
  •             rspfile = “{{output}}.rsp“
      
  •             rspfile_content = “{{inputs}}“
      
  •             command = “$ar cr {{output}} @\“$rspfile\““
      

  •   
  •             description = “AR {{output}}“
      
  •             outputs = [
      
  •                 outfile
      
  •             ]
      

  •   
  •             default_output_dir = “{{root_out_dir}}/libs“
      
  •             default_output_extension = “.a“
      
  •             output_prefix = “l(fā)ib“
      
  •         }
      
  •         tool(“l(fā)ink“) {
      
  •             outfile = “{{output_dir}}/bin/{{target_output_name}}.elf“
      
  •             rspfile = “$outfile.rsp“
      
  •             command = “$ld {{inputs}} {{ldflags}} $extra_ldflags -specs=nano.specs “ +
      
  •             # set ld file patch in vendor path
      
  •                       “-lc -lm -lnosys {{libs}} -Wl,-Map={{target_output_name}}.map,--cref “ +
      
  •                       “-Wl,--gc-sections -o $outfile “
      
  •             if(need_strip) {
      
  •                 command += “&& $cp -O binary -S $outfile {{output_dir}}/bin/{{target_output_name}}.bin“
      
  •             }
      

  •   
  •             description = “LINK $outfile“
      
  •             default_output_dir = “{{root_out_dir}}“
      
  •             rspfile_content = “{{inputs}}“
      
  •             outputs = [
      
  •                 outfile
      
  •             ]
      
  •         }
      
  •         tool(“stamp“) {
      
  •             if (host_os == “win“) {
      
  •                 command = “cmd /c type nul > \“{{output}}\““
      
  •             } else {
      
  •                 command = “/usr/bin/touch {{output}}“
      
  •             }
      
  •             description = “STAMP {{output}}“
      
  •         }
      
  •         tool(“copy“) {
      
  •             command = “$cp -O binary -S {{source}} {{output}}.bin && echo $strip“
      
  •             description = “COPY {{source}} {{output}}“
      
  •         }
      
  •     }

復(fù)制代碼

同時(shí)在stm32l4xx/Src/BUILD.gn文件中添加ldflags,實(shí)現(xiàn)ld文件在廠商文件內(nèi)設(shè)置。





  •     ldflags = [
      
  •       “-T“,
      
  •       “../../vendor/st/stm32l4xx/STM32L476RGTx_FLASH.ld“
      
  •     ]

復(fù)制代碼

最終,順利生成了elf文件,bin文件以及hex文件。

其實(shí)gn配置相對(duì)來(lái)說(shuō),命令行的提示,以及配置的可讀性都是相當(dāng)不錯(cuò)的。還是建議大家多動(dòng)手,多看,多想。

發(fā)表回復(fù)

本版積分規(guī)則


聯(lián)系客服 關(guān)注微信 下載APP 返回頂部 返回列表