|
Session
|
Topic
|
Key Concepts & Activities
|
|
1
|
Introduction to SPI
|
The need for SPI, its advantages (simplicity, high speed) and disadvantages. Comparison with I2C and UART. Master-Slave architecture.
|
|
2
|
SPI Signals and Timing
|
Detailed analysis of the four wires: SCLK (Clock), MOSI (Master Out Slave In), MISO (Master In Slave Out), SS/CS (Slave Select/Chip Select). Role of Chip Select.
|
|
3
|
SPI Modes (Clock Polarity & Phase)
|
Understanding CPOL and CPHA (Mode 0, 1, 2, 3). How they dictate data sampling and clock edge. Clock frequency and duty cycle considerations.
|
|
4
|
Data Frames, Word Size, and Transactions
|
Analyzing data frames (typically 8-bit). Concepts of word size and transactions. Handling multiple slaves and bus sharing.
|
|
Session
|
Topic
|
Key Concepts & Activities
|
|
5
|
The Linux Device Model & SPI
|
Review of bus-device-driver model. Introduction to the SPI Bus Type. The SPI Master (Controller) and SPI Slave (Device) roles in the kernel.
|
|
6
|
SPI Subsystem Structures
|
Detailed look at the core structures: struct spi_master, struct spi_device, and struct spi_driver. How they interconnect.
|
|
7
|
The spi_message & spi_transfer
|
Understanding the data structures used for communication. spi_message (the container) vs. spi_transfer (the data units). Full-duplex communication.
|
|
8
|
SPI Communication APIs
|
Core functions: spi_sync(), spi_async(), spi_write(), spi_read(). Choosing the right API for different scenarios (blocking vs. non-blocking).
|
|
Session
|
Topic
|
Key Concepts & Activities
|
|
9
|
Driver Registration and Probe
|
Creating the struct spi_driver. Implementing the probe() and remove() functions. Accessing device-specific configuration from Device Tree.
|
|
10
|
Accessing Device Tree Data
|
Reviewing Device Tree (DT) basics for SPI. Reading properties like chip select, mode, and max speed from the DT node using of_get_xxx() APIs.
|
|
11
|
Setting Up Character Device Interface
|
Integrating the SPI driver with the familiar character device (cdev) interface. Storing the struct spi_device reference in the character device private data.
|
|
12
|
Implementing read() and write()
|
Mapping user-space read/write calls to kernel-space spi_sync() calls. Handling data transfer buffers and length checks.
|
|
13
|
Handling Device Configuration (IOCTL)
|
Using ioctl() to allow user-space to configure device-specific settings (e.g., turning on/off a feature, changing sample rate). Implementing the unlocked_ioctl method.
|
|
14
|
Practical: Building and Testing I/O
|
Lab Session: Compile and load the basic driver. Use user-space tools (dd, custom test program) to verify basic read/write functionality with the target device.
|
|
Session
|
Topic
|
Key Concepts & Activities
|
|
15
|
Error Handling and Resource Cleanup
|
Implementing robust error paths in probe() and remove(). Proper resource deallocation (cdev, memory, IRQ). Handling SPI transfer errors.
|
|
16
|
Integrating Interrupts (IRQ)
|
Handling device-initiated interrupts. Registering and writing a Linux IRQ handler (request_irq()). Using interrupt context vs. process context (Bottom Halves: Tasklets or Workqueues).
|
|
17
|
Handling Multi-Word Transfers
|
Implementing sequential transfers (e.g., command + address + data) using multiple spi_transfer structures within a single spi_message.
|
|
18
|
Power Management (PM) Hooks
|
Implementing the struct dev_pm_ops for the SPI device driver. Handling suspend and resume calls to save and restore the device state.
|
|
Session
|
Topic
|
Key Concepts & Activities
|
|
19
|
Debugging SPI Drivers
|
Essential debugging techniques: printk() usage and log levels. Using the dynamic_debug feature. ftrace and hardware logic analyzer usage for verifying SPI signals.
|
|
20
|
Code Review & Next Steps
|
Reviewing common SPI driver issues (endianness, race conditions). Best practices for upstreaming patches. Final Q&A and Project Review.
|