Skip to content

Commit d71371e

Browse files
committed
Added support DMA for OTG HS (thank Maxjta)
1 parent 871609b commit d71371e

File tree

21 files changed

+2396
-13
lines changed

21 files changed

+2396
-13
lines changed

demos/AT32/RT-AT-START-F405/cfg/mcuconf.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -261,6 +261,7 @@
261261
#define AT32_USB_OTG2_IRQ_PRIORITY 14
262262
#define AT32_USB_OTG1_RX_FIFO_SIZE 512
263263
#define AT32_USB_OTG2_RX_FIFO_SIZE 1024
264+
#define AT32_USE_USB_OTG2_HS_DMA FALSE
264265

265266
/*
266267
* WDG driver system settings.

os/hal/ports/AT32/LLD/OTGv1/at32_otg.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
33
ChibiOS - Copyright (C) 2023..2025 HorrorTroll
44
ChibiOS - Copyright (C) 2023..2025 Zhaqian
5+
ChibiOS - Copyright (C) 2024..2025 Maxjta
56
67
Licensed under the Apache License, Version 2.0 (the "License");
78
you may not use this file except in compliance with the License.
@@ -777,6 +778,8 @@ typedef struct {
777778
#define DIEPINT_INTKNTXFEMP (1U << 4) /**< IN Token received when
778779
TxFIFO is empty. */
779780
#define DIEPINT_TIMEOUT (1U << 3) /**< Timeout condition. */
781+
#define DIEPINT_AHBERR (1U << 2) /**< AHB error interrupt
782+
(HS only). */
780783
#define DIEPINT_EPTDISD (1U << 1) /**< Endpoint disabled
781784
interrupt. */
782785
#define DIEPINT_XFERC (1U << 0) /**< Transfer completed
@@ -834,11 +837,15 @@ typedef struct {
834837
* @name DOEPINT register bit definitions
835838
* @{
836839
*/
840+
#define DOEPINT_STPPKRX (1U << 15) /**< Setup packet received
841+
(HS only). */
837842
#define DOEPINT_B2BSTUP (1U << 6) /**< Back-to-back SETUP packets
838843
received. */
839844
#define DOEPINT_OUTTEPD (1U << 4) /**< OUT token received when
840845
endpoint disabled. */
841846
#define DOEPINT_SETUP (1U << 3) /**< SETUP phase done. */
847+
#define DOEPINT_AHBERR (1U << 2) /**< AHB error interrupt
848+
(HS only). */
842849
#define DOEPINT_EPTDISD (1U << 1) /**< Endpoint disabled
843850
interrupt. */
844851
#define DOEPINT_XFERC (1U << 0) /**< Transfer completed

os/hal/ports/AT32/LLD/OTGv1/hal_usb_lld.c

Lines changed: 136 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -119,15 +119,21 @@ static const USBEndpointConfig ep0config = {
119119
static const at32_otg_params_t fsparams = {
120120
AT32_USB_OTG1_RX_FIFO_SIZE / 4,
121121
AT32_OTG1_FIFO_MEM_SIZE,
122-
AT32_OTG1_ENDPOINTS
122+
AT32_OTG1_ENDPOINTS,
123+
0
123124
};
124125
#endif
125126

126127
#if AT32_USB_USE_OTG2
127128
static const at32_otg_params_t hsparams = {
128129
AT32_USB_OTG2_RX_FIFO_SIZE / 4,
129130
AT32_OTG2_FIFO_MEM_SIZE,
130-
AT32_OTG2_ENDPOINTS
131+
AT32_OTG2_ENDPOINTS,
132+
#if AT32_USE_USB_OTG2_HS_DMA
133+
1
134+
#else
135+
0
136+
#endif
131137
};
132138
#endif
133139

@@ -376,9 +382,17 @@ static bool otg_txfifo_handler(USBDriver *usbp, usbep_t ep) {
376382
#if AT32_USB_OTGFIFO_FILL_BASEPRI
377383
__set_BASEPRI(CORTEX_PRIO_MASK(AT32_USB_OTGFIFO_FILL_BASEPRI));
378384
#endif
385+
#if AT32_USE_USB_OTG2_HS_DMA
386+
if (usbp->otgparams->dma_en) {
387+
usbp->otg->ie[ep].DIEPDMA = (uint32_t)(usbp->epc[ep]->in_state->txbuf);
388+
}
389+
else
390+
#endif
391+
{
379392
otg_fifo_write_from_buffer(usbp->otg->FIFO[ep],
380393
usbp->epc[ep]->in_state->txbuf,
381394
n);
395+
}
382396
usbp->epc[ep]->in_state->txbuf += n;
383397
usbp->epc[ep]->in_state->txcnt += n;
384398
#if AT32_USB_OTGFIFO_FILL_BASEPRI
@@ -412,6 +426,11 @@ static void otg_epin_handler(USBDriver *usbp, usbep_t ep) {
412426
/* In case the transaction covered only part of the total transfer
413427
then another transaction is immediately started in order to
414428
cover the remaining.*/
429+
#if AT32_USE_USB_OTG2_HS_DMA
430+
if (usbp->otgparams->dma_en) {
431+
isp->txbuf += isp->txsize;
432+
}
433+
#endif
415434
isp->txsize = isp->totsize - isp->txsize;
416435
isp->txcnt = 0;
417436
osalSysLockFromISR();
@@ -422,11 +441,25 @@ static void otg_epin_handler(USBDriver *usbp, usbep_t ep) {
422441
/* End on IN transfer.*/
423442
_usb_isr_invoke_in_cb(usbp, ep);
424443
}
444+
#if AT32_USE_USB_OTG2_HS_DMA
445+
if (usbp->otgparams->dma_en) {
446+
if (ep == 0 && 0 == isp->totsize) {
447+
usbp->otg->oe[0].DOEPTSIZ = DOEPTSIZ_SETUPCNT(3);
448+
usbp->otg->oe[0].DOEPDMA = (uint32_t)(usbp->epc[0]->setup_buf);
449+
usbp->otg->oe[0].DOEPCTL |= DOEPCTL_EPTENA | DOEPCTL_USBACEPT |
450+
DOEPCTL_CNAK;
451+
}
452+
}
453+
#endif
454+
}
455+
if (usbp->otgparams->dma_en) {
425456
}
426-
if ((epint & DIEPINT_TXFEMP) &&
427-
(otgp->DIEPEMPMSK & DIEPEMPMSK_INEPTXFEMSK(ep))) {
428-
/* TX FIFO empty or emptying.*/
429-
otg_txfifo_handler(usbp, ep);
457+
else {
458+
if ((epint & DIEPINT_TXFEMP) &&
459+
(otgp->DIEPEMPMSK & DIEPEMPMSK_INEPTXFEMSK(ep))) {
460+
/* TX FIFO empty or emptying.*/
461+
otg_txfifo_handler(usbp, ep);
462+
}
430463
}
431464
}
432465

@@ -449,13 +482,40 @@ static void otg_epout_handler(USBDriver *usbp, usbep_t ep) {
449482
/* Setup packets handling, setup packets are handled using a
450483
specific callback.*/
451484
_usb_isr_invoke_setup_cb(usbp, ep);
485+
#if AT32_USE_USB_OTG2_HS_DMA
486+
if (usbp->otgparams->dma_en) {
487+
return;
488+
}
489+
#endif
452490
}
453491

454492
if ((epint & DOEPINT_XFERC) && (otgp->DOEPMSK & DOEPMSK_XFERCMSK)) {
455493
USBOutEndpointState *osp;
456494

457495
/* OUT state structure pointer for this endpoint.*/
458496
osp = usbp->epc[ep]->out_state;
497+
#if AT32_USE_USB_OTG2_HS_DMA
498+
if (usbp->otgparams->dma_en) {
499+
if (epint & DOEPINT_STPPKRX) {
500+
if (epint & DOEPINT_SETUP) {
501+
}
502+
else {
503+
return;
504+
}
505+
}
506+
if (osp->totsize) {
507+
uint32_t sz = osp->rxsize - (usbp->otg->oe[ep].DOEPTSIZ & DOEPTSIZ_XFERSIZE_MASK);
508+
osp->rxcnt += sz;
509+
osp->rxbuf += sz;
510+
}
511+
else {
512+
usbp->otg->oe[0].DOEPTSIZ = DOEPTSIZ_SETUPCNT(3);
513+
usbp->otg->oe[0].DOEPDMA = (uint32_t)(usbp->epc[0]->setup_buf);
514+
usbp->otg->oe[0].DOEPCTL |= DOEPCTL_EPTENA | DOEPCTL_USBACEPT |
515+
DOEPCTL_CNAK;
516+
}
517+
}
518+
#endif
459519

460520
/* EP0 requires special handling.*/
461521
if (ep == 0) {
@@ -860,8 +920,16 @@ void usb_lld_start(USBDriver *usbp) {
860920
/* Soft core reset.*/
861921
otg_core_reset(usbp);
862922

863-
/* Interrupts on TXFIFOs half empty.*/
864-
otgp->GAHBCFG = 0;
923+
#if AT32_USE_USB_OTG2_HS_DMA
924+
if (usbp->otgparams->dma_en) {
925+
otgp->GAHBCFG = GAHBCFG_DMAEN | GAHBCFG_HBSTLEN(1);
926+
}
927+
else
928+
#endif
929+
{
930+
/* Interrupts on TXFIFOs half empty.*/
931+
otgp->GAHBCFG = 0;
932+
}
865933

866934
/* Endpoints re-initialization.*/
867935
otg_disable_ep(usbp);
@@ -963,15 +1031,31 @@ void usb_lld_reset(USBDriver *usbp) {
9631031
otgp->DCFG = (otgp->DCFG & ~DCFG_DEVADDR_MASK) | DCFG_DEVADDR(0);
9641032

9651033
/* Enables also EP-related interrupt sources.*/
966-
otgp->GINTMSK |= GINTMSK_RXFLVLMSK | GINTMSK_OEPTINTMSK | GINTMSK_IEPTINTMSK;
967-
otgp->DIEPMSK = DIEPMSK_TIMEOUTMSK | DIEPMSK_XFERCMSK;
968-
otgp->DOEPMSK = DOEPMSK_SETUPMSK | DOEPMSK_XFERCMSK;
1034+
otgp->GINTMSK |= GINTMSK_RXFLVLMSK | GINTMSK_OEPTINTMSK | GINTMSK_IEPTINTMSK;
1035+
#if AT32_USE_USB_OTG2_HS_DMA
1036+
if (usbp->otgparams->dma_en) {
1037+
otgp->GINTMSK &= ~GINTMSK_RXFLVLMSK;
1038+
}
1039+
#endif
1040+
otgp->DIEPMSK = DIEPMSK_TIMEOUTMSK | DIEPMSK_XFERCMSK;
1041+
otgp->DOEPMSK = DOEPMSK_SETUPMSK | DOEPMSK_XFERCMSK;
9691042

9701043
/* EP0 initialization, it is a special case.*/
9711044
usbp->epc[0] = &ep0config;
9721045
otgp->oe[0].DOEPTSIZ = DOEPTSIZ_SETUPCNT(3);
973-
otgp->oe[0].DOEPCTL = DOEPCTL_SETD0PID | DOEPCTL_USBACEPT | DOEPCTL_EPTYPE_CTRL |
974-
DOEPCTL_MPS(ep0config.out_maxsize);
1046+
#if AT32_USE_USB_OTG2_HS_DMA
1047+
if (usbp->otgparams->dma_en) {
1048+
otgp->oe[0].DOEPDMA = (uint32_t)(usbp->epc[0]->setup_buf);
1049+
otgp->oe[0].DOEPCTL = DOEPCTL_SETD0PID | DOEPCTL_USBACEPT | DOEPCTL_EPTYPE_CTRL | DOEPCTL_EPTENA |
1050+
DOEPCTL_MPS(ep0config.out_maxsize);
1051+
}
1052+
else
1053+
#endif
1054+
{
1055+
otgp->oe[0].DOEPCTL = DOEPCTL_SETD0PID | DOEPCTL_USBACEPT | DOEPCTL_EPTYPE_CTRL |
1056+
DOEPCTL_MPS(ep0config.out_maxsize);
1057+
}
1058+
9751059
otgp->ie[0].DIEPTSIZ = 0;
9761060
otgp->ie[0].DIEPCTL = DIEPCTL_SETD0PID | DIEPCTL_USBACEPT | DIEPCTL_EPTYPE_CTRL |
9771061
DIEPCTL_TXFNUM(0) | DIEPCTL_MPS(ep0config.in_maxsize);
@@ -1165,14 +1249,37 @@ void usb_lld_start_out(USBDriver *usbp, usbep_t ep) {
11651249
"For OUT transfers, the transfer size field in the endpoint's transfer
11661250
size register must be a multiple of the maximum packet size of the
11671251
endpoint, adjusted to the Word boundary".*/
1252+
#if AT32_USE_USB_OTG2_HS_DMA
1253+
if (usbp->otgparams->dma_en && ep == 0) {
1254+
pcnt = 1;
1255+
}
1256+
else {
1257+
pcnt = (osp->rxsize + usbp->epc[ep]->out_maxsize - 1U) /
1258+
usbp->epc[ep]->out_maxsize;
1259+
}
1260+
#else
11681261
pcnt = (osp->rxsize + usbp->epc[ep]->out_maxsize - 1U) /
11691262
usbp->epc[ep]->out_maxsize;
1263+
#endif
11701264
rxsize = (pcnt * usbp->epc[ep]->out_maxsize + 3U) & 0xFFFFFFFCU;
11711265

11721266
/* Setting up transaction parameters in DOEPTSIZ.*/
11731267
usbp->otg->oe[ep].DOEPTSIZ = DOEPTSIZ_SETUPCNT(3) | DOEPTSIZ_PKTCNT(pcnt) |
11741268
DOEPTSIZ_XFERSIZE(rxsize);
11751269

1270+
#if AT32_USE_USB_OTG2_HS_DMA
1271+
if (usbp->otgparams->dma_en) {
1272+
if (osp->rxbuf) {
1273+
usbp->otg->oe[ep].DOEPDMA = (uint32_t)(osp->rxbuf);
1274+
}
1275+
else {
1276+
if (ep == 0) {
1277+
usbp->otg->oe[ep].DOEPDMA = (uint32_t)(usbp->epc[0]->setup_buf);
1278+
}
1279+
}
1280+
}
1281+
#endif
1282+
11761283
/* Special case of isochronous endpoint.*/
11771284
if ((usbp->epc[ep]->ep_mode & USB_EP_MODE_TYPE) == USB_EP_MODE_TYPE_ISOC) {
11781285
/* Odd/even bit toggling for isochronous endpoint.*/
@@ -1202,6 +1309,11 @@ void usb_lld_start_in(USBDriver *usbp, usbep_t ep) {
12021309
if (isp->txsize == 0) {
12031310
/* Special case, sending zero size packet.*/
12041311
usbp->otg->ie[ep].DIEPTSIZ = DIEPTSIZ_PKTCNT(1) | DIEPTSIZ_XFERSIZE(0);
1312+
#if AT32_USE_USB_OTG2_HS_DMA
1313+
if (usbp->otgparams->dma_en) {
1314+
usbp->otg->ie[ep].DIEPDMA = 0;
1315+
}
1316+
#endif
12051317
}
12061318
else {
12071319
if ((ep == 0) && (isp->txsize > EP0_MAX_INSIZE))
@@ -1213,6 +1325,11 @@ void usb_lld_start_in(USBDriver *usbp, usbep_t ep) {
12131325
/* CHTODO: Support more than one packet per frame for isochronous transfers.*/
12141326
usbp->otg->ie[ep].DIEPTSIZ = DIEPTSIZ_MC(1) | DIEPTSIZ_PKTCNT(pcnt) |
12151327
DIEPTSIZ_XFERSIZE(isp->txsize);
1328+
#if AT32_USE_USB_OTG2_HS_DMA
1329+
if (usbp->otgparams->dma_en) {
1330+
usbp->otg->ie[ep].DIEPDMA = (uint32_t)(isp->txbuf);
1331+
}
1332+
#endif
12161333
}
12171334

12181335
/* Special case of isochronous endpoint.*/
@@ -1226,7 +1343,13 @@ void usb_lld_start_in(USBDriver *usbp, usbep_t ep) {
12261343

12271344
/* Starting operation.*/
12281345
usbp->otg->ie[ep].DIEPCTL |= DIEPCTL_EPTENA | DIEPCTL_CNAK;
1346+
#if AT32_USE_USB_OTG2_HS_DMA
1347+
if (usbp->otgparams->dma_en == 0) {
1348+
usbp->otg->DIEPEMPMSK |= DIEPEMPMSK_INEPTXFEMSK(ep);
1349+
}
1350+
#else
12291351
usbp->otg->DIEPEMPMSK |= DIEPEMPMSK_INEPTXFEMSK(ep);
1352+
#endif
12301353
}
12311354

12321355
/**

os/hal/ports/AT32/LLD/OTGv1/hal_usb_lld.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
33
ChibiOS - Copyright (C) 2023..2025 HorrorTroll
44
ChibiOS - Copyright (C) 2023..2025 Zhaqian
5+
ChibiOS - Copyright (C) 2024..2025 Maxjta
56
67
Licensed under the Apache License, Version 2.0 (the "License");
78
you may not use this file except in compliance with the License.
@@ -111,6 +112,15 @@
111112
#define AT32_USE_USB_OTG2_HS TRUE
112113
#endif
113114

115+
/**
116+
* @brief Enables DMA mode on OTG2.
117+
* @note The default is @p TRUE.
118+
* @note Has effect only if @p BOARD_OTG2_USES_ULPI is defined.
119+
*/
120+
#if !defined(AT32_USE_USB_OTG2_HS_DMA) || defined(__DOXYGEN__)
121+
#define AT32_USE_USB_OTG2_HS_DMA FALSE
122+
#endif
123+
114124
/**
115125
* @brief Exception priority level during TXFIFOs operations.
116126
* @note Because an undocumented silicon behavior the operation of
@@ -243,6 +253,7 @@ typedef struct {
243253
uint32_t rx_fifo_size;
244254
uint32_t otg_ram_size;
245255
uint32_t num_endpoints;
256+
uint32_t dma_en;
246257
} at32_otg_params_t;
247258

248259
/**

testhal/AT32/multi/ERTC/cfg/at-start-f405/mcuconf.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -260,6 +260,7 @@
260260
#define AT32_USB_OTG2_IRQ_PRIORITY 14
261261
#define AT32_USB_OTG1_RX_FIFO_SIZE 512
262262
#define AT32_USB_OTG2_RX_FIFO_SIZE 1024
263+
#define AT32_USE_USB_OTG2_HS_DMA FALSE
263264

264265
/*
265266
* WDG driver system settings.

testhal/AT32/multi/I2C_HW/cfg/at-start-f405/mcuconf.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -260,6 +260,7 @@
260260
#define AT32_USB_OTG2_IRQ_PRIORITY 14
261261
#define AT32_USB_OTG1_RX_FIFO_SIZE 512
262262
#define AT32_USB_OTG2_RX_FIFO_SIZE 1024
263+
#define AT32_USE_USB_OTG2_HS_DMA FALSE
263264

264265
/*
265266
* WDG driver system settings.

testhal/AT32/multi/I2C_SW/cfg/at-start-f405/mcuconf.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -260,6 +260,7 @@
260260
#define AT32_USB_OTG2_IRQ_PRIORITY 14
261261
#define AT32_USB_OTG1_RX_FIFO_SIZE 512
262262
#define AT32_USB_OTG2_RX_FIFO_SIZE 1024
263+
#define AT32_USE_USB_OTG2_HS_DMA FALSE
263264

264265
/*
265266
* WDG driver system settings.

testhal/AT32/multi/PWM_ICU/cfg/at-start-f405/mcuconf.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -260,6 +260,7 @@
260260
#define AT32_USB_OTG2_IRQ_PRIORITY 14
261261
#define AT32_USB_OTG1_RX_FIFO_SIZE 512
262262
#define AT32_USB_OTG2_RX_FIFO_SIZE 1024
263+
#define AT32_USE_USB_OTG2_HS_DMA FALSE
263264

264265
/*
265266
* WDG driver system settings.

testhal/AT32/multi/SIO/cfg/at-start-f405/mcuconf.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -260,6 +260,7 @@
260260
#define AT32_USB_OTG2_IRQ_PRIORITY 14
261261
#define AT32_USB_OTG1_RX_FIFO_SIZE 512
262262
#define AT32_USB_OTG2_RX_FIFO_SIZE 1024
263+
#define AT32_USE_USB_OTG2_HS_DMA FALSE
263264

264265
/*
265266
* WDG driver system settings.

testhal/AT32/multi/UART/cfg/at-start-f405/mcuconf.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -260,6 +260,7 @@
260260
#define AT32_USB_OTG2_IRQ_PRIORITY 14
261261
#define AT32_USB_OTG1_RX_FIFO_SIZE 512
262262
#define AT32_USB_OTG2_RX_FIFO_SIZE 1024
263+
#define AT32_USE_USB_OTG2_HS_DMA FALSE
263264

264265
/*
265266
* WDG driver system settings.

0 commit comments

Comments
 (0)