Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #pragma once
- #ifdef __cplusplus
- extern "C" {
- #endif
- #include "stm32u5xx.h"
- /**
- *Helpers to access different STM32 USB registers.
- */
- #define FSDEV_EP_COUNT 8
- #define FSDEV_PMA_SIZE 2048u // 2 KB packet buffer, 32-bit access
- #define FSDEV_PMA_STRIDE 1 // word stride (32-bit bus)
- #ifndef FSDEV_REG_BASE
- #define FSDEV_REG_BASE (USB_DRD_BASE) // BASE USB REGISTER
- #endif
- #define _va32 volatile //__attribute__ ((aligned(4)))
- typedef struct {
- struct {
- _va32 uint32_t reg;
- } CHEPnR[FSDEV_EP_COUNT];
- _va32 uint32_t RESERVED7[8]; // Reserved
- _va32 uint32_t CNTR; // 40: Control register
- _va32 uint32_t ISTR; // 44: Interrupt status register
- _va32 uint32_t FNR; // 48: Frame number register
- _va32 uint32_t DADDR; // 4C: Device address register
- _va32 uint32_t _reserved_old_BTABLE; // 50: Buffer Table address register (16-bit only)
- _va32 uint32_t LPMCSR; // 54: LPM Control and Status Register (32-bit only)
- _va32 uint32_t BCDR; // 58: Battery Charging Detector Register (32-bit only)
- } usb_reg_t;
- #define USB_REG ((volatile usb_reg_t*)FSDEV_REG_BASE)
- typedef struct {
- struct {
- _va32 uint32_t txrx;
- _va32 uint32_t rxtx;
- } btable[FSDEV_EP_COUNT];
- _va32 uint8_t free_mem[496]; // 64 -> size of btable. We have 2048. Since 32 bit word, 2048 - 64 = 1984 bytes = 496 words
- } usb_sram_t;
- #define USB_SRAM ((volatile usb_sram_t*) USB_DRD_PMAADDR)
- static inline void fsdev_usb_set_global_interrupt(bool enabled) {
- if (enabled) {
- // printf("Enabling global USB interrupt\r\n");
- HAL_NVIC_EnableIRQ(USB_IRQn);
- } else {
- // printf("Disabling global USB interrupt\r\n");
- HAL_NVIC_DisableIRQ(USB_IRQn);
- }
- }
- // Reset control register
- static inline void fsdev_cntr_reset() {
- USB_REG->CNTR = 0x00000003; // Reset + Power down, reset state according to docs
- }
- // reset (clear) interrupt status register
- static inline void fsdev_istr_reset() {
- USB_REG->ISTR = 0L;
- }
- #define USB_ISTR_RC_W0_MASK ( USB_ISTR_DCON | USB_ISTR_THR512 | USB_ISTR_PMAOVR | USB_ISTR_ERR | USB_ISTR_WKUP | USB_ISTR_SUSP \
- | USB_ISTR_RESET | USB_ISTR_SOF | USB_ISTR_ESOF | USB_ISTR_L1REQ )
- /**
- * Clears the specified interrupt flags in the ISTR register.
- * The USB_ISTR only allows writing to some pins.
- * To avoid spurious clearing (hardware setting bits while we have old value in memory)
- * we set the bits we want to clear to 0, and all other bits to 1.
- * @param mask
- */
- static inline void fsdev_istr_clear_irq(uint32_t mask) {
- USB_REG->ISTR = ~(USB_ISTR_RC_W0_MASK & mask);
- }
- static inline uint8_t fsdev_istr_read_idn(volatile uint32_t *istr) {
- return (*istr & USB_ISTR_IDN) >> USB_ISTR_IDN_Pos;
- }
- typedef enum {
- FSDEV_CHEP_STATUS_DISABLED = 0b00,
- FSDEV_CHEP_STATUS_STALL = 0b01,
- FSDEV_CHEP_STATUS_NAK = 0b10,
- FSDEV_CHEP_STATUS_VALID = 0b11
- } FsdevChepStatus;
- typedef enum {
- FSDEV_CHEP_TYPE_BULK = 0b00,
- FSDEV_CHEP_TYPE_CONTROL = 0b01,
- FSDEV_CHEP_TYPE_ISOCHRONOUS = 0b10,
- FSDEV_CHEP_TYPE_INTERRUPT = 0b11
- } FsdevChepType;
- // The following masks are for some reason missing in the HAL headers
- #define USB_CHEP_THREE_ERR_RX_Pos (29UL)
- #define USB_CHEP_THREE_ERR_RX_Msk (0x3UL << USB_CHEP_THREE_ERR_RX_Pos) /*!< 0x60000000 */
- #define USB_CHEP_THREE_ERR_RX USB_CHEP_THREE_ERR_RX_Msk /*!< Three consecutive IN transaction errors */
- #define USB_CHEP_THREE_ERR_TX_Pos (27UL)
- #define USB_CHEP_THREE_ERR_TX_Msk (0x3UL << USB_CHEP_THREE_ERR_TX_Pos) /*!< 0x18000000 */
- #define USB_CHEP_THREE_ERR_TX USB_CHEP_THREE_ERR_TX_Msk /*!< Three consecutive OUT/SETUP transaction errors */
- // W0 (write 0 to clear, 1 indifferent) pins in CHEP
- #define USB_CHEP_RC_W0_MASK (USB_CHEP_ERRRX | USB_CHEP_ERRTX | USB_CHEP_THREE_ERR_RX | USB_CHEP_THREE_ERR_TX | \
- USB_CHEP_NAK | USB_CHEP_VTRX | USB_CHEP_VTTX)
- // rw pins in CHEP
- #define USB_CHEP_RW_MASK (USB_CHEP_DEVADDR | USB_CHEP_UTYPE | USB_CHEP_LSEP | USB_CHEP_ADDR | USB_EP_KIND | USB_CHEP_SETUP)
- // Toglge pins in CHEP
- #define USB_CHEP_T_MASK (USB_CHEP_DTOG_RX | USB_CHEP_RX_STRX | USB_CHEP_DTOG_TX | USB_CHEP_TX_STTX)
- static inline uint32_t _bf_get(uint32_t reg, uint32_t mask, unsigned pos) {
- return (reg & mask) >> pos;
- }
- static inline uint32_t _bf_prep(uint32_t mask, unsigned pos, uint32_t v) {
- return (v << pos) & mask;
- }
- static inline void fsdev_chep_write_rw(volatile uint32_t *chep,
- uint32_t field_mask, unsigned field_pos,
- uint32_t value) {
- uint32_t r = *chep;
- uint32_t desired = (r & ~field_mask) | _bf_prep(field_mask, field_pos, value);
- // 1 → keep rc_w0 unchanged; 0 → keep t unchanged
- uint32_t w = desired;
- w |= USB_CHEP_RC_W0_MASK;
- w &= ~USB_CHEP_T_MASK;
- *chep = w;
- }
- static inline void fsdev_chep_write_t_field(volatile uint32_t *chep,
- uint32_t field_mask, unsigned field_pos,
- uint32_t target) {
- uint32_t r = *chep;
- uint32_t current = _bf_get(r, field_mask, field_pos);
- uint32_t toggles = ((current ^ target) << field_pos) & field_mask;
- // Start from current: preserve RW fields exactly as they are.
- uint32_t w = r;
- // rc_w0 invariants: write 1 to "keep" (except any we explicitly clear elsewhere)
- w |= USB_CHEP_RC_W0_MASK;
- // t invariants: default 0 = don't toggle
- w &= ~USB_CHEP_T_MASK;
- // Apply required toggles (write 1 only where a toggle is needed)
- w |= toggles;
- *chep = w;
- }
- static inline void fsdev_chep_clear_rcw0(volatile uint32_t *chep, uint32_t mask) {
- uint32_t r = *chep;
- // Only clear bits that are both rc_w0 and requested in mask
- uint32_t to_clear = mask & USB_CHEP_RC_W0_MASK;
- // Base: start from current value, set those rc_w0 bits to 0
- uint32_t w = r & ~to_clear;
- // Set invariants for other categories:
- w |= (USB_CHEP_RC_W0_MASK & ~to_clear); // 1 → keep rc_w0 not being cleared
- w &= ~USB_CHEP_T_MASK; // 0 → keep t unchanged
- *chep = w;
- }
- static inline FsdevChepStatus fsdev_chep_get_rx_status(uint32_t chep) {
- return (FsdevChepStatus) _bf_get(chep, USB_CHEP_RX_STRX, USB_CHEP_RX_STRX_Pos);
- }
- static inline void fsdev_chep_set_rx_status(volatile uint32_t *chep, FsdevChepStatus s) {
- fsdev_chep_write_t_field(chep, USB_CHEP_RX_STRX, USB_CHEP_RX_STRX_Pos, (uint32_t) s & 0x3u);
- }
- static inline FsdevChepStatus fsdev_chep_get_tx_status(uint32_t chep) {
- return (FsdevChepStatus) _bf_get(chep, USB_CHEP_TX_STTX, USB_CHEP_TX_STTX_Pos);
- }
- static inline void fsdev_chep_set_tx_status(volatile uint32_t *chep, FsdevChepStatus s) {
- fsdev_chep_write_t_field(chep, USB_CHEP_TX_STTX, USB_CHEP_TX_STTX_Pos, (uint32_t) s & 0x3u);
- }
- static inline FsdevChepType fsdev_chep_get_type(uint32_t chep) {
- return (FsdevChepType) _bf_get(chep, USB_CHEP_UTYPE, USB_CHEP_UTYPE_Pos);
- }
- static inline void fsdev_chep_set_type(volatile uint32_t *chep, FsdevChepType t) {
- fsdev_chep_write_rw(chep, USB_CHEP_UTYPE, USB_CHEP_UTYPE_Pos, (uint32_t) t & 0x3u);
- }
- static inline uint32_t fsdev_chep_get_devaddr(uint32_t chep) {
- return _bf_get(chep, USB_CHEP_DEVADDR, USB_CHEP_DEVADDR_Pos);
- }
- static inline void fsdev_chep_set_devaddr(volatile uint32_t *chep, uint32_t addr) {
- fsdev_chep_write_rw(chep, USB_CHEP_DEVADDR, USB_CHEP_DEVADDR_Pos, addr & 0x7Fu);
- }
- /**
- * USB SRAM HELPERS
- * The USB SRAM fist features a 64 byte BTABLE (buffer table) area,
- * followed by free memory area.
- */
- #define FSDEV_BD_ADDR_Pos 0u
- #define FSDEV_BD_ADDR_Msk 0x0000FFFFu
- #define FSDEV_BD_COUNT_TX_Pos 16u
- #define FSDEV_BD_COUNT_TX_Msk 0x03FF0000u
- #define FSDEV_BD_BLSIZE_Pos 31u
- #define FSDEV_BD_BLSIZE_Msk 0x80000000u
- #define FSDEV_BD_NUMBLK_Pos 26u
- #define FSDEV_BD_NUMBLK_Msk 0x7C000000u
- #define FSDEV_BD_COUNT_RX_Pos 16u
- #define FSDEV_BD_COUNT_RX_Msk 0x03FF0000u
- static inline void fsdev_bd_tx_set_addr_ptr(volatile uint32_t *txrx, uint16_t pma_off) {
- if (pma_off & 0x3) {
- printf("[ERROR] fsdev_bd_tx_set_addr_ptr: Address 0x%04X not word-aligned!\n", pma_off);
- // Optionally: return early, assert, or handle error
- }
- uint32_t v = *txrx;
- v &= ~FSDEV_BD_ADDR_Msk;
- v |= (uint32_t) (pma_off & 0xFFFCu);
- *txrx = v;
- // printf("[fsdev_bd_tx_set_addr_ptr] Set TX addr_ptr to 0x%04X, raw reg now 0x%08X\r\n",
- // pma_off & 0xFFFCu, *txrx);
- }
- static inline void fsdev_bd_tx_set_count_ptr(volatile uint32_t *txrx, uint16_t count) {
- uint32_t v = *txrx;
- v &= ~FSDEV_BD_COUNT_TX_Msk;
- v |= ((uint32_t) (count & 0x03FFu) << FSDEV_BD_COUNT_TX_Pos);
- *txrx = v;
- // printf("[fsdev_bd_tx_set_count_ptr] Set TX count to %u, raw reg now 0x%08X\r\n",
- // count, *txrx);
- }
- static inline void fsdev_bd_tx(volatile uint32_t *txrx, uint16_t pma_off, uint16_t count) {
- // [16:25] -> count
- // [0:15] -> addr
- if (pma_off & 0x3) {
- printf("[ERROR] fsdev_bd_tx_set: Address 0x%04X not word-aligned!\n", pma_off);
- }
- // Build clean descriptor from zero
- uint32_t bd_val = 0;
- // printf("Writing pma offset %x, count %u to BD\r\n", pma_off, count);
- bd_val |= (uint32_t) (pma_off & 0xFFFCu);
- bd_val |= ((uint32_t) (count & 0x03FFu) << FSDEV_BD_COUNT_TX_Pos);
- *txrx = bd_val;
- }
- static inline uint16_t fsdev_bd_tx_get_addr_ptr(volatile uint32_t *txrx) {
- return (uint16_t) (*txrx & FSDEV_BD_ADDR_Msk);
- }
- static inline uint16_t fsdev_bd_tx_get_count_ptr(volatile uint32_t *txrx) {
- return (uint16_t) ((*txrx & FSDEV_BD_COUNT_TX_Msk) >> FSDEV_BD_COUNT_TX_Pos);
- }
- static inline void fsdev_bd_rx_set_addr_ptr(volatile uint32_t *rxtx, uint16_t pma_off) {
- if (pma_off & 0x3) {
- printf("[ERROR] fsdev_bd_tx_set_addr_ptr: Address 0x%04X not word-aligned!\n", pma_off);
- // Optionally: return early, assert, or handle error
- }
- uint32_t v = *rxtx;
- v &= ~FSDEV_BD_ADDR_Msk;
- v |= (uint32_t) (pma_off & 0xFFFCu);
- *rxtx = v;
- }
- static inline uint16_t fsdev_bd_rx_get_addr_ptr(volatile uint32_t *rxtx) {
- return fsdev_bd_tx_get_addr_ptr(rxtx); // same address layout
- }
- static inline void fsdev_bd_rx_set_count_ptr(volatile uint32_t *rxtx, uint16_t alloc_size) {
- uint32_t v = *rxtx;
- // Clear previous settings
- v &= ~(FSDEV_BD_BLSIZE_Msk | FSDEV_BD_NUMBLK_Msk | FSDEV_BD_COUNT_RX_Msk);
- // Configure block size (BLSIZE) and number of blocks (NUM_BLOCK)
- if (alloc_size <= 62) {
- // Use 2-byte blocks (BLSIZE=0)
- v |= (0 << FSDEV_BD_BLSIZE_Pos);
- v |= ((alloc_size / 2) << FSDEV_BD_NUMBLK_Pos);
- } else {
- // Use 32-byte blocks (BLSIZE=1)
- v |= (1 << FSDEV_BD_BLSIZE_Pos);
- v |= ((alloc_size / 32) << FSDEV_BD_NUMBLK_Pos);
- }
- *rxtx = v;
- }
- #define USB_PMA_FIRST_FREE 0x40 // First free byte offset in PMA (after BTABLE)
- /**
- * Align value up to next multiple of 4.
- * Is used as PMA access uses 32-bit words.
- */
- static inline uint16_t _align_up4(uint16_t value) {
- uint16_t remainder = value % 4;
- if (remainder == 0)
- return value; // already aligned
- else
- return (uint16_t) (value + (4 - remainder)); // round up to next multiple of 4
- }
- typedef struct {
- uint16_t next; /* next free byte offset (relative to PMA base) */
- } UsbPmaAllocator;
- static inline void usb_pma_allocator_init(UsbPmaAllocator *a) {
- a->next = USB_PMA_FIRST_FREE;
- }
- /**
- * Allocate `size_bytes` bytes from PMA.
- * Return -1 if not enough space.
- * @param allocator USB PMA allocator
- * @param size_bytes Number of bytes to allocate
- * @return
- */
- static inline uint16_t usb_pma_alloc(UsbPmaAllocator *allocator, uint16_t size_bytes) {
- const uint16_t start = _align_up4(allocator->next);
- const uint32_t end32 = (uint32_t) start + (uint32_t) size_bytes;
- /* end is exclusive; must not exceed the total PMA size */
- if (end32 > (uint32_t) FSDEV_PMA_SIZE) {
- return -1;
- }
- allocator->next = (int16_t) end32;
- // printf("[usb_pma_alloc] Allocated %u bytes at PMA offset 0x%04X, next free at 0x%04X\r\n",
- // size_bytes, start, allocator->next);
- return start;
- }
- /* Bytes consumed from PMA base (0..USB_PMA_LIMIT) */
- static inline uint16_t usb_pma_bytes_used(const UsbPmaAllocator *a) {
- return a->next;
- }
- /* Remaining bytes (clamped at 0) */
- static inline uint16_t usb_pma_bytes_free(const UsbPmaAllocator *a) {
- return (FSDEV_PMA_SIZE > a->next) ? (uint16_t) (FSDEV_PMA_SIZE - a->next) : (uint16_t) 0;
- }
- /* Pack 0..3 bytes into a 32-bit word (little-endian), zero-padding */
- static inline uint32_t fsdev_pack_le32(const uint8_t *s, uint16_t n) {
- uint32_t w = 0;
- if (n >= 1) w |= (uint32_t) s[0];
- if (n >= 2) w |= (uint32_t) s[1] << 8;
- if (n >= 3) w |= (uint32_t) s[2] << 16;
- return w;
- }
- /* Unpack up to 3 bytes from a 32-bit word (little-endian) */
- static inline void fsdev_unpack_le32(uint32_t w, uint8_t *d, uint16_t n) {
- if (n >= 1) d[0] = (uint8_t) (w & 0xFF);
- if (n >= 2) d[1] = (uint8_t) ((w >> 8) & 0xFF);
- if (n >= 3) d[2] = (uint8_t) ((w >> 16) & 0xFF);
- }
- //#define FSDEV_PMA_U32_BASE ((volatile uint32_t *)(USB_DRD_PMAADDR)) // PMA as 32-bit pointer
- static inline void fsdev_pma_write(uint16_t dst_off, const void *src, uint16_t len) {
- if ((dst_off & 0x3u) != 0u) {
- printf("[fsdev_pma_write] ERROR: PMA offset 0x%04X not 4-byte aligned\r\n", dst_off);
- return;
- }
- const uint8_t *s = (const uint8_t *) src;
- // Access entire PMA as 32-bit array (not just free_mem)
- volatile uint32_t *pma = (volatile uint32_t *) USB_DRD_PMAADDR;
- uint32_t idx = dst_off >> 2; // Convert byte offset to word index
- // printf("[fsdev_pma_write] Writing %u bytes to PMA offset 0x%04X (idx=%u)\r\n", len, dst_off, idx);
- while (len >= 4u) {
- uint32_t w = s[0] | (s[1] << 8) | (s[2] << 16) | (s[3] << 24);
- pma[idx++] = w;
- // printf("[fsdev_pma_write] Wrote 0x%08X\r\n", w);
- s += 4;
- len -= 4;
- }
- if (len != 0u) {
- uint32_t w = fsdev_pack_le32(s, len);
- pma[idx] = w;
- // printf("[fsdev_pma_write] Wrote tail 0x%08X for %u bytes\r\n", w, len);
- }
- }
- static inline void fsdev_pma_read(void *dst, uint16_t src_off, uint16_t len) {
- if ((src_off & 0x3u) != 0u) {
- printf("[fsdev_pma_read] ERROR: PMA offset 0x%04X not 4-byte aligned\r\n", src_off);
- return;
- }
- uint8_t *d = (uint8_t *) dst;
- // Access entire PMA as 32-bit array (not just free_mem)
- volatile uint32_t *pma = (volatile uint32_t *) USB_DRD_PMAADDR;
- uint32_t idx = src_off >> 2; // Convert byte offset to word index
- // printf("[fsdev_pma_read] Reading %u bytes from PMA offset 0x%04X (idx=%u)\r\n", len, src_off, idx);
- while (len >= 4u) {
- uint32_t w = pma[idx++];
- d[0] = (uint8_t) w;
- d[1] = (uint8_t) (w >> 8);
- d[2] = (uint8_t) (w >> 16);
- d[3] = (uint8_t) (w >> 24);
- // printf("[fsdev_pma_read] Read 0x%08X\r\n", w);
- d += 4;
- len -= 4;
- }
- if (len != 0u) {
- uint32_t w = pma[idx];
- fsdev_unpack_le32(w, d, len);
- // printf("[fsdev_pma_read] Read tail 0x%08X for %u bytes\r\n", w, len);
- }
- }
- /**
- *
- * PRINTING HELPERS FOR THE REGISTERS
- *
- */
- static inline const char *yesno(bool v) {
- return v ? "Yes" : "No";
- }
- static inline const char *onoff(bool v) { return v ? "On" : "Off"; }
- static inline const char *setclr(bool v) { return v ? "Set" : "Clear"; }
- static inline const char *enable(bool v) { return v ? "Enabled" : "Disabled"; }
- static inline void fsdev_usb_print_istr(uint32_t reg) {
- printf("[USB_ISTR] = 0x%08lX\r\n", (unsigned long) reg);
- printf(" CTR:%s PMAOVR:%s ERR:%s WKUP:%s SUSP:%s RST_DCON:%s\r\n",
- yesno(reg & USB_ISTR_CTR),
- yesno(reg & USB_ISTR_PMAOVR),
- yesno(reg & USB_ISTR_ERR),
- yesno(reg & USB_ISTR_WKUP),
- yesno(reg & USB_ISTR_SUSP),
- yesno(reg & USB_ISTR_RESET));
- printf(" SOF:%s ESOF:%s L1REQ:%s THR512:%s DCON_STAT:%s DDISC:%s LS_DCON:%s\r\n",
- yesno(reg & USB_ISTR_SOF),
- yesno(reg & USB_ISTR_ESOF),
- yesno(reg & USB_ISTR_L1REQ),
- yesno(reg & USB_ISTR_THR512),
- yesno(reg & USB_ISTR_DCON_STAT),
- yesno(reg & USB_ISTR_DCON),
- yesno(reg & USB_ISTR_LS_DCONN));
- const bool dir_rx = (reg & USB_ISTR_DIR) != 0;
- const unsigned idn = (reg & USB_ISTR_IDN);
- printf(" DIR:%s IDN:%u\r\n",
- dir_rx ? "RX/OUT (host->device)" : "TX/IN (device->host)",
- idn);
- }
- static inline void fsdev_usb_print_cntr(uint32_t reg) {
- printf("[USB_CNTR] = 0x%08lX\r\n", (unsigned long) reg);
- printf(" HOST:%s THR512M:%s CTRM:%s PMAOVRM:%s ERRM:%s WKUPM:%s SUSPM:%s\r\n",
- (reg & USB_CNTR_HOST) ? "Enabled" : "Device",
- onoff(reg & USB_CNTR_THR512M),
- onoff(reg & USB_CNTR_CTRM),
- onoff(reg & USB_CNTR_PMAOVRM),
- onoff(reg & USB_CNTR_ERRM),
- onoff(reg & USB_CNTR_WKUPM),
- onoff(reg & USB_CNTR_SUSPM));
- printf(" RESETM:%s SOFM:%s ESOFM:%s L1REQM:%s L1RES:%s L2RES:%s SUSPEN:%s\r\n",
- onoff(reg & USB_CNTR_RESETM),
- onoff(reg & USB_CNTR_SOFM),
- onoff(reg & USB_CNTR_ESOFM),
- onoff(reg & USB_CNTR_L1REQM),
- setclr(reg & USB_CNTR_L1RES),
- setclr(reg & USB_CNTR_L2RES),
- enable(reg & USB_CNTR_SUSPEN));
- printf(" SUSPRDY:%s PDWN:%s USBRST:%s\r\n",
- yesno(reg & USB_CNTR_SUSPRDY),
- onoff(reg & USB_CNTR_PDWN),
- (reg & USB_CNTR_USBRST) ? "Active" : "Inactive");
- }
- static inline void fsdev_usb_print_chep(uint32_t reg, unsigned chep_n) {
- const FsdevChepStatus rx = fsdev_chep_get_rx_status(reg);
- const FsdevChepStatus tx = fsdev_chep_get_tx_status(reg);
- const FsdevChepType tp = fsdev_chep_get_type(reg);
- static const char *stS[] = {"DIS", "STALL", "NAK", "VAL"};
- static const char *tpS[] = {"BULK", "CTRL", "ISO", "INTR"};
- const unsigned ea = (unsigned) fsdev_chep_get_devaddr(reg);
- const unsigned kind = (reg & USB_EP_KIND) ? 1u : 0u;
- const unsigned setup = (reg & USB_CHEP_SETUP) ? 1u : 0u;
- const unsigned dtog_rx = (reg & USB_CHEP_DTOG_RX) ? 1u : 0u;
- const unsigned dtog_tx = (reg & USB_CHEP_DTOG_TX) ? 1u : 0u;
- const unsigned vtrx = (reg & USB_CHEP_VTRX) ? 1u : 0u;
- const unsigned vttx = (reg & USB_CHEP_VTTX) ? 1u : 0u;
- const unsigned errrx = (reg & USB_CHEP_ERRRX) ? 1u : 0u;
- const unsigned errtx = (reg & USB_CHEP_ERRTX) ? 1u : 0u;
- const unsigned nak = (reg & USB_CHEP_NAK) ? 1u : 0u;
- // Optional “three consecutive errors” bits (present on U5):
- const unsigned three_rx = (reg & USB_CHEP_THREE_ERR_RX) ? 1u : 0u;
- const unsigned three_tx = (reg & USB_CHEP_THREE_ERR_TX) ? 1u : 0u;
- printf("[CHEP%u] 0x%08lX EA=%u TYPE=%s KIND=%u SETUP=%u RX:%s TX:%s\r\n",
- chep_n, (unsigned long) reg, ea, tpS[(unsigned) tp], kind, setup,
- stS[(unsigned) rx], stS[(unsigned) tx]);
- printf(" DTOG_RX:%u DTOG_TX:%u VTRX:%u VTTX:%u ERRrx:%u ERRtx:%u NAK:%u 3ERRrx:%u 3ERRtx:%u\r\n",
- dtog_rx, dtog_tx, vtrx, vttx, errrx, errtx, nak, three_rx, three_tx);
- }
- static inline void fsdev_usb_print_btable_at(volatile usb_sram_t *pma) {
- printf("[BTABLE] base=%p, entries=%u\r\n", (void *) &pma->btable[0], (unsigned) FSDEV_EP_COUNT);
- for (unsigned n = 0; n < FSDEV_EP_COUNT; ++n) {
- uint32_t tx = pma->btable[n].txrx;
- uint32_t rx = pma->btable[n].rxtx;
- uint16_t addr_tx = (uint16_t) (tx & FSDEV_BD_ADDR_Msk);
- uint16_t cnt_tx = (uint16_t) ((tx & FSDEV_BD_COUNT_TX_Msk) >> FSDEV_BD_COUNT_TX_Pos);
- uint16_t addr_rx = (uint16_t) (rx & FSDEV_BD_ADDR_Msk);
- uint16_t cnt_rx = (uint16_t) ((rx & FSDEV_BD_COUNT_RX_Msk) >> FSDEV_BD_COUNT_RX_Pos);
- uint8_t bl = (uint8_t) ((rx & FSDEV_BD_BLSIZE_Msk) >> FSDEV_BD_BLSIZE_Pos); /* 0=2B blocks, 1=32B blocks */
- uint8_t numblk = (uint8_t) ((rx & FSDEV_BD_NUMBLK_Msk) >> FSDEV_BD_NUMBLK_Pos);
- uint16_t cap = (numblk == 0) ? 0 : (bl ? (uint16_t) (32u * numblk) : (uint16_t) (2u * numblk));
- /* Optional: flag misalignment if ADDR bits[1:0] are not 0 (should always be 0) */
- const char *ax = ((addr_tx & 0x3u) == 0u) ? "" : "(!)";
- const char *ar = ((addr_rx & 0x3u) == 0u) ? "" : "(!)";
- printf(" EP%u TX:A=0x%04X%s C=%3u RX:A=0x%04X%s C=%3u ALLOC=%3u (%s, nb=%u)\r\n",
- n,
- addr_tx, ax, (unsigned) cnt_tx,
- addr_rx, ar, (unsigned) cnt_rx,
- (unsigned) cap, bl ? "32B" : "2B", (unsigned) numblk);
- }
- }
- static inline void fsdev_usb_print_btable_entry(uint32_t bd, bool is_tx) {
- const uint16_t addr = (uint16_t) (bd & FSDEV_BD_ADDR_Msk);
- const int misal = (addr & 0x3u) != 0u;
- if (is_tx) {
- const uint16_t cnt_tx = (uint16_t) ((bd & FSDEV_BD_COUNT_TX_Msk) >> FSDEV_BD_COUNT_TX_Pos);
- printf(" [BD TX] raw:0x%08lX ADDR:0x%04X%s CNT:%4u\r\n",
- (unsigned long) bd,
- addr, misal ? "(!)" : "",
- (unsigned) cnt_tx);
- } else {
- const uint16_t cnt_rx = (uint16_t) ((bd & FSDEV_BD_COUNT_RX_Msk) >> FSDEV_BD_COUNT_RX_Pos);
- const uint8_t bl = (uint8_t) ((bd & FSDEV_BD_BLSIZE_Msk) >> FSDEV_BD_BLSIZE_Pos); /* 0=2B, 1=32B */
- const uint8_t numblk = (uint8_t) ((bd & FSDEV_BD_NUMBLK_Msk) >> FSDEV_BD_NUMBLK_Pos);
- const uint16_t cap = (numblk == 0) ? 0u : (uint16_t) (bl ? (32u * numblk) : (2u * numblk));
- printf(" [BD RX] raw:0x%08lX ADDR:0x%04X%s CNT:%4u ALLOC:%4u (%s, nb=%u)\r\n",
- (unsigned long) bd,
- addr, misal ? "(!)" : "",
- (unsigned) cnt_rx,
- (unsigned) cap, bl ? "32B" : "2B", (unsigned) numblk);
- }
- }
- static inline void fsdev_usb_print_pma(const UsbPmaAllocator *a) {
- printf("[PMA] used=%u, free=%u, limit=%u\r\n",
- (unsigned) usb_pma_bytes_used(a),
- (unsigned) usb_pma_bytes_free(a),
- (unsigned) FSDEV_PMA_SIZE);
- }
- #ifdef __cplusplus
- }
- #endif
Advertisement
Add Comment
Please, Sign In to add comment