Created
March 28, 2023 07:43
-
-
Save SelvinPL/a871e26d6226d51e50add62a2681388d to your computer and use it in GitHub Desktop.
TinyUSB host implementation for CH58X (dirty not using IRQ)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include "ch58x_common.h" | |
#include "common/tusb_common.h" | |
#include "common/tusb_types.h" | |
#include "common/tusb_debug.h" | |
#include "hcd.h" | |
#include <assert.h> | |
#define ch58x_info(...) TU_LOG(2, __VA_ARGS__) | |
#define ch58x_trace(...) TU_LOG(3, __VA_ARGS__) | |
bool hcd_configure(uint8_t rhport, uint32_t cfg_id, const void* cfg_param) | |
{ | |
ch58x_info("hcd_configure\n"); | |
(void) rhport; | |
return true; | |
} | |
const uint8_t ENABLED_INTERRUPTS = RB_UIE_DETECT;// | RB_UIE_TRANSFER; | |
bool hcd_init(uint8_t rhport) | |
{ | |
ch58x_info("hcd_init\n"); | |
(void) rhport; | |
//setup | |
R8_USB2_CTRL = RB_UC_HOST_MODE; | |
R8_U2HOST_CTRL = 0; | |
R8_USB2_DEV_AD = 0x00; | |
R8_U2H_EP_MOD = RB_UH_EP_TX_EN | RB_UH_EP_RX_EN; | |
R16_U2H_RX_DMA = (uint16_t)(uint32_t)0; | |
R16_U2H_TX_DMA = (uint16_t)(uint32_t)0; | |
R8_U2H_RX_CTRL = 0x00; | |
R8_U2H_TX_CTRL = 0x00; | |
R8_USB2_CTRL = RB_UC_HOST_MODE | RB_UC_INT_BUSY | RB_UC_DMA_EN; | |
R8_U2H_SETUP = RB_UH_SOF_EN; | |
R8_USB2_INT_FG = 0xFF; | |
R8_USB2_INT_EN = ENABLED_INTERRUPTS; | |
PFIC_EnableIRQ(USB2_IRQn); | |
return true; | |
} | |
TU_ATTR_ALWAYS_INLINE static inline void SetupSpeed(tusb_speed_t speed) | |
{ | |
if(speed == TUSB_SPEED_FULL) | |
{ | |
R8_USB2_CTRL &= ~RB_UC_LOW_SPEED; | |
R8_U2H_SETUP &= ~RB_UH_PRE_PID_EN; | |
} | |
else | |
{ | |
R8_USB2_CTRL |= RB_UC_LOW_SPEED; | |
} | |
} | |
void hcd_port_reset(uint8_t rhport) | |
{ | |
ch58x_info("hcd_port_reset\n"); | |
R8_USB2_INT_EN &= ~ENABLED_INTERRUPTS; //disable detect interrupt | |
R8_USB2_DEV_AD = (R8_USB2_DEV_AD & RB_UDA_GP_BIT) | (0x00 & MASK_USB_ADDR); // set address to 0 | |
R8_U2HOST_CTRL &= ~RB_UH_PORT_EN; // disable port | |
SetupSpeed(TUSB_SPEED_FULL); | |
R8_U2HOST_CTRL = (R8_U2HOST_CTRL & ~RB_UH_LOW_SPEED) | RB_UH_BUS_RESET; // set full speed and reset | |
mDelaymS(15); // reset time 10-20ms | |
R8_U2HOST_CTRL = R8_U2HOST_CTRL & ~RB_UH_BUS_RESET; // reset end | |
mDelayuS(250); | |
R8_USB2_INT_FG = ENABLED_INTERRUPTS; // clear detect flag | |
} | |
TU_ATTR_ALWAYS_INLINE static inline bool StillAttached() | |
{ | |
if(R8_USB2_MIS_ST & RB_UMS_DEV_ATTACH) | |
{ | |
if((R8_U2HOST_CTRL & RB_UH_PORT_EN) == 0x00) | |
{ | |
if((R8_USB2_MIS_ST & RB_UMS_DM_LEVEL)) | |
R8_U2HOST_CTRL |= RB_UH_LOW_SPEED; | |
} | |
R8_U2HOST_CTRL |= RB_UH_PORT_EN; | |
return true; | |
} | |
return false; | |
} | |
tusb_speed_t hcd_port_speed_get(uint8_t rhport) | |
{ | |
ch58x_info("hcd_port_speed_get\n"); | |
return (R8_USB2_MIS_ST & RB_UMS_DM_LEVEL) ? TUSB_SPEED_LOW : TUSB_SPEED_FULL; | |
} | |
void hcd_port_reset_end(uint8_t rhport) | |
{ | |
ch58x_info("hcd_port_reset_end\n"); | |
int i, s; | |
for(i = 0, s = 0; i < 100; i++) | |
{ | |
mDelaymS(1); | |
if(StillAttached()) | |
{ | |
i = 0; | |
s++; | |
if(s > 100) | |
break; | |
} | |
} | |
if(i > 0) | |
ch58x_info("not connected!!!!\n"); | |
SetupSpeed(hcd_port_speed_get(rhport)); | |
R8_USB2_INT_EN |= ENABLED_INTERRUPTS; | |
} | |
TU_ATTR_ALWAYS_INLINE static inline uint8_t StartTransact(uint8_t control, uint8_t endp_pid, uint32_t timeout) | |
{ | |
uint8_t r; | |
uint16_t i; | |
uint8_t TransRetry = 0; | |
R8_U2H_RX_CTRL = R8_U2H_TX_CTRL = control; | |
do | |
{ | |
R8_U2H_EP_PID = endp_pid; | |
R8_USB2_INT_FG = RB_UIF_TRANSFER; | |
for(i = WAIT_USB_TOUT_200US; i != 0 && (R8_USB2_INT_FG & RB_UIF_TRANSFER) == 0; i--) | |
; | |
R8_U2H_EP_PID = 0x00; | |
if((R8_USB2_INT_FG & RB_UIF_TRANSFER) == 0) | |
{ | |
return (ERR_USB_UNKNOWN); | |
} | |
if(R8_USB2_INT_FG & RB_UIF_TRANSFER) | |
{ | |
if(R8_USB2_INT_ST & RB_UIS_TOG_OK) | |
{ | |
return (ERR_SUCCESS); | |
} | |
r = R8_USB2_INT_ST & MASK_UIS_H_RES; | |
if(r == USB_PID_STALL) | |
{ | |
return (r | ERR_USB_TRANSFER); | |
} | |
if(r == USB_PID_NAK) | |
{ | |
if(timeout == 0) | |
{ | |
return (r | ERR_USB_TRANSFER); | |
} | |
if(timeout < 0xFFFFFFFF) | |
timeout--; | |
--TransRetry; | |
} | |
else | |
switch(endp_pid >> 4) | |
{ | |
case USB_PID_SETUP: | |
case USB_PID_OUT: | |
if(r) | |
{ | |
return (r | ERR_USB_TRANSFER); | |
} | |
break; | |
case USB_PID_IN: | |
if(r == USB_PID_DATA0 || r == USB_PID_DATA1) | |
{ | |
} | |
else if(r) | |
{ | |
return (r | ERR_USB_TRANSFER); | |
} | |
break; | |
default: | |
return (ERR_USB_UNKNOWN); | |
} | |
} | |
else | |
{ | |
R8_USB2_INT_FG = 0xFF; | |
} | |
mDelayuS(15); | |
} while(++TransRetry < 3); | |
return (ERR_USB_TRANSFER); | |
} | |
bool hcd_port_connect_status(uint8_t rhport) | |
{ | |
bool status = R8_USB2_MIS_ST & RB_UMS_DEV_ATTACH; | |
ch58x_info("hcd_port_connect_status: %d\n", status); | |
return status; | |
} | |
// Close all opened endpoint belong to this device | |
void hcd_device_close(uint8_t rhport, uint8_t dev_addr) | |
{ | |
ch58x_info("hcd_device_close %d\n", dev_addr); | |
(void) rhport; | |
} | |
uint8_t saved_int = RB_UIE_DETECT | RB_UIE_TRANSFER; | |
void hcd_int_enable(uint8_t rhport) | |
{ | |
(void) rhport; | |
} | |
void hcd_int_disable(uint8_t rhport) | |
{ | |
(void) rhport; | |
} | |
bool hcd_edpt_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_endpoint_t const * desc_ep) | |
{ | |
R8_USB2_DEV_AD = (R8_USB2_DEV_AD & RB_UDA_GP_BIT) | (dev_addr & MASK_USB_ADDR); | |
ch58x_info("hcd_edpt_open dev_addr %d, ep_addr %d\n", dev_addr, desc_ep->bEndpointAddress); | |
return true; | |
} | |
bool hcd_edpt_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, uint8_t * buffer, uint16_t buflen) | |
{ | |
uint16_t RemLen = buflen; | |
uint8_t RxLen; | |
uint8_t *pBuf = buffer; | |
uint16_t len = 0; | |
ch58x_info("hcd_edpt_xfer dev_addr %d, ep_addr 0x%x, len %d\n", dev_addr, ep_addr, buflen); | |
if((ep_addr & 0xf0) == USB_REQ_TYP_IN) | |
{ | |
if((ep_addr & 0x7F) == 0) | |
{ | |
R8_U2H_RX_CTRL = R8_U2H_TX_CTRL = RB_UH_R_TOG | RB_UH_R_AUTO_TOG | RB_UH_T_TOG | RB_UH_T_AUTO_TOG; | |
} | |
R8_U2H_TX_LEN = 0x01; | |
if(RemLen) | |
{ | |
uint8_t s; | |
u_int8_t control; | |
R16_U2H_RX_DMA = (uint16_t)(uint32_t)pBuf; | |
while(RemLen) | |
{ | |
mDelayuS(200); | |
control = (ep_addr & 0x7F) ? RB_UH_R_TOG | RB_UH_T_TOG : R8_U2H_RX_CTRL; | |
s = StartTransact(control, USB_PID_IN << 4 | (ep_addr & 0x7F), (ep_addr & 0x7F) ? 0 : 200000 / 20); | |
control = 0; | |
if(s != ERR_SUCCESS) | |
{ | |
break; | |
} | |
RxLen = R8_USB2_RX_LEN < RemLen ? R8_USB2_RX_LEN : RemLen; | |
RemLen -= RxLen; | |
len += RxLen; | |
if(R8_USB2_RX_LEN == 0) | |
break; | |
pBuf += RxLen; | |
R16_U2H_RX_DMA = (uint16_t)(uint32_t)pBuf; | |
} | |
R16_U2H_RX_DMA = (uint16_t)(uint32_t)0; | |
R8_U2H_TX_LEN = 0x00; | |
if(s == ERR_SUCCESS) | |
{ | |
hcd_event_xfer_complete(dev_addr, (ep_addr & 0x7F) ? ep_addr : 0, len, XFER_RESULT_SUCCESS, false); | |
} | |
return true; | |
} | |
else | |
{ | |
if(StartTransact(RB_UH_R_TOG | RB_UH_T_TOG, (R8_U2H_TX_LEN ? USB_PID_IN << 4 | (ep_addr & 0x7F) : USB_PID_OUT << 4 | (ep_addr & 0x7F)), 200000 / 20) == ERR_SUCCESS) | |
{ | |
hcd_event_xfer_complete(dev_addr, 0, 0, XFER_RESULT_SUCCESS, false); | |
} | |
} | |
} | |
else if((ep_addr & 0xf0) == USB_REQ_TYP_STANDARD) | |
{ | |
ch58x_info("Toggle..\n"); | |
if(StartTransact(RB_UH_R_TOG | RB_UH_T_TOG, (R8_U2H_TX_LEN ? USB_PID_IN << 4 | (ep_addr & 0x7F) : USB_PID_OUT << 4 | (ep_addr & 0x7F)), 200000 / 20) == ERR_SUCCESS) | |
{ | |
hcd_event_xfer_complete(dev_addr, 0, 0, XFER_RESULT_SUCCESS, false); | |
} | |
} | |
else | |
{ | |
ch58x_info("What?\n"); | |
} | |
return true; | |
} | |
bool hcd_setup_send(uint8_t rhport, uint8_t dev_addr, uint8_t const setup_packet[8]) | |
{ | |
(void) rhport; | |
R16_U2H_TX_DMA = (uint16_t)(uint32_t)&setup_packet[0]; | |
R8_U2H_TX_LEN = 8; | |
if(StartTransact(0, USB_PID_SETUP << 4 | 0x00, 200000 / 20) == ERR_SUCCESS) | |
{ | |
hcd_event_xfer_complete(dev_addr, 0, 8, XFER_RESULT_SUCCESS, false); | |
} | |
return true; | |
} | |
__INTERRUPT | |
__HIGH_CODE | |
void USB2_IRQHandler(void) | |
{ | |
if(R8_USB2_INT_FG & RB_UIF_DETECT) | |
{ | |
R8_USB2_INT_EN &= ~RB_UIE_DETECT; | |
R8_USB2_INT_FG = RB_UIF_DETECT; | |
if(R8_USB2_MIS_ST & RB_UMS_DEV_ATTACH) | |
{ | |
hcd_event_device_attach(0, true); | |
} | |
else | |
{ | |
hcd_event_device_remove(0, true); | |
R8_USB2_INT_EN |= RB_UIE_DETECT; | |
} | |
} | |
if(R8_USB2_INT_FG & RB_UIF_TRANSFER) | |
{ | |
if((R8_USB2_INT_ST & USB_PID_ACK) == 0) | |
{ | |
printf("I:%x\n", R8_USB2_INT_ST); | |
} | |
else | |
{ | |
R8_USB2_INT_FG = RB_UIF_TRANSFER; | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment