diff --git a/cpu/nrf52/periph/usbdev.c b/cpu/nrf52/periph/usbdev.c index e63d6b8cdc..26d8ef4ff8 100644 --- a/cpu/nrf52/periph/usbdev.c +++ b/cpu/nrf52/periph/usbdev.c @@ -112,6 +112,8 @@ static inline void poweron(nrfusb_t *usbdev) *(volatile uint32_t *)0x4006EC00 = 0x00009375; /* Enable peripheral a second time */ + /* cppcheck-suppress redundantAssignment + * (reason: re-enabled as per nordic instructions for this errata) */ usbdev->device->ENABLE = USBD_ENABLE_ENABLE_Msk; } @@ -129,7 +131,8 @@ static void usb_detach(nrfusb_t *usbdev) static void _ep_set_address(usbdev_ep_t *ep) { - nrfusb_t *usbdev = (nrfusb_t*)ep->dev; + nrfusb_t *usbdev = (nrfusb_t *)ep->dev; + if (ep->dir == USB_EP_DIR_OUT) { usbdev->device->EPOUT[ep->num].PTR = (uint32_t)ep->buf; } @@ -140,8 +143,9 @@ static void _ep_set_address(usbdev_ep_t *ep) static void _copy_setup(usbdev_ep_t *ep) { - nrfusb_t *usbdev = (nrfusb_t*)ep->dev; - usb_setup_t *setup = (usb_setup_t*)ep->buf; + nrfusb_t *usbdev = (nrfusb_t *)ep->dev; + usb_setup_t *setup = (usb_setup_t *)ep->buf; + setup->type = usbdev->device->BMREQUESTTYPE; setup->request = usbdev->device->BREQUEST; setup->value = usbdev->device->WVALUEL | usbdev->device->WVALUEH << 8; @@ -158,7 +162,8 @@ static void _copy_setup(usbdev_ep_t *ep) static int _ep_set_size(usbdev_ep_t *ep) { /* TODO: validate size */ - nrfusb_t *usbdev = (nrfusb_t*)ep->dev; + nrfusb_t *usbdev = (nrfusb_t *)ep->dev; + if (ep->dir == USB_EP_DIR_OUT) { usbdev->device->EPOUT[ep->num].MAXCNT = (uint32_t)ep->len; } @@ -168,7 +173,8 @@ static int _ep_set_size(usbdev_ep_t *ep) static void _ep_enable(usbdev_ep_t *ep) { DEBUG("Enabling endpoint %u dir %s\n", ep->num, ep->dir == USB_EP_DIR_OUT ? "OUT" : "IN"); - nrfusb_t *usbdev = (nrfusb_t*)ep->dev; + nrfusb_t *usbdev = (nrfusb_t *)ep->dev; + if (ep->dir == USB_EP_DIR_OUT) { usbdev->device->EPOUTEN |= 1 << ep->num; } @@ -181,7 +187,8 @@ static void _ep_disable(usbdev_ep_t *ep) { /* TODO: validate size */ DEBUG("disabling endpoint %u dir %s\n", ep->num, ep->dir == USB_EP_DIR_OUT ? "OUT" : "IN"); - nrfusb_t *usbdev = (nrfusb_t*)ep->dev; + nrfusb_t *usbdev = (nrfusb_t *)ep->dev; + if (ep->dir == USB_EP_DIR_OUT) { usbdev->device->EPOUTEN &= ~(1 << ep->num); } @@ -193,17 +200,19 @@ static void _ep_disable(usbdev_ep_t *ep) static void _ep_set_stall(usbdev_ep_t *ep, usbopt_enable_t enable) { /* TODO: validate size */ - nrfusb_t *usbdev = (nrfusb_t*)ep->dev; + nrfusb_t *usbdev = (nrfusb_t *)ep->dev; uint32_t val = (ep->num & USBD_EPSTALL_EP_Msk) | - (ep->dir == USB_EP_DIR_IN ? USBD_EPSTALL_IO_Msk : 0) | - (enable ? USBD_EPSTALL_STALL_Msk : 0); + (ep->dir == USB_EP_DIR_IN ? USBD_EPSTALL_IO_Msk : 0) | + (enable ? USBD_EPSTALL_STALL_Msk : 0); + usbdev->device->EPSTALL = val; } static usbopt_enable_t _ep_get_stall(usbdev_ep_t *ep) { /* TODO: validate size */ - nrfusb_t *usbdev = (nrfusb_t*)ep->dev; + nrfusb_t *usbdev = (nrfusb_t *)ep->dev; + if (ep->dir == USB_EP_DIR_OUT) { return usbdev->device->HALTED.EPOUT[ep->num] ? USBOPT_ENABLE : USBOPT_DISABLE; @@ -217,7 +226,8 @@ static usbopt_enable_t _ep_get_stall(usbdev_ep_t *ep) static size_t _ep_get_available(usbdev_ep_t *ep) { /* TODO: validate size */ - nrfusb_t *usbdev = (nrfusb_t*)ep->dev; + nrfusb_t *usbdev = (nrfusb_t *)ep->dev; + if (ep->dir == USB_EP_DIR_OUT) { return usbdev->device->SIZE.EPOUT[ep->num]; } @@ -228,7 +238,8 @@ static size_t _ep_get_available(usbdev_ep_t *ep) static void _ep_dma_out(usbdev_ep_t *ep) { - nrfusb_t *usbdev = (nrfusb_t*)ep->dev; + nrfusb_t *usbdev = (nrfusb_t *)ep->dev; + assert(ep->dir == USB_EP_DIR_OUT); _enable_errata_199(); usbdev->device->TASKS_STARTEPOUT[ep->num] = 1; @@ -241,7 +252,8 @@ static void _ep_dma_out(usbdev_ep_t *ep) static void _ep_dma_in(usbdev_ep_t *ep) { - nrfusb_t *usbdev = (nrfusb_t*)ep->dev; + nrfusb_t *usbdev = (nrfusb_t *)ep->dev; + assert(ep->dir == USB_EP_DIR_IN); _enable_errata_199(); usbdev->device->TASKS_STARTEPIN[ep->num] = 1; @@ -270,9 +282,10 @@ static void _init(usbdev_t *dev) { DEBUG("nrfusb: initializing\n"); /* Engineering revision version A is affected by errata 94, crash * - * instead of pretending to have functional USB */ + * instead of pretending to have functional USB */ assert(NRF_FICR->INFO.VARIANT != 0x41414141); - nrfusb_t *usbdev = (nrfusb_t*)dev; + nrfusb_t *usbdev = (nrfusb_t *)dev; + poweron(usbdev); usbdev->used = 0; usbdev->sstate = NRFUSB_SETUP_READY; @@ -289,51 +302,57 @@ static int _get(usbdev_t *usbdev, usbopt_t opt, void *value, size_t max_len) (void)usbdev; (void)max_len; int res = -ENOTSUP; + switch (opt) { - case USBOPT_MAX_VERSION: - assert(max_len == sizeof(usb_version_t)); - *(usb_version_t *)value = USB_VERSION_20; - res = sizeof(usb_version_t); - break; - case USBOPT_MAX_SPEED: - assert(max_len == sizeof(usb_speed_t)); - *(usb_speed_t *)value = USB_SPEED_FULL; - res = sizeof(usb_speed_t); - break; - default: - DEBUG("unhandled get call: 0x%x\n", opt); - break; + case USBOPT_MAX_VERSION: + assert(max_len == sizeof(usb_version_t)); + *(usb_version_t *)value = USB_VERSION_20; + res = sizeof(usb_version_t); + break; + case USBOPT_MAX_SPEED: + assert(max_len == sizeof(usb_speed_t)); + *(usb_speed_t *)value = USB_SPEED_FULL; + res = sizeof(usb_speed_t); + break; + default: + DEBUG("unhandled get call: 0x%x\n", opt); + break; } return res; } static int _set(usbdev_t *dev, usbopt_t opt, - const void *value, size_t value_len) + const void *value, size_t value_len) { - nrfusb_t *usbdev = (nrfusb_t*)dev; + nrfusb_t *usbdev = (nrfusb_t *)dev; + (void)value_len; int res = -ENOTSUP; + switch (opt) { - case USBOPT_ATTACH: - assert(value_len == sizeof(usbopt_enable_t)); - if (*((usbopt_enable_t *)value)) { - usb_attach(usbdev); - } - else { - usb_detach(usbdev); - } - res = sizeof(usbopt_enable_t); - break; - default: - DEBUG("Unhandled set call: 0x%x\n", opt); - break; + case USBOPT_ATTACH: + assert(value_len == sizeof(usbopt_enable_t)); + if (*((usbopt_enable_t *)value)) { + usb_attach(usbdev); + } + else { + usb_detach(usbdev); + } + res = sizeof(usbopt_enable_t); + break; + default: + DEBUG("Unhandled set call: 0x%x\n", opt); + break; } return res; } -static usbdev_ep_t *_new_ep(usbdev_t *dev, usb_ep_type_t type, usb_ep_dir_t dir, size_t buf_len) +static usbdev_ep_t *_new_ep(usbdev_t *dev, + usb_ep_type_t type, + usb_ep_dir_t dir, + size_t buf_len) { - nrfusb_t *usbdev = (nrfusb_t*)dev; + nrfusb_t *usbdev = (nrfusb_t *)dev; /* The IP supports all types for all endpoints */ usbdev_ep_t *res = NULL; @@ -355,7 +374,9 @@ static usbdev_ep_t *_new_ep(usbdev_t *dev, usb_ep_type_t type, usb_ep_dir_t dir, if (res) { res->dev = dev; res->dir = dir; - DEBUG("nrfusb: Allocated new ep (%d %s)\n", res->num, res->dir == USB_EP_DIR_OUT ? "OUT" : "IN"); + DEBUG("nrfusb: Allocated new ep (%d %s)\n", + res->num, + res->dir == USB_EP_DIR_OUT ? "OUT" : "IN"); if (usbdev->used + buf_len < NRF_USB_BUF_SPACE) { res->buf = usbdev->buffer + usbdev->used; res->len = buf_len; @@ -376,7 +397,8 @@ static usbdev_ep_t *_new_ep(usbdev_t *dev, usb_ep_type_t type, usb_ep_dir_t dir, static void _ep_enable_irq(usbdev_ep_t *ep) { - nrfusb_t *usbdev = (nrfusb_t*)ep->dev; + nrfusb_t *usbdev = (nrfusb_t *)ep->dev; + if (ep->dir == USB_EP_DIR_IN) { if (ep->num == 0) { usbdev->device->INTENSET = USBD_INTENSET_EP0DATADONE_Msk; @@ -391,7 +413,8 @@ static void _ep_enable_irq(usbdev_ep_t *ep) static void _ep_disable_irq(usbdev_ep_t *ep) { - nrfusb_t *usbdev = (nrfusb_t*)ep->dev; + nrfusb_t *usbdev = (nrfusb_t *)ep->dev; + if (ep->dir == USB_EP_DIR_IN) { if (ep->num == 0) { usbdev->device->INTENCLR = USBD_INTENCLR_EP0DATADONE_Msk; @@ -406,7 +429,8 @@ static void _ep_disable_irq(usbdev_ep_t *ep) static void _ep_init(usbdev_ep_t *ep) { - nrfusb_t *usbdev = (nrfusb_t*)ep->dev; + nrfusb_t *usbdev = (nrfusb_t *)ep->dev; + _ep_set_size(ep); _ep_set_address(ep); if (ep->num == 0) { @@ -423,67 +447,70 @@ static void _ep_init(usbdev_ep_t *ep) } static int _ep_get(usbdev_ep_t *ep, usbopt_ep_t opt, - void *value, size_t max_len) + void *value, size_t max_len) { (void)max_len; int res = -ENOTSUP; + switch (opt) { - case USBOPT_EP_STALL: - assert(max_len == sizeof(usbopt_enable_t)); - *(usbopt_enable_t *)value = _ep_get_stall(ep); - res = sizeof(usbopt_enable_t); - break; - case USBOPT_EP_AVAILABLE: - assert(max_len == sizeof(size_t)); - *(size_t *)value = _ep_get_available(ep); - res = sizeof(size_t); - break; - default: - DEBUG("Unhandled get call: 0x%x\n", opt); - break; + case USBOPT_EP_STALL: + assert(max_len == sizeof(usbopt_enable_t)); + *(usbopt_enable_t *)value = _ep_get_stall(ep); + res = sizeof(usbopt_enable_t); + break; + case USBOPT_EP_AVAILABLE: + assert(max_len == sizeof(size_t)); + *(size_t *)value = _ep_get_available(ep); + res = sizeof(size_t); + break; + default: + DEBUG("Unhandled get call: 0x%x\n", opt); + break; } return res; } static int _ep_set(usbdev_ep_t *ep, usbopt_ep_t opt, - const void *value, size_t value_len) + const void *value, size_t value_len) { (void)value_len; int res = -ENOTSUP; + switch (opt) { - case USBOPT_EP_ENABLE: - assert(value_len == sizeof(usbopt_enable_t)); - if (*((usbopt_enable_t *)value)) { - _ep_enable(ep); - _ep_init(ep); - } - else { - _ep_disable(ep); - } + case USBOPT_EP_ENABLE: + assert(value_len == sizeof(usbopt_enable_t)); + if (*((usbopt_enable_t *)value)) { + _ep_enable(ep); + _ep_init(ep); + } + else { + _ep_disable(ep); + } + res = sizeof(usbopt_enable_t); + break; + case USBOPT_EP_STALL: + assert(value_len == sizeof(usbopt_enable_t)); + _ep_set_stall(ep, *(usbopt_enable_t *)value); + res = sizeof(usbopt_enable_t); + break; + case USBOPT_EP_READY: + assert(value_len == sizeof(usbopt_enable_t)); + if (*((usbopt_enable_t *)value)) { + _ep_ready(ep, 0); res = sizeof(usbopt_enable_t); - break; - case USBOPT_EP_STALL: - assert(value_len == sizeof(usbopt_enable_t)); - _ep_set_stall(ep, *(usbopt_enable_t *)value); - res = sizeof(usbopt_enable_t); - break; - case USBOPT_EP_READY: - assert(value_len == sizeof(usbopt_enable_t)); - if (*((usbopt_enable_t *)value)) { - _ep_ready(ep, 0); - res = sizeof(usbopt_enable_t); - } - break; - default: - DEBUG("Unhandled set call: 0x%x\n", opt); - break; + } + break; + default: + DEBUG("Unhandled set call: 0x%x\n", opt); + break; } return res; } static int _ep0_ready(usbdev_ep_t *ep, size_t len) { - nrfusb_t *usbdev = (nrfusb_t*)ep->dev; + nrfusb_t *usbdev = (nrfusb_t *)ep->dev; + if (ep->dir == USB_EP_DIR_IN) { if (len == 0 && usbdev->sstate == NRFUSB_SETUP_WRITE) { usbdev->device->TASKS_EP0STATUS = 1; @@ -512,7 +539,8 @@ static int _ep0_ready(usbdev_ep_t *ep, size_t len) static int _ep_ready(usbdev_ep_t *ep, size_t len) { - nrfusb_t *usbdev = (nrfusb_t*)ep->dev; + nrfusb_t *usbdev = (nrfusb_t *)ep->dev; + if (ep->num == 0) { /* Endpoint 0 requires special handling as per datasheet sec 6.35.9 */ return _ep0_ready(ep, len); @@ -531,7 +559,8 @@ static int _ep_ready(usbdev_ep_t *ep, size_t len) static void _esr(usbdev_t *dev) { - nrfusb_t *usbdev = (nrfusb_t*)dev; + nrfusb_t *usbdev = (nrfusb_t *)dev; + if (usbdev->device->EVENTS_USBRESET) { DEBUG("nrfusb: reset condition\n"); usbdev->device->EVENTS_USBRESET = 0; @@ -556,8 +585,9 @@ static void _esr(usbdev_t *dev) static signed _ep0_esr(usbdev_ep_t *ep) { - nrfusb_t *usbdev = (nrfusb_t*)ep->dev; + nrfusb_t *usbdev = (nrfusb_t *)ep->dev; signed event = -1; + if (ep->dir == USB_EP_DIR_OUT) { if (usbdev->sstate == NRFUSB_SETUP_ACKOUT) { usbdev->sstate = NRFUSB_SETUP_READY; @@ -593,8 +623,9 @@ static signed _ep0_esr(usbdev_ep_t *ep) static void _ep_esr(usbdev_ep_t *ep) { - nrfusb_t *usbdev = (nrfusb_t*)ep->dev; + nrfusb_t *usbdev = (nrfusb_t *)ep->dev; signed event = -1; + if (ep->num == 0) { event = _ep0_esr(ep); } @@ -628,14 +659,15 @@ void isr_usbd(void) { /* Only one usb peripheral possible at the moment */ nrfusb_t *usbdev = &_usbdevs[0]; + /* Generic USB peripheral events */ if (usbdev->device->EVENTS_USBRESET && - (usbdev->device->INTEN & USBD_INTEN_USBRESET_Msk)) { + (usbdev->device->INTEN & USBD_INTEN_USBRESET_Msk)) { usbdev->device->INTENCLR = USBD_INTENCLR_USBRESET_Msk; usbdev->usbdev.cb(&usbdev->usbdev, USBDEV_EVENT_ESR); } else if (usbdev->device->EVENTS_USBEVENT && - (usbdev->device->INTEN & USBD_INTEN_USBEVENT_Msk)) { + (usbdev->device->INTEN & USBD_INTEN_USBEVENT_Msk)) { usbdev->device->INTENCLR = USBD_INTENCLR_USBEVENT_Msk; usbdev->usbdev.cb(&usbdev->usbdev, USBDEV_EVENT_ESR); } @@ -643,12 +675,12 @@ void isr_usbd(void) /* Endpoint specific isr handling*/ /* Endpoint 0 SETUP data received requests */ if (usbdev->device->EVENTS_EP0SETUP && - (usbdev->device->INTEN & USBD_INTEN_EP0SETUP_Msk)) { + (usbdev->device->INTEN & USBD_INTEN_EP0SETUP_Msk)) { usbdev->usbdev.epcb(_get_ep_out(usbdev, 0), USBDEV_EVENT_ESR); _ep_disable_irq(_get_ep_out(usbdev, 0)); } if (usbdev->device->EVENTS_EP0DATADONE && - (usbdev->device->INTEN & USBD_INTEN_EP0DATADONE_Msk)) { + (usbdev->device->INTEN & USBD_INTEN_EP0DATADONE_Msk)) { if (usbdev->sstate == NRFUSB_SETUP_READ) { usbdev->usbdev.epcb(_get_ep_in(usbdev, 0), USBDEV_EVENT_ESR); _ep_disable_irq(_get_ep_in(usbdev, 0)); @@ -668,14 +700,14 @@ void isr_usbd(void) if (ep->type != USB_EP_TYPE_NONE) { /* OUT type endpoint */ usbdev->usbdev.epcb(ep, - USBDEV_EVENT_ESR); + USBDEV_EVENT_ESR); } } else { usbdev_ep_t *ep = _get_ep_in(usbdev, epnum); if (ep->type != USB_EP_TYPE_NONE) { usbdev->usbdev.epcb(ep, - USBDEV_EVENT_ESR); + USBDEV_EVENT_ESR); } } epdatastatus &= ~(1 << epnum);