1
0
mirror of https://github.com/RIOT-OS/RIOT.git synced 2025-12-26 06:53:52 +01:00

cpu/stm32/usbdev_fs: fix EP_REG(x) assignment for toggleable bits

EP_REG(x) registers have a total of 6 toggleable bits. Those bits can only be toggled if we write a one to it, otherwise writing a zero has no effect
This commit fixes all the access to these registers to prevent from modifying these bits when not needed

Signed-off-by: Dylan Laduranty <dylan.laduranty@mesotic.com>
This commit is contained in:
Dylan Laduranty 2023-04-07 21:21:30 +02:00
parent 164331eb0d
commit 701242d38d

View File

@ -132,6 +132,10 @@ typedef struct {
#error "_PMA_ACCESS_SCHEME is not defined"
#endif
/* Bit mask containing all toggleable bits in a EP_REG(x) register */
#define _EP_REG_TOGGLE_ONLY_BITS_MASK (USB_EP_DTOG_TX | USB_EP_DTOG_RX | \
USB_EPTX_STAT | USB_EPRX_STAT )
#define EP_DESC ((ep_buf_desc_t*)USB1_PMAADDR)
#define EP_REG(x) (*((volatile uint32_t*) (((uintptr_t)(USB)) + (4*x))))
@ -313,8 +317,9 @@ void USBDEV_ISR(void) {
unsigned epnum = irq_status & 0x000F;
usbdev_ep_t *ep = (irq_status & USB_ISTR_DIR) ? &_ep_out[epnum] : &_ep_in[epnum];
/* get type and add endpoint address */
uint16_t reg = _type_to_reg(ep->type) | ep->num;
uint16_t reg = (_type_to_reg(ep->type) | ep->num);
/* Avoid toggling by mistake these bits */
CLRBIT(reg, (_EP_REG_TOGGLE_ONLY_BITS_MASK));
if (irq_status & USB_ISTR_DIR) {
/* Clear RX CTR by writing 0, avoid clear TX CTR so leave it to one */
EP_REG(epnum) = reg | USB_EP_CTR_TX;
@ -422,8 +427,10 @@ static bool _ep_check(stm32_usbdev_fs_t *usbdev, unsigned idx,
static void _ep_enable(usbdev_ep_t *ep)
{
uint16_t reg = EP_REG(ep->num);
/* Avoid modification of the following registers */
/* Avoid modification of the following bits in the register as writing
1 has no effect on these bits */
SETBIT(reg, USB_EP_CTR_RX | USB_EP_CTR_TX);
CLRBIT(reg, USB_EP_DTOG_RX | USB_EP_DTOG_TX);
if (ep->dir == USB_EP_DIR_OUT) {
_set_ep_out_status(&reg, USB_EP_RX_NAK);
/* Avoid toggling the other direction */
@ -441,7 +448,8 @@ static void _ep_enable(usbdev_ep_t *ep)
static void _ep_disable(usbdev_ep_t *ep)
{
uint16_t reg = EP_REG(ep->num);
/* Avoid modification of the following registers */
/* Avoid modification of the following bits in the register as writing
1 has no effect on these bits */
SETBIT(reg, USB_EP_CTR_RX | USB_EP_CTR_TX);
if (ep->dir == USB_EP_DIR_OUT) {
@ -580,16 +588,17 @@ static void _usbdev_esr(usbdev_t *dev)
static void _usbdev_ep_init(usbdev_ep_t *ep)
{
uint16_t reg = EP_REG(ep->num);
/* Set endpoint type */
uint16_t reg = _type_to_reg(ep->type);
/* Keep previous state if already set */
reg |= EP_REG(ep->num) & (USB_EPTX_STAT | USB_EPRX_STAT);
_set_ep_out_status(&reg, USB_EP_RX_VALID);
reg &= ~(USB_EP_TYPE_MASK);
reg |= _type_to_reg(ep->type);
/* Keep the state ouf the other endpoint direction if already sets */
CLRBIT(reg, _EP_REG_TOGGLE_ONLY_BITS_MASK);
/* Assign EP address */
reg |= (ep->num & 0x000F);
/* Ensure interrupts are cleared */
reg |= USB_EP_CTR_RX | USB_EP_CTR_TX;
reg &= ~(USB_EP_CTR_RX | USB_EP_CTR_TX);
/* Write the configuration to the register */
EP_REG(ep->num) = reg;
if (ep->dir == USB_EP_DIR_IN) {
EP_DESC[ep->num].addr_tx = _ep_in_buf[ep->num];
@ -653,7 +662,8 @@ static int _usbdev_ep_get(usbdev_ep_t *ep, usbopt_ep_t opt,
static void _ep_set_stall(usbdev_ep_t *ep, usbopt_enable_t enable)
{
uint16_t reg = EP_REG(ep->num);
/* Avoid modification of the following registers */
/* Avoid modification of the following bits in the register as writing
1 has no effect on these bits */
SETBIT(reg, USB_EP_CTR_RX | USB_EP_CTR_TX);
if (ep->dir == USB_EP_DIR_IN) {
@ -742,11 +752,12 @@ static int _usbdev_ep_xmit(usbdev_ep_t *ep, uint8_t* buf, size_t len)
{
unsigned irq = irq_disable();
uint16_t reg = EP_REG(ep->num);
/* Avoid modification of the following registers */
/* Avoid modification of the following bits in the register as writing
1 has no effect on these bits */
SETBIT(reg, USB_EP_CTR_RX | USB_EP_CTR_TX);
if (ep->dir == USB_EP_DIR_OUT) {
_set_ep_out_status(&reg, USB_EP_RX_VALID);
_set_ep_in_status(&reg, USB_EP_TX_NAK);
CLRBIT(reg, USB_EPTX_STAT);
if (len == 0) {
len = ep->len;
}
@ -761,8 +772,7 @@ static int _usbdev_ep_xmit(usbdev_ep_t *ep, uint8_t* buf, size_t len)
_app_pbuf[ep->num] = buf;
} else {
_set_ep_in_status(&reg, USB_EP_TX_VALID);
_set_ep_out_status(&reg, USB_EP_RX_VALID);
CLRBIT(reg, USB_EPRX_STAT);
/* Transfer IN buffer content to USB PMA SRAM */
uint16_t* pma_ptr = (uint16_t *)(USB1_PMAADDR +
(EP_DESC[ep->num].addr_tx * _PMA_ACCESS_STEP_SIZE));