打印
[AT32F407]

【AT-START-F407测评】+ 第三篇_LWIP移植和简单网页服务器

[复制链接]
1512|4
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
本帖最后由 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



使用特权

评论回复
沙发
forgot| | 2023-1-4 17:18 | 只看该作者
巧了我也是F407的板子,准备这两天搞一下,评测都快截止了,着急

使用特权

评论回复
板凳
caigang13| | 2023-1-5 08:13 | 只看该作者
搭建网页脚本页面比较麻烦

使用特权

评论回复
地板
zhanzr21|  楼主 | 2023-1-13 00:36 | 只看该作者
forgot 发表于 2023-1-4 17:18
巧了我也是F407的板子,准备这两天搞一下,评测都快截止了,着急

把自己学习经过写一写,不需要很复杂的文章.

使用特权

评论回复
5
zhanzr21|  楼主 | 2023-1-13 00:37 | 只看该作者
caigang13 发表于 2023-1-5 08:13
搭建网页脚本页面比较麻烦

恩恩 没办法, 主要是嵌入式系统本身限制太多, 不支持的Web功能太多.

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

个人签名:每天都進步

91

主题

1013

帖子

34

粉丝