mirror of
https://github.com/tinygo-org/drivers.git
synced 2026-08-14 20:03:40 +00:00
espnet: WIP support for on-chip WiFi on an ESP32C3
Work in progress. Does not work yet.
Some notes:
- This requires some changes to TinyGo, look at the espnet branch.
- The next step is probably defining all the functions in
g_wifi_osi_funcs (see espnet.c). Right now it hangs in
esp_wifi_init_internal, probably a NULL pointer dereference.
- This is only for the ESP32-C3. This will require some work to work
on other chips from Espressif.
This commit is contained in:
@@ -0,0 +1,3 @@
|
|||||||
|
[submodule "espnet/esp-idf"]
|
||||||
|
path = espnet/esp-idf
|
||||||
|
url = https://github.com/espressif/esp-idf.git
|
||||||
@@ -0,0 +1,40 @@
|
|||||||
|
package espnet
|
||||||
|
|
||||||
|
/*
|
||||||
|
#cgo CFLAGS: -DCONFIG_IDF_TARGET_ESP32C3
|
||||||
|
#cgo CFLAGS: -Iinclude
|
||||||
|
#cgo CFLAGS: -Iesp-idf/components/esp_common/include
|
||||||
|
#cgo CFLAGS: -Iesp-idf/components/esp_event/include
|
||||||
|
#cgo CFLAGS: -Iesp-idf/components/esp_netif/include
|
||||||
|
#cgo CFLAGS: -Iesp-idf/components/esp_wifi/include
|
||||||
|
|
||||||
|
#cgo LDFLAGS: -Lesp-idf/components/esp_wifi/lib/esp32c3 -lnet80211 -lpp -lphy -lmesh -lcore
|
||||||
|
#cgo LDFLAGS: -Tesp-idf/components/esp_rom/esp32c3/ld/esp32c3.rom.ld
|
||||||
|
|
||||||
|
#include "esp_private/wifi.h"
|
||||||
|
#include "esp_wifi_types.h"
|
||||||
|
#include "espnet.h"
|
||||||
|
*/
|
||||||
|
import "C"
|
||||||
|
|
||||||
|
type ESPWiFi struct {
|
||||||
|
}
|
||||||
|
|
||||||
|
var WiFi = &ESPWiFi{}
|
||||||
|
|
||||||
|
type Config struct {
|
||||||
|
}
|
||||||
|
|
||||||
|
var internalConfig = C.wifi_init_config_t{
|
||||||
|
osi_funcs: &C.g_wifi_osi_funcs,
|
||||||
|
}
|
||||||
|
|
||||||
|
func (wifi ESPWiFi) Configure(config Config) error {
|
||||||
|
return makeError(C.esp_wifi_init_internal(&internalConfig))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (wifi ESPWiFi) AccessPointMAC() ([6]byte, error) {
|
||||||
|
var mac [6]byte
|
||||||
|
errCode := C.esp_wifi_get_mac(C.ESP_IF_WIFI_AP, &mac[0])
|
||||||
|
return mac, makeError(errCode)
|
||||||
|
}
|
||||||
+103
@@ -0,0 +1,103 @@
|
|||||||
|
package espnet
|
||||||
|
|
||||||
|
// #include <esp_err.h>
|
||||||
|
// #include <esp_wifi.h>
|
||||||
|
import "C"
|
||||||
|
|
||||||
|
// Wrapper for C.esp_err_t. Don't convert a C.esp_err_t to an Error type,
|
||||||
|
// instead use makeError to handle ESP_OK.
|
||||||
|
type Error C.esp_err_t
|
||||||
|
|
||||||
|
// makeError converts a C.esp_err_t into an error or nil depending on whether
|
||||||
|
// errCode indicates an error or not.
|
||||||
|
func makeError(errCode C.esp_err_t) error {
|
||||||
|
if errCode == C.ESP_OK {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return Error(errCode)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e Error) Error() string {
|
||||||
|
switch {
|
||||||
|
case e < C.ESP_ERR_WIFI_BASE:
|
||||||
|
// esp-idf/components/esp_common/include/esp_err.h
|
||||||
|
switch e {
|
||||||
|
case C.ESP_OK:
|
||||||
|
return "OK" // not an error
|
||||||
|
case C.ESP_FAIL:
|
||||||
|
return "ESP FAIL"
|
||||||
|
case C.ESP_ERR_NO_MEM:
|
||||||
|
return "Out of memory"
|
||||||
|
case C.ESP_ERR_INVALID_ARG:
|
||||||
|
return "Invalid argument"
|
||||||
|
case C.ESP_ERR_INVALID_STATE:
|
||||||
|
return "Invalid state"
|
||||||
|
case C.ESP_ERR_INVALID_SIZE:
|
||||||
|
return "Invalid size"
|
||||||
|
case C.ESP_ERR_NOT_FOUND:
|
||||||
|
return "Requested resource not found"
|
||||||
|
case C.ESP_ERR_NOT_SUPPORTED:
|
||||||
|
return "Operation or feature not supported"
|
||||||
|
case C.ESP_ERR_TIMEOUT:
|
||||||
|
return "Operation timed out"
|
||||||
|
case C.ESP_ERR_INVALID_RESPONSE:
|
||||||
|
return "Received response was invalid"
|
||||||
|
case C.ESP_ERR_INVALID_CRC:
|
||||||
|
return "CRC or checksum was invalid"
|
||||||
|
case C.ESP_ERR_INVALID_VERSION:
|
||||||
|
return "Version was invalid"
|
||||||
|
case C.ESP_ERR_INVALID_MAC:
|
||||||
|
return "MAC address was invalid"
|
||||||
|
default:
|
||||||
|
return "Unknown error"
|
||||||
|
}
|
||||||
|
case e >= C.ESP_ERR_WIFI_BASE && e < C.ESP_ERR_MESH_BASE:
|
||||||
|
// esp-idf/components/esp_wifi/include/esp_wifi.h
|
||||||
|
switch e {
|
||||||
|
case C.ESP_ERR_WIFI_NOT_INIT:
|
||||||
|
return "WiFi driver was not installed by esp_wifi_init"
|
||||||
|
case C.ESP_ERR_WIFI_NOT_STARTED:
|
||||||
|
return "WiFi driver was not started by esp_wifi_start"
|
||||||
|
case C.ESP_ERR_WIFI_NOT_STOPPED:
|
||||||
|
return "WiFi driver was not stopped by esp_wifi_stop"
|
||||||
|
case C.ESP_ERR_WIFI_IF:
|
||||||
|
return "WiFi interface error"
|
||||||
|
case C.ESP_ERR_WIFI_MODE:
|
||||||
|
return "WiFi mode error"
|
||||||
|
case C.ESP_ERR_WIFI_STATE:
|
||||||
|
return "WiFi internal state error"
|
||||||
|
case C.ESP_ERR_WIFI_CONN:
|
||||||
|
return "WiFi internal control block of station or soft-AP error"
|
||||||
|
case C.ESP_ERR_WIFI_NVS:
|
||||||
|
return "WiFi internal NVS module error"
|
||||||
|
case C.ESP_ERR_WIFI_MAC:
|
||||||
|
return "MAC address is invalid"
|
||||||
|
case C.ESP_ERR_WIFI_SSID:
|
||||||
|
return " SSID is invalid"
|
||||||
|
case C.ESP_ERR_WIFI_PASSWORD:
|
||||||
|
return "Password is invalid"
|
||||||
|
case C.ESP_ERR_WIFI_TIMEOUT:
|
||||||
|
return "Timeout error"
|
||||||
|
case C.ESP_ERR_WIFI_WAKE_FAIL:
|
||||||
|
return "WiFi is in sleep state(RF closed) and wakeup fail"
|
||||||
|
case C.ESP_ERR_WIFI_WOULD_BLOCK:
|
||||||
|
return "The caller would block"
|
||||||
|
case C.ESP_ERR_WIFI_NOT_CONNECT:
|
||||||
|
return "Station still in disconnect status"
|
||||||
|
case C.ESP_ERR_WIFI_POST:
|
||||||
|
return "Failed to post the event to WiFi task"
|
||||||
|
case C.ESP_ERR_WIFI_INIT_STATE:
|
||||||
|
return "Invalid WiFi state when init/deinit is called"
|
||||||
|
case C.ESP_ERR_WIFI_STOP_STATE:
|
||||||
|
return "Returned when WiFi is stopping"
|
||||||
|
case C.ESP_ERR_WIFI_NOT_ASSOC:
|
||||||
|
return "The WiFi connection is not associated"
|
||||||
|
case C.ESP_ERR_WIFI_TX_DISALLOW:
|
||||||
|
return "The WiFi TX is disallowed"
|
||||||
|
default:
|
||||||
|
return "Other WiFi error"
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
return "Other error"
|
||||||
|
}
|
||||||
|
}
|
||||||
Submodule
+1
Submodule espnet/esp-idf added at c9646ff0be
@@ -0,0 +1,98 @@
|
|||||||
|
#include <stdint.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include "espnet.h"
|
||||||
|
|
||||||
|
// OS adapter functions.
|
||||||
|
// See: esp-idf/components/esp_wifi/include/esp_private/wifi_os_adapter.h
|
||||||
|
wifi_osi_funcs_t g_wifi_osi_funcs = {
|
||||||
|
._version = ESP_WIFI_OS_ADAPTER_VERSION,
|
||||||
|
// TODO: define these functions.
|
||||||
|
._magic = ESP_WIFI_OS_ADAPTER_MAGIC,
|
||||||
|
};
|
||||||
|
|
||||||
|
// This is a string constant that is used all over ESP-IDF and is also used by
|
||||||
|
// libnet80211.a. The main purpose is to be a fixed pointer that can be compared
|
||||||
|
// against etc.
|
||||||
|
const char *WIFI_EVENT = "WIFI_EVENT";
|
||||||
|
|
||||||
|
// Required by libphy.a
|
||||||
|
int phy_printf(const char *format, ...) {
|
||||||
|
va_list args;
|
||||||
|
va_start(args, format);
|
||||||
|
printf("phy: ");
|
||||||
|
int res = vprintf(format, args);
|
||||||
|
va_end(args);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Required by libpp.a
|
||||||
|
int pp_printf(const char *format, ...) {
|
||||||
|
va_list args;
|
||||||
|
va_start(args, format);
|
||||||
|
printf("pp: ");
|
||||||
|
int res = vprintf(format, args);
|
||||||
|
va_end(args);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Required by libnet80211.a
|
||||||
|
int net80211_printf(const char *format, ...) {
|
||||||
|
va_list args;
|
||||||
|
va_start(args, format);
|
||||||
|
printf("net80211: ");
|
||||||
|
int res = vprintf(format, args);
|
||||||
|
va_end(args);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Source: esp-idf/components/wpa_supplicant/src/utils/common.c
|
||||||
|
static int hex2num(char c)
|
||||||
|
{
|
||||||
|
if (c >= '0' && c <= '9')
|
||||||
|
return c - '0';
|
||||||
|
if (c >= 'a' && c <= 'f')
|
||||||
|
return c - 'a' + 10;
|
||||||
|
if (c >= 'A' && c <= 'F')
|
||||||
|
return c - 'A' + 10;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Source: esp-idf/components/wpa_supplicant/src/utils/common.c
|
||||||
|
int hex2byte(const char *hex)
|
||||||
|
{
|
||||||
|
int a, b;
|
||||||
|
a = hex2num(*hex++);
|
||||||
|
if (a < 0)
|
||||||
|
return -1;
|
||||||
|
b = hex2num(*hex++);
|
||||||
|
if (b < 0)
|
||||||
|
return -1;
|
||||||
|
return (a << 4) | b;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Source: esp-idf/components/wpa_supplicant/src/utils/common.c
|
||||||
|
/**
|
||||||
|
* hexstr2bin - Convert ASCII hex string into binary data
|
||||||
|
* @hex: ASCII hex string (e.g., "01ab")
|
||||||
|
* @buf: Buffer for the binary data
|
||||||
|
* @len: Length of the text to convert in bytes (of buf); hex will be double
|
||||||
|
* this size
|
||||||
|
* Returns: 0 on success, -1 on failure (invalid hex string)
|
||||||
|
*/
|
||||||
|
int hexstr2bin(const char *hex, uint8_t *buf, size_t len)
|
||||||
|
{
|
||||||
|
size_t i;
|
||||||
|
int a;
|
||||||
|
const char *ipos = hex;
|
||||||
|
uint8_t *opos = buf;
|
||||||
|
|
||||||
|
for (i = 0; i < len; i++) {
|
||||||
|
a = hex2byte(ipos);
|
||||||
|
if (a < 0)
|
||||||
|
return -1;
|
||||||
|
*opos++ = a;
|
||||||
|
ipos += 2;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
#include <stdbool.h>
|
||||||
|
#include "esp_private/wifi_os_adapter.h"
|
||||||
|
|
||||||
|
extern wifi_osi_funcs_t g_wifi_osi_funcs;
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import "tinygo.org/x/drivers/espnet"
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
err := espnet.WiFi.Configure(espnet.Config{})
|
||||||
|
if err != nil {
|
||||||
|
println("failed to configure:", err.Error())
|
||||||
|
}
|
||||||
|
mac, err := espnet.WiFi.AccessPointMAC()
|
||||||
|
if err != nil {
|
||||||
|
println("failed to read MAC address:", err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
print("MAC address:")
|
||||||
|
for _, b := range mac {
|
||||||
|
print(" ", b)
|
||||||
|
}
|
||||||
|
println()
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user