ESP32移植wolfssl方法
轉自:https://www.jarviswang.me/?p=599
?
自2015年ESP32發布以后,官方號稱很牛逼,關注度也挺高,但實際上呢,我們這些拿到芯片開發的第一批用戶來說,也踩了不少坑,文檔渣、例子少,生態相比傳統大公司比如TI,ST之流還是有很大差距,這次打算移植wolfssl這個庫到ESP32上也費了不少勁,過程順便記錄下方便大家參考。
wolfssl是一個輕量級的的SSL庫,支持的協議還挺全的,比較適合嵌入式系統,而且使用起來比OpenSSL和mbedTLS簡單多了。所以就打算在ESP32上移植這個ssl庫。另外,ESP32上自帶了OpenSSL和mbedTLS,如果僅僅是實現SSL功能,用這兩個庫已經足夠,但是api用起來沒有wolfssl那么簡潔好用,所以個人還是更喜歡wolfssl這個庫。
好了接下來開始吧,網上完全找不到類似的資料,在wolfssl論壇上有人嘗試移植成功過,但是并沒有放出方法以及源碼,所以此時此刻只能自己嘗試移植了。我這里移植用的是樂鑫官方的esp-idf模板庫,arduino應該也大同小異。
ESP官方的esp-idf把組件也就是庫放在components目錄下,每個組件一個文件夾,在組件文件夾目錄里會有一個component.mk文件,用于指定每個組件的include目錄和源碼目錄。而整個工程的project.mk會搜索components目錄下的每個目錄,尋找component.mk來對每個組件進行編譯。所以我們要把wolfssl源碼放在components目錄下。
首先,我們去wolfssl官網下載最新的源代碼:
https://wolfssl.com/wolfSSL/download/downloadForm.php
然后,我們在components文件夾下新建wolfssl目錄,然后把源碼拷貝過來,目錄結構如下:
?
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 | . ├── build ├── components │?? │ │?? │????? ... │?? ├── wolfssl │?? │ │????????? ... ├── main │?? ... ├── Makefile ├── README.md ├── sdkconfig └── sdkconfig.old |
wolfssl目錄下保持源碼原來的結構即可,如圖:
然后,在wolfssl目錄下新建一個component.mk文件,內容如下:
?
| 1 2 3 4 5 6 7 | # # Component Makefile # ? COMPONENT_ADD_INCLUDEDIRS := ../wolfssl COMPONENT_PRIV_INCLUDEDIRS := ../freertos/include/freertos COMPONENT_SRCDIRS := src wolfcrypt/src |
為什么是這樣我大概解釋一下,如果有需要的可以看wolfssl官方的說明,wolfssl根目錄下面看似有很多文件夾,但實際有用的只有這幾個:
./wolfssl — 這個文件夾是wolfssl的所有頭文件
./src — 這個是wolfssl功能代碼
./wolfcrypt/src — 這個是wolfssl的所有加密算法源碼實現
由于wolfssl的代碼中對頭文件的引用都是wolfssl/xxxx.h這種形式的,所以我們頭文件包含的目錄應該是wolfssl的根目錄,所以我們COMPONENT_ADD_INCLUDEDIRS變量要設置為當前目錄,才變成我的這種寫法,另外由于esp-idf使用的系統是FreeRTOS,所以wolfssl也要結合FreeRTOS來編譯,所以FreeRTOS的頭文件目錄也要加上。
這一步完成了之后,我們需要修改wolfssl/wolfcrypt/settings.h
大致修改如下幾處:
一、反注釋FREERTOS和WOLFSSL_LWIP宏定義,因為esp-idf使用的是FreeRTOS+lwip方式的系統+協議棧。
?
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | ... /* Uncomment next line if using PIC32MZ Crypto Engine */ /* #define WOLFSSL_MICROCHIP_PIC32MZ */ ? /* Uncomment next line if using FreeRTOS */ ?#define FREERTOS ? /* Uncomment next line if using FreeRTOS+ TCP */ /* #define FREERTOS_TCP */ ? /* Uncomment next line if using FreeRTOS Windows Simulator */ /* #define FREERTOS_WINSIM */ ? /* Uncomment next line if using RTIP */ /* #define EBSNET */ ? /* Uncomment next line if using lwip */ ?#define WOLFSSL_LWIP ? /* Uncomment next line if building wolfSSL for a game console */ /* #define WOLFSSL_GAME_BUILD */ ... |
二、找到如下地方,添加一些宏定義:
?
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 | ... #ifdef FREERTOS ????#include "FreeRTOS.h" ? ????/* FreeRTOS pvPortRealloc() only in AVR32_UC3 port */ ????#if !defined(XMALLOC_USER) && !defined(NO_WOLFSSL_MEMORY) ????????#define XMALLOC(s, h, type)? pvPortMalloc((s)) ????????#define XFREE(p, h, type)??? vPortFree((p)) ????????//新增如下一行: ????????#define XREALLOC(p, n, h, type) pvPortRealloc((p), (n)) ? ????#endif ? ????#ifndef NO_WRITEV ????????#define NO_WRITEV ????#endif ????#ifndef HAVE_SHA512 ????????#ifndef NO_SHA512 ????????????#define NO_SHA512 ????????#endif ????#endif ????#ifndef HAVE_DH ????????#ifndef NO_DH ????????????#define NO_DH ????????#endif ????#endif ????#ifndef NO_DSA ????????#define NO_DSA ????#endif ????#ifndef NO_HC128 ????????#define NO_HC128 ????#endif ? ????#ifndef SINGLE_THREADED ????????#include "semphr.h" ????#endif ? ????//新增下面的宏定義: ????#ifndef HAVE_ECC ????????#define HAVE_ECC ????#endif ? ????#define WOLFSSL_DTLS ????#define HAVE_SOCKADDR ????#define DEBUG_WOLFSSL ????#define NO_DEV_RANDOM ????#include "esp_system.h" #endif ... |
另外,由于esp-idf里的freeRTOS沒有pvPortRealloc這個定義,但這個功能是已經實現的只是沒封裝,所以現在要自己去封裝這個函數:
找到components/freertos/port.c,在vPortFree函數后面添加如下函數:
?
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | ... void *pvPortMalloc(?size_t xWantedSize ) { ????return heap_caps_malloc(xWantedSize, MALLOC_CAP_8BIT); } ? void vPortFree(?void *pv ) { ????return heap_caps_free(pv); } //添加如下內容: void *pvPortRealloc(?void *pv,?size_t size ) { ????return heap_caps_realloc(pv, size,MALLOC_CAP_8BIT); } ... |
然后找到components/freertos/include/freertos/portable.h
在vPortFree的定義后面添加pvPortRealloc的定義:
?
| 1 2 3 4 5 6 7 | ... void *pvPortMalloc(?size_t xSize ) PRIVILEGED_FUNCTION; void vPortFree(?void *pv ) PRIVILEGED_FUNCTION; //添加如下一行: void *pvPortRealloc(?void *pv,?size_t size ) PRIVILEGED_FUNCTION; void vPortInitialiseBlocks(?void ) PRIVILEGED_FUNCTION; ... |
最后,由于wolfssl要正常工作還需要一個隨機數發生器,默認使用的是/dev/urandom,但是FreeRTOS上面是沒有這個io設備的,所以我們在前面有定義過NO_DEV_RANDOM,這時候我們需要自己實現隨機數生成的函數,不過好在ESP32自帶了硬件隨機數發生器,所以寫起來也比較簡單:
修改wolfcrypt/src/random.c
找到如下位置,在wc_GenerateSeed函數里填上具體實現的代碼,下面的代碼是我的實現,你也可以自己實現,esp_random()函數一次能獲得4個字節隨機數,我直接只用最低字節,方便點:
?
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 | ... #elif defined(NO_DEV_RANDOM) ? ????//#error "you need to write an os specific wc_GenerateSeed() here" ? ? ????int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz) ????{ ????????for (int i=0;i<sz;i++) ????????????output[i] = esp_random()&0xFF; ? ????????return 0; ????} ... |
完成這些步驟之后,我們編譯esp-idf,這時候wolfssl庫應該就能正常編譯通過了,會在build/wolfssl目錄下生成libwolfssl.a,這時候我們在自己編寫app的時候就可以使用wolfssl相關的頭文件了。
最后,如果app要引用wolfssl的話,編譯到wolfssl的時候可能會報錯找不到頭文件,這時候就需要在app/main目錄下的component.mk文件中添加如下行:
?
| 1 2 3 4 5 6 7 8 9 | # # Main component makefile. # # This Makefile can be left empty. By default, it will take the sources in the # src/ directory, compile them and link them into lib(subdirectory_name).a # in the build directory. This behaviour is entirely configurable, # please read the ESP-IDF documents if you need to do this. # COMPONENT_PRIV_INCLUDEDIRS := ../../components/freertos/include/freertos ../../components/wolfssl |
然后就可以正常使用wolfssl的函數了
《新程序員》:云原生和全面數字化實踐50位技術專家共同創作,文字、視頻、音頻交互閱讀總結
以上是生活随笔為你收集整理的ESP32移植wolfssl方法的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 如何使用jlink从flash中读取数据
- 下一篇: RTT设备与驱动之I2C: