前面幾篇文章寫了一下關於cmake改造嵌入式編程的體驗,點擊查看
擺脫MDK,用cmake改造嵌入式軟件開發體驗
用IDE配置並運行cmake工程
讀者反響不錯,至今已有3個讚了,給了我很大的鼓舞(手動滑稽),今天就來分享一下嵌入式開發中最重要的環節,固件發佈,畢竟,程序寫的再溜,不出固件,老闆拿什麼賣錢嘛.python
首先說明一下通常你們作嵌入式發佈程序的通常流程:程序猿在MDK編好固件以後,在工程目錄的build的文件夾會產生編譯出來的hex文件,以下圖:
而後程序猿就把固件拷貝到一個新建的文件夾,從新命個名(由於mdk裏生成的固件名稱是固定的),通常是寫上產品名稱,版本號啊而後有一些特殊的定義也會加上(好比什麼至尊版,增強版,普通版之類的區分同一產品的不一樣價位或者功能),再編寫一個changlist或者版本記錄,而後把版本記錄也拷貝一份到文件夾內,而後再壓縮發給測試人員或者生產負責人.shell
高級作法是編寫一個腳本,好比python腳本或者bat(shell)腳本,在腳本里面執行一些拷貝或者某些系統命令,好比nrf52832帶sdk的程序就須要把sdk合併到最終的hex文件裏去.
好比這樣:
這種方式比手動修改就要高級一些,咱們稱爲高級1.0,可是這種作法有一個弊端,無法根據固件編譯時的參數去定製固件的名稱,卻是有一個方法,在build文件夾下有一個.dep文件能夠利用python腳本去解析裏面的特定字符,好比:
好比我須要知道固件編譯的時候有沒有定義TIANYI這個宏,能夠這樣寫:
這樣的話能夠作到針對某個編譯參數生成特定名稱的固件,能夠算是一個提升吧,用MDK的話就能夠採起這種方式編程
高級作法2.0是高級作法1.0的升級版,前提是須要搭建好cmake的編譯環境,閒話少說,上法寶:
這段代碼是cmake裏面添加編譯期間定義的語句,結合前面的cmake環境搭建教程,結合語句按字面意思應該不難理解,首先咱們定義了這麼一些編譯參數,而後咱們把全部的編譯參數獲取出來,造成一個叫defs的數組(cmake語法裏的數組類型,這裏不用理解這個數組到底怎麼存儲的)
在cmake裏面添加一個目標,叫作merge,名字能夠隨便取:
這段代碼能夠理解爲:若是我須要產生一個merge的目標,就調用後面的cmd命令行語句,這個語句的做用是用python來啓動一個腳本,啓動腳本的時候會帶上相應的參數,這個參數就是咱們提取出來的defs,而後在python腳本里面把參數打印出來會是這樣會是這樣:
看到沒有,剛剛咱們定義的宏定義在python文件裏面獲取到了,可是有一點不太好,好比咱們cmake文件裏面SOFT_VER=809,在python裏面也是這樣子顯示的,不利於咱們把真實的數據提取出來,沒事,python這麼先進的語言,這還不是小事一樁,盤他:
如上圖所示,咱們花分把鍾(專業人員,請勿羨慕)把解析函數寫出來,造成一個字典(dict,python的一種數據結構):
字典是一種鍵值對的數據結構,能夠理解成不用數字作下標的數組,可是python的類型很靈活,不理解的同窗能夠研究一下python
接下來的事就太簡單了,咱們只須要把字典的鍵和值分別取出來就好了,對於有的參數,沒有值的說明我們不須要他的值,看圖:
這樣的操做就把以前咱們複雜的須要把.dep文件打開而後一行一行的找對應的宏有沒有來的簡便,並且效率也更高(不須要讀文件了)
你覺得到這就完事了,錯,接下來咱們還有合併固件,而後把全部相關文件壓縮成壓縮包,單獨存儲,而你只須要點一個按鈕
好比個人工程裏,除了要把hex生成出來,還要生成一個用於ota升級的固件包,同時編譯的源hex也要保存,以方便追溯問題,請上眼:
對,就是這麼短短的幾行語句,你以前須要花好幾分鐘還不必定不出錯的步驟,咱們用幾行腳本語句就實現了,接下來就是運行腳本了,怎麼運行:
打開cmd命令行,輸入:
`
cmake --build .build --target merge
`
就等着電腦幫你打包吧,若是還想簡單一點,qtcreater,clion,包括mdk都有一個外部工具能夠建立,建立完以後點擊運行就ok了:
這是clion的
這是qtcreater的
這是mdk的
json
---------19-12-10更新-----------segmentfault
最近發現MDK一樣能夠作到clion或者qtcreater一樣的高級方法,共享以下,本質上仍是運用python腳本,python真的能夠作好多事情,配置如圖:
很簡單,就是調用python去執行merge.py腳本,那麼如何實現獲取編譯的時候定義的各類參數呢,一種方法是上面講的讀取.dep文件,這是最簡單高效的,另外附上高級用法:
1).高級獲取宏定義方法一
mdk編譯的時候有一個選項是misc_ctrl,如圖,在這裏加上一行:--via defines.opt
而後在工程目錄下建立一個defines.opt文件,用文本編輯器打開,填入形如-DSOFTVERSION=101
-DUSE_UART
這樣的宏定義就行,例如:
那這個文件起什麼做用呢,用過MAKEFILE的童鞋可能反應過來了,由於makefile裏面就是這樣的語法,這個文件這樣寫的做用跟編譯的時候指定的宏定義效果是同樣的,好比這樣:
同窗們能夠實驗一下,用這個文件編譯的話在程序裏面定義-D以後的變量能夠讀取到,那既然有文件就好辦了,用python解析一下文件不就造成了定義字典了嗎,好比:
仍是熟悉的正則,仍是熟悉的py,換湯不換藥,這裏注意一下里面有個re.sub函數,這個函數是替換'""這樣的字符的由於opt文件的語法緣由直接定義某個字符串會致使程序沒法正確識別,必須用''把""裏面的內容括起來才能讓程序識別成字符串.
後面的事情就清楚了,跟高級版3.0同樣,固件打包神馬的都同樣,願意研究的同窗自行研究就行
2).高級獲取宏定義方法二
這種方法要用到xml文件解析,咱們都知道每一個MDK項目都是由一個.uvprojx文件管理的(mdk四是.uvproj),咱們嘗試用文本編輯器看一下里面是什麼:
喔吼吼,這不就是xml文件嘛,再看看裏面有什麼具體內容:
哦吼吼吼,怎麼這麼眼熟呢,原來,咱們在編輯器上宏定義的東西都在這裏,看這裏:
理解不了的同窗本身把宏定義改幾個而後編譯一下或者退出mdk而後從新打開就能看到效果了
嗯,接下來還不是py一把梭:
這段代碼也很簡單,無非就是打開xml文件,而後讀取tag,attr和text,不熟悉XML文件的同窗自行百度一下就知道了,比json難不到哪去,
利用python咱們仍是很容易的就得到了咱們定義的宏定義,接下來的事就不用多說了,不過值得一提的是,若是在這種方法定義的宏包含字符串的話須要處理一下,好比:PRODUCT="S350N"
,不用像opt文件那樣用單引號包起來,可是程序裏面要使用的話得這樣:
也不是很難理解,具體爲何我就不講了,同窗們照着個人葫蘆能畫出來瓢就行.數組
以上就是更新的內容,最近發現MDk也不是那麼的爛,仍是算比較靈活的,後面一篇搞幾個MDK高級操做,列位看官請上眼.數據結構
目前,關於固件生成的批量化就簡單研究到這裏了,若是同窗們還有什麼需求能夠一塊兒探討.文章有錯誤在所不免,歡迎指正.編輯器