前几天见看到网友用STM32跑WIFI,觉得这东西很有意思,所以自己也想开始搞一个。
由于刚刚开始现在只发送命令扫描无线节点 ,所以想开个帖子记录一下开发过程。虽然还没搞好,但是既然有网友搞通过因此我也还是很有信心的,希望能坚持走下去,同时也希望大家多多讨论。
我采用的方案同样也是STM32 + Marvell88w8686 的组合。
通讯方式采用SPI方式,虽然比SDIO慢了许多,但是调试和接线比较方便。
目前已经实现了固件的下载和CMD命令发送。
固件下载主要参考linux下的if_spi.c中固件下载和手册中的固件下载部分
1.首先将设备引导代码写入IF_SPI_CMD_WRITEBASE_REG(0x14)寄存器
2.设置IF_SPI_CARD_INT_STATUS_REG寄存器时期进入等待固件下载状态
3.等待IF_SPI_CARD_INT_STATUS_REG寄存器返回
4.将固件数据写入命令读写寄存器(0x18)中
5.err = spu_write_u16(card, IF_SPI_HOST_INT_STATUS_REG, 0);清空寄存器
上面几个步骤是下载第一个固件也就是helper.bin的一个大致流程,详细的可以参考if_spi_prog_helper_firmware函数,其实移植起来也是相当简单的。
接下来就是下载第二个固件和检查固件是否成功并运行。也就是校验0x38寄存器中是不是0x88888888。
若固件校验下载成功并运行下面的工作就相对流程化了,但是工作量可不小哦。
大致上可分为CMD的发送和接收与数据的发送和接收
命令的发送主要是由802.11控制协议转换成8686的控制命令,其数据结构基本上都在host.h中
struct cmd_ds_802_11_scan {
struct cmd_header hdr;
uint8_t bsstype;
uint8_t bssid[ETH_ALEN];
uint8_t tlvbuffer[0];
} __packed;
struct cmd_ds_802_11_scan_rsp {
struct cmd_header hdr;
__le16 bssdescriptsize;
uint8_t nr_sets;
uint8_t bssdesc_and_tlvbuffer[0];
} __packed;
是扫描命令的发送和接收的数据结构。
数据的发送和接受没什么说的,也就是普通的802.3包,LINUX驱动中tx.c中lbs_process_rxed_packet 函数将其转换成sk_buff来交与LINUX网络子系统进行处理
在8686的LINUX驱动大致过程为:
lbs_spi_thread 一个SPI线程负责while(1)轮训卡上是否有读取的CMD或者DATA,如果是DATA将调用if_spi_c2h_data如果是CMD将调用if_spi_c2h_cmd
if_spi_c2h_data 函数负责将卡中的数据转到主机中,然后调用lbs_process_rxed_packet
err = spu_read_u16(card, IF_SPI_SCRATCH_1_REG, &len); 读取卡中有多数据需要读取
err = spu_read(card, IF_SPI_DATA_RDWRPORT_REG, data, ALIGN(len, 4));开始读取数据
lbs_process_rxed_packet 函数负责将收到的数据转换成802.3格式的包。
lbs_thread 负责传输数据或命令的线程 ,他会调用lbs_execute_next_command或者if_spi_host_to_card(hw_host_to_card*)
if_spi_host_to_card 从主机到卡上的数据lbs_submit_command和lbs_thread都会调用他
lbs_execute_next_command 调用 lbs_submit_command
static struct cfg80211_ops lbs_cfg80211_ops = {//负责控制的OPS
lbs_process_command_response 负责处理命令的返回,通过内核线程锁来实现同步的,由lbs_thread调用,一般是在调用lbs_execute_next_command后调用
例如扫描命令的发送流程
//开始扫描
lbs_scan_worker 执行扫描命令,在其中中创建CMD命令格式,首先,分配LBS_SCAN_MAX_CMD_SIZE大小的空间
cmd_ctrl_node cmdnode 中 cmdnode->cmdbuf 是要被发送的数据cmd->size时要被发送的大小
cmd_header 在 host.h中,是命CMD的头对应PDF p62
__lbs_cmd_async 负责填充一个CMD头
lbs_add_ssid_tlv ,lbs_add_channel_list_tlv 两是构造BODY的函数
cmd_ds_802_11_scan SCAN命令的BODY