Skip to content

Commit 06232bb

Browse files
jfischer-nokartben
authored andcommitted
drivers: udc_rpi_pico: replace message queue with k_events
Using k_events eliminates the drawback of the queue potentially dropping messages and provides a reliable event notification mechanism. It is similar to commit c2f2d8c ("drivers: usb: udc_dwc2: Replace queue with events") Signed-off-by: Johann Fischer <[email protected]>
1 parent 2f64a42 commit 06232bb

File tree

2 files changed

+112
-62
lines changed

2 files changed

+112
-62
lines changed

drivers/usb/udc/Kconfig.rpi_pico

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ config UDC_RPI_PICO
66
default y
77
depends on DT_HAS_RASPBERRYPI_PICO_USBD_ENABLED
88
select SYS_MEM_BLOCKS
9+
select EVENTS
910
help
1011
Driver for an Raspberry PI Pico USB device controller.
1112

drivers/usb/udc/udc_rpi_pico.c

Lines changed: 111 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -41,32 +41,57 @@ struct rpi_pico_ep_data {
4141
uint8_t next_pid;
4242
};
4343

44+
enum rpi_pico_event_type {
45+
/* Setup packet received */
46+
RPI_PICO_EVT_SETUP,
47+
/* Trigger new transfer (except control OUT) */
48+
RPI_PICO_EVT_XFER_NEW,
49+
/* Transfer for specific endpoint is finished */
50+
RPI_PICO_EVT_XFER_FINISHED,
51+
};
52+
4453
struct rpi_pico_data {
4554
struct k_thread thread_data;
55+
/*
56+
* events are events that the driver thread waits.
57+
* xfer_new and xfer_finished contain information on which endpoints
58+
* events RPI_PICO_EVT_XFER_NEW or RPI_PICO_EVT_XFER_FINISHED are
59+
* triggered. The mapping is bits 31..16 for IN endpoints and bits
60+
* 15..0 for OUT endpoints.
61+
*/
62+
struct k_event events;
63+
struct k_event xfer_new;
64+
struct k_event xfer_finished;
4665
struct rpi_pico_ep_data out_ep[USB_NUM_ENDPOINTS];
4766
struct rpi_pico_ep_data in_ep[USB_NUM_ENDPOINTS];
4867
bool rwu_pending;
4968
uint8_t setup[8];
5069
};
5170

52-
enum rpi_pico_event_type {
53-
/* Trigger next transfer, must not be used for control OUT */
54-
RPI_PICO_EVT_XFER,
55-
/* Setup packet received */
56-
RPI_PICO_EVT_SETUP,
57-
/* OUT transaction for specific endpoint is finished */
58-
RPI_PICO_EVT_DOUT,
59-
/* IN transaction for specific endpoint is finished */
60-
RPI_PICO_EVT_DIN,
61-
};
71+
static inline uint32_t udc_ep_to_bmsk(const uint8_t ep)
72+
{
73+
if (USB_EP_DIR_IS_IN(ep)) {
74+
return BIT(16UL + USB_EP_GET_IDX(ep));
75+
}
6276

63-
struct rpi_pico_event {
64-
const struct device *dev;
65-
enum rpi_pico_event_type type;
66-
uint8_t ep;
67-
};
77+
return BIT(USB_EP_GET_IDX(ep));
78+
}
79+
80+
static inline uint8_t udc_pull_ep_from_bmsk(uint32_t *const bitmap)
81+
{
82+
unsigned int bit;
83+
84+
__ASSERT_NO_MSG(bitmap && *bitmap);
6885

69-
K_MSGQ_DEFINE(drv_msgq, sizeof(struct rpi_pico_event), 16, sizeof(void *));
86+
bit = find_lsb_set(*bitmap) - 1;
87+
*bitmap &= ~BIT(bit);
88+
89+
if (bit >= 16) {
90+
return USB_EP_DIR_IN | (bit - 16);
91+
} else {
92+
return USB_EP_DIR_OUT | bit;
93+
}
94+
}
7095

