spi_wifi_rw009.c 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602
  1. /*
  2. * File : spi_wifi_rw009.c
  3. * This file is part of RT-Thread RTOS
  4. * Copyright by Shanghai Real-Thread Electronic Technology Co.,Ltd
  5. *
  6. * This program is free software; you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as published by
  8. * the Free Software Foundation; either version 2 of the License, or
  9. * (at your option) any later version.
  10. *
  11. * This program is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License along
  17. * with this program; if not, write to the Free Software Foundation, Inc.,
  18. * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  19. *
  20. * Change Logs:
  21. * Date Author Notes
  22. * 2014-07-31 aozima the first version
  23. */
  24. #include <rtthread.h>
  25. #include <drivers/spi.h>
  26. #include <netif/ethernetif.h>
  27. #include <netif/etharp.h>
  28. #include <lwip/icmp.h>
  29. #include "lwipopts.h"
  30. #include "spi_wifi_rw009.h"
  31. #define SSID_NAME "AP_SSID"
  32. #define SSID_PASSWORD "AP_passwd"
  33. // #define WIFI_DEBUG_ON
  34. // #define ETH_RX_DUMP
  35. // #define ETH_TX_DUMP
  36. #ifdef WIFI_DEBUG_ON
  37. #define WIFI_DEBUG rt_kprintf("[WIFI] ");rt_kprintf
  38. #else
  39. #define WIFI_DEBUG(...)
  40. #endif /* #ifdef WIFI_DEBUG_ON */
  41. #define MAX_BUFFER_SIZE (sizeof(struct response) + MAX_DATA_LEN)
  42. #define MAX_ADDR_LEN 6
  43. struct spi_wifi_eth
  44. {
  45. /* inherit from ethernet device */
  46. struct eth_device parent;
  47. struct rt_spi_device *rt_spi_device;
  48. /* interface address info. */
  49. rt_uint8_t dev_addr[MAX_ADDR_LEN]; /* hw address */
  50. rt_uint8_t active;
  51. struct rt_mempool spi_tx_mp;
  52. struct rt_mempool spi_rx_mp;
  53. struct rt_mailbox spi_tx_mb;
  54. struct rt_mailbox eth_rx_mb;
  55. int spi_tx_mb_pool[SPI_TX_POOL_SIZE + 1];
  56. int eth_rx_mb_pool[SPI_RX_POOL_SIZE + 1];
  57. int spi_wifi_cmd_mb_pool[3];
  58. struct rt_mailbox spi_wifi_cmd_mb;
  59. ALIGN(4)
  60. rt_uint8_t spi_tx_mempool[(sizeof(struct spi_data_packet) + 4) * SPI_TX_POOL_SIZE];
  61. ALIGN(4)
  62. rt_uint8_t spi_rx_mempool[(sizeof(struct spi_data_packet) + 4) * SPI_RX_POOL_SIZE];
  63. ALIGN(4)
  64. uint8_t spi_hw_rx_buffer[MAX_BUFFER_SIZE];
  65. };
  66. static struct spi_wifi_eth spi_wifi_device;
  67. static struct rt_event spi_wifi_data_event;
  68. static void resp_handler(struct spi_wifi_eth *wifi_device, struct spi_wifi_resp *resp)
  69. {
  70. struct spi_wifi_resp *resp_return;
  71. switch (resp->cmd)
  72. {
  73. case SPI_WIFI_CMD_INIT:
  74. WIFI_DEBUG("resp_handler SPI_WIFI_CMD_INIT\n");
  75. resp_return = (struct spi_wifi_resp *)rt_malloc(sizeof(struct spi_wifi_resp)); //TODO:
  76. memcpy(resp_return, resp, 10);
  77. rt_mb_send(&wifi_device->spi_wifi_cmd_mb, (rt_uint32_t)resp_return);
  78. break;
  79. case SPI_WIFI_CMD_SCAN:
  80. WIFI_DEBUG("resp_handler SPI_WIFI_CMD_SCAN\n");
  81. break;
  82. case SPI_WIFI_CMD_JOIN:
  83. WIFI_DEBUG("resp_handler SPI_WIFI_CMD_JOIN\n");
  84. wifi_device->active = 1;
  85. eth_device_linkchange(&wifi_device->parent, RT_TRUE);
  86. break;
  87. default:
  88. WIFI_DEBUG("resp_handler %d\n", resp->cmd);
  89. break;
  90. }
  91. }
  92. static rt_err_t spi_wifi_transfer(struct spi_wifi_eth *dev)
  93. {
  94. struct pbuf *p = RT_NULL;
  95. struct cmd_request cmd;
  96. struct response resp;
  97. rt_err_t result;
  98. const struct spi_data_packet *data_packet = RT_NULL;
  99. struct spi_wifi_eth *wifi_device = (struct spi_wifi_eth *)dev;
  100. struct rt_spi_device *rt_spi_device = wifi_device->rt_spi_device;
  101. spi_wifi_int_cmd(0);
  102. while (spi_wifi_is_busy());
  103. WIFI_DEBUG("sequence start!\n");
  104. memset(&cmd, 0, sizeof(struct cmd_request));
  105. cmd.magic1 = CMD_MAGIC1;
  106. cmd.magic2 = CMD_MAGIC2;
  107. cmd.flag |= CMD_FLAG_MRDY;
  108. result = rt_mb_recv(&wifi_device->spi_tx_mb,
  109. (rt_uint32_t *)&data_packet,
  110. 0);
  111. if ((result == RT_EOK) && (data_packet != RT_NULL) && (data_packet->data_len > 0))
  112. {
  113. cmd.M2S_len = data_packet->data_len + member_offset(struct spi_data_packet, buffer);
  114. //WIFI_DEBUG("cmd.M2S_len = %d\n", cmd.M2S_len);
  115. }
  116. rt_spi_send(rt_spi_device, &cmd, sizeof(cmd));
  117. while (spi_wifi_is_busy());
  118. {
  119. struct rt_spi_message message;
  120. uint32_t max_data_len = 0;
  121. /* setup message */
  122. message.send_buf = RT_NULL;
  123. message.recv_buf = &resp;
  124. message.length = sizeof(resp);
  125. message.cs_take = 1;
  126. message.cs_release = 0;
  127. rt_spi_take_bus(rt_spi_device);
  128. /* transfer message */
  129. rt_spi_device->bus->ops->xfer(rt_spi_device, &message);
  130. if ((resp.magic1 != RESP_MAGIC1) || (resp.magic2 != RESP_MAGIC2))
  131. {
  132. WIFI_DEBUG("bad resp magic, abort!\n");
  133. goto _bad_resp_magic;
  134. }
  135. if (resp.flag & RESP_FLAG_SRDY)
  136. {
  137. WIFI_DEBUG("RESP_FLAG_SRDY\n");
  138. max_data_len = cmd.M2S_len;
  139. }
  140. if (resp.S2M_len)
  141. {
  142. WIFI_DEBUG("resp.S2M_len: %d\n", resp.S2M_len);
  143. if (resp.S2M_len > MAX_SPI_PACKET_SIZE)
  144. {
  145. WIFI_DEBUG("resp.S2M_len %d > %d(MAX_SPI_PACKET_SIZE), drop!\n", resp.S2M_len, MAX_SPI_PACKET_SIZE);
  146. resp.S2M_len = 0;//drop
  147. }
  148. if (resp.S2M_len > max_data_len)
  149. max_data_len = resp.S2M_len;
  150. }
  151. if (max_data_len == 0)
  152. {
  153. WIFI_DEBUG("no rx or tx data!\n");
  154. }
  155. //WIFI_DEBUG("max_data_len = %d\n", max_data_len);
  156. _bad_resp_magic:
  157. /* setup message */
  158. message.send_buf = data_packet;//&tx_buffer;
  159. message.recv_buf = wifi_device->spi_hw_rx_buffer;//&rx_buffer;
  160. message.length = max_data_len;
  161. message.cs_take = 0;
  162. message.cs_release = 1;
  163. /* transfer message */
  164. rt_spi_device->bus->ops->xfer(rt_spi_device, &message);
  165. rt_spi_release_bus(rt_spi_device);
  166. if (cmd.M2S_len && (resp.flag & RESP_FLAG_SRDY))
  167. {
  168. rt_mp_free((void *)data_packet);
  169. }
  170. if ((resp.S2M_len) && (resp.S2M_len <= MAX_SPI_PACKET_SIZE))
  171. {
  172. data_packet = (struct spi_data_packet *)wifi_device->spi_hw_rx_buffer;
  173. if (data_packet->data_type == data_type_eth_data)
  174. {
  175. if (wifi_device->active)
  176. {
  177. p = pbuf_alloc(PBUF_LINK, data_packet->data_len, PBUF_RAM);
  178. pbuf_take(p, (rt_uint8_t *)data_packet->buffer, data_packet->data_len);
  179. rt_mb_send(&wifi_device->eth_rx_mb, (rt_uint32_t)p);
  180. eth_device_ready((struct eth_device *)dev);
  181. }
  182. else
  183. {
  184. WIFI_DEBUG("!active, RX drop.\n");
  185. }
  186. }
  187. else if (data_packet->data_type == data_type_resp)
  188. {
  189. WIFI_DEBUG("data_type_resp\n");
  190. resp_handler(dev, (struct spi_wifi_resp *)data_packet->buffer);
  191. }
  192. else
  193. {
  194. WIFI_DEBUG("data_type: %d, %dbyte\n",
  195. data_packet->data_type,
  196. data_packet->data_len);
  197. }
  198. }
  199. }
  200. spi_wifi_int_cmd(1);
  201. WIFI_DEBUG("sequence finish!\n\n");
  202. if ((cmd.M2S_len == 0) && (resp.S2M_len == 0))
  203. {
  204. return -RT_ERROR;
  205. }
  206. return RT_EOK;
  207. }
  208. #if defined(ETH_RX_DUMP) || defined(ETH_TX_DUMP)
  209. static void packet_dump(const char *msg, const struct pbuf *p)
  210. {
  211. const struct pbuf* q;
  212. rt_uint32_t i,j;
  213. rt_uint8_t *ptr = p->payload;
  214. rt_kprintf("%s %d byte\n", msg, p->tot_len);
  215. i=0;
  216. for(q=p; q != RT_NULL; q= q->next)
  217. {
  218. ptr = q->payload;
  219. for(j=0; j<q->len; j++)
  220. {
  221. if( (i%8) == 0 )
  222. {
  223. rt_kprintf(" ");
  224. }
  225. if( (i%16) == 0 )
  226. {
  227. rt_kprintf("\r\n");
  228. }
  229. rt_kprintf("%02x ",*ptr);
  230. i++;
  231. ptr++;
  232. }
  233. }
  234. rt_kprintf("\n\n");
  235. }
  236. #endif /* dump */
  237. /* initialize the interface */
  238. static rt_err_t spi_wifi_eth_init(rt_device_t dev)
  239. {
  240. return RT_EOK;
  241. }
  242. static rt_err_t spi_wifi_eth_open(rt_device_t dev, rt_uint16_t oflag)
  243. {
  244. return RT_EOK;
  245. }
  246. static rt_err_t spi_wifi_eth_close(rt_device_t dev)
  247. {
  248. return RT_EOK;
  249. }
  250. static rt_size_t spi_wifi_eth_read(rt_device_t dev, rt_off_t pos, void *buffer, rt_size_t size)
  251. {
  252. rt_set_errno(-RT_ENOSYS);
  253. return 0;
  254. }
  255. static rt_size_t spi_wifi_eth_write(rt_device_t dev, rt_off_t pos, const void *buffer, rt_size_t size)
  256. {
  257. rt_set_errno(-RT_ENOSYS);
  258. return 0;
  259. }
  260. static rt_err_t spi_wifi_eth_control(rt_device_t dev, rt_uint8_t cmd, void *args)
  261. {
  262. struct spi_wifi_eth *wifi_device = (struct spi_wifi_eth *)dev;
  263. struct spi_data_packet *data_packet;
  264. struct spi_wifi_cmd *wifi_cmd;
  265. struct spi_wifi_resp *resp;
  266. switch (cmd)
  267. {
  268. case NIOCTL_GADDR:
  269. memcpy(args, wifi_device->dev_addr, 6);
  270. break;
  271. case SPI_WIFI_CMD_INIT:
  272. /* get mac address */
  273. if (args)
  274. {
  275. rt_err_t result;
  276. data_packet = (struct spi_data_packet *)rt_mp_alloc(&wifi_device->spi_tx_mp, RT_WAITING_FOREVER);
  277. // TODO: check result.
  278. wifi_cmd = (struct spi_wifi_cmd *)data_packet->buffer;
  279. wifi_cmd->cmd = SPI_WIFI_CMD_INIT;
  280. data_packet->data_type = data_type_cmd;
  281. data_packet->data_len = member_offset(struct spi_wifi_cmd, buffer) + 0;
  282. rt_mb_send(&wifi_device->spi_tx_mb, (rt_uint32_t)data_packet);
  283. rt_event_send(&spi_wifi_data_event, 1);
  284. result = rt_mb_recv(&wifi_device->spi_wifi_cmd_mb,
  285. (rt_uint32_t *)&resp,
  286. RT_WAITING_FOREVER);
  287. if ((result == RT_EOK) && (resp != RT_NULL))
  288. {
  289. WIFI_DEBUG("resp cmd: %d\n", resp->cmd);
  290. rt_memcpy(args, resp->buffer, 6);
  291. }
  292. }
  293. else return -RT_ERROR;
  294. break;
  295. case SPI_WIFI_CMD_SCAN:
  296. case SPI_WIFI_CMD_JOIN:
  297. if (args)
  298. {
  299. struct cmd_join *cmd_join;
  300. data_packet = (struct spi_data_packet *)rt_mp_alloc(&wifi_device->spi_tx_mp, RT_WAITING_FOREVER);
  301. wifi_cmd = (struct spi_wifi_cmd *)data_packet->buffer;
  302. wifi_cmd->cmd = SPI_WIFI_CMD_JOIN;
  303. cmd_join = (struct cmd_join *)wifi_cmd->buffer;
  304. #define WPA_SECURITY 0x00200000
  305. #define WPA2_SECURITY 0x00400000
  306. #define TKIP_ENABLED 0x0002
  307. #define AES_ENABLED 0x0004
  308. strncpy(cmd_join->ssid, SSID_NAME, SSID_NAME_LENGTH_MAX);
  309. strncpy(cmd_join->passwd, SSID_PASSWORD, PASSWORD_LENGTH_MAX);
  310. cmd_join->security = WPA_SECURITY | TKIP_ENABLED | AES_ENABLED;
  311. // cmd_join->security = WPA_SECURITY | TKIP_ENABLED;
  312. data_packet->data_type = data_type_cmd;
  313. data_packet->data_len = sizeof(struct cmd_join) + member_offset(struct spi_wifi_cmd, buffer);
  314. rt_mb_send(&wifi_device->spi_tx_mb, (rt_uint32_t)data_packet);
  315. rt_event_send(&spi_wifi_data_event, 1);
  316. }
  317. else return -RT_ERROR;
  318. break;
  319. default :
  320. break;
  321. }
  322. return RT_EOK;
  323. }
  324. /* transmit packet. */
  325. rt_err_t spi_wifi_eth_tx(rt_device_t dev, struct pbuf *p)
  326. {
  327. rt_err_t result = RT_EOK;
  328. struct spi_data_packet *data_packet;
  329. struct spi_wifi_eth *wifi_device = (struct spi_wifi_eth *)dev;
  330. if (!wifi_device->active)
  331. {
  332. WIFI_DEBUG("!active, TX drop!\n");
  333. return RT_EOK;
  334. }
  335. /* get free tx buffer */
  336. data_packet = (struct spi_data_packet *)rt_mp_alloc(&wifi_device->spi_tx_mp, RT_WAITING_FOREVER);
  337. if (data_packet != RT_NULL)
  338. {
  339. data_packet->data_type = data_type_eth_data;
  340. data_packet->data_len = p->tot_len;
  341. pbuf_copy_partial(p, data_packet->buffer, data_packet->data_len, 0);
  342. rt_mb_send(&wifi_device->spi_tx_mb, (rt_uint32_t)data_packet);
  343. rt_event_send(&spi_wifi_data_event, 1);
  344. }
  345. else
  346. return -RT_ERROR;
  347. #ifdef ETH_TX_DUMP
  348. packet_dump("TX dump", p);
  349. #endif /* ETH_TX_DUMP */
  350. /* Return SUCCESS */
  351. return result;
  352. }
  353. /* reception packet. */
  354. struct pbuf *spi_wifi_eth_rx(rt_device_t dev)
  355. {
  356. struct pbuf *p = RT_NULL;
  357. struct spi_wifi_eth *wifi_device = (struct spi_wifi_eth *)dev;
  358. if (rt_mb_recv(&wifi_device->eth_rx_mb, (rt_uint32_t *)&p, 0) != RT_EOK)
  359. {
  360. return RT_NULL;
  361. }
  362. #ifdef ETH_RX_DUMP
  363. if(p)
  364. packet_dump("RX dump", p);
  365. #endif /* ETH_RX_DUMP */
  366. return p;
  367. }
  368. static void spi_wifi_data_thread_entry(void *parameter)
  369. {
  370. rt_uint32_t e;
  371. rt_err_t result;
  372. while (1)
  373. {
  374. /* receive first event */
  375. if (rt_event_recv(&spi_wifi_data_event,
  376. 1,
  377. RT_EVENT_FLAG_AND | RT_EVENT_FLAG_CLEAR,
  378. RT_WAITING_FOREVER,
  379. &e) != RT_EOK)
  380. {
  381. continue;
  382. }
  383. result = spi_wifi_transfer(&spi_wifi_device);
  384. if (result == RT_EOK)
  385. {
  386. rt_event_send(&spi_wifi_data_event, 1);
  387. }
  388. }
  389. }
  390. rt_err_t rt_hw_wifi_init(const char *spi_device_name)
  391. {
  392. memset(&spi_wifi_device, 0, sizeof(struct spi_wifi_eth));
  393. spi_wifi_device.rt_spi_device = (struct rt_spi_device *)rt_device_find(spi_device_name);
  394. if (spi_wifi_device.rt_spi_device == RT_NULL)
  395. {
  396. WIFI_DEBUG("spi device %s not found!\r\n", spi_device_name);
  397. return -RT_ENOSYS;
  398. }
  399. /* config spi */
  400. {
  401. struct rt_spi_configuration cfg;
  402. cfg.data_width = 8;
  403. cfg.mode = RT_SPI_MODE_0 | RT_SPI_MSB; /* SPI Compatible: Mode 0. */
  404. cfg.max_hz = 15 * 1000000; /* 30M */
  405. rt_spi_configure(spi_wifi_device.rt_spi_device, &cfg);
  406. }
  407. spi_wifi_device.parent.parent.init = spi_wifi_eth_init;
  408. spi_wifi_device.parent.parent.open = spi_wifi_eth_open;
  409. spi_wifi_device.parent.parent.close = spi_wifi_eth_close;
  410. spi_wifi_device.parent.parent.read = spi_wifi_eth_read;
  411. spi_wifi_device.parent.parent.write = spi_wifi_eth_write;
  412. spi_wifi_device.parent.parent.control = spi_wifi_eth_control;
  413. spi_wifi_device.parent.parent.user_data = RT_NULL;
  414. spi_wifi_device.parent.eth_rx = spi_wifi_eth_rx;
  415. spi_wifi_device.parent.eth_tx = spi_wifi_eth_tx;
  416. rt_mp_init(&spi_wifi_device.spi_tx_mp,
  417. "spi_tx",
  418. &spi_wifi_device.spi_tx_mempool[0],
  419. sizeof(spi_wifi_device.spi_tx_mempool),
  420. sizeof(struct spi_data_packet));
  421. rt_mp_init(&spi_wifi_device.spi_rx_mp,
  422. "spi_rx",
  423. &spi_wifi_device.spi_rx_mempool[0],
  424. sizeof(spi_wifi_device.spi_rx_mempool),
  425. sizeof(struct spi_data_packet));
  426. rt_mb_init(&spi_wifi_device.spi_tx_mb,
  427. "spi_tx",
  428. &spi_wifi_device.spi_tx_mb_pool[0],
  429. SPI_TX_POOL_SIZE,
  430. RT_IPC_FLAG_PRIO);
  431. rt_mb_init(&spi_wifi_device.eth_rx_mb,
  432. "eth_rx",
  433. &spi_wifi_device.eth_rx_mb_pool[0],
  434. SPI_TX_POOL_SIZE,
  435. RT_IPC_FLAG_PRIO);
  436. rt_mb_init(&spi_wifi_device.spi_wifi_cmd_mb,
  437. "wifi_cmd",
  438. &spi_wifi_device.spi_wifi_cmd_mb_pool[0],
  439. sizeof(spi_wifi_device.spi_wifi_cmd_mb_pool) / 4,
  440. RT_IPC_FLAG_PRIO);
  441. rt_event_init(&spi_wifi_data_event, "wifi", RT_IPC_FLAG_FIFO);
  442. spi_wifi_hw_init();
  443. {
  444. rt_thread_t tid;
  445. tid = rt_thread_create("wifi",
  446. spi_wifi_data_thread_entry,
  447. RT_NULL,
  448. 2048,
  449. RT_THREAD_PRIORITY_MAX - 2,
  450. 20);
  451. if (tid != RT_NULL)
  452. rt_thread_startup(tid);
  453. }
  454. /* init: get mac address */
  455. {
  456. WIFI_DEBUG("wifi_control SPI_WIFI_CMD_INIT\n");
  457. spi_wifi_eth_control((rt_device_t)&spi_wifi_device,
  458. SPI_WIFI_CMD_INIT,
  459. (void *)&spi_wifi_device.dev_addr[0]);
  460. }
  461. /* register eth device */
  462. eth_device_init(&(spi_wifi_device.parent), "w0");
  463. eth_device_linkchange(&spi_wifi_device.parent, RT_FALSE);
  464. {
  465. WIFI_DEBUG("wifi_control SPI_WIFI_CMD_JOIN\n");
  466. spi_wifi_eth_control((rt_device_t)&spi_wifi_device,
  467. SPI_WIFI_CMD_JOIN,
  468. (void *)&spi_wifi_device.dev_addr[0]);
  469. WIFI_DEBUG("wifi_control exit\n");
  470. }
  471. return RT_EOK;
  472. }
  473. void spi_wifi_isr(int vector)
  474. {
  475. /* enter interrupt */
  476. rt_interrupt_enter();
  477. WIFI_DEBUG("spi_wifi_isr\n");
  478. rt_event_send(&spi_wifi_data_event, 1);
  479. /* leave interrupt */
  480. rt_interrupt_leave();
  481. }