本帖最后由 zhanzr21 于 2023-1-2 20:57 编辑
#申请原创#
开发版例程已经带有一个http+webserver的工程,为了学习LWIP,参照这个例程走了一遍简单的LWIP移植.
第一步:移植LWIP
这里选了最新的2.1.3版本
http://download.savannah.nongnu.org/releases/lwip/lwip-2.1.3.zip
下载后,把不要的代码删除掉,因为里面有这个工程中不用的代码,比如IPv6,串口转接以太网等等.当然不删除也可以,只是在AT32IDE中一个个去排除操作起来比较累.
左边是原版代码解压出来,右边是复制到工程中去的代码结构.
下一步就是提供移植代码,在用户代码目录下建立这么一个目录:user/port/
├── arch
│ ├── bpstruct.h
│ ├── cc.h
│ ├── epstruct.h
│ ├── perf.h
│ └── sys_arch.h
├── ethernetif.c
├── ethernetif.h
└── sys_arch.c
其中ethernetif.c和ethernetif.h就是将LWIP的代码与AT32F407芯片的MAC和板上PHY连接起来的移植文件,要调用AT32芯片的MAC外设,其余文件都是一些系统相关的配置,参照例程复制过来即可.
最主要的几个函数在ethernetif.h中定义,同时这里也可以定义MAC地址:
#ifndef __ETHERNETIF_H__
#define __ETHERNETIF_H__
#include"lwip/err.h"
#include"lwip/netif.h"
err_tethernetif_init(structnetif *netif);
err_tethernetif_input(structnetif *netif);
structnetif *ethernetif_register(void);
intethernetif_poll(void);
voidlwip_set_mac_address(unsignedchar* macadd);
#ifdef SERVER
#define MAC_ADDR0 0x00
#define MAC_ADDR1 0x00
#define MAC_ADDR2 0x00
#define MAC_ADDR3 0x00
#define MAC_ADDR4 0x00
#define MAC_ADDR5 0x01
#else
#define MAC_ADDR0 0x00
#define MAC_ADDR1 0x00
#define MAC_ADDR2 0x00
#define MAC_ADDR3 0x00
#define MAC_ADDR4 0x00
//#define MAC_ADDR5 0x02
#define MAC_ADDR5 0x03
//#define MAC_ADDR5 0x04
#endif
#endif
再就是配置工程的头文件目录,使之可以找到LWIP代码树的包含路径.
到这里移植就差不多了.当然这都是建立在官方的例程基础上的,比如MAC和PHY的底层函数是从官方例程直接copy来的.
第二步:准备和转换网页资源
HTTP协议如果不考虑HTTP2,HTTPS和JavaScript的话,是个很简单的协议.就是客户端发送请求,服务端根据请求进行处理之后返回HTML内容供客户端显示.
但是这个工程中不打算使用文件系统,所以要将网页资源(静态HTML页面,图片文件,CSS文件)转换成二进制的C/C++语言能访问的数组.AT官方的例程没有这样做,直接把静态页面以字符串的形式嵌入在C代码中了.这样做的缺点就是不好支持二进制的文件,如图片就没法处理了.
这里我采用了ARM Keil官方提供的一个工具:
FCARM
https://www.keil.com/pack/doc/mw ... w__util__fcarm.html
这个工具本来是跟Keil的RL-Network协议栈配套使用的,不过原理是类似的,就是把资源文件转换成C/C++语言便于访问的数组文件,所以也拿来用了.把网页目录直接放在用户的源代码目录下,这样使用工具时方便,也可以将网页文件和代码文件一起做版本管理.
web_resource/
└── simple_webserver_resource
├── adc_info.html
├── atstartf407_with_ethernet.jpg
├── binary_resource.c
├── binary_resource.lst
├── create_resource_fcarm.sh
├── favicon.ico
├── homepage.html
└── led_info.html
其中create_resource_fcarm.sh是转换脚本,在cygwin环境下使用:
FCARM=/d/Keil_v5/ARM/BIN/FCARM.exe
OUTPUT=binary_resource.c
$FCARM adc_info.html,led_info.html,homepage.html,atstartf407_with_ethernet.jpg,favicon.ico TO $OUTPUT
echo "post processing"
sed -i 's/#include <Net_Config.h>/\/\/#include <Net_Config.h>/' $OUTPUT
sed -i '1 a post processed by zhanzr21 script' $OUTPUT
sed -i '11 a #include <inttypes.h>' $OUTPUT
sed -i '12 a #include "at32f403a_407_board.h"' $OUTPUT
sed -i 's/U32/uint32_t/' $OUTPUT
sed -i 's/U8/uint8_t/' $OUTPUT
echo "post process complete"
后面的sed语句是将生成的RL_Network相关的定义修改成gcc可以直接构建的定义.
binary_resource.c即是生成好的二进制数组文件.在用户的代码中还需要做一点点处理:
const unsigned char homepage_name[] = "/homepage.html";
const unsigned char led_info_name[] = "/led_info.html";
const unsigned char adc_info_name[] = "/adc_info.html";
const unsigned char f407board_img_name[] = "/atstartf407_with_ethernet.jpg";
const unsigned char favicon_name[] = "/favicon.ico";
extern const HTTP_FILE FileTab[];
struct fsdata_file file_adc_info_html[] = { {
file_NULL, adc_info_name, 0, 0,
FS_FILE_FLAGS_HEADER_INCLUDED | FS_FILE_FLAGS_HEADER_PERSISTENT, } };
struct fsdata_file file_led_info_html[] = { { file_adc_info_html, led_info_name,
0, 0,
FS_FILE_FLAGS_HEADER_INCLUDED | FS_FILE_FLAGS_HEADER_PERSISTENT, } };
struct fsdata_file file_homepage_html[] = { { file_led_info_html,
homepage_name, 0, 0,
FS_FILE_FLAGS_HEADER_INCLUDED | FS_FILE_FLAGS_HEADER_PERSISTENT, } };
struct fsdata_file file_board_jpg[] = { { file_homepage_html,
f407board_img_name, 0, 0,
FS_FILE_FLAGS_HEADER_INCLUDED | FS_FILE_FLAGS_HEADER_PERSISTENT, } };
struct fsdata_file file_favicon_ico[] = { { file_board_jpg, favicon_name, 0, 0,
FS_FILE_FLAGS_HEADER_INCLUDED | FS_FILE_FLAGS_HEADER_PERSISTENT, } };
#define FS_ROOT file_favicon_ico
#define FS_NUMFILES 5
void web_resource_prepare(void) {
file_adc_info_html->data = FileTab[0].Start;
file_adc_info_html->len = (uint32_t)FileTab[1].Start-(uint32_t)FileTab[0].Start;
file_led_info_html->data = FileTab[1].Start;
file_led_info_html->len = (uint32_t)FileTab[2].Start-(uint32_t)FileTab[1].Start;
file_homepage_html->data = FileTab[2].Start;
file_homepage_html->len = (uint32_t)FileTab[3].Start-(uint32_t)FileTab[2].Start;
file_board_jpg->data = FileTab[3].Start;
file_board_jpg->len = (uint32_t)FileTab[4].Start-(uint32_t)FileTab[3].Start;
file_favicon_ico->data = FileTab[4].Start;
file_favicon_ico->len = (uint32_t)FileTab[5].Start-(uint32_t)FileTab[4].Start;
printf("%s %p %u\n", file_adc_info_html->name, file_adc_info_html->data, file_adc_info_html->len);
printf("%s %p %u\n", file_led_info_html->name, file_led_info_html->data, file_led_info_html->len);
printf("%s %p %u\n", file_homepage_html->name, file_homepage_html->data, file_homepage_html->len);
printf("%s %p %u\n", file_board_jpg->name, file_board_jpg->data, file_board_jpg->len);
printf("%s %p %u\n", file_favicon_ico->name, file_favicon_ico->data, file_favicon_ico->len);
}
这样,后面如果还需要修改网页文件,可以方便地使用脚本更新资源.本次分享结束,谢谢阅读.
代码放在github上供参考.
https://github.com/zhanzr/at32-start-f407.git
|
共1人点赞
|