7196
/* Use Atomic Register Access to set bits */
7297
static void ALWAYS_INLINE rpi_pico_bit_set(const mm_reg_t reg, const uint32_t bit)
@@ -438,45 +463,71 @@ static void rpi_pico_handle_xfer_next(const struct device *dev,
438463
static ALWAYS_INLINE void rpi_pico_thread_handler(void *const arg)
439464
{
440465
const struct device *dev = (const struct device *)arg;
466+
struct rpi_pico_data *priv = udc_get_private(dev);
441467
struct udc_ep_config *ep_cfg;
442-
struct rpi_pico_event evt;
468+
uint32_t evt;
469+
uint32_t eps;
470+
uint8_t ep;
443471

444-
k_msgq_get(&drv_msgq, &evt, K_FOREVER);
445-
ep_cfg = udc_get_ep_cfg(dev, evt.ep);
472+
evt = k_event_wait(&priv->events, UINT32_MAX, false, K_FOREVER);
473+
udc_lock_internal(dev, K_FOREVER);
474+
475+
if (evt & BIT(RPI_PICO_EVT_XFER_FINISHED)) {
476+
k_event_clear(&priv->events, BIT(RPI_PICO_EVT_XFER_FINISHED));
477+
478+
eps = k_event_clear(&priv->xfer_finished, UINT32_MAX);
479+
480+
while (eps) {
481+
ep = udc_pull_ep_from_bmsk(&eps);
482+
ep_cfg = udc_get_ep_cfg(dev, ep);
483+
LOG_DBG("Finished event ep 0x%02x", ep);
484+
485+
if (USB_EP_DIR_IS_IN(ep)) {
486+
rpi_pico_handle_evt_din(dev, ep_cfg);
487+
} else {
488+
rpi_pico_handle_evt_dout(dev, ep_cfg);
489+
}
490+
491+
if (!udc_ep_is_busy(ep_cfg)) {
492+
rpi_pico_handle_xfer_next(dev, ep_cfg);
493+
} else {
494+
LOG_ERR("Endpoint 0x%02x busy", ep);
495+
}
496+
}
497+
}
498+
499+
if (evt & BIT(RPI_PICO_EVT_XFER_NEW)) {
500+
k_event_clear(&priv->events, BIT(RPI_PICO_EVT_XFER_NEW));
501+
502+
eps = k_event_clear(&priv->xfer_new, UINT32_MAX);
503+
504+
while (eps) {
505+
ep = udc_pull_ep_from_bmsk(&eps);
506+
ep_cfg = udc_get_ep_cfg(dev, ep);
507+
LOG_DBG("New transfer ep 0x%02x in the queue", ep);
446508

447-
switch (evt.type) {
448-
case RPI_PICO_EVT_XFER:
449-
LOG_DBG("New transfer in the queue");
450-
break;
451-
case RPI_PICO_EVT_SETUP:
509+
if (!udc_ep_is_busy(ep_cfg)) {
510+
rpi_pico_handle_xfer_next(dev, ep_cfg);
511+
} else {
512+
LOG_ERR("Endpoint 0x%02x busy", ep);
513+
}
514+
}
515+
}
516+
517+
if (evt & BIT(RPI_PICO_EVT_SETUP)) {
518+
k_event_clear(&priv->events, BIT(RPI_PICO_EVT_SETUP));
452519
LOG_DBG("SETUP event");
453520
rpi_pico_handle_evt_setup(dev);
454-
break;
455-
case RPI_PICO_EVT_DOUT:
456-
LOG_DBG("DOUT event ep 0x%02x", ep_cfg->addr);
457-
rpi_pico_handle_evt_dout(dev, ep_cfg);
458-
break;
459-
case RPI_PICO_EVT_DIN:
460-
LOG_DBG("DIN event");
461-
rpi_pico_handle_evt_din(dev, ep_cfg);
462-
break;
463521
}
464522

465-
if (ep_cfg->addr != USB_CONTROL_EP_OUT && !udc_ep_is_busy(ep_cfg)) {
466-
rpi_pico_handle_xfer_next(dev, ep_cfg);
467-
}
523+
udc_unlock_internal(dev);
468524
}
469525

470526
static void rpi_pico_handle_setup(const struct device *dev)
471527
{
472528
const struct rpi_pico_config *config = dev->config;
473529
struct rpi_pico_data *priv = udc_get_private(dev);
474530
usb_device_dpram_t *dpram = config->dpram;
475-
struct rpi_pico_event evt = {
476-
.type = RPI_PICO_EVT_SETUP,
477-
.ep = USB_CONTROL_EP_OUT,
478-
};
479-
480531
/*
481532
* Host may issue a new setup packet even if the previous control transfer
482533
* did not complete. Cancel any active transaction.
@@ -491,16 +542,13 @@ static void rpi_pico_handle_setup(const struct device *dev)
491542
get_ep_data(dev, USB_CONTROL_EP_IN)->next_pid = 1;
492543
get_ep_data(dev, USB_CONTROL_EP_OUT)->next_pid = 1;
493544

494-
k_msgq_put(&drv_msgq, &evt, K_NO_WAIT);
545+
k_event_post(&priv->events, BIT(RPI_PICO_EVT_SETUP));
495546
}
496547

497548
static void rpi_pico_handle_buff_status_in(const struct device *dev, const uint8_t ep)
498549
{
499550
struct udc_ep_config *ep_cfg = udc_get_ep_cfg(dev, ep);
500-
struct rpi_pico_event evt = {
501-
.ep = ep,
502-
.type = RPI_PICO_EVT_DIN,
503-
};
551+
struct rpi_pico_data *priv = udc_get_private(dev);
504552
__maybe_unused int err;
505553
struct net_buf *buf;
506554
size_t len;
@@ -524,7 +572,8 @@ static void rpi_pico_handle_buff_status_in(const struct device *dev, const uint8
524572
__ASSERT(err == 0, "Failed to start new IN transaction");
525573
udc_ep_buf_clear_zlp(buf);
526574
} else {
527-
k_msgq_put(&drv_msgq, &evt, K_NO_WAIT);
575+
k_event_post(&priv->xfer_finished, udc_ep_to_bmsk(ep));
576+
k_event_post(&priv->events, BIT(RPI_PICO_EVT_XFER_FINISHED));
528577
}
529578
}
530579
}
@@ -533,10 +582,7 @@ static void rpi_pico_handle_buff_status_out(const struct device *dev, const uint
533582
{
534583
struct rpi_pico_ep_data *ep_data = get_ep_data(dev, ep);
535584
struct udc_ep_config *ep_cfg = udc_get_ep_cfg(dev, ep);
536-
struct rpi_pico_event evt = {
537-
.ep = ep,
538-
.type = RPI_PICO_EVT_DOUT,
539-
};
585+
struct rpi_pico_data *priv = udc_get_private(dev);
540586
struct net_buf *buf;
541587
size_t len;
542588

@@ -557,7 +603,8 @@ static void rpi_pico_handle_buff_status_out(const struct device *dev, const uint
557603
err = rpi_pico_prep_rx(dev, buf, ep_cfg);
558604
__ASSERT(err == 0, "Failed to start new OUT transaction");
559605
} else {
560-
k_msgq_put(&drv_msgq, &evt, K_NO_WAIT);
606+
k_event_post(&priv->xfer_finished, udc_ep_to_bmsk(ep));
607+
k_event_post(&priv->events, BIT(RPI_PICO_EVT_XFER_FINISHED));
561608
}
562609
}
563610

@@ -720,15 +767,13 @@ static int udc_rpi_pico_ep_enqueue(const struct device *dev,
720767
struct udc_ep_config *const cfg,
721768
struct net_buf *buf)
722769
{
723-
struct rpi_pico_event evt = {
724-
.ep = cfg->addr,
725-
.type = RPI_PICO_EVT_XFER,
726-
};
770+
struct rpi_pico_data *priv = udc_get_private(dev);
727771

728772
udc_buf_put(cfg, buf);
729773

730774
if (!cfg->stat.halted) {
731-
k_msgq_put(&drv_msgq, &evt, K_NO_WAIT);
775+
k_event_post(&priv->xfer_new, udc_ep_to_bmsk(cfg->addr));
776+
k_event_post(&priv->events, BIT(RPI_PICO_EVT_XFER_NEW));
732777
}
733778

734779
return 0;
@@ -842,11 +887,8 @@ static int udc_rpi_pico_ep_clear_halt(const struct device *dev,
842887
struct udc_ep_config *const cfg)
843888
{
844889
struct rpi_pico_ep_data *const ep_data = get_ep_data(dev, cfg->addr);
890+
struct rpi_pico_data *priv = udc_get_private(dev);
845891
mem_addr_t buf_ctrl_reg = get_buf_ctrl_reg(dev, cfg->addr);
846-
struct rpi_pico_event evt = {
847-
.ep = cfg->addr,
848-
.type = RPI_PICO_EVT_XFER,
849-
};
850892

851893
if (USB_EP_GET_IDX(cfg->addr) != 0) {
852894
ep_data->next_pid = 0;
@@ -861,7 +903,8 @@ static int udc_rpi_pico_ep_clear_halt(const struct device *dev,
861903
rpi_pico_bit_clr(buf_ctrl_reg, USB_BUF_CTRL_STALL);
862904

863905
if (udc_buf_peek(cfg)) {
864-
k_msgq_put(&drv_msgq, &evt, K_NO_WAIT);
906+
k_event_post(&priv->xfer_new, udc_ep_to_bmsk(cfg->addr));
907+
k_event_post(&priv->events, BIT(RPI_PICO_EVT_XFER_NEW));
865908
}
866909
}
867910

@@ -1000,11 +1043,15 @@ static int udc_rpi_pico_shutdown(const struct device *dev)
10001043
static int udc_rpi_pico_driver_preinit(const struct device *dev)
10011044
{
10021045
const struct rpi_pico_config *config = dev->config;
1046+
struct rpi_pico_data *priv = udc_get_private(dev);
10031047
struct udc_data *data = dev->data;
10041048
uint16_t mps = 1023;
10051049
int err;
10061050

10071051
k_mutex_init(&data->mutex);
1052+
k_event_init(&priv->events);
1053+
k_event_init(&priv->xfer_new);
1054+
k_event_init(&priv->xfer_finished);
10081055

10091056
data->caps.rwup = true;
10101057
data->caps.mps0 = UDC_MPS0_64;
@@ -1056,12 +1103,14 @@ static int udc_rpi_pico_driver_preinit(const struct device *dev)
10561103

10571104
static void udc_rpi_pico_lock(const struct device *dev)
10581105
{
1106+
k_sched_lock();
10591107
udc_lock_internal(dev, K_FOREVER);
10601108
}
10611109

10621110
static void udc_rpi_pico_unlock(const struct device *dev)
10631111
{
10641112
udc_unlock_internal(dev);
1113+
k_sched_unlock();
10651114
}
10661115

10671116
static const struct udc_api udc_rpi_pico_api = {

0 commit comments

Comments
 (0)