pio_usb_ll.h
1 /** 2 * Copyright (c) 2021 sekigon-gonnoc 3 * Ha Thach (thach@tinyusb.org) 4 */ 5 6 #pragma once 7 8 #include "hardware/pio.h" 9 #include "pio_usb_configuration.h" 10 #include "usb_definitions.h" 11 #include <stdint.h> 12 13 enum { 14 PIO_USB_INTS_CONNECT_POS = 0, 15 PIO_USB_INTS_DISCONNECT_POS, 16 PIO_USB_INTS_RESET_END_POS, 17 PIO_USB_INTS_SETUP_REQ_POS, 18 PIO_USB_INTS_SOF_POS, 19 20 PIO_USB_INTS_ENDPOINT_COMPLETE_POS, 21 PIO_USB_INTS_ENDPOINT_ERROR_POS, 22 PIO_USB_INTS_ENDPOINT_STALLED_POS, 23 PIO_USB_INTS_ENDPOINT_CONTINUE_POS, 24 }; 25 26 #define PIO_USB_INTS_CONNECT_BITS (1u << PIO_USB_INTS_CONNECT_POS) 27 #define PIO_USB_INTS_DISCONNECT_BITS (1u << PIO_USB_INTS_DISCONNECT_POS) 28 #define PIO_USB_INTS_RESET_END_BITS (1u << PIO_USB_INTS_RESET_END_POS) 29 #define PIO_USB_INTS_SETUP_REQ_BITS (1u << PIO_USB_INTS_SETUP_REQ_POS) 30 31 #define PIO_USB_INTS_SOF_BITS (1u << PIO_USB_INTS_SOF_POS) 32 33 #define PIO_USB_INTS_ENDPOINT_COMPLETE_BITS \ 34 (1u << PIO_USB_INTS_ENDPOINT_COMPLETE_POS) 35 #define PIO_USB_INTS_ENDPOINT_ERROR_BITS (1u << PIO_USB_INTS_ENDPOINT_ERROR_POS) 36 #define PIO_USB_INTS_ENDPOINT_STALLED_BITS \ 37 (1u << PIO_USB_INTS_ENDPOINT_STALLED_POS) 38 #define PIO_USB_INTS_ENDPOINT_CONTINUE_BITS \ 39 (1u << PIO_USB_INTS_ENDPOINT_CONTINUE_POS) 40 41 typedef enum { 42 PORT_PIN_SE0 = 0b00, 43 PORT_PIN_FS_IDLE = 0b01, 44 PORT_PIN_LS_IDLE = 0b10, 45 PORT_PIN_SE1 = 0b11, 46 } port_pin_status_t; 47 48 typedef struct { 49 uint16_t div_int; 50 uint8_t div_frac; 51 } pio_clk_div_t; 52 53 typedef struct { 54 PIO pio_usb_tx; // could not set to volatile 55 uint sm_tx; 56 uint offset_tx; 57 uint tx_ch; 58 59 PIO pio_usb_rx; // could not set to volatile 60 uint sm_rx; 61 uint offset_rx; 62 uint sm_eop; 63 uint offset_eop; 64 uint tx_reset_instr; 65 uint tx_start_instr; 66 uint rx_reset_instr; 67 uint rx_reset_instr2; 68 uint device_rx_irq_num; 69 70 int8_t debug_pin_rx; 71 int8_t debug_pin_eop; 72 73 const pio_program_t *fs_tx_program; 74 const pio_program_t *fs_tx_pre_program; 75 const pio_program_t *ls_tx_program; 76 77 pio_clk_div_t clk_div_fs_tx; 78 pio_clk_div_t clk_div_fs_rx; 79 pio_clk_div_t clk_div_ls_tx; 80 pio_clk_div_t clk_div_ls_rx; 81 82 bool need_pre; 83 84 uint8_t usb_rx_buffer[128]; 85 } pio_port_t; 86 87 //--------------------------------------------------------------------+ 88 // 89 //--------------------------------------------------------------------+ 90 91 enum { 92 PIO_USB_MODE_INVALID = 0, 93 PIO_USB_MODE_DEVICE, 94 PIO_USB_MODE_HOST, 95 }; 96 97 extern usb_device_t pio_usb_device[PIO_USB_DEVICE_CNT]; 98 99 extern root_port_t pio_usb_root_port[PIO_USB_ROOT_PORT_CNT]; 100 #define PIO_USB_ROOT_PORT(_idx) (pio_usb_root_port + (_idx)) 101 102 extern endpoint_t pio_usb_ep_pool[PIO_USB_EP_POOL_CNT]; 103 #define PIO_USB_ENDPOINT(_idx) (pio_usb_ep_pool + (_idx)) 104 105 extern pio_port_t pio_port[1]; 106 #define PIO_USB_PIO_PORT(_idx) (pio_port + (_idx)) 107 108 //--------------------------------------------------------------------+ 109 // Bus functions 110 //--------------------------------------------------------------------+ 111 112 #define IRQ_TX_EOP_MASK (1 << IRQ_TX_EOP) 113 #define IRQ_TX_ALL_MASK (IRQ_TX_EOP_MASK) 114 #define IRQ_RX_COMP_MASK (1 << IRQ_RX_EOP) 115 #define IRQ_RX_ALL_MASK \ 116 ((1 << IRQ_RX_EOP) | (1 << IRQ_RX_BS_ERR) | (1 << IRQ_RX_START) | \ 117 (1 << DECODER_TRIGGER)) 118 119 #define SM_SET_CLKDIV(pio, sm, div) \ 120 pio_sm_set_clkdiv_int_frac(pio, sm, div.div_int, div.div_frac) 121 #define SM_SET_CLKDIV_MAXSPEED(pio, sm) \ 122 pio_sm_set_clkdiv_int_frac(pio, sm, 1, 0) 123 124 void pio_usb_bus_init(pio_port_t *pp, const pio_usb_configuration_t *c, 125 root_port_t *root); 126 127 void pio_usb_bus_start_receive(const pio_port_t *pp); 128 void pio_usb_bus_prepare_receive(const pio_port_t *pp); 129 int pio_usb_bus_receive_packet_and_handshake(pio_port_t *pp, uint8_t handshake); 130 void pio_usb_bus_usb_transfer(const pio_port_t *pp, uint8_t *data, 131 uint16_t len); 132 133 uint8_t pio_usb_bus_wait_handshake(pio_port_t *pp); 134 void pio_usb_bus_send_handshake(const pio_port_t *pp, uint8_t pid); 135 void pio_usb_bus_send_token(const pio_port_t *pp, uint8_t token, uint8_t addr, 136 uint8_t ep_num); 137 138 static __always_inline port_pin_status_t 139 pio_usb_bus_get_line_state(root_port_t *root) { 140 uint8_t dp = gpio_get(root->pin_dp) ? 0 : 1; 141 uint8_t dm = gpio_get(root->pin_dm) ? 0 : 1; 142 143 return (dm << 1) | dp; 144 } 145 146 //--------------------------------------------------------------------+ 147 // Low Level functions 148 //--------------------------------------------------------------------+ 149 150 void pio_usb_ll_configure_endpoint(endpoint_t *ep, 151 uint8_t const *desc_endpoint); 152 bool pio_usb_ll_transfer_start(endpoint_t *ep, uint8_t *buffer, 153 uint16_t buflen); 154 bool pio_usb_ll_transfer_continue(endpoint_t *ep, uint16_t xferred_bytes); 155 void pio_usb_ll_transfer_complete(endpoint_t *ep, uint32_t flag); 156 157 static inline __force_inline uint16_t 158 pio_usb_ll_get_transaction_len(endpoint_t *ep) { 159 uint16_t remaining = ep->total_len - ep->actual_len; 160 return (remaining < ep->size) ? remaining : ep->size; 161 } 162 163 enum { 164 PIO_USB_TX_ENCODED_DATA_SE0 = 0, 165 PIO_USB_TX_ENCODED_DATA_K = 1, 166 PIO_USB_TX_ENCODED_DATA_COMP = 2, 167 PIO_USB_TX_ENCODED_DATA_J = 3, 168 }; 169 uint8_t pio_usb_ll_encode_tx_data(uint8_t const *buffer, uint8_t buffer_len, 170 uint8_t *encoded_data); 171 172 //-------------------------------------------------------------------- 173 // Host Controller functions 174 //-------------------------------------------------------------------- 175 176 // Host IRQ Handler 177 void pio_usb_host_irq_handler(uint8_t root_idx); 178 179 void pio_usb_host_port_reset_start(uint8_t root_idx); 180 void pio_usb_host_port_reset_end(uint8_t root_idx); 181 182 void pio_usb_host_close_device(uint8_t root_idx, uint8_t device_address); 183 184 bool pio_usb_host_endpoint_open(uint8_t root_idx, uint8_t device_address, 185 uint8_t const *desc_endpoint, bool need_pre); 186 bool pio_usb_host_send_setup(uint8_t root_idx, uint8_t device_address, 187 uint8_t const setup_packet[8]); 188 bool pio_usb_host_endpoint_transfer(uint8_t root_idx, uint8_t device_address, 189 uint8_t ep_address, uint8_t *buffer, 190 uint16_t buflen); 191 bool pio_usb_host_endpoint_abort_transfer(uint8_t root_idx, uint8_t device_address, 192 uint8_t ep_address); 193 194 //-------------------------------------------------------------------- 195 // Device Controller functions 196 //-------------------------------------------------------------------- 197 198 // Device IRQ Handler 199 void pio_usb_device_irq_handler(uint8_t root_idx); 200 201 void pio_usb_device_set_address(uint8_t dev_addr); 202 bool pio_usb_device_endpoint_open(uint8_t const *desc_endpoint); 203 bool pio_usb_device_transfer(uint8_t ep_address, uint8_t *buffer, 204 uint16_t buflen); 205 206 static inline __force_inline endpoint_t * 207 pio_usb_device_get_endpoint_by_address(uint8_t ep_address) { 208 // index = 2*num + dir e.g out1, in1, out2, in2 209 uint8_t const ep_idx = ((ep_address & 0x7f) << 1) | (ep_address >> 7); 210 return PIO_USB_ENDPOINT(ep_idx); 211 }