Pico W má na sobě wifi kartu, ale nemá operační systém. Přesněji, nemá síťové vlastnosti operačního systému jako Linux. Musíme proto při programování spoléhat na knihovny a doufat, že budeme mí stejné výsledky jako na Linuxu.
V Pico SDK máme k dispozici ovladač pro wifi kartu cyw43_driver, dále pico_cyw43_arch, pico_lwip a pico_mbedtls.
Toto jsou nízkoúrovňové knihovny a je docela těžké s nimi pracovat i pokud jste síťový programátor seznámený s síťovým API, třeba sockety.
Tato část by vám měla pomoci zaplnit mezery v dokumentaci a ukázat některé příklady.
Cílem není jenom vytvořit třeba síťového TCP klienta, ale i rozumnět tomu, jak to všechno funguje.
Rozpracovaný dokument
Toto je rozpracovaný překlad z angličtiny, dokud to nebude hotové, můžete používat originální anglický text Master the Raspberry Pi Pico in C: Wifi with iwIP & mbedtls. Až budu mít překlad hotov, tento odstavec zmizí.
Architektura WiFi
Pico W má k dispozici dvě knihovny, pomocí nichž můžeme wifi používat, aniž bychom příliš zabředávali na základní úroveň programování hardwaru. Tyto knihovny můžeme považovat za základ, který má tři úrovně.
Na nejnižší úrovni je cyw43_driver, což je ovladač hardwaru a poskytuje SPI rozhraní, kterým je Pico spojeno s CYW43439 obvodem.
V mnoha případech nemusíme funkce toho ovladače používat, protože si vystačíme s vyšší úrovní, kterou nám poskytuje pico_cyw43_arch.
pico_cyw43_arch je knihovna vyšší úrovně, jejíž funkce se týkají převážně nastavení parametrů rádia a navázání spojení.
Je dobře dokumentována a odtud začneme.
pico_lwip další knihovna vyšší úrovně, je to množství funkcí, které nám umožňují pracovat s lwIP (A Lightweight TCP/IP stack), svobodnou implementací TCP/IP protokolu pro malá zařízení.
Není mnoho dokumentace o této knihovně, ale naštěstí je lwIP popsán v dokuemtaci docela dobře.
pico_lwip poskytuje řadu funkcí pro práci s vyššími protokoly postavenými nad IP (Internet Protocol), jako je TCP (Transmission Control Protokol), UDP (User Datagram Protocol), DNS (Domain Name System) atd.
Jakmile bude Pico W radiově připojeno, tak budeme používat převážně funkce z knihovny pico_lwip.
Ovladač CYW43439
Pico W používá obvod Infineon CYW43439, což je dvojice ARM procesorů, která je připojena k Picu pomocí jednoduché třívodičové SPI sběrnice. Obvod umí Wifi 4 (802.11n) v pásmu 2.4 GHz a také Bluetooth.

Jak to vypadá je ukázáno v oficiální dokumentaci Pico W Datasheet na straně 23:

