Skip to content

Instantly share code, notes, and snippets.

@SelvinPL
Created March 28, 2023 07:43
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save SelvinPL/a871e26d6226d51e50add62a2681388d to your computer and use it in GitHub Desktop.
Save SelvinPL/a871e26d6226d51e50add62a2681388d to your computer and use it in GitHub Desktop.
TinyUSB host implementation for CH58X (dirty not using IRQ)
#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