nrf52/usb: Adapt to xmit API

This commit is contained in:
Koen Zandberg 2021-10-26 19:44:17 +02:00
parent f8e7e2f557
commit 617027ab5c
No known key found for this signature in database
GPG Key ID: BA1718B37D79F51C
3 changed files with 35 additions and 71 deletions

View File

@ -36,11 +36,6 @@ extern "C" {
*/ */
#define NRF_USB_NUM_PERIPH 1 #define NRF_USB_NUM_PERIPH 1
/**
* USB endpoint buffer space
*/
#define NRF_USB_BUF_SPACE USBDEV_EP_BUF_SPACE
/** /**
* Number of USB IN and OUT endpoints * Number of USB IN and OUT endpoints
*/ */
@ -65,9 +60,6 @@ typedef struct {
usbdev_ep_t ep_ins[NRF_USB_NUM_EP]; /**< IN type endpoints */ usbdev_ep_t ep_ins[NRF_USB_NUM_EP]; /**< IN type endpoints */
usbdev_ep_t ep_outs[ NRF_USB_NUM_EP]; /**< OUT type endpoints */ usbdev_ep_t ep_outs[ NRF_USB_NUM_EP]; /**< OUT type endpoints */
NRF_USBD_Type *device; /**< Ptr to the device registers */ NRF_USBD_Type *device; /**< Ptr to the device registers */
size_t used; /**< Number of bytes from the
buffer that are used */
uint8_t buffer[NRF_USB_BUF_SPACE]; /**< Buffer space for endpoint data */
nrfusb_setup_state_t sstate; /**< Setup request state machine */ nrfusb_setup_state_t sstate; /**< Setup request state machine */
} nrfusb_t; } nrfusb_t;

View File