Obvod CYW43439 má 4bitovou sběrnici Secure Digital Input Output (SDIO), která pochází z SD karet. SDIO sběrnice je rozšíření SPI protokolu, které používá přídavné datové linky. U SD karet se obvykle používá Quad nebo 4bit režim, někdy se nazývá QSPI (Quad SPI), existují však i 2bitové a 1bitové režimy a dvoulinkový SPI režim. To nejsou opravdové SPI sběrnice, protože datové linky jsou obousměrné. Obvod CYW43439 používá SPI sběrnici, ale režim sběrnice použitý v Picu je SD 1bitový, který používá jednu obousměrnou datovou linku.
Ovladač, který najdete v adresáři pico-sdk/lib/cyw43-driver má dva binární soubory (bloby), které obsahují program, nahrávaný do obvodu CYW43439.
Dále zde najdete Céčkový kód pro čtení a zápis dat na SPI sběrnici a do některých registrů.
Ovladač nepoužívá příslušné piny SPI sběrnice v režimu GPIO, ale používá je jako programovatelné vstupně výstupní PIO piny. To znamená, že byste neměli používat stejné piny pro GPIO (to ani nejde) a stejný PIO, jako používá wifi ovladač. Jaký PIO je použit se nastavuje v:
#define CYW43_SPI_PIO_PREFERRED_PIO 1
Implicitně se používá PIO 1, můžeme to přenastavit, ale je lepší používat ve svém programu raději PIO 0.
Ovladač používá jeden stavový automat a 10 bajtů instrukční paměti.
Potřebujete-li používat PIO 1 v volné instrukční paměti, můžete zjistil volný stavový automat pomocí pio_claim_unused_sm.
Modul cyw43_ll — dokumentace
Ovladač používá nízkoúrovňový modul cyw43_ll, který pracuje přímo s hardwarem.
Pokud se chcete dozvědět více, podívejte se do zdrojového kódu v souborech:
pico-sdk/lib/cyw43-driver/src/cyw43_ll.h
pico-sdk/lib/cyw43-driver/src/cyw43_ll.c
Mnoho funkcí je dokumentováno, ale je poměrně obtížné je používat, dokud nemáte kompletní přehled o tom jak pracuje Wifi na Picu kvůli tomu, že je složité najít význam jednotlivých konfiguračních parametrů.
Ovladač má množství funkcí, které můžete používat, ale používají je převážně vyšší vrstvy. Hlavní důvod dokumentace je v tom, abyste mohli debugovat nízkoúrovňové problémy.
Mnoho z nich používá stav self jako ukazatel na strukturu cyw43_t.
Když dovolíte provést inicializaci přímo driveru, naleznete globální proměnnou cyw43_state definovanou v:
pico-sdk/lib/cyw43-driver/src/cyw43_ctrl.c
To znamená, že můžete použít cyw43_state kdykoliv, když uvidíte v definici funkce self.
Podobně můžete použít CYW43_ITF_STA nebo CYW43_ITF_AP kdykoliv uvidíte parametr itf v nastavení režimu klienta nebo AP.
typedef struct _cyw43_t {
cyw43_ll_t cyw43_ll;
uint8_t itf_state;
uint32_t trace_flags;
// State for async events
volatile uint32_t wifi_scan_state;
uint32_t wifi_join_state;
void *wifi_scan_env;
int (*wifi_scan_cb)(void *, const cyw43_ev_scan_result_t *);
bool initted;
// Pending things to do
bool pend_disassoc;
bool pend_rejoin;
bool pend_rejoin_wpa;
// AP settings
uint32_t ap_auth;
uint8_t ap_channel;
uint8_t ap_ssid_len;
uint8_t ap_key_len;
uint8_t ap_ssid[32];
uint8_t ap_key[64];
#if CYW43_LWIP
// lwIP data
struct netif netif[2];
#if LWIP_IPV4 && LWIP_DHCP
struct dhcp dhcp_client;
#endif
#endif
#if CYW43_NETUTILS
dhcp_server_t dhcp_server;
#endif
// mac from otp (or from cyw43_hal_generate_laa_mac if not set)
uint8_t mac[6];
#if CYW43_ENABLE_BLUETOOTH
bool bt_loaded;
#endif
} cyw43_t;
Inicializace a navázání spojení
-
void cyw43_init( *self )
inicializuje ovladač -
void cyw43_deinit( *self )
ukončí ovladač -
void cyw43_wifi_set_up( *self, itf, up, country )
nastaví a inicializuje WiFi, kde parametrup(bool) řídí režim,1nebotrueznamená AP,0falseSTA.
countryje nastavení WiFi z hlediska země používání, pro nás platíCYW43_COUNTRY_CZECH_REPUBLIC.
Seznam všech zemí je vpiso-sdk/lib/cyw43-driver/src/cyw43_country.h. -
int cyw43_wifi_join(*self, ssid_len, *ssid, key_len, *key, auth_type, *bssid, channel)připojí se do WiFi sítě v módu STA, kdessidje Service Set IDentifier, za použítí klíčekeyaauth_typemůže být jeden z:-
CYW43_AUTH_OPEN -
CYW43_AUTH_WPA_TKIP_PSK -
CYW43_AUTH_WPA2_AES_PSK -
CYW43_AUTH_WPA2_MIXED_PSK
bssidje buďNULLnebo MAC adresa AP achannelje pásmo pokud jebssidnastaveno.
-
-
int cyw43 wifi_leave(*self, itf)
odpojí se z WiFi sítě -
void cyw43_cb_tcpip_init(*self, itf)
inicializuje IP protokol -
void cyw43_cb_tcpip_deinit(*self, itf)
ukončí IP protokol -
void cyw43_cb_tcpip_set_link_up(*self, itf)
upozorní IP protokol, že spojení je navázáno (link up) -
void cyw43_cb_tcpip_set_link_down(*self, itf)
upozorní IP protokol, že spojení je ztraceno (link down)
Zjišťování stavu
-
bool cyw43_is_initialized(*self)
zjistí, zda byl ovladačcyw43inicializován -
int cyw43_wifi_link_status (*self, itf)
vrací stav WiFi linky, což může být:-
CYw43_LINK_DOWN— WiFi spadla -
CYW43_LINK_JOIN— připojeno k WiFi -
CYW43_LINK_FAIL— připojování selhalo -
CYW43_LINK_NONET— nenalezeno SSID (může být nedostupné anebo spadlo) -
CYW43_LINK_BADAUTH— chyba autentizace
-
-
int cyw43_tcpip_link_status(*self, itf)
vrací stav linky, což může být pět předchozích stavů a:-
CYW43_LINK_NOIP— připojeno k WiFi bez IP adresy -
CYW43_LINK_UP— připojeno k WiFi máme IP adresu
-
-
int cyw43_wifi_get_mac (*self, itf, mac[6])
vrací MAC adresu zařízení v 6 bajtovém poli -
cyw43_wifi_get_rssi(*self, uint32_t *rssi)
vrací sílu signálu RSSI u navázaného spojení
Ovládání napájení (power management)
-
int cyw43_wifi_pm(*self, pm)
nastavuje šetření energií podle parametrupm(int), hodnotapmje počítána pomocnou funkcí. -
uint32_t cyw43_pm_value(pm_mode, pm2_sleep_ret_ms, li_beacon_period, li_dtim_period, li_assoc)
kdepm_modejedna z:-
CYW43_NO_POWERSAVE_MODEbez šetření energie -
CYW43_PM1_POWERSAVE_MODEvelké šetření energie, které omezuje propustnost WiFi -
CYW43_PM2_POWERSAVE_MODEšetření energie bez ztráty propustnosti (preferované), šetří energi jenom pokud je WiFi nějaký čas neaktivní
pm2_sleep_ret_msmaximum time to wait before going back to sleep for CYw43_PM2_POWERSAVE MODE mode measured in milliseconds and must be between 10 and 2000ms and divisible by 10
li_beacon_periodwake interval measured in beacon periods
li_dtim_periodwake interval measured in DTIMs; if set to 0, the wake interval is measured in beacon periods
li_assocWake interval sent to the access point
-
Tři předdefinované režimy šetření energie:
-
CYW43_DEFAULT_PMcyw43_pm_value(CYW43_PM2_POWERSAVE_MODE, 200, 1, 1, 10)
implicitní režim -
CYW43_AGGRESSIVE_PMcyw43_pm_value(CYW43_PM2_POWERSAVE_MODE, 2000, 1, 1, 10)
silně šetřící režim za cenu nižší propustnosti Wifi -
CYW43_PERFORMANCE_PMcyw43_pm_value(CYW43_PM2_POWERSAVE MODE, 20, 1, 1, 1)
menší setření energií s větším příkonem, aby byla lepší propustnost Wifi