add basic STM32G0 support
This commit is contained in:
@@ -216,7 +216,7 @@ TU_ATTR_ALWAYS_INLINE static inline void reg16_clear_bits(__IO uint16_t *reg, ui
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Bits in ISTR are cleared upon writing 0
|
// Bits in ISTR are cleared upon writing 0
|
||||||
TU_ATTR_ALWAYS_INLINE static inline void clear_istr_bits(uint16_t mask) {
|
TU_ATTR_ALWAYS_INLINE static inline void clear_istr_bits(uint32_t mask) {
|
||||||
USB->ISTR = ~mask;
|
USB->ISTR = ~mask;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -242,7 +242,13 @@ void dcd_init (uint8_t rhport)
|
|||||||
{
|
{
|
||||||
asm("NOP");
|
asm("NOP");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef PMA_32BIT_ACCESS // CNTR register is 32bits on STM32G0, 16bit on older versions
|
||||||
|
USB->CNTR &= ~USB_CNTR_PDWN;
|
||||||
|
#else
|
||||||
reg16_clear_bits(&USB->CNTR, USB_CNTR_PDWN);// Remove powerdown
|
reg16_clear_bits(&USB->CNTR, USB_CNTR_PDWN);// Remove powerdown
|
||||||
|
#endif
|
||||||
|
|
||||||
// Wait startup time, for F042 and F070, this is <= 1 us.
|
// Wait startup time, for F042 and F070, this is <= 1 us.
|
||||||
for(uint32_t i = 0; i<200; i++) // should be a few us
|
for(uint32_t i = 0; i<200; i++) // should be a few us
|
||||||
{
|
{
|
||||||
@@ -250,8 +256,9 @@ void dcd_init (uint8_t rhport)
|
|||||||
}
|
}
|
||||||
USB->CNTR = 0; // Enable USB
|
USB->CNTR = 0; // Enable USB
|
||||||
|
|
||||||
|
#ifndef STM32G0 // BTABLE register does not exist any more on STM32G0, it is fixed to USB SRAM base address
|
||||||
USB->BTABLE = DCD_STM32_BTABLE_BASE;
|
USB->BTABLE = DCD_STM32_BTABLE_BASE;
|
||||||
|
#endif
|
||||||
USB->ISTR = 0; // Clear pending interrupts
|
USB->ISTR = 0; // Clear pending interrupts
|
||||||
|
|
||||||
// Reset endpoints to disabled
|
// Reset endpoints to disabled
|
||||||
@@ -312,7 +319,7 @@ void dcd_sof_enable(uint8_t rhport, bool en)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
USB->CNTR &= (uint16_t) ~USB_CNTR_SOFM;
|
USB->CNTR &= ~USB_CNTR_SOFM;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -358,6 +365,9 @@ void dcd_int_enable (uint8_t rhport)
|
|||||||
NVIC_EnableIRQ(USB_LP_IRQn);
|
NVIC_EnableIRQ(USB_LP_IRQn);
|
||||||
NVIC_EnableIRQ(USBWakeUp_IRQn);
|
NVIC_EnableIRQ(USBWakeUp_IRQn);
|
||||||
|
|
||||||
|
#elif CFG_TUSB_MCU == OPT_MCU_STM32G0
|
||||||
|
NVIC_EnableIRQ(USB_UCPD1_2_IRQn);
|
||||||
|
|
||||||
#elif CFG_TUSB_MCU == OPT_MCU_STM32WB
|
#elif CFG_TUSB_MCU == OPT_MCU_STM32WB
|
||||||
NVIC_EnableIRQ(USB_HP_IRQn);
|
NVIC_EnableIRQ(USB_HP_IRQn);
|
||||||
NVIC_EnableIRQ(USB_LP_IRQn);
|
NVIC_EnableIRQ(USB_LP_IRQn);
|
||||||
@@ -405,6 +415,9 @@ void dcd_int_disable(uint8_t rhport)
|
|||||||
NVIC_DisableIRQ(USB_LP_IRQn);
|
NVIC_DisableIRQ(USB_LP_IRQn);
|
||||||
NVIC_DisableIRQ(USBWakeUp_IRQn);
|
NVIC_DisableIRQ(USBWakeUp_IRQn);
|
||||||
|
|
||||||
|
#elif CFG_TUSB_MCU == OPT_MCU_STM32G0
|
||||||
|
NVIC_DisableIRQ(USB_UCPD1_2_IRQn);
|
||||||
|
|
||||||
#elif CFG_TUSB_MCU == OPT_MCU_STM32WB
|
#elif CFG_TUSB_MCU == OPT_MCU_STM32WB
|
||||||
NVIC_DisableIRQ(USB_HP_IRQn);
|
NVIC_DisableIRQ(USB_HP_IRQn);
|
||||||
NVIC_DisableIRQ(USB_LP_IRQn);
|
NVIC_DisableIRQ(USB_LP_IRQn);
|
||||||
@@ -433,7 +446,7 @@ void dcd_remote_wakeup(uint8_t rhport)
|
|||||||
{
|
{
|
||||||
(void) rhport;
|
(void) rhport;
|
||||||
|
|
||||||
USB->CNTR |= (uint16_t) USB_CNTR_RESUME;
|
USB->CNTR |= USB_CNTR_RESUME;
|
||||||
remoteWakeCountdown = 4u; // required to be 1 to 15 ms, ESOF should trigger every 1ms.
|
remoteWakeCountdown = 4u; // required to be 1 to 15 ms, ESOF should trigger every 1ms.
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -534,9 +547,6 @@ static void dcd_ep_ctr_rx_handler(uint32_t wIstr)
|
|||||||
|
|
||||||
if((ep_addr == 0U) && ((wEPRegVal & USB_EP_SETUP) != 0U)) /* Setup packet */
|
if((ep_addr == 0U) && ((wEPRegVal & USB_EP_SETUP) != 0U)) /* Setup packet */
|
||||||
{
|
{
|
||||||
// The setup_received function uses memcpy, so this must first copy the setup data into
|
|
||||||
// user memory, to allow for the 32-bit access that memcpy performs.
|
|
||||||
uint8_t userMemBuf[8];
|
|
||||||
uint32_t count = pcd_get_ep_rx_cnt(USB, EPindex);
|
uint32_t count = pcd_get_ep_rx_cnt(USB, EPindex);
|
||||||
/* Get SETUP Packet*/
|
/* Get SETUP Packet*/
|
||||||
if(count == 8) // Setup packet should always be 8 bytes. If not, ignore it, and try again.
|
if(count == 8) // Setup packet should always be 8 bytes. If not, ignore it, and try again.
|
||||||
@@ -544,8 +554,15 @@ static void dcd_ep_ctr_rx_handler(uint32_t wIstr)
|
|||||||
// Must reset EP to NAK (in case it had been stalling) (though, maybe too late here)
|
// Must reset EP to NAK (in case it had been stalling) (though, maybe too late here)
|
||||||
pcd_set_ep_rx_status(USB,0u,USB_EP_RX_NAK);
|
pcd_set_ep_rx_status(USB,0u,USB_EP_RX_NAK);
|
||||||
pcd_set_ep_tx_status(USB,0u,USB_EP_TX_NAK);
|
pcd_set_ep_tx_status(USB,0u,USB_EP_TX_NAK);
|
||||||
dcd_read_packet_memory(userMemBuf, *pcd_ep_rx_address_ptr(USB,EPindex), 8);
|
#ifdef PMA_32BIT_ACCESS
|
||||||
|
dcd_event_setup_received(0, (uint8_t*)(USB_PMAADDR + pcd_get_ep_rx_address(USB, EPindex)), true);
|
||||||
|
#else
|
||||||
|
// The setup_received function uses memcpy, so this must first copy the setup data into
|
||||||
|
// user memory, to allow for the 32-bit access that memcpy performs.
|
||||||
|
uint8_t userMemBuf[8];
|
||||||
|
dcd_read_packet_memory(userMemBuf, pcd_get_ep_rx_address(USB,EPindex), 8);
|
||||||
dcd_event_setup_received(0, (uint8_t*)userMemBuf, true);
|
dcd_event_setup_received(0, (uint8_t*)userMemBuf, true);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -568,7 +585,7 @@ static void dcd_ep_ctr_rx_handler(uint32_t wIstr)
|
|||||||
|
|
||||||
if (count != 0U)
|
if (count != 0U)
|
||||||
{
|
{
|
||||||
uint16_t addr = *pcd_ep_rx_address_ptr(USB, EPindex);
|
uint16_t addr = pcd_get_ep_rx_address(USB, EPindex);
|
||||||
|
|
||||||
if (xfer->ff)
|
if (xfer->ff)
|
||||||
{
|
{
|
||||||
@@ -672,8 +689,13 @@ void dcd_int_handler(uint8_t rhport) {
|
|||||||
|
|
||||||
if (int_status & USB_ISTR_WKUP)
|
if (int_status & USB_ISTR_WKUP)
|
||||||
{
|
{
|
||||||
|
#ifdef PMA_32BIT_ACCESS // CNTR register is 32bits on STM32G0, 16bit on older versions
|
||||||
|
USB->CNTR &= ~USB_CNTR_LPMODE;
|
||||||
|
USB->CNTR &= ~USB_CNTR_FSUSP;
|
||||||
|
#else
|
||||||
reg16_clear_bits(&USB->CNTR, USB_CNTR_LPMODE);
|
reg16_clear_bits(&USB->CNTR, USB_CNTR_LPMODE);
|
||||||
reg16_clear_bits(&USB->CNTR, USB_CNTR_FSUSP);
|
reg16_clear_bits(&USB->CNTR, USB_CNTR_FSUSP);
|
||||||
|
#endif
|
||||||
clear_istr_bits(USB_ISTR_WKUP);
|
clear_istr_bits(USB_ISTR_WKUP);
|
||||||
dcd_event_bus_signal(0, DCD_EVENT_RESUME, true);
|
dcd_event_bus_signal(0, DCD_EVENT_RESUME, true);
|
||||||
}
|
}
|
||||||
@@ -695,7 +717,7 @@ void dcd_int_handler(uint8_t rhport) {
|
|||||||
if(int_status & USB_ISTR_ESOF) {
|
if(int_status & USB_ISTR_ESOF) {
|
||||||
if(remoteWakeCountdown == 1u)
|
if(remoteWakeCountdown == 1u)
|
||||||
{
|
{
|
||||||
USB->CNTR &= (uint16_t)(~USB_CNTR_RESUME);
|
USB->CNTR &= ~USB_CNTR_RESUME;
|
||||||
}
|
}
|
||||||
if(remoteWakeCountdown > 0u)
|
if(remoteWakeCountdown > 0u)
|
||||||
{
|
{
|
||||||
@@ -722,8 +744,13 @@ void dcd_edpt0_status_complete(uint8_t rhport, tusb_control_request_t const * re
|
|||||||
uint8_t const dev_addr = (uint8_t) request->wValue;
|
uint8_t const dev_addr = (uint8_t) request->wValue;
|
||||||
|
|
||||||
// Setting new address after the whole request is complete
|
// Setting new address after the whole request is complete
|
||||||
|
#ifdef PMA_32BIT_ACCESS
|
||||||
|
USB->DADDR &= ~USB_DADDR_ADD;
|
||||||
|
USB->DADDR = (USB->DADDR & ~USB_DADDR_ADD_Msk) | dev_addr; // leave the enable bit set
|
||||||
|
#else
|
||||||
reg16_clear_bits(&USB->DADDR, USB_DADDR_ADD);
|
reg16_clear_bits(&USB->DADDR, USB_DADDR_ADD);
|
||||||
USB->DADDR = (uint16_t)(USB->DADDR | dev_addr); // leave the enable bit set
|
USB->DADDR = (uint16_t)(USB->DADDR | dev_addr); // leave the enable bit set
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -925,14 +952,14 @@ bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * p_endpoint_desc
|
|||||||
|
|
||||||
if( (dir == TUSB_DIR_IN) || (wType == USB_EP_ISOCHRONOUS) )
|
if( (dir == TUSB_DIR_IN) || (wType == USB_EP_ISOCHRONOUS) )
|
||||||
{
|
{
|
||||||
*pcd_ep_tx_address_ptr(USB, ep_idx) = pma_addr;
|
pcd_set_ep_tx_address(USB, ep_idx, pma_addr);
|
||||||
pcd_set_ep_tx_bufsize(USB, ep_idx, buffer_size);
|
pcd_set_ep_tx_bufsize(USB, ep_idx, buffer_size);
|
||||||
pcd_clear_tx_dtog(USB, ep_idx);
|
pcd_clear_tx_dtog(USB, ep_idx);
|
||||||
}
|
}
|
||||||
|
|
||||||
if( (dir == TUSB_DIR_OUT) || (wType == USB_EP_ISOCHRONOUS) )
|
if( (dir == TUSB_DIR_OUT) || (wType == USB_EP_ISOCHRONOUS) )
|
||||||
{
|
{
|
||||||
*pcd_ep_rx_address_ptr(USB, ep_idx) = pma_addr;
|
pcd_set_ep_rx_address(USB, ep_idx, pma_addr);
|
||||||
pcd_set_ep_rx_bufsize(USB, ep_idx, buffer_size);
|
pcd_set_ep_rx_bufsize(USB, ep_idx, buffer_size);
|
||||||
pcd_clear_rx_dtog(USB, ep_idx);
|
pcd_clear_rx_dtog(USB, ep_idx);
|
||||||
}
|
}
|
||||||
@@ -1012,8 +1039,8 @@ bool dcd_edpt_iso_alloc(uint8_t rhport, uint8_t ep_addr, uint16_t largest_packet
|
|||||||
|
|
||||||
pcd_set_eptype(USB, ep_idx, USB_EP_ISOCHRONOUS);
|
pcd_set_eptype(USB, ep_idx, USB_EP_ISOCHRONOUS);
|
||||||
|
|
||||||
*pcd_ep_tx_address_ptr(USB, ep_idx) = pma_addr;
|
pcd_set_ep_tx_address(USB, ep_idx, pma_addr);
|
||||||
*pcd_ep_rx_address_ptr(USB, ep_idx) = pma_addr;
|
pcd_set_ep_rx_address(USB, ep_idx, pma_addr);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -1063,7 +1090,7 @@ static void dcd_transmit_packet(xfer_ctl_t * xfer, uint16_t ep_ix)
|
|||||||
}
|
}
|
||||||
|
|
||||||
uint16_t ep_reg = pcd_get_endpoint(USB, ep_ix);
|
uint16_t ep_reg = pcd_get_endpoint(USB, ep_ix);
|
||||||
uint16_t addr_ptr = *pcd_ep_tx_address_ptr(USB,ep_ix);
|
uint16_t addr_ptr = pcd_get_ep_tx_address(USB, ep_ix);
|
||||||
|
|
||||||
if (xfer->ff)
|
if (xfer->ff)
|
||||||
{
|
{
|
||||||
@@ -1197,6 +1224,19 @@ void dcd_edpt_clear_stall (uint8_t rhport, uint8_t ep_addr)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef PMA_32BIT_ACCESS
|
||||||
|
static bool dcd_write_packet_memory(uint16_t dst, const void *__restrict src, size_t wNBytes)
|
||||||
|
{
|
||||||
|
// FIXME original function uses byte-access to source memory (to support non-aligned buffers)
|
||||||
|
const uint32_t* src32 = (uint32_t*)(src);
|
||||||
|
uint32_t* dst32 = (uint32_t*)(USB_PMAADDR + dst);
|
||||||
|
for (unsigned n=wNBytes/4; n>0; --n) {
|
||||||
|
*dst32++ = *src32++;
|
||||||
|
}
|
||||||
|
*dst32 = (*src32) & ((1<<8*(wNBytes % 4)) - 1);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
#else
|
||||||
// Packet buffer access can only be 8- or 16-bit.
|
// Packet buffer access can only be 8- or 16-bit.
|
||||||
/**
|
/**
|
||||||
* @brief Copy a buffer from user memory area to packet memory area (PMA).
|
* @brief Copy a buffer from user memory area to packet memory area (PMA).
|
||||||
@@ -1239,6 +1279,7 @@ static bool dcd_write_packet_memory(uint16_t dst, const void *__restrict src, si
|
|||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Copy from FIFO to packet memory area (PMA).
|
* @brief Copy from FIFO to packet memory area (PMA).
|
||||||
@@ -1290,6 +1331,14 @@ static bool dcd_write_packet_memory_ff(tu_fifo_t * ff, uint16_t dst, uint16_t wN
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef PMA_32BIT_ACCESS
|
||||||
|
static bool dcd_read_packet_memory(void *__restrict dst, uint16_t src, size_t wNBytes)
|
||||||
|
{
|
||||||
|
// FIXME this should probably be modified for possible unaligned access?
|
||||||
|
memcpy(dst, (void*)(USB_PMAADDR+src), wNBytes);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
#else
|
||||||
/**
|
/**
|
||||||
* @brief Copy a buffer from packet memory area (PMA) to user memory area.
|
* @brief Copy a buffer from packet memory area (PMA) to user memory area.
|
||||||
* Uses byte-access of system memory and 16-bit access of packet memory
|
* Uses byte-access of system memory and 16-bit access of packet memory
|
||||||
@@ -1323,6 +1372,7 @@ static bool dcd_read_packet_memory(void *__restrict dst, uint16_t src, size_t wN
|
|||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Copy a buffer from user packet memory area (PMA) to FIFO.
|
* @brief Copy a buffer from user packet memory area (PMA) to FIFO.
|
||||||
|
@@ -82,6 +82,34 @@
|
|||||||
#include "stm32g4xx.h"
|
#include "stm32g4xx.h"
|
||||||
#define PMA_LENGTH (1024u)
|
#define PMA_LENGTH (1024u)
|
||||||
|
|
||||||
|
#elif CFG_TUSB_MCU == OPT_MCU_STM32G0
|
||||||
|
#include "STM32/stm32g0xx.h"
|
||||||
|
#define PMA_32BIT_ACCESS
|
||||||
|
#define PMA_LENGTH (1024u) // FIXME it is 2048, really
|
||||||
|
#undef USB_PMAADDR
|
||||||
|
#define USB_PMAADDR USB_DRD_PMAADDR
|
||||||
|
#define USB_TypeDef USB_DRD_TypeDef
|
||||||
|
#define EP0R CHEP0R
|
||||||
|
#define USB_EP_CTR_RX USB_EP_VTRX
|
||||||
|
#define USB_EP_CTR_TX USB_EP_VTTX
|
||||||
|
#define USB_EP_T_FIELD USB_CHEP_UTYPE
|
||||||
|
#define USB_EPREG_MASK USB_CHEP_REG_MASK
|
||||||
|
#define USB_EPTX_DTOGMASK USB_CHEP_TX_DTOGMASK
|
||||||
|
#define USB_EPRX_DTOGMASK USB_CHEP_RX_DTOGMASK
|
||||||
|
#define USB_EPTX_DTOG1 USB_CHEP_TX_DTOG1
|
||||||
|
#define USB_EPTX_DTOG2 USB_CHEP_TX_DTOG2
|
||||||
|
#define USB_EPRX_DTOG1 USB_CHEP_RX_DTOG1
|
||||||
|
#define USB_EPRX_DTOG2 USB_CHEP_RX_DTOG2
|
||||||
|
#define USB_EPRX_STAT USB_CH_RX_VALID
|
||||||
|
#define USB_EPKIND_MASK USB_EP_KIND_MASK
|
||||||
|
#define USB USB_DRD_FS
|
||||||
|
#define USB_CNTR_FRES USB_CNTR_USBRST
|
||||||
|
#define USB_CNTR_RESUME USB_CNTR_L2RES
|
||||||
|
#define USB_ISTR_EP_ID USB_ISTR_IDN
|
||||||
|
#define USB_EPADDR_FIELD USB_CHEP_ADDR
|
||||||
|
#define USB_CNTR_LPMODE USB_CNTR_SUSPRDY
|
||||||
|
#define USB_CNTR_FSUSP USB_CNTR_SUSPEN
|
||||||
|
|
||||||
#elif CFG_TUSB_MCU == OPT_MCU_STM32WB
|
#elif CFG_TUSB_MCU == OPT_MCU_STM32WB
|
||||||
#include "stm32wbxx.h"
|
#include "stm32wbxx.h"
|
||||||
#define PMA_LENGTH (1024u)
|
#define PMA_LENGTH (1024u)
|
||||||
@@ -105,15 +133,31 @@
|
|||||||
#define PMA_STRIDE (1u)
|
#define PMA_STRIDE (1u)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// And for type-safety create a new macro for the volatile address of PMAADDR
|
// For type-safety create a new macro for the volatile address of PMAADDR
|
||||||
// The compiler should warn us if we cast it to a non-volatile type?
|
// The compiler should warn us if we cast it to a non-volatile type?
|
||||||
|
#ifdef PMA_32BIT_ACCESS
|
||||||
|
static __IO uint32_t * const pma32 = (__IO uint32_t*)USB_PMAADDR;
|
||||||
|
#else
|
||||||
// Volatile is also needed to prevent the optimizer from changing access to 32-bit (as 32-bit access is forbidden)
|
// Volatile is also needed to prevent the optimizer from changing access to 32-bit (as 32-bit access is forbidden)
|
||||||
static __IO uint16_t * const pma = (__IO uint16_t*)USB_PMAADDR;
|
static __IO uint16_t * const pma = (__IO uint16_t*)USB_PMAADDR;
|
||||||
|
|
||||||
// prototypes
|
TU_ATTR_ALWAYS_INLINE static inline __IO uint16_t * pcd_btable_word_ptr(USB_TypeDef * USBx, size_t x)
|
||||||
TU_ATTR_ALWAYS_INLINE static inline __IO uint16_t* pcd_ep_rx_cnt_ptr(USB_TypeDef * USBx, uint32_t bEpIdx);
|
{
|
||||||
TU_ATTR_ALWAYS_INLINE static inline __IO uint16_t* pcd_ep_tx_cnt_ptr(USB_TypeDef * USBx, uint32_t bEpIdx);
|
size_t total_word_offset = (((USBx)->BTABLE)>>1) + x;
|
||||||
TU_ATTR_ALWAYS_INLINE static inline void pcd_set_endpoint(USB_TypeDef * USBx, uint32_t bEpIdx, uint32_t wRegValue);
|
total_word_offset *= PMA_STRIDE;
|
||||||
|
return &(pma[total_word_offset]);
|
||||||
|
}
|
||||||
|
|
||||||
|
TU_ATTR_ALWAYS_INLINE static inline __IO uint16_t* pcd_ep_tx_cnt_ptr(USB_TypeDef * USBx, uint32_t bEpIdx)
|
||||||
|
{
|
||||||
|
return pcd_btable_word_ptr(USBx,(bEpIdx)*4u + 1u);
|
||||||
|
}
|
||||||
|
|
||||||
|
TU_ATTR_ALWAYS_INLINE static inline __IO uint16_t* pcd_ep_rx_cnt_ptr(USB_TypeDef * USBx, uint32_t bEpIdx)
|
||||||
|
{
|
||||||
|
return pcd_btable_word_ptr(USBx,(bEpIdx)*4u + 3u);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Aligned buffer size according to hardware */
|
/* Aligned buffer size according to hardware */
|
||||||
TU_ATTR_ALWAYS_INLINE static inline uint16_t pcd_aligned_buffer_size(uint16_t size)
|
TU_ATTR_ALWAYS_INLINE static inline uint16_t pcd_aligned_buffer_size(uint16_t size)
|
||||||
@@ -131,13 +175,22 @@ TU_ATTR_ALWAYS_INLINE static inline uint16_t pcd_aligned_buffer_size(uint16_t si
|
|||||||
/* SetENDPOINT */
|
/* SetENDPOINT */
|
||||||
TU_ATTR_ALWAYS_INLINE static inline void pcd_set_endpoint(USB_TypeDef * USBx, uint32_t bEpIdx, uint32_t wRegValue)
|
TU_ATTR_ALWAYS_INLINE static inline void pcd_set_endpoint(USB_TypeDef * USBx, uint32_t bEpIdx, uint32_t wRegValue)
|
||||||
{
|
{
|
||||||
|
#ifdef PMA_32BIT_ACCESS
|
||||||
|
__O uint32_t *reg = (__O uint32_t *)(USB_DRD_BASE + bEpIdx*4);
|
||||||
|
*reg = wRegValue;
|
||||||
|
#else
|
||||||
__O uint16_t *reg = (__O uint16_t *)((&USBx->EP0R) + bEpIdx*2u);
|
__O uint16_t *reg = (__O uint16_t *)((&USBx->EP0R) + bEpIdx*2u);
|
||||||
*reg = (uint16_t)wRegValue;
|
*reg = (uint16_t)wRegValue;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/* GetENDPOINT */
|
/* GetENDPOINT */
|
||||||
TU_ATTR_ALWAYS_INLINE static inline uint16_t pcd_get_endpoint(USB_TypeDef * USBx, uint32_t bEpIdx) {
|
TU_ATTR_ALWAYS_INLINE static inline uint32_t pcd_get_endpoint(USB_TypeDef * USBx, uint32_t bEpIdx) {
|
||||||
|
#ifdef PMA_32BIT_ACCESS
|
||||||
|
__I uint32_t *reg = (__I uint32_t *)(USB_DRD_BASE + bEpIdx*4);
|
||||||
|
#else
|
||||||
__I uint16_t *reg = (__I uint16_t *)((&USBx->EP0R) + bEpIdx*2u);
|
__I uint16_t *reg = (__I uint16_t *)((&USBx->EP0R) + bEpIdx*2u);
|
||||||
|
#endif
|
||||||
return *reg;
|
return *reg;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -187,34 +240,22 @@ TU_ATTR_ALWAYS_INLINE static inline void pcd_clear_tx_ep_ctr(USB_TypeDef * USBx,
|
|||||||
*/
|
*/
|
||||||
TU_ATTR_ALWAYS_INLINE static inline uint32_t pcd_get_ep_tx_cnt(USB_TypeDef * USBx, uint32_t bEpIdx)
|
TU_ATTR_ALWAYS_INLINE static inline uint32_t pcd_get_ep_tx_cnt(USB_TypeDef * USBx, uint32_t bEpIdx)
|
||||||
{
|
{
|
||||||
|
#ifdef PMA_32BIT_ACCESS
|
||||||
|
return (pma32[2*bEpIdx] & 0x03FF0000) >> 16;
|
||||||
|
#else
|
||||||
__I uint16_t *regPtr = pcd_ep_tx_cnt_ptr(USBx, bEpIdx);
|
__I uint16_t *regPtr = pcd_ep_tx_cnt_ptr(USBx, bEpIdx);
|
||||||
return *regPtr & 0x3ffU;
|
return *regPtr & 0x3ffU;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
TU_ATTR_ALWAYS_INLINE static inline uint32_t pcd_get_ep_rx_cnt(USB_TypeDef * USBx, uint32_t bEpIdx)
|
TU_ATTR_ALWAYS_INLINE static inline uint32_t pcd_get_ep_rx_cnt(USB_TypeDef * USBx, uint32_t bEpIdx)
|
||||||
{
|
{
|
||||||
|
#ifdef PMA_32BIT_ACCESS
|
||||||
|
return (pma32[2*bEpIdx + 1] & 0x03FF0000) >> 16;
|
||||||
|
#else
|
||||||
__I uint16_t *regPtr = pcd_ep_rx_cnt_ptr(USBx, bEpIdx);
|
__I uint16_t *regPtr = pcd_ep_rx_cnt_ptr(USBx, bEpIdx);
|
||||||
return *regPtr & 0x3ffU;
|
return *regPtr & 0x3ffU;
|
||||||
}
|
#endif
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Sets counter of rx buffer with no. of blocks.
|
|
||||||
* @param dwReg Register
|
|
||||||
* @param wCount Counter.
|
|
||||||
* @param wNBlocks no. of Blocks.
|
|
||||||
* @retval None
|
|
||||||
*/
|
|
||||||
TU_ATTR_ALWAYS_INLINE static inline void pcd_set_ep_cnt_reg(__O uint16_t * pdwReg, size_t wCount)
|
|
||||||
{
|
|
||||||
/* We assume that the buffer size is already aligned to hardware requirements. */
|
|
||||||
uint16_t blocksize = (wCount > 62) ? 1 : 0;
|
|
||||||
uint16_t numblocks = wCount / (blocksize ? 32 : 2);
|
|
||||||
|
|
||||||
/* There should be no remainder in the above calculation */
|
|
||||||
TU_ASSERT((wCount - (numblocks * (blocksize ? 32 : 2))) == 0, /**/);
|
|
||||||
|
|
||||||
/* Encode into register. When BLSIZE==1, we need to subtract 1 block count */
|
|
||||||
*pdwReg = (blocksize << 15) | ((numblocks - blocksize) << 10);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -233,57 +274,96 @@ TU_ATTR_ALWAYS_INLINE static inline void pcd_set_ep_address(USB_TypeDef * USBx,
|
|||||||
pcd_set_endpoint(USBx, bEpIdx,regVal);
|
pcd_set_endpoint(USBx, bEpIdx,regVal);
|
||||||
}
|
}
|
||||||
|
|
||||||
TU_ATTR_ALWAYS_INLINE static inline __IO uint16_t * pcd_btable_word_ptr(USB_TypeDef * USBx, size_t x)
|
TU_ATTR_ALWAYS_INLINE static inline uint32_t pcd_get_ep_tx_address(USB_TypeDef * USBx, uint32_t bEpIdx)
|
||||||
{
|
{
|
||||||
size_t total_word_offset = (((USBx)->BTABLE)>>1) + x;
|
#ifdef PMA_32BIT_ACCESS
|
||||||
total_word_offset *= PMA_STRIDE;
|
return pma32[2*bEpIdx] & 0x0000FFFFu ;
|
||||||
return &(pma[total_word_offset]);
|
#else
|
||||||
|
return *pcd_btable_word_ptr(USBx,(bEpIdx)*4u + 0u);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
// Pointers to the PMA table entries (using the ARM address space)
|
TU_ATTR_ALWAYS_INLINE static inline uint32_t pcd_get_ep_rx_address(USB_TypeDef * USBx, uint32_t bEpIdx)
|
||||||
TU_ATTR_ALWAYS_INLINE static inline __IO uint16_t* pcd_ep_tx_address_ptr(USB_TypeDef * USBx, uint32_t bEpIdx)
|
|
||||||
{
|
{
|
||||||
return pcd_btable_word_ptr(USBx,(bEpIdx)*4u + 0u);
|
#ifdef PMA_32BIT_ACCESS
|
||||||
}
|
return pma32[2*bEpIdx + 1] & 0x0000FFFFu;
|
||||||
TU_ATTR_ALWAYS_INLINE static inline __IO uint16_t* pcd_ep_tx_cnt_ptr(USB_TypeDef * USBx, uint32_t bEpIdx)
|
#else
|
||||||
{
|
return *pcd_btable_word_ptr(USBx,(bEpIdx)*4u + 2u);
|
||||||
return pcd_btable_word_ptr(USBx,(bEpIdx)*4u + 1u);
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
TU_ATTR_ALWAYS_INLINE static inline __IO uint16_t* pcd_ep_rx_address_ptr(USB_TypeDef * USBx, uint32_t bEpIdx)
|
TU_ATTR_ALWAYS_INLINE static inline void pcd_set_ep_tx_address(USB_TypeDef * USBx, uint32_t bEpIdx, uint32_t addr)
|
||||||
{
|
{
|
||||||
return pcd_btable_word_ptr(USBx,(bEpIdx)*4u + 2u);
|
#ifdef PMA_32BIT_ACCESS
|
||||||
|
pma32[2*bEpIdx] = (pma32[2*bEpIdx] & 0xFFFF0000u) | (addr & 0x0000FFFCu);
|
||||||
|
#else
|
||||||
|
*pcd_btable_word_ptr(USBx,(bEpIdx)*4u + 0u) = addr;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
TU_ATTR_ALWAYS_INLINE static inline __IO uint16_t* pcd_ep_rx_cnt_ptr(USB_TypeDef * USBx, uint32_t bEpIdx)
|
TU_ATTR_ALWAYS_INLINE static inline void pcd_set_ep_rx_address(USB_TypeDef * USBx, uint32_t bEpIdx, uint32_t addr)
|
||||||
{
|
{
|
||||||
return pcd_btable_word_ptr(USBx,(bEpIdx)*4u + 3u);
|
#ifdef PMA_32BIT_ACCESS
|
||||||
|
pma32[2*bEpIdx + 1] = (pma32[2*bEpIdx + 1] & 0xFFFF0000u) | (addr & 0x0000FFFCu);
|
||||||
|
#else
|
||||||
|
*pcd_btable_word_ptr(USBx,(bEpIdx)*4u + 2u) = addr;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
TU_ATTR_ALWAYS_INLINE static inline void pcd_set_ep_tx_cnt(USB_TypeDef * USBx, uint32_t bEpIdx, uint32_t wCount)
|
TU_ATTR_ALWAYS_INLINE static inline void pcd_set_ep_tx_cnt(USB_TypeDef * USBx, uint32_t bEpIdx, uint32_t wCount)
|
||||||
{
|
{
|
||||||
|
#ifdef PMA_32BIT_ACCESS
|
||||||
|
pma32[2*bEpIdx] = (pma32[2*bEpIdx] & ~0x03FF0000u) | ((wCount & 0x3FFu) << 16);
|
||||||
|
#else
|
||||||
__IO uint16_t * reg = pcd_ep_tx_cnt_ptr(USBx, bEpIdx);
|
__IO uint16_t * reg = pcd_ep_tx_cnt_ptr(USBx, bEpIdx);
|
||||||
*reg = (uint16_t) (*reg & (uint16_t) ~0x3FFU) | (wCount & 0x3FFU);
|
*reg = (uint16_t) (*reg & (uint16_t) ~0x3FFU) | (wCount & 0x3FFU);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
TU_ATTR_ALWAYS_INLINE static inline void pcd_set_ep_rx_cnt(USB_TypeDef * USBx, uint32_t bEpIdx, uint32_t wCount)
|
TU_ATTR_ALWAYS_INLINE static inline void pcd_set_ep_rx_cnt(USB_TypeDef * USBx, uint32_t bEpIdx, uint32_t wCount)
|
||||||
{
|
{
|
||||||
|
#ifdef PMA_32BIT_ACCESS
|
||||||
|
pma32[2*bEpIdx + 1] = (pma32[2*bEpIdx + 1] & ~0x03FF0000u) | ((wCount & 0x3FFu) << 16);
|
||||||
|
#else
|
||||||
__IO uint16_t * reg = pcd_ep_rx_cnt_ptr(USBx, bEpIdx);
|
__IO uint16_t * reg = pcd_ep_rx_cnt_ptr(USBx, bEpIdx);
|
||||||
*reg = (uint16_t) (*reg & (uint16_t) ~0x3FFU) | (wCount & 0x3FFU);
|
*reg = (uint16_t) (*reg & (uint16_t) ~0x3FFU) | (wCount & 0x3FFU);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
TU_ATTR_ALWAYS_INLINE static inline void pcd_set_ep_blsize_num_blocks(USB_TypeDef * USBx, uint32_t rxtx_idx, uint32_t blocksize, uint32_t numblocks)
|
||||||
|
{
|
||||||
|
/* Encode into register. When BLSIZE==1, we need to subtract 1 block count */
|
||||||
|
#ifdef PMA_32BIT_ACCESS
|
||||||
|
pma32[rxtx_idx] = (pma32[rxtx_idx] & 0x0000FFFFu) | (blocksize << 31) | ((numblocks - blocksize) << 26);
|
||||||
|
#else
|
||||||
|
__IO uint16_t *pdwReg = pcd_btable_word_ptr(USBx, rxtx_idx*2u + 1u);
|
||||||
|
*pdwReg = (blocksize << 15) | ((numblocks - blocksize) << 10);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
TU_ATTR_ALWAYS_INLINE static inline void pcd_set_ep_bufsize(USB_TypeDef * USBx, uint32_t rxtx_idx, uint32_t wCount)
|
||||||
|
{
|
||||||
|
wCount = pcd_aligned_buffer_size(wCount);
|
||||||
|
|
||||||
|
/* We assume that the buffer size is already aligned to hardware requirements. */
|
||||||
|
uint16_t blocksize = (wCount > 62) ? 1 : 0;
|
||||||
|
uint16_t numblocks = wCount / (blocksize ? 32 : 2);
|
||||||
|
|
||||||
|
/* There should be no remainder in the above calculation */
|
||||||
|
TU_ASSERT((wCount - (numblocks * (blocksize ? 32 : 2))) == 0, /**/);
|
||||||
|
|
||||||
|
/* Encode into register. When BLSIZE==1, we need to subtract 1 block count */
|
||||||
|
pcd_set_ep_blsize_num_blocks(USBx, rxtx_idx, blocksize, numblocks);
|
||||||
}
|
}
|
||||||
|
|
||||||
TU_ATTR_ALWAYS_INLINE static inline void pcd_set_ep_tx_bufsize(USB_TypeDef * USBx, uint32_t bEpIdx, uint32_t wCount)
|
TU_ATTR_ALWAYS_INLINE static inline void pcd_set_ep_tx_bufsize(USB_TypeDef * USBx, uint32_t bEpIdx, uint32_t wCount)
|
||||||
{
|
{
|
||||||
__IO uint16_t *pdwReg = pcd_ep_tx_cnt_ptr((USBx),(bEpIdx));
|
pcd_set_ep_bufsize(USBx, 2*bEpIdx, wCount);
|
||||||
wCount = pcd_aligned_buffer_size(wCount);
|
|
||||||
pcd_set_ep_cnt_reg(pdwReg, wCount);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TU_ATTR_ALWAYS_INLINE static inline void pcd_set_ep_rx_bufsize(USB_TypeDef * USBx, uint32_t bEpIdx, uint32_t wCount)
|
TU_ATTR_ALWAYS_INLINE static inline void pcd_set_ep_rx_bufsize(USB_TypeDef * USBx, uint32_t bEpIdx, uint32_t wCount)
|
||||||
{
|
{
|
||||||
__IO uint16_t *pdwReg = pcd_ep_rx_cnt_ptr((USBx),(bEpIdx));
|
pcd_set_ep_bufsize(USBx, 2*bEpIdx + 1, wCount);
|
||||||
wCount = pcd_aligned_buffer_size(wCount);
|
|
||||||
pcd_set_ep_cnt_reg(pdwReg, wCount);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
Reference in New Issue
Block a user