@ -263,6 +263,17 @@ void spi_twi_irq_register_spi(NRF_SPIM_Type *bus,
*/ */
void spi_twi_irq_register_i2c(NRF_TWIM_Type *bus, void spi_twi_irq_register_i2c(NRF_TWIM_Type *bus,
spi_twi_irq_cb_t cb, void *arg); spi_twi_irq_cb_t cb, void *arg);
/**
* @brief USBDEV buffers must be word aligned because of DMA restrictions
*/
#define USBDEV_CPU_DMA_ALIGNMENT (4)
/**
* @brief USBDEV buffer instantiation requirement
*/
#define USBDEV_CPU_DMA_REQUIREMENTS __attribute__((aligned(USBDEV_CPU_DMA_ALIGNMENT)))
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

View File

@ -27,6 +27,7 @@
#include <stdlib.h> #include <stdlib.h>
#include <errno.h> #include <errno.h>
#include "architecture.h"
#include "cpu.h" #include "cpu.h"
#include "nrfusb.h" #include "nrfusb.h"
#include "periph/usbdev.h" #include "periph/usbdev.h"
@ -42,12 +43,12 @@ static nrfusb_t _usbdevs[NRF_USB_NUM_PERIPH];
static void _init(usbdev_t *usbdev); static void _init(usbdev_t *usbdev);
static int _get(usbdev_t *usbdev, usbopt_t opt, void *value, size_t max_len); static int _get(usbdev_t *usbdev, usbopt_t opt, void *value, size_t max_len);
static int _set(usbdev_t *usbdev, usbopt_t opt, const void *value, size_t value_len); static int _set(usbdev_t *usbdev, usbopt_t opt, const void *value, size_t value_len);
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 len);
static void _esr(usbdev_t *usbdev); static void _esr(usbdev_t *usbdev);
static void _ep_init(usbdev_ep_t *ep); 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); static int _ep_get(usbdev_ep_t *ep, usbopt_ep_t opt, void *value, size_t max_len);
static int _ep_set(usbdev_ep_t *ep, usbopt_ep_t opt, const void *value, size_t value_len); static int _ep_set(usbdev_ep_t *ep, usbopt_ep_t opt, const void *value, size_t value_len);
static int _ep_ready(usbdev_ep_t *ep, size_t len); static int _ep_xmit(usbdev_ep_t *ep, uint8_t *buf, size_t len);
static void _ep_esr(usbdev_ep_t *ep); static void _ep_esr(usbdev_ep_t *ep);
static const usbdev_driver_t _driver = { static const usbdev_driver_t _driver = {
@ -60,7 +61,7 @@ static const usbdev_driver_t _driver = {
.ep_get = _ep_get, .ep_get = _ep_get,
.ep_set = _ep_set, .ep_set = _ep_set,
.ep_esr = _ep_esr, .ep_esr = _ep_esr,
.ready = _ep_ready, .xmit = _ep_xmit,
}; };
static inline usbdev_ep_t *_get_ep_in(nrfusb_t *usbdev, unsigned num) static inline usbdev_ep_t *_get_ep_in(nrfusb_t *usbdev, unsigned num)
@ -129,22 +130,10 @@ static void usb_detach(nrfusb_t *usbdev)
usbdev->device->USBPULLUP = 0x00; usbdev->device->USBPULLUP = 0x00;
} }
static void _ep_set_address(usbdev_ep_t *ep)
{
nrfusb_t *usbdev = (nrfusb_t *)ep->dev;
if (ep->dir == USB_EP_DIR_OUT) {
usbdev->device->EPOUT[ep->num].PTR = (uint32_t)ep->buf;
}
else {
usbdev->device->EPIN[ep->num].PTR = (uint32_t)ep->buf;
}
}
static void _copy_setup(usbdev_ep_t *ep) static void _copy_setup(usbdev_ep_t *ep)
{ {
nrfusb_t *usbdev = (nrfusb_t*)ep->dev; nrfusb_t *usbdev = (nrfusb_t*)ep->dev;
usb_setup_t *setup = (usb_setup_t *)ep->buf; usb_setup_t *setup = (usb_setup_t*)(intptr_t)usbdev->device->EPOUT[0].PTR;
setup->type = usbdev->device->BMREQUESTTYPE; setup->type = usbdev->device->BMREQUESTTYPE;
setup->request = usbdev->device->BREQUEST; setup->request = usbdev->device->BREQUEST;
@ -159,17 +148,6 @@ 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;
if (ep->dir == USB_EP_DIR_OUT) {
usbdev->device->EPOUT[ep->num].MAXCNT = (uint32_t)ep->len;
}
return 1;
}
static void _ep_enable(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"); DEBUG("Enabling endpoint %u dir %s\n", ep->num, ep->dir == USB_EP_DIR_OUT ? "OUT" : "IN");
@ -287,7 +265,6 @@ static void _init(usbdev_t *dev)
nrfusb_t *usbdev = (nrfusb_t *)dev; nrfusb_t *usbdev = (nrfusb_t *)dev;
poweron(usbdev); poweron(usbdev);
usbdev->used = 0;
usbdev->sstate = NRFUSB_SETUP_READY; usbdev->sstate = NRFUSB_SETUP_READY;
/* Enable a set of interrupts */ /* Enable a set of interrupts */
@ -350,7 +327,7 @@ static int _set(usbdev_t *dev, usbopt_t opt,
static usbdev_ep_t *_new_ep(usbdev_t *dev, static usbdev_ep_t *_new_ep(usbdev_t *dev,
usb_ep_type_t type, usb_ep_type_t type,
usb_ep_dir_t dir, usb_ep_dir_t dir,
size_t buf_len) size_t len)
{ {
nrfusb_t *usbdev = (nrfusb_t*)dev; nrfusb_t *usbdev = (nrfusb_t*)dev;
/* The IP supports all types for all endpoints */ /* The IP supports all types for all endpoints */
@ -374,23 +351,9 @@ static usbdev_ep_t *_new_ep(usbdev_t *dev,
if (res) { if (res) {
res->dev = dev; res->dev = dev;
res->dir = dir; res->dir = dir;
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;
if (_ep_set_size(res) < 0) {
return NULL;
}
usbdev->used += buf_len;
_ep_set_address(res);
res->type = type; res->type = type;
res->dev = dev; res->len = len;
} DEBUG("nrfusb: Allocated new ep (%d %s)\n", res->num, res->dir == USB_EP_DIR_OUT ? "OUT" : "IN");
else {
DEBUG("nrfusb: error allocating buffer space\n");
}
} }
return res; return res;
} }
@ -431,8 +394,6 @@ 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) { if (ep->num == 0) {
usbdev->device->EVENTS_EP0SETUP = 0; usbdev->device->EVENTS_EP0SETUP = 0;
} }
@ -493,13 +454,6 @@ static int _ep_set(usbdev_ep_t *ep, usbopt_ep_t opt,
_ep_set_stall(ep, *(usbopt_enable_t *)value); _ep_set_stall(ep, *(usbopt_enable_t *)value);
res = sizeof(usbopt_enable_t); res = sizeof(usbopt_enable_t);
break; 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: default:
DEBUG("Unhandled set call: 0x%x\n", opt); DEBUG("Unhandled set call: 0x%x\n", opt);
break; break;
@ -507,9 +461,11 @@ static int _ep_set(usbdev_ep_t *ep, usbopt_ep_t opt,
return res; return res;
} }
static int _ep0_ready(usbdev_ep_t *ep, size_t len) static int _ep0_xmit(usbdev_ep_t *ep, uint8_t *buf, size_t len)
{ {
nrfusb_t *usbdev = (nrfusb_t *)ep->dev; nrfusb_t *usbdev = (nrfusb_t *)ep->dev;
/* Assert the alignment required for the buffers */
assert(HAS_ALIGNMENT_OF(buf, USBDEV_CPU_DMA_ALIGNMENT));
if (ep->dir == USB_EP_DIR_IN) { if (ep->dir == USB_EP_DIR_IN) {
if (len == 0 && usbdev->sstate == NRFUSB_SETUP_WRITE) { if (len == 0 && usbdev->sstate == NRFUSB_SETUP_WRITE) {
@ -518,12 +474,14 @@ static int _ep0_ready(usbdev_ep_t *ep, size_t len)
usbdev->sstate = NRFUSB_SETUP_ACKIN; usbdev->sstate = NRFUSB_SETUP_ACKIN;
} }
else { else {
usbdev->device->EPIN[0].PTR = (uint32_t)ep->buf; usbdev->device->EPIN[0].PTR = (uint32_t)(intptr_t)buf;
usbdev->device->EPIN[0].MAXCNT = (uint32_t)len; usbdev->device->EPIN[0].MAXCNT = (uint32_t)len;
usbdev->device->TASKS_STARTEPIN[0] = 1; usbdev->device->TASKS_STARTEPIN[0] = 1;
} }
} }
else { else {
usbdev->device->EPOUT[0].PTR = (uint32_t)(intptr_t)buf;
usbdev->device->EPOUT[0].MAXCNT = (uint32_t)len;
/* USB_EP_DIR_OUT */ /* USB_EP_DIR_OUT */
if (usbdev->sstate == NRFUSB_SETUP_READ) { if (usbdev->sstate == NRFUSB_SETUP_READ) {
usbdev->device->TASKS_EP0STATUS = 1; usbdev->device->TASKS_EP0STATUS = 1;
@ -537,20 +495,23 @@ static int _ep0_ready(usbdev_ep_t *ep, size_t len)
return len; return len;
} }
static int _ep_ready(usbdev_ep_t *ep, size_t len) static int _ep_xmit(usbdev_ep_t *ep, uint8_t *buf, size_t len)
{ {
nrfusb_t *usbdev = (nrfusb_t *)ep->dev; nrfusb_t *usbdev = (nrfusb_t *)ep->dev;
if (ep->num == 0) { if (ep->num == 0) {
/* Endpoint 0 requires special handling as per datasheet sec 6.35.9 */ /* Endpoint 0 requires special handling as per datasheet sec 6.35.9 */
return _ep0_ready(ep, len); return _ep0_xmit(ep, buf, len);
} }
if (ep->dir == USB_EP_DIR_IN) { if (ep->dir == USB_EP_DIR_IN) {
usbdev->device->EPIN[ep->num].PTR = (uint32_t)ep->buf; usbdev->device->EPIN[ep->num].PTR = (uint32_t)(intptr_t)buf;
usbdev->device->EPIN[ep->num].MAXCNT = (uint32_t)len; usbdev->device->EPIN[ep->num].MAXCNT = (uint32_t)len;
_ep_dma_in(ep); _ep_dma_in(ep);
} }
else { else {
/* Pre-Setup the EasyDMA settings */
usbdev->device->EPOUT[ep->num].PTR = (uint32_t)(intptr_t)buf;
usbdev->device->EPOUT[ep->num].MAXCNT = (uint32_t)(intptr_t)len;
/* Write nonzero value to EPOUT to indicate ready */ /* Write nonzero value to EPOUT to indicate ready */
usbdev->device->SIZE.EPOUT[ep->num] = 1; usbdev->device->SIZE.EPOUT[ep->num] = 1;
} }