Skip to content

Latest commit

 

History

History
254 lines (174 loc) · 6.9 KB

File metadata and controls

254 lines (174 loc) · 6.9 KB

Lecture 1 — Linux mental model for this host stack

Course: Jetson ESP-Hosted Host Code guide · Phase 2 — Embedded Linux

Next: Lecture 02 — Build, load, and board policy


1. What Linux thinks is happening

From Linux userspace, the validated Jetson flow eventually looks ordinary:

  • wlan0 exists
  • hci0 exists
  • nmcli can scan Wi-Fi
  • bluetoothctl can scan BLE devices

But Linux is not talking to a native Wi-Fi or Bluetooth chip over PCIe or USB. It is talking to an ESP32-C6 over a custom SPI transport.

So the real question is:

How do ordinary Linux abstractions come out of a non-ordinary transport?

The answer is the host stack in esp_hosted_ng/host/.

Related Linux kernel concepts

Use these earlier OS lectures as the conceptual base under this case study:

Lecture 1 from the OS course explains the kernel as the layer that owns hardware and exposes clean abstractions to userspace. That is exactly what this host stack is doing: it hides a custom ESP-over-SPI link and instead gives Linux normal objects like wlan0 and hci0.

Lecture 5 matters here because this code only makes sense after boot has already described the board and loaded the right driver path. The ESP-Hosted host code is not inventing hardware from scratch; it is sitting on top of a kernel that already knows about SPI devices, modules, and board description.

Another way to say it is: userspace does not get to “talk to GPIO 471” or “talk to SPI mode 2” directly as a networking model. The kernel driver absorbs those low-level details and publishes higher-level subsystem objects, so userspace can work with Wi‑Fi and Bluetooth concepts instead of transport wiring.

This is why wlan0 and hci0 are such important milestones in the bring-up story. They prove not just that bytes moved over SPI, but that the kernel accepted the driver’s integration with real Linux subsystems and exposed the expected interfaces upward.

The Linux-facing interfaces to keep in mind in this lecture are:

  • cfg80211
  • HCI / BlueZ
  • wireless_dev
  • wiphy
  • net_device

2. The layered picture

Read this from top to bottom:

  1. userspace tools
  2. Linux subsystem APIs
  3. host driver integration code
  4. transport code
  5. ESP side firmware

In this codebase, that becomes:

  • userspace:
    • nmcli
    • iw
    • bluetoothctl
    • hciconfig
  • Linux subsystems:
    • cfg80211 for Wi-Fi
    • HCI / BlueZ for Bluetooth/BLE
  • host integration:
    • esp_cfg80211.c
    • esp_bt.c
    • main.c
  • transport:
    • spi/esp_spi.c
  • board bring-up policy:
    • jetson_orin_nano_init.sh

That is the first Embedded Linux lesson:

  • the Linux-facing code is not the same thing as
  • the hardware-facing transport code

If you blur those together, driver reading becomes confusing fast.

Code anchor: one boot event creates two Linux personalities

The cleanest place to see the split is in main.c. A single ESP boot-up event eventually fans out into:

  • Wi-Fi registration through esp_add_card(...)
  • Bluetooth registration through init_bt(...)
static void init_bt(struct esp_adapter *adapter)
{
	if ((adapter->capabilities & ESP_BT_SPI_SUPPORT) ||
		(adapter->capabilities & ESP_BT_SDIO_SUPPORT)) {
		msleep(200);
		esp_info("ESP Bluetooth init\n");
		esp_init_bt(adapter);
	}
}

static int process_event_esp_bootup(struct esp_adapter *adapter, u8 *evt_buf, u8 len)
{
	...
	if (esp_add_card(adapter)) {
		esp_err("network interface init failed\n");
		return -1;
	}
	init_bt(adapter);
	...
	print_capabilities(adapter->capabilities);
}

And the Wi-Fi side is explicitly created as a normal Linux station interface:

static int esp_add_network_ifaces(struct esp_adapter *adapter)
{
	struct wireless_dev *wdev = NULL;

	rtnl_lock();
	wdev = esp_cfg80211_add_iface(adapter->wiphy, "wlan%d", 1,
				      NL80211_IFTYPE_STATION, NULL);
	rtnl_unlock();

	if (wdev)
		return 0;

	return -1;
}

That is the whole course in miniature:

  • one remote chip
  • one transport
  • two different Linux subsystem identities

3. The file-reading order that actually works

Use this order:

  1. jetson_orin_nano_init.sh
  2. Makefile
  3. main.c
  4. spi/esp_spi.c
  5. esp_cfg80211.c
  6. esp_bt.c

Why this order works:

  • the shell script tells you the board assumptions
  • the Makefile tells you the kernel module shape
  • main.c shows the lifecycle
  • esp_spi.c shows how the bytes actually move
  • esp_cfg80211.c shows how Linux Wi-Fi appears
  • esp_bt.c shows how Linux Bluetooth appears

Do not start in the middle of esp_spi.c unless you already know what the host is trying to produce.


4. What the host code is really producing

The host code is not just “a kernel module.”

It is producing two Linux personalities:

  • a Wi-Fi device through cfg80211
  • an HCI controller through the Bluetooth stack

That means this repo is really a study in Linux subsystem integration.

The transport could change in theory:

  • SPI
  • SDIO
  • UART

But the way Linux sees Wi-Fi and Bluetooth would still need to map into the same upper subsystem expectations.

That is why the repo splits:

  • common logic
  • transport-specific logic
  • Linux integration logic

5. The validated runtime story

On the validated Jetson path, the important runtime stages were:

  1. module inserted
  2. SPI device claimed
  3. handshake/data-ready IRQs attached
  4. ESP boot-up event received
  5. chipset identified over SPI
  6. Wi-Fi interface created
  7. Bluetooth controller created

That sequence matters.

For Embedded Linux debugging, “module inserted successfully” is not enough.

You want to know:

  • did the protocol event arrive?
  • did the upper subsystem register?
  • did Linux gain a real interface?

This is how you avoid false success during bring-up.


6. The exact files to have open while reading

Keep these open side by side:

  • esp_hosted_ng/host/jetson_orin_nano_init.sh
  • esp_hosted_ng/host/Makefile
  • esp_hosted_ng/host/main.c
  • esp_hosted_ng/host/spi/esp_spi.c
  • esp_hosted_ng/host/esp_cfg80211.c
  • esp_hosted_ng/host/esp_bt.c

As you read, ask:

  • what Linux subsystem is this file talking to?
  • what hardware assumption does it encode?
  • what log line would prove this stage worked?

That habit is the real course objective.


Lab

Write a one-page note that answers:

  1. Which files are mostly board policy?
  2. Which files are mostly transport logic?
  3. Which files are mostly Linux subsystem integration?
  4. Why does wlan0 mean more than /dev/spidev0.0?

Previous: Course hub · Next: Lecture 02 — Build, load, and board policy