
Credits:
Optimistic / Inspirational by Mixaund | https://mixaund.bandcamp.com
Music promoted by https://www.free-stock-music.com
Credits:
Five stars: http://www.pngall.com/?p=39082
The definition of universal serial bus (USB) and the motivation behind USB development.
The history of USB development and USB versions.
The most common USB cables and connectors.
A quick look on the inner-structure of the specified cable in USB 2.0.
The main features of USB protocol regardless of the USB version.
Demonstration of the USB star topology and the meaning of USB function.
Explanation about the history of different power supply specifications for USB devices.
Explanation about the principle of smart chargers.
Explore how USB uses differential signaling with the D+ and D- lines to encode differential zero and one, focusing on full-speed devices and noise immunity.
Identify USB 2.0 speed by noting host pull-downs on D+ and D− data lines, and device pull-ups on D− for low speed or D+ for full/high speed.
Explore bit stuffing as the insertion of non-information bits to maintain clock sync on the USB bus, inserting a zero after six consecutive ones to prevent long idle states.
Learn how non-return-to-zero inverted (nrzi) encoding toggles the bus state on zeros and leaves ones unchanged, and how bit stuffing and hardware-managed nrzi encoding keep usb signaling in sync.
Explain how frames, marked by the start of frame signal every one millisecond in full-speed USB, allocate minimum portions to each device, balancing camera, keyboard, and mouse bandwidth.
Explore USB endpoints, their direction, in and out endpoints, and endpoint zero, with practical examples of sensor data streams and host–device configuration.
Here you can find a PDF file that contains the slides of some of the important upcoming lectures that you may need frequently to be opened next to you while watching the videos (e.g. to be able to compare the transaction types without switching between the videos).
Understand how USB transmits data in packets, with packet structure, endpoint-based size decisions, and signaling from sync to end, including bit stuffing and least significant bit first.
Explore USB behind the scenes by examining packet types and fields, including start of frame, token, data, and handshake packets, with PID, addresses, endpoints, CRC checks, and synchronization.
Understand USB packet identifiers (PIDs) and the PID field, outlining token, data, and handshake packets, their in and out directions, and how a PID value indicates packet type.
Explore token packets—in, out, and setup—that start every USB transaction. Learn how the host reads from or writes to the device and how setup begins control transfers on endpoint zero.
Handshake packets report the status of the previous data packet, with Ack, not acknowledged, and stall as three options; some endpoints, like endpoint zero, stall on not supported requests.
Explore usb bus polling, where the physical layer samples a buffered data stream instead of continuous monitoring, and interrupt transfers are implemented by polling.
Explore how USB is host driven, where the host triggers all transactions with out and setup tokens, and the host requests device data using in tokens.
Usb is host driven; the host sends tokens and data to the device and requests data back with in tokens, while the device acknowledges or retries as needed.
Understand the four USB transfer types—interrupt, bulk, isochronous, and control—and how endpoints, including the control endpoint zero, perform transfers. The host learns endpoint configuration and descriptors during device enumeration.
Understand USB interrupt transfers: periodic, latency-guaranteed data using in/out token and handshake packets for mice, keyboards, and joysticks, with up to 64 bytes full-speed or 1024 bytes high-speed payloads.
Explore isochronous transfer, a periodic, guaranteed-bandwidth USB transfer with no handshaking, used for webcam and microphone streams; max payload is 1023 bytes full speed, 1024 high speed.
Explore how USB control transfer enables device enumeration and configuration through endpoint zero, detailing setup, data, and status stages and their handshaking for error-free transmission.
Allocate bus bandwidth for each endpoint during enumeration to guarantee periodic transfers up to 90% for full speed and 80% for high speed, then control and bulk transfers.
Learn how to download, install, and set up stm32 cube ide on Windows, including license acceptance, extracting the installer, and selecting default options and debugging drivers.
Create a new stm32 cube ide project for the usb device targeting stm32 f429 discovery board, with executable project and writing your own hardware access in C (no cube libraries).
Learn how CMSIS header files map each register and bit, and SIMS macros simplify bare-metal STM32 firmware development.
Delete the auto-generated files syscalls.c and system.c from the source folder to keep the USB behind the scenes project simple, after reviewing their contents.
Master the art of logging with SWO to debug USB firmware, redirect printf output to SWO after soldering the bridge, override the underscore_write weak symbol, and build modular logging helpers.
Organize a logging helper for hid firmware by adding include and source helpers and implementing logger c and h with error, information, and debug levels, and set system_log_level in system_init.
Explore two ways to configure the system clock with an interactive STM32 Cube MK tool, then configure the clock by registers and build a custom hardware access layer.
Create a temporary stm32 cube mx project to explore clock configuration for usb device development, enable usb otg hs, select device only, and validate clocks with an mco output.
Configure the microcontroller clock to feed a fixed 48 MHz USB clock, using an 8 MHz external oscillator, HSE, PLL multipliers/dividers, and prescalers, with CubeMX guiding the calculations.
Explain how to configure MCO one source mux to output the PLL clock on PA8, routing USB and system clocks, and verify a 36 MHz signal on the MCO1 pin.
Configure the system clock in system init by including the stm32f4xx header and stdint, and implement a static configure clock function to set the 72 MHz core clock.
Configure flash memory read latency as wait states before raising the CPU clock to 72 MHz, by modifying the flash ACR latency field using standard macros and datasheet guidance.
Use the fld2val macro to convert a value into a field with proper bit shifting and masking, then examine the first register modification and USB-related code glimpses.
Enable the module via cr register, configure pll with pl cfg r using m, n, p, q prescalers, wait for the ready bit, then switch clock to pll.
Disable the high-speed internal oscillator to save power by clearing the HSC bit in the CR register after switching the system clock to use the HSC as clock source.
Fix two PLL configuration traps by recognizing a macro as a mask, choosing the correct shift method, and correcting enable-before-configuration per datasheet; verify clock frequency with an oscilloscope.
Configure mco1 to output clock on pin a8 by selecting the clock source, setting prescaler to two, enabling gpio a, and setting pin a8 to alternate function with medium speed.
Discover a three-layer USB firmware architecture—driver layer, framework (protocol-specific) layer, and application layer—balancing hardware access, host interactions, endpoints, and FIFO buffer management.
Create driver and framework header and source files, include stm32 f4 headers, and access usb register regions by offsetting the base address using sims structures.
Use two firmware functions to connect or disconnect the USB device by setting the software disconnect bit in the device control register and toggling the power down bit for transceivers.
Use a global interrupt status handler to read the USB core interrupts register, unmask interrupts during core init, route to the correct ISR, and clear flags by setting bits.
Explore argument validation within the USB HID driver abstraction and learn to document code with doxygen, balancing hardware specific checks with forward progress in the driver layer.
Reconfigure all endpoints and their fifos after a USB reset, unmask transfer completion interrupts for in and out endpoints in the core initialization, and log the reset handling.
Handle the speed enumeration done interrupt by configuring endpoint zero for an eight-byte packet on a full-speed USB device, then clear the interrupt after logging and invoking the handler.
Implement the rx fifo not-empty interrupt handler by popping the status word, decoding endpoint and byte count, and routing setup versus out data packets.
Understand how setup and out transfer statuses from the fifo may appear without data, and how to re-enable endpoints after transfers in USB HID firmware.
Describe how to pop data from the RxFIFO in a USB HID firmware, using a shared FIFO, per-endpoint pointers, and 32-bit word reads with final-byte realignment to reconstruct packets.
Push data into a txfifo for an in endpoint by implementing the write packet function, configuring transfer size, packet count, and clearing stall before enabling transmission.
Resolve compilation errors by including the USB standards header, then reorder functions so definitions appear before use, enabling the project to compile successfully.
Define and differentiate USB control transfer stages—setup, data in/out, and status—and explain termination via zero-length data packets and data-in zero/idle transitions in firmware.
Define a usb_device structure in header to store device state, default address, endpoint zero control transfer stage, current configuration, and data buffers; declare a usb_events variable in the driver header.
Initialize the USB device by passing and storing a USB device pointer in a static global variable, then set an out buffer in main.c and compile.
Understand the usb reset handler during device enumeration, reset data size and configuration, set endpoint zero to setup stage, and initialize the device address to zero via the driver layer.
Implement set device address function in the USB driver, write the address to the device configuration register's address field, expose it via a pointer in the driver structure, and compile.
Define a USB events instance, assign the USB reset handler, and trigger on USB reset received to invoke the framework and driver handlers in this HID firmware workflow.
Explore the usb request structure used in setup transactions, detailing the eight-byte data packet and the fields bmRequestType, bRequest, wValue, wIndex, and wLength.
Explore USB standard device requests, focusing on get descriptor, set address, and set configuration. Understand how request type, b request, w value, w index, and w length govern data stage.
Define a USB request structure and masks to simplify parsing host requests, casting the buffer to the USB standard structure and exposing direction, type, and recipient fields.
Cast the incoming buffer to a USB request, route standard device requests via a dedicated handler, and start with get descriptor to access device descriptors.
investigate the host's first usb request by examining the get device descriptor transaction, showing an eight-byte setup with bm request 0x80, bRequest 6, descriptor type 1, length 64.
Define the USB standard device descriptor and other descriptor types, explain get descriptor requests, and show how host requests specify descriptor types using the value byte.
Define standard USB request macros in the USB standards header and handle get descriptor requests by extracting the descriptor type from the w value field.
Identify and fix a variable after case error in a switch by inserting a semicolon or wrapping the case in braces, then log the get descriptor request and recompile.
Write a packet only when the endpoint is empty to avoid overwriting data in USB control transfers. The lecture explains endpoint zero, host fetch, and multi-packet transfers.
Implement the function to process the control transfer stage and handle the USB pulled event to manage setup and data in stages, including get device descriptor, in a bus-polling loop.
Define and attach the in transfer completed handler to USB events, check the in data buffer, and resume the in data stage to send the next packet to endpoint zero.
Watch the first successful host–device USB communication, as the device replies to the get device descriptor and moves to the set address phase, verified in syslog and Wireshark.
Set address requests are handled in the outer switch with no data stage; read W value, update device address via the driver, then switch to in status stage.
Demonstrate viewing a USB set address request and its immediate response in Wireshark, alongside capturing device descriptor traffic and debugging USB timeouts during firmware development.
View the full get device descriptor response and confirm the device descriptor contents, including the vendor ID, product ID, and version, after the set address exchange with the host.
View how a get configuration descriptor request appears in Wireshark, why the host receives no response yet, and how the configuration descriptor describes interfaces, endpoints, and power.
Define a placeholder USB configuration descriptor and assemble a configuration descriptor combination for host requests. Build a structure that aggregates multiple descriptors for a single configuration.
Inline the USB configuration descriptor within the configuration combination, using constants for global structures and removing separate definitions to ensure the C code compiles.
Handle get configuration descriptor requests by sending the configuration descriptor plus attached descriptors, selecting the correct configuration by index, and switching to the data in stage for host transfer.
The host first requests the nine-byte configuration descriptor header, then uses its total length to learn the full size of the configuration descriptor combination and fetches the complete descriptor.
Process the USB set configuration request by recording the chosen configuration index, switch the device state from addressed to configured, and advance the control transfer to the status stage.
Define a use-case specific USB configuration function that configures endpoints according to the host's selected configuration descriptor, handles set configuration, and prepares the device for enumeration.
Explore usb device classes and how peripherals like mice interact with hosts, and implement a simple hid mouse firmware that moves the cursor periodically, with buttons and position sensor enhancements.
Write the USB configuration descriptor for a mouse HID device, defining the configuration, interfaces, and endpoints, calculating the total length, and setting attributes, max power, and wake capability.
Define the Usb endpoint descriptor for the mouse, selecting endpoint three as an in interrupt endpoint with a 64-byte max packet size and a 50-frame interval.
Add the USB ID descriptor for HID, create a dedicated ID standards header, link to an ID report descriptor, and clarify descriptor versus report descriptor to prepare testing.
The lecture explains HID report descriptors and the HID report structure by building a simple mouse report with X and Y deltas and three buttons.
Describe HID buttons by setting the usage page to button, defining min/max and logical ranges, and specifying report size, count, input as absolute, with padding for compatibility.
Describe the HID x and y axes on the generic desktop page, set logical min and max, and configure an 8-bit, single input report with relative delta values for axes.
Diagnose usb behind the scenes firmware by packing usb descriptors to prevent alignment padding, fix nine-byte configuration descriptor length, and verify correct descriptor sets with Wireshark against the Linux host.
Implement handling of standard USB interface requests, including get report descriptor, to deliver HID report data via a control transfer and endpoint three.
Instantiate a mouse report, fill the x and y values, and write it to endpoint three after a successful transfer using the in transfer completed handler.
Explore Windows-specific HID descriptor ordering in USB devices and fix cross-platform compatibility by placing the HID descriptor before the endpoint, guided by Linux debugging with syslog and Wireshark.
Have you ever wanted to develop your own device that can be connected to a computer using USB? Are you familiar with using USB <-> UART adapters but want to take your USB knowledge and understanding to the next ultimate level? If yes, then this course is absolutely for you!
I made the whole content of slides and code by myself after a lot of preparation and fine-tuning to give you the best experience you can find today online to learn and understand USB protocol and framework in theory and in practice.
Your journey with me in this course should save you from any frustration that could happen when you try to learn or understand USB from any other online source. USB is for most a mystery and a very complex protocol, and most engineers try to avoid it or at least try to convert it to other simpler protocols. However, after taking this course, you will be able to be a confident native USB engineer, and you will be able to develop your first bare-metal USB device with me without using any library, which will give you full control over the powers of USB. Even if you want in your career to use a USB library, taking this course will give you a full understanding of what is going on behind the scenes, and will allow you to be able to develop and fine-tune and USB device you want, because, after the end of this course, I would expect from you to have a full understanding of the concept of USB and how it works.
In this course, we will:
- Start with some theoretical information about USB.
- Understand the essential details of USB protocol.
- Take our time to understand how to configure the clock of any embedded system correctly.
- Implement a bare-metal USB firmware for ARM Cortex M4 based microcontroller (STM32F4xx family).
- Implement a bare-metal USB framework.
- Develop our own USB HID mouse from zero to fully functional!
Of course, the source code of the project we are going to develop together in this course will be available for you to download. You may use it as a template (fully or partially) for your projects in the future.
This course is in its early stages and some new additional content will be added or enhanced if necessary frequently. Nevertheless, the current content is full and sufficient to get a fully functional USB human interface device.
Happy engineering! See you inside the course!