1
0
mirror of https://github.com/RIOT-OS/RIOT.git synced 2024-12-29 04:50:03 +01:00
19397: drivers/usbdev_synopsys_dwc2: fix and reenable DMA mode r=benpicco a=gschorcht

### Contribution description

This PR fixes the DMA mode for all STM32 USB OTG HS cores (including that for STM32F4xx CID 1.xxx) and reenables it. It fixes remaining problems in issue #19359.

This PR includes also includes some changes that are needed to use the DMA mode:
- EP number is used as defined in CMSIS (if defined) for STM32
- `periph_usbdev_hs` feature is added in Kconfig
- `periph_usbdev_hs` feature is added in board definition of `stm32f429i-disc1`
- largest number of available EPs is used for STM32 instead of the smallest number (to be able to use all EPs of HS peripheral)
- `stm32f429i-disco` is removed from blacklist in `tests/usbus_cdc_ecm` since it uses the HS peripheral

### Testing procedure

The following tests should work
```python
USEMODULE=stdio_cdc_acm BOARD=stm32f429i-disc1 make -j8 -C tests/usbus_cdc_ecm flash
```
<details>
<summary>Test results</summary>

```python
[526755.875691] usb 1-2.2: new full-speed USB device number 106 using xhci_hcd
[526755.977853] usb 1-2.2: config 1 interface 3 altsetting 1 endpoint 0x84 has invalid maxpacket 512, setting to 64
[526755.977856] usb 1-2.2: config 1 interface 3 altsetting 1 endpoint 0x2 has invalid maxpacket 512, setting to 64
[526755.978762] usb 1-2.2: New USB device found, idVendor=1209, idProduct=7d01, bcdDevice= 1.00
[526755.978764] usb 1-2.2: New USB device strings: Mfr=3, Product=2, SerialNumber=4
[526755.978766] usb 1-2.2: Product: stm32f429i-disc1
[526755.978768] usb 1-2.2: Manufacturer: RIOT-os.org
[526755.978769] usb 1-2.2: SerialNumber: 7C156425A950A8EB
[526755.991190] cdc_acm 1-2.2:1.0: ttyACM1: USB ACM device
[526755.998131] cdc_ether 1-2.2:1.2 usb0: register 'cdc_ether' at usb-0000:00:14.0-2.2, CDC Ethernet Device, a6:f6:4a:85:1d:c9
[526756.044150] cdc_ether 1-2.2:1.2 enp0s20f0u2u2i2: renamed from usb0
```

</details>

```python
USEMODULE='stdio_cdc_acm periph_usbdev_hs_utmi' BOARD=stm32f723e-disco make -j8 -C tests/usbus_cdc_ecm flash
```
<details>
<summary>Test results</summary>

```python
[528733.480207] usb 1-4.3.4: reset high-speed USB device number 32 using xhci_hcd
[528733.707800] usb 1-4.4: new high-speed USB device number 111 using xhci_hcd
[528733.808257] usb 1-4.4: config 1 interface 0 altsetting 0 endpoint 0x81 has an invalid bInterval 255, changing to 11
[528733.808260] usb 1-4.4: config 1 interface 1 altsetting 0 bulk endpoint 0x1 has invalid maxpacket 64
[528733.808263] usb 1-4.4: config 1 interface 1 altsetting 0 bulk endpoint 0x82 has invalid maxpacket 64
[528733.808642] usb 1-4.4: New USB device found, idVendor=1209, idProduct=7d01, bcdDevice= 1.00
[528733.808645] usb 1-4.4: New USB device strings: Mfr=3, Product=2, SerialNumber=4
[528733.808647] usb 1-4.4: Product: stm32f723e-disco
[528733.808649] usb 1-4.4: Manufacturer: RIOT-os.org
[528733.808651] usb 1-4.4: SerialNumber: A6BAC4E1B1E0806B
[528733.811988] cdc_acm 1-4.4:1.0: ttyACM1: USB ACM device
[528733.814456] cdc_ether 1-4.4:1.2 usb0: register 'cdc_ether' at usb-0000:00:14.0-4.4, CDC Ethernet Device, e6:75:97:3a:74:ba
[528733.854371] cdc_ether 1-4.4:1.2 enp0s20f0u4u4i2: renamed from usb0
```

</details>

```python
USEMODULE='stdio_cdc_acm periph_usbdev_hs_ulpi' BOARD=stm32f746g-disco make -j8 -C tests/usbus_cdc_ecm flash
```
<details>
<summary>Test results</summary>

```python
[529000.944482] usb 1-4.3.4: reset high-speed USB device number 32 using xhci_hcd
[529003.728260] usb 1-4.4: new high-speed USB device number 114 using xhci_hcd
[529003.833107] usb 1-4.4: config 1 interface 0 altsetting 0 endpoint 0x81 has an invalid bInterval 255, changing to 11
[529003.833111] usb 1-4.4: config 1 interface 1 altsetting 0 bulk endpoint 0x1 has invalid maxpacket 64
[529003.833113] usb 1-4.4: config 1 interface 1 altsetting 0 bulk endpoint 0x82 has invalid maxpacket 64
[529003.833743] usb 1-4.4: New USB device found, idVendor=1209, idProduct=7d00, bcdDevice= 1.00
[529003.833747] usb 1-4.4: New USB device strings: Mfr=3, Product=2, SerialNumber=4
[529003.833749] usb 1-4.4: Product: stm32f746g-disco
[529003.833751] usb 1-4.4: Manufacturer: RIOT-os.org
[529003.833753] usb 1-4.4: SerialNumber: 66FE8934D1A363E0
[529003.837143] cdc_acm 1-4.4:1.0: ttyACM1: USB ACM device
[529003.839755] cdc_ether 1-4.4:1.2 usb0: register 'cdc_ether' at usb-0000:00:14.0-4.4, CDC Ethernet Device, 6a:88:1f:1f:b1:f0
[529003.879025] cdc_ether 1-4.4:1.2 enp0s20f0u4u4i2: renamed from usb0```
```
</details>

### Issues/PRs references

Fixes #19359


19416: cpu/rpx0xx/cmsis: Update vendor header files r=benpicco a=maribu

### Contribution description

Generated new vendor header files from upstream SVD files using:

    ./SVDConv "$PICO_SDK_DIR"/src/rp2040/hardware_regs/rp2040.svd \
        --generate=header --fields=macro --fields=enum

Note: The missing `--fields=struct` flag resulted in the header no longer containing bit-fields to represent different fields within registers. While this would generally ease writing code, the RP2040 has the unpleasant feature of corrupting the remaining bits of the register when a write access that is not word-sized occurs in the memory mapped I/O area. This could happen e.g. when a bit field is byte-sized and byte-aligned.
### Testing procedure

No binary changes (hopefully).

### Issues/PRs references

This adds a few additional vendor defines, notably for USB. If anyone were to implement USB, this would be a requirement.

19418: cpu/gd32v: fix gpio_read in periph_gpio r=benpicco a=gschorcht

### Contribution description

This PR fixes a bug in `gpio_read` which made `gpio_read` completely unusable!

A small bug with big consequences. In `gpio_read` the combined port | pin_num parameter `pin` was used instead of the pin number `pin_num` for the call of `_pin_is_input`. This caused the problem that for example instead of accessing GPIOA->CTL0 with address 0x40010800, address 0x60018c00 was accessed. As a result, a pin was randomly detected as input or output and thus a result was arbitrarily returned. Approx. 50% of all inputs always returned LOW.

I found this error by coincidence when I tried to find out why the BOOT0 button on a Sipeed Longan Nano is not usable as a button in RIOT.

### Testing procedure

Flash `tests/periph_gpio`
```
BOARD=sipeed-longan-nano make -j8 -C tests/periph_gpio flash
```
and use commands
```
init_in 0 8
read 0 8
```
Without this PR, the pin is always LOW. With the PR, the pin should be HIGH when the BOOT button is pressed.

### Issues/PRs references

19419: boards/sipeed-longan-nano: add BOOT as user button r=benpicco a=gschorcht

### Contribution description

This PR makes the BOOT button usable as a user button.

### Testing procedure

The test requires PR #19418 to work.

Flash and test:
```
BOARD=sipeed-longan-nano make -j8 -C tests/saul flash term
```
The output
```
Dev: BOOT	Type: SENSE_BTN
Data:	              0 
```
should change to
```
Dev: BOOT	Type: SENSE_BTN
Data:	              1 
```
when the BOOT button is pressed.

### Issues/PRs references

Depends on PR #19418 


Co-authored-by: Gunar Schorcht <gunar@schorcht.net>
Co-authored-by: Marian Buschsieweke <marian.buschsieweke@ovgu.de>
This commit is contained in:
bors[bot] 2023-03-24 08:38:06 +00:00 committed by GitHub
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
23 changed files with 3553 additions and 13261 deletions

View File

@ -34,9 +34,9 @@ extern "C" {
* @{
*/
#define LED0_PIN GPIO_PIN(0, 25)
#define LED0_ON do {SIO->GPIO_OUT_SET.reg = 1UL << 25;} while (0)
#define LED0_OFF do {SIO->GPIO_OUT_CLR.reg = 1UL << 25;} while (0)
#define LED0_TOGGLE do {SIO->GPIO_OUT_XOR.reg = 1UL << 25;} while (0)
#define LED0_ON do {SIO->GPIO_OUT_SET = 1UL << 25;} while (0)
#define LED0_OFF do {SIO->GPIO_OUT_CLR = 1UL << 25;} while (0)
#define LED0_TOGGLE do {SIO->GPIO_OUT_XOR = 1UL << 25;} while (0)
#define LED0_NAME "LED(Green)"
/** @} */

View File

@ -67,9 +67,9 @@ by pins.
| ADC_LINE(5) | PB1 | ADC01_IN9 | TFT RST | N/A if TFT is used |
| ADC_LINE(6) | PA6 | ADC01_IN6 | | N/A if TFT is used |
| ADC_LINE(7) | PA7 | ADC01_IN7 | | N/A if TFT is used |
| ADC_LINE(8) | PA8 | ADC01_IN4 | | N/A if TFT is used |
| ADC_LINE(9) | PA9 | ADC01_IN5 | | N/A if TFT is used |
| BTN0 | PA0 | BOOT0 | BOOT | |
| ADC_LINE(8) | PA4 | ADC01_IN4 | | N/A if TFT is used |
| ADC_LINE(9) | PA5 | ADC01_IN5 | | N/A if TFT is used |
| BTN0 | PA8 | BOOT0 | BOOT | |
| DAC_LINE(0) | PA4 | DAC0 | | N/A if TFT is used |
| DAC_LINE(1) | PA5 | DAC1 | | N/A if TFT is used |
| GPIO_PIN(1, 2) | PB2 | | TFT CS | |
@ -105,7 +105,7 @@ by pins.
| PA5 | TFT SCL | SPI_DEV(1) SCLK | ADC_LINE(9)* | DAC_LINE(1)* |
| PA6 | | SPI_DEV(1) MISO | ADC_LINE(6)* | |
| PA7 | TFT SDA | SPI_DEV(1) MOSI | ADC_LINE(7)* | |
| PA8 | | | | |
| PA8 | BOOT | | | BTN0 |
| PA9 | | UART_DEV(0) TX | | |
| PA10 | | UART_DEV(0) RX | | |
| PA11 | USB D- | | | |

View File

@ -26,6 +26,15 @@
extern "C" {
#endif
/**
* @name Button pin definitions
* @{
*/
#define BTN0_PIN GPIO_PIN(PORT_A, 8)
#define BTN0_MODE GPIO_IN
#define BTN0_INT_FLANK GPIO_RISING
/** @} */
/**
* @name LED (on-board) configuration
* @{

View File

@ -31,6 +31,11 @@ extern "C" {
*/
static const saul_gpio_params_t saul_gpio_params[] =
{
{
.name = "BOOT",
.pin = BTN0_PIN,
.mode = BTN0_MODE,
},
{
.name = "LED RED",
.pin = LED0_PIN,

View File

@ -20,6 +20,7 @@ config BOARD_STM32F429I_DISC1
select HAS_PERIPH_TIMER
select HAS_PERIPH_UART
select HAS_PERIPH_USBDEV
select HAS_PERIPH_USBDEV_HS
# Put other features for this board (in alphabetical order)
select HAS_RIOTBOOT
@ -38,4 +39,6 @@ config BOARD_STM32F429I_DISC1
select HAVE_I3G4250D
select HAVE_L3GD20
select MODULE_PERIPH_USBDEV_HS if MODULE_PERIPH_USBDEV
source "$(RIOTBOARD)/common/stm32/Kconfig"

View File

@ -1,3 +1,7 @@
ifneq (,$(filter periph_usbdev,$(USEMODULE)))
USEMODULE += periph_usbdev_hs
endif
ifneq (,$(filter saul_default,$(USEMODULE)))
USEMODULE += saul_gpio
USEMODULE += l3gxxxx

View File

@ -8,6 +8,7 @@ FEATURES_PROVIDED += periph_spi
FEATURES_PROVIDED += periph_timer
FEATURES_PROVIDED += periph_uart
FEATURES_PROVIDED += periph_usbdev
FEATURES_PROVIDED += periph_usbdev_hs
# Put other features for this board (in alphabetical order)
FEATURES_PROVIDED += riotboot

View File

@ -165,7 +165,7 @@ int gpio_read(gpio_t pin)
GPIO_Type *port = _port(pin);
unsigned pin_num = _pin_num(pin);
if (_pin_is_output(port, pin)) {
if (_pin_is_output(port, pin_num)) {
/* pin is output */
return (port->OCTL & (1 << pin_num));
}

View File

@ -29,25 +29,25 @@
static void _clk_sys_set_source(CLOCKS_CLK_SYS_CTRL_SRC_Enum source)
{
io_reg_write_dont_corrupt(&CLOCKS->CLK_SYS_CTRL.reg, source << CLOCKS_CLK_SYS_CTRL_SRC_Pos,
io_reg_write_dont_corrupt(&CLOCKS->CLK_SYS_CTRL, source << CLOCKS_CLK_SYS_CTRL_SRC_Pos,
CLOCKS_CLK_SYS_CTRL_SRC_Msk);
}
static void _clk_sys_set_aux_source(CLOCKS_CLK_SYS_CTRL_AUXSRC_Enum source)
{
io_reg_write_dont_corrupt(&CLOCKS->CLK_SYS_CTRL.reg, source << CLOCKS_CLK_SYS_CTRL_AUXSRC_Pos,
io_reg_write_dont_corrupt(&CLOCKS->CLK_SYS_CTRL, source << CLOCKS_CLK_SYS_CTRL_AUXSRC_Pos,
CLOCKS_CLK_SYS_CTRL_AUXSRC_Msk);
}
static void _clk_ref_set_source(CLOCKS_CLK_REF_CTRL_SRC_Enum source)
{
io_reg_write_dont_corrupt(&CLOCKS->CLK_REF_CTRL.reg, source << CLOCKS_CLK_REF_CTRL_SRC_Pos,
io_reg_write_dont_corrupt(&CLOCKS->CLK_REF_CTRL, source << CLOCKS_CLK_REF_CTRL_SRC_Pos,
CLOCKS_CLK_REF_CTRL_SRC_Msk);
}
static void _clk_ref_set_aux_source(CLOCKS_CLK_REF_CTRL_AUXSRC_Enum source)
{
io_reg_write_dont_corrupt(&CLOCKS->CLK_REF_CTRL.reg, source << CLOCKS_CLK_REF_CTRL_AUXSRC_Pos,
io_reg_write_dont_corrupt(&CLOCKS->CLK_REF_CTRL, source << CLOCKS_CLK_REF_CTRL_AUXSRC_Pos,
CLOCKS_CLK_REF_CTRL_AUXSRC_Msk);
}
@ -66,7 +66,7 @@ void clock_sys_configure_source(uint32_t f_in, uint32_t f_out, CLOCKS_CLK_SYS_CT
/* switch the glitchless mux to clk_ref */
_clk_sys_set_source(source);
/* apply divider */
CLOCKS->CLK_SYS_DIV.reg = div;
CLOCKS->CLK_SYS_DIV = div;
/* poll SELECTED until the switch is completed */
while (!(CLOCKS->CLK_SYS_SELECTED & (1U << source))) { }
}
@ -83,7 +83,7 @@ void clock_sys_configure_aux_source(uint32_t f_in, uint32_t f_out,
/* change the auxiliary mux */
_clk_sys_set_aux_source(aux);
/* apply divider */
CLOCKS->CLK_SYS_DIV.reg = div;
CLOCKS->CLK_SYS_DIV = div;
/* switch the glitchless mux to clk_sys_aux */
_clk_sys_set_source(CLOCKS_CLK_SYS_CTRL_SRC_clksrc_clk_sys_aux);
/* poll SELECTED until the switch is completed */
@ -98,7 +98,7 @@ void clock_ref_configure_source(uint32_t f_in, uint32_t f_out, CLOCKS_CLK_REF_CT
/* switch the glitchless mux to clock source */
_clk_ref_set_source(source);
/* apply divider */
CLOCKS->CLK_REF_DIV.reg = div & CLOCKS_CLK_REF_DIV_INT_Msk;
CLOCKS->CLK_REF_DIV = div & CLOCKS_CLK_REF_DIV_INT_Msk;
/* poll SELECTED until the switch is completed */
while (!(CLOCKS->CLK_REF_SELECTED & (1U << source))) { }
}
@ -115,7 +115,7 @@ void clock_ref_configure_aux_source(uint32_t f_in, uint32_t f_out,
/* change the auxiliary mux */
_clk_ref_set_aux_source(aux);
/* apply divider */
CLOCKS->CLK_REF_DIV.reg = div & CLOCKS_CLK_REF_DIV_INT_Msk;
CLOCKS->CLK_REF_DIV = div & CLOCKS_CLK_REF_DIV_INT_Msk;
/* switch the glitchless mux to clk_ref_aux */
_clk_ref_set_source(CLOCKS_CLK_REF_CTRL_SRC_clksrc_clk_ref_aux);
/* poll SELECTED until the switch is completed */
@ -124,21 +124,21 @@ void clock_ref_configure_aux_source(uint32_t f_in, uint32_t f_out,
void clock_periph_configure(CLOCKS_CLK_PERI_CTRL_AUXSRC_Enum aux)
{
io_reg_atomic_clear(&CLOCKS->CLK_PERI_CTRL.reg, (1u << CLOCKS_CLK_PERI_CTRL_ENABLE_Pos));
io_reg_write_dont_corrupt(&CLOCKS->CLK_PERI_CTRL.reg, aux << CLOCKS_CLK_PERI_CTRL_AUXSRC_Pos,
io_reg_atomic_clear(&CLOCKS->CLK_PERI_CTRL, (1u << CLOCKS_CLK_PERI_CTRL_ENABLE_Pos));
io_reg_write_dont_corrupt(&CLOCKS->CLK_PERI_CTRL, aux << CLOCKS_CLK_PERI_CTRL_AUXSRC_Pos,
CLOCKS_CLK_PERI_CTRL_AUXSRC_Msk);
io_reg_atomic_set(&CLOCKS->CLK_PERI_CTRL.reg, (1u << CLOCKS_CLK_PERI_CTRL_ENABLE_Pos));
io_reg_atomic_set(&CLOCKS->CLK_PERI_CTRL, (1u << CLOCKS_CLK_PERI_CTRL_ENABLE_Pos));
}
void clock_gpout0_configure(uint32_t f_in, uint32_t f_out, CLOCKS_CLK_GPOUT0_CTRL_AUXSRC_Enum aux)
{
assert(f_out <= f_in);
uint32_t div = (((uint64_t)f_in) << CLOCKS_CLK_REF_DIV_INT_Pos) / f_out;
io_reg_atomic_clear(&CLOCKS->CLK_GPOUT0_CTRL.reg, 1U << CLOCKS_CLK_GPOUT0_CTRL_ENABLE_Pos);
_gpout_set_aux_source(&CLOCKS->CLK_GPOUT0_CTRL.reg, aux);
CLOCKS->CLK_GPOUT0_DIV.reg = div;
io_reg_atomic_set(&CLOCKS->CLK_GPOUT0_CTRL.reg, 1U << CLOCKS_CLK_GPOUT0_CTRL_ENABLE_Pos);
io_reg_atomic_set(&PADS_BANK0->GPIO21.reg, 1U << PADS_BANK0_GPIO21_IE_Pos);
io_reg_atomic_clear(&CLOCKS->CLK_GPOUT0_CTRL, 1U << CLOCKS_CLK_GPOUT0_CTRL_ENABLE_Pos);
_gpout_set_aux_source(&CLOCKS->CLK_GPOUT0_CTRL, aux);
CLOCKS->CLK_GPOUT0_DIV = div;
io_reg_atomic_set(&CLOCKS->CLK_GPOUT0_CTRL, 1U << CLOCKS_CLK_GPOUT0_CTRL_ENABLE_Pos);
io_reg_atomic_set(&PADS_BANK0->GPIO21, 1U << PADS_BANK0_GPIO21_IE_Pos);
gpio_set_function_select(21, FUNCTION_SELECT_CLOCK);
}
@ -146,11 +146,11 @@ void clock_gpout1_configure(uint32_t f_in, uint32_t f_out, CLOCKS_CLK_GPOUT1_CTR
{
assert(f_out <= f_in);
uint32_t div = (((uint64_t)f_in) << CLOCKS_CLK_REF_DIV_INT_Pos) / f_out;
io_reg_atomic_clear(&CLOCKS->CLK_GPOUT1_CTRL.reg, 1U << CLOCKS_CLK_GPOUT1_CTRL_ENABLE_Pos);
_gpout_set_aux_source(&CLOCKS->CLK_GPOUT1_CTRL.reg, aux);
CLOCKS->CLK_GPOUT1_DIV.reg = div;
io_reg_atomic_set(&CLOCKS->CLK_GPOUT1_CTRL.reg, 1U << CLOCKS_CLK_GPOUT1_CTRL_ENABLE_Pos);
io_reg_atomic_set(&PADS_BANK0->GPIO23.reg, 1U << PADS_BANK0_GPIO23_IE_Pos);
io_reg_atomic_clear(&CLOCKS->CLK_GPOUT1_CTRL, 1U << CLOCKS_CLK_GPOUT1_CTRL_ENABLE_Pos);
_gpout_set_aux_source(&CLOCKS->CLK_GPOUT1_CTRL, aux);
CLOCKS->CLK_GPOUT1_DIV = div;
io_reg_atomic_set(&CLOCKS->CLK_GPOUT1_CTRL, 1U << CLOCKS_CLK_GPOUT1_CTRL_ENABLE_Pos);
io_reg_atomic_set(&PADS_BANK0->GPIO23, 1U << PADS_BANK0_GPIO23_IE_Pos);
gpio_set_function_select(23, FUNCTION_SELECT_CLOCK);
}
@ -158,11 +158,11 @@ void clock_gpout2_configure(uint32_t f_in, uint32_t f_out, CLOCKS_CLK_GPOUT2_CTR
{
assert(f_out <= f_in);
uint32_t div = (((uint64_t)f_in) << CLOCKS_CLK_REF_DIV_INT_Pos) / f_out;
io_reg_atomic_clear(&CLOCKS->CLK_GPOUT2_CTRL.reg, 1U << CLOCKS_CLK_GPOUT2_CTRL_ENABLE_Pos);
_gpout_set_aux_source(&CLOCKS->CLK_GPOUT2_CTRL.reg, aux);
CLOCKS->CLK_GPOUT2_DIV.reg = div;
io_reg_atomic_set(&CLOCKS->CLK_GPOUT2_CTRL.reg, 1U << CLOCKS_CLK_GPOUT2_CTRL_ENABLE_Pos);
io_reg_atomic_set(&PADS_BANK0->GPIO24.reg, 1U << PADS_BANK0_GPIO24_IE_Pos);
io_reg_atomic_clear(&CLOCKS->CLK_GPOUT2_CTRL, 1U << CLOCKS_CLK_GPOUT2_CTRL_ENABLE_Pos);
_gpout_set_aux_source(&CLOCKS->CLK_GPOUT2_CTRL, aux);
CLOCKS->CLK_GPOUT2_DIV = div;
io_reg_atomic_set(&CLOCKS->CLK_GPOUT2_CTRL, 1U << CLOCKS_CLK_GPOUT2_CTRL_ENABLE_Pos);
io_reg_atomic_set(&PADS_BANK0->GPIO24, 1U << PADS_BANK0_GPIO24_IE_Pos);
gpio_set_function_select(24, FUNCTION_SELECT_CLOCK);
}
@ -170,10 +170,10 @@ void clock_gpout3_configure(uint32_t f_in, uint32_t f_out, CLOCKS_CLK_GPOUT3_CTR
{
assert(f_out <= f_in);
uint32_t div = (((uint64_t)f_in) << CLOCKS_CLK_REF_DIV_INT_Pos) / f_out;
io_reg_atomic_clear(&CLOCKS->CLK_GPOUT3_CTRL.reg, 1U << CLOCKS_CLK_GPOUT3_CTRL_ENABLE_Pos);
_gpout_set_aux_source(&CLOCKS->CLK_GPOUT3_CTRL.reg, aux);
CLOCKS->CLK_GPOUT3_DIV.reg = div;
io_reg_atomic_set(&CLOCKS->CLK_GPOUT3_CTRL.reg, 1U << CLOCKS_CLK_GPOUT3_CTRL_ENABLE_Pos);
io_reg_atomic_set(&PADS_BANK0->GPIO25.reg, 1U << PADS_BANK0_GPIO25_IE_Pos);
io_reg_atomic_clear(&CLOCKS->CLK_GPOUT3_CTRL, 1U << CLOCKS_CLK_GPOUT3_CTRL_ENABLE_Pos);
_gpout_set_aux_source(&CLOCKS->CLK_GPOUT3_CTRL, aux);
CLOCKS->CLK_GPOUT3_DIV = div;
io_reg_atomic_set(&CLOCKS->CLK_GPOUT3_CTRL, 1U << CLOCKS_CLK_GPOUT3_CTRL_ENABLE_Pos);
io_reg_atomic_set(&PADS_BANK0->GPIO25, 1U << PADS_BANK0_GPIO25_IE_Pos);
gpio_set_function_select(25, FUNCTION_SELECT_CLOCK);
}

View File

@ -121,7 +121,7 @@ static inline void io_reg_atomic_clear(volatile uint32_t *reg, uint32_t mask)
*
* Example use:
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.c}
* io_reg_write_dont_corrupt(&CLOCKS->CLK_SYS_CTRL.reg, source << CLOCKS_CLK_SYS_CTRL_SRC_Pos,
* io_reg_write_dont_corrupt(&CLOCKS->CLK_SYS_CTRL, source << CLOCKS_CLK_SYS_CTRL_SRC_Pos,
* CLOCKS_CLK_SYS_CTRL_SRC_Msk);
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*/

View File

@ -487,7 +487,7 @@ static inline void gpio_reset_all_config(uint8_t pin)
*/
static inline void periph_reset(uint32_t components)
{
io_reg_atomic_set(&RESETS->RESET.reg, components);
io_reg_atomic_set(&RESETS->RESET, components);
}
/**
@ -498,8 +498,8 @@ static inline void periph_reset(uint32_t components)
*/
static inline void periph_reset_done(uint32_t components)
{
io_reg_atomic_clear(&RESETS->RESET.reg, components);
while ((~RESETS->RESET_DONE.reg) & components) { }
io_reg_atomic_clear(&RESETS->RESET, components);
while ((~RESETS->RESET_DONE) & components) { }
}
/**

File diff suppressed because it is too large Load Diff

View File

@ -42,8 +42,8 @@ static void *_args[GPIO_PIN_NUMOF];
int gpio_init(gpio_t pin, gpio_mode_t mode)
{
assert(pin < GPIO_PIN_NUMOF);
SIO->GPIO_OE_CLR.reg = 1LU << pin;
SIO->GPIO_OUT_CLR.reg = 1LU << pin;
SIO->GPIO_OE_CLR = 1LU << pin;
SIO->GPIO_OUT_CLR = 1LU << pin;
switch (mode) {
case GPIO_IN:
@ -98,7 +98,7 @@ int gpio_init(gpio_t pin, gpio_mode_t mode)
gpio_set_pad_config(pin, pad_config);
gpio_set_io_config(pin, io_config);
}
SIO->GPIO_OE_SET.reg = 1LU << pin;
SIO->GPIO_OE_SET = 1LU << pin;
break;
default:
return -ENOTSUP;
@ -108,27 +108,27 @@ int gpio_init(gpio_t pin, gpio_mode_t mode)
int gpio_read(gpio_t pin)
{
if (SIO->GPIO_OE.reg & (1LU << pin)) {
if (SIO->GPIO_OE & (1LU << pin)) {
/* pin is output: */
return SIO->GPIO_OUT.reg & (1LU << pin);
return SIO->GPIO_OUT & (1LU << pin);
}
/* pin is input: */
return SIO->GPIO_IN.reg & (1LU << pin);
return SIO->GPIO_IN & (1LU << pin);
}
void gpio_set(gpio_t pin)
{
SIO->GPIO_OUT_SET.reg = 1LU << pin;
SIO->GPIO_OUT_SET = 1LU << pin;
}
void gpio_clear(gpio_t pin)
{
SIO->GPIO_OUT_CLR.reg = 1LU << pin;
SIO->GPIO_OUT_CLR = 1LU << pin;
}
void gpio_toggle(gpio_t pin)
{
SIO->GPIO_OUT_XOR.reg = 1LU << pin;
SIO->GPIO_OUT_XOR = 1LU << pin;
}
void gpio_write(gpio_t pin, int value)
@ -144,8 +144,8 @@ void gpio_write(gpio_t pin, int value)
#ifdef MODULE_PERIPH_GPIO_IRQ
static void _irq_enable(gpio_t pin, unsigned flank)
{
volatile uint32_t *irq_enable_regs = &IO_BANK0->PROC0_INTE0.reg;
volatile uint32_t *irq_ack_regs = &IO_BANK0->INTR0.reg;
volatile uint32_t *irq_enable_regs = &IO_BANK0->PROC0_INTE0;
volatile uint32_t *irq_ack_regs = &IO_BANK0->INTR0;
/* There are 4 bits to control IRQs per pin, hence the configuration is split across multiple
* I/O registers. The following calculates the position the four bits matching the given pin,
* where idx refers to the I/O register and shift_amount to the position in the I/O register.
@ -201,15 +201,15 @@ int gpio_init_int(gpio_t pin, gpio_mode_t mode, gpio_flank_t flank, gpio_cb_t cb
void isr_io_bank0(void)
{
unsigned offset = 0;
volatile uint32_t *irq_status_regs = &IO_BANK0->PROC0_INTS0.reg;
volatile uint32_t *irq_ack_regs = &IO_BANK0->INTR0.reg;
volatile uint32_t *irq_status_regs = &IO_BANK0->PROC0_INTS0;
volatile uint32_t *irq_ack_regs = &IO_BANK0->INTR0;
DEBUG("[rp0x00] GPIO IRQ mask: %08x, %08x, %08x, %08x\n",
(unsigned)IO_BANK0->PROC0_INTE0.reg, (unsigned)IO_BANK0->PROC0_INTE1.reg,
(unsigned)IO_BANK0->PROC0_INTE2.reg, (unsigned)IO_BANK0->PROC0_INTE3.reg);
(unsigned)IO_BANK0->PROC0_INTE0, (unsigned)IO_BANK0->PROC0_INTE1,
(unsigned)IO_BANK0->PROC0_INTE2, (unsigned)IO_BANK0->PROC0_INTE3);
DEBUG("[rp0x00] GPIO IRQ status: %08x, %08x, %08x, %08x\n",
(unsigned)IO_BANK0->PROC0_INTS0.reg, (unsigned)IO_BANK0->PROC0_INTS1.reg,
(unsigned)IO_BANK0->PROC0_INTS2.reg, (unsigned)IO_BANK0->PROC0_INTS3.reg);
(unsigned)IO_BANK0->PROC0_INTS0, (unsigned)IO_BANK0->PROC0_INTS1,
(unsigned)IO_BANK0->PROC0_INTS2, (unsigned)IO_BANK0->PROC0_INTS3);
/* There are four IRQ status bits per pin, so there is info for 8 pins per I/O register.
* We will iterate over all IRQ status I/O registers in the outer loop, and over all 8 pins

View File

@ -88,14 +88,14 @@ static inline void _irq_enable(tim_t dev)
{
for (uint8_t i = 0; i < timer_config[dev].ch_numof; i++) {
NVIC_EnableIRQ(timer_config[dev].ch[i].irqn);
io_reg_atomic_set(&DEV(dev)->INTE.reg, (1U << i));
io_reg_atomic_set(&DEV(dev)->INTE, (1U << i));
}
}
static void _isr(tim_t dev, int channel)
{
/* clear latched interrupt */
io_reg_atomic_clear(&DEV(dev)->INTR.reg, 1U << channel);
io_reg_atomic_clear(&DEV(dev)->INTR, 1U << channel);
if (_timer_is_periodic(dev, channel)) {
if (_timer_reset_on_match(dev, channel)) {
@ -118,7 +118,8 @@ int timer_init(tim_t dev, uint32_t freq, timer_cb_t cb, void *arg)
}
/* The timer must run at 1000000 Hz (µs precision)
because the number of cycles per µs is shared with the watchdog.
The reference clock (clk_ref) is divided by WATCHDOG->TICK.bits.CYCLES
The reference clock (clk_ref) is divided by
(WATCHDOG->TICK & WATCHDOC_TICK_CYCLES_Mask)
to generate µs ticks.
*/
assert(freq == US_PER_SEC); (void)freq;
@ -126,7 +127,7 @@ int timer_init(tim_t dev, uint32_t freq, timer_cb_t cb, void *arg)
_timer_ctx_arg[dev] = arg;
periph_reset(RESETS_RESET_timer_Msk);
periph_reset_done(RESETS_RESET_timer_Msk);
io_reg_write_dont_corrupt(&WATCHDOG->TICK.reg,
io_reg_write_dont_corrupt(&WATCHDOG->TICK,
(CLOCK_XOSC / MHZ(1)) << WATCHDOG_TICK_CYCLES_Pos,
WATCHDOG_TICK_CYCLES_Msk);
_irq_enable(dev);
@ -205,7 +206,7 @@ int timer_clear(tim_t dev, int channel)
return -EINVAL;
}
/* ARMED bits are write clear */
io_reg_atomic_set(&DEV(dev)->ARMED.reg, (1 << channel));
io_reg_atomic_set(&DEV(dev)->ARMED, (1 << channel));
unsigned state = irq_disable();
_timer_disable_periodic(dev, channel);
irq_restore(state);
@ -223,13 +224,13 @@ unsigned int timer_read(tim_t dev)
void timer_start(tim_t dev)
{
assert(dev < TIMER_NUMOF);
io_reg_atomic_clear(&DEV(dev)->PAUSE.reg, (1 << TIMER_PAUSE_PAUSE_Pos));
io_reg_atomic_clear(&DEV(dev)->PAUSE, (1 << TIMER_PAUSE_PAUSE_Pos));
}
void timer_stop(tim_t dev)
{
assert(dev < TIMER_NUMOF);
io_reg_atomic_set(&DEV(dev)->PAUSE.reg, (1 << TIMER_PAUSE_PAUSE_Pos));
io_reg_atomic_set(&DEV(dev)->PAUSE, (1 << TIMER_PAUSE_PAUSE_Pos));
}
/* timer 0 IRQ0 */

View File

@ -48,7 +48,7 @@ static uint32_t uartcr;
void _irq_enable(uart_t uart)
{
UART0_Type *dev = uart_config[uart].dev;
dev->UARTIMSC.reg = UART0_UARTIMSC_RXIM_Msk;
dev->UARTIMSC = UART0_UARTIMSC_RXIM_Msk;
NVIC_EnableIRQ(uart_config[uart].irqn);
}
@ -72,8 +72,8 @@ void _set_symbolrate(uart_t uart, uint32_t baud)
baud_fbrd = ((baud_rate_div & 0x7f) + 1) / 2;
}
dev->UARTIBRD.reg = baud_ibrd;
dev->UARTFBRD.reg = baud_fbrd;
dev->UARTIBRD = baud_ibrd;
dev->UARTFBRD = baud_fbrd;
}
int uart_mode(uart_t uart, uart_data_bits_t data_bits, uart_parity_t uart_parity,
@ -82,7 +82,7 @@ int uart_mode(uart_t uart, uart_data_bits_t data_bits, uart_parity_t uart_parity
assert((unsigned)uart < UART_NUMOF);
UART0_Type *dev = uart_config[uart].dev;
io_reg_atomic_clear(&dev->UARTCR.reg,
io_reg_atomic_clear(&dev->UARTCR,
UART0_UARTCR_UARTEN_Msk | UART0_UARTCR_TXE_Msk | UART0_UARTCR_RXE_Msk);
/* Beware of strange hardware bug: If the configuration bitmask is prepared in register and
@ -91,26 +91,26 @@ int uart_mode(uart_t uart, uart_data_bits_t data_bits, uart_parity_t uart_parity
* next char send out. If the configuration is updated in multiple bus accesses, it will apply
* directly to the next char. So: Double check e.g. with tests/periph_uart_mode after touching
* the initialization code here */
dev->UARTLCR_H.reg = (uint32_t)data_bits << UART0_UARTLCR_H_WLEN_Pos;
dev->UARTLCR_H = (uint32_t)data_bits << UART0_UARTLCR_H_WLEN_Pos;
if (stop_bits == UART_STOP_BITS_2) {
io_reg_atomic_set(&dev->UARTLCR_H.reg, UART0_UARTLCR_H_STP2_Msk);
io_reg_atomic_set(&dev->UARTLCR_H, UART0_UARTLCR_H_STP2_Msk);
}
switch (uart_parity) {
case UART_PARITY_NONE:
break;
case UART_PARITY_EVEN:
io_reg_atomic_set(&dev->UARTLCR_H.reg, UART0_UARTLCR_H_EPS_Msk | UART0_UARTLCR_H_PEN_Msk);
io_reg_atomic_set(&dev->UARTLCR_H, UART0_UARTLCR_H_EPS_Msk | UART0_UARTLCR_H_PEN_Msk);
break;
case UART_PARITY_ODD:
io_reg_atomic_set(&dev->UARTLCR_H.reg, UART0_UARTLCR_H_PEN_Msk);
io_reg_atomic_set(&dev->UARTLCR_H, UART0_UARTLCR_H_PEN_Msk);
break;
default:
return UART_NOMODE;
}
io_reg_atomic_set(&dev->UARTCR.reg,
io_reg_atomic_set(&dev->UARTCR,
UART0_UARTCR_UARTEN_Msk | UART0_UARTCR_TXE_Msk | UART0_UARTCR_RXE_Msk);
return UART_OK;
@ -148,7 +148,7 @@ void uart_deinit_pins(uart_t uart)
{
assert((unsigned)uart < UART_NUMOF);
gpio_reset_all_config(uart_config[uart].tx_pin);
SIO->GPIO_OE_CLR.reg = 1LU << uart_config[uart].tx_pin;
SIO->GPIO_OE_CLR = 1LU << uart_config[uart].tx_pin;
if (ctx[uart].rx_cb) {
gpio_reset_all_config(uart_config[uart].rx_pin);
}
@ -167,10 +167,10 @@ void uart_poweron(uart_t uart)
_poweron(uart);
UART0_Type *dev = uart_config[uart].dev;
/* restore configuration registers */
dev->UARTIBRD.reg = uartibrd;
dev->UARTFBRD.reg = uartfbrd;
dev->UARTLCR_H.reg = uartlcr_h;
dev->UARTCR.reg = uartcr;
dev->UARTIBRD = uartibrd;
dev->UARTFBRD = uartfbrd;
dev->UARTLCR_H = uartlcr_h;
dev->UARTCR = uartcr;
/* restore IRQs, if needed */
if (ctx[uart].rx_cb != NULL) {
_irq_enable(uart);
@ -183,10 +183,10 @@ void uart_poweroff(uart_t uart)
assert((unsigned)uart < UART_NUMOF);
UART0_Type *dev = uart_config[uart].dev;
/* backup configuration registers */
uartibrd = dev->UARTIBRD.reg;
uartfbrd = dev->UARTFBRD.reg;
uartlcr_h = dev->UARTLCR_H.reg;
uartcr = dev->UARTCR.reg;
uartibrd = dev->UARTIBRD;
uartfbrd = dev->UARTFBRD;
uartlcr_h = dev->UARTLCR_H;
uartcr = dev->UARTCR;
/* disconnect GPIOs and power off peripheral */
uart_deinit_pins(uart);
periph_reset((uart) ? RESETS_RESET_uart1_Msk : RESETS_RESET_uart0_Msk);
@ -217,10 +217,10 @@ int uart_init(uart_t uart, uint32_t baud, uart_rx_cb_t rx_cb, void *arg)
if (rx_cb != NULL) {
_irq_enable(uart);
/* clear any pending data and IRQ to avoid receiving a garbage char */
uint32_t status = dev->UARTRIS.reg;
dev->UARTICR.reg = status;
(void)dev->UARTDR.reg;
io_reg_atomic_set(&dev->UARTCR.reg, UART0_UARTCR_RXE_Msk);
uint32_t status = dev->UARTRIS;
dev->UARTICR = status;
(void)dev->UARTDR;
io_reg_atomic_set(&dev->UARTCR, UART0_UARTCR_RXE_Msk);
}
return UART_OK;
@ -232,8 +232,8 @@ void uart_write(uart_t uart, const uint8_t *data, size_t len)
UART0_Type *dev = uart_config[uart].dev;
for (size_t i = 0; i < len; i++) {
dev->UARTDR.reg = data[i];
while (!(dev->UARTRIS.reg & UART0_UARTRIS_TXRIS_Msk)) { }
dev->UARTDR = data[i];
while (!(dev->UARTRIS & UART0_UARTRIS_TXRIS_Msk)) { }
}
}
@ -253,11 +253,11 @@ void isr_handler(uint8_t num)
{
UART0_Type *dev = uart_config[num].dev;
uint32_t status = dev->UARTMIS.reg;
dev->UARTICR.reg = status;
uint32_t status = dev->UARTMIS;
dev->UARTICR = status;
if (status & UART0_UARTMIS_RXMIS_Msk) {
uint32_t data = dev->UARTDR.reg;
uint32_t data = dev->UARTDR;
if (data & (UART0_UARTDR_BE_Msk | UART0_UARTDR_PE_Msk | UART0_UARTDR_FE_Msk)) {
DEBUG_PUTS("[rpx0xx] uart RX error (parity, break, or framing error");
}

View File

@ -44,22 +44,22 @@ static void _pll_start(PLL_SYS_Type *pll, uint8_t ref_div,
assert(post_div_2 <= PLL_POSTDIV_MAX);
/* program reference clock divider */
io_reg_write_dont_corrupt(&pll->CS.reg, ref_div << PLL_SYS_CS_REFDIV_Pos,
io_reg_write_dont_corrupt(&pll->CS, ref_div << PLL_SYS_CS_REFDIV_Pos,
PLL_SYS_CS_REFDIV_Msk);
/* program feedback divider */
io_reg_write_dont_corrupt(&pll->FBDIV_INT.reg,
io_reg_write_dont_corrupt(&pll->FBDIV_INT,
vco_feedback_scale << PLL_SYS_FBDIV_INT_FBDIV_INT_Pos,
PLL_SYS_FBDIV_INT_FBDIV_INT_Msk);
/* turn on the main power */
io_reg_atomic_clear(&pll->PWR.reg, (1U << PLL_SYS_PWR_VCOPD_Pos)
io_reg_atomic_clear(&pll->PWR, (1U << PLL_SYS_PWR_VCOPD_Pos)
| (1U << PLL_SYS_PWR_DSMPD_Pos)
| (1U << PLL_SYS_PWR_PD_Pos));
/* wait for VCO to lock (i.e. keep its output stable) */
while (!pll->CS.bit.LOCK) { }
while (!(pll->CS & PLL_SYS_CS_LOCK_Msk)) { }
/* set up post divisors and turn them on */
pll->PRIM.reg = (post_div_1 << PLL_SYS_PRIM_POSTDIV1_Pos)
pll->PRIM = (post_div_1 << PLL_SYS_PRIM_POSTDIV1_Pos)
| (post_div_2 << PLL_SYS_PRIM_POSTDIV2_Pos);
io_reg_atomic_clear(&pll->PWR.reg, 1U << PLL_SYS_PWR_POSTDIVPD_Pos);
io_reg_atomic_clear(&pll->PWR, 1U << PLL_SYS_PWR_POSTDIVPD_Pos);
}
/**
@ -72,7 +72,7 @@ static void _pll_stop(PLL_SYS_Type *pll)
| (1U << PLL_SYS_PWR_POSTDIVPD_Pos)
| (1U << PLL_SYS_PWR_DSMPD_Pos)
| (1U << PLL_SYS_PWR_PD_Pos);
io_reg_atomic_set(&pll->PWR.reg, reg);
io_reg_atomic_set(&pll->PWR, reg);
}
void pll_start_sys(uint8_t ref_div,

View File

@ -31,19 +31,19 @@
void rosc_start(void)
{
/* set drive strengths to default 0 */
io_reg_atomic_clear(&ROSC->FREQA.reg, ROSC_FREQA_PASSWD_Msk);
io_reg_atomic_clear(&ROSC->FREQB.reg, ROSC_FREQB_PASSWD_Msk);
io_reg_atomic_clear(&ROSC->FREQA, ROSC_FREQA_PASSWD_Msk);
io_reg_atomic_clear(&ROSC->FREQB, ROSC_FREQB_PASSWD_Msk);
/* apply settings with magic value 0x9696 */
const uint32_t magic = 0x9696U;
io_reg_write_dont_corrupt(&ROSC->FREQA.reg, magic << ROSC_FREQA_PASSWD_Pos,
io_reg_write_dont_corrupt(&ROSC->FREQA, magic << ROSC_FREQA_PASSWD_Pos,
ROSC_FREQA_PASSWD_Msk);
io_reg_write_dont_corrupt(&ROSC->FREQB.reg, magic << ROSC_FREQB_PASSWD_Pos,
io_reg_write_dont_corrupt(&ROSC->FREQB, magic << ROSC_FREQB_PASSWD_Pos,
ROSC_FREQB_PASSWD_Msk);
/* default divider is 16 */
io_reg_write_dont_corrupt(&ROSC->DIV.reg, 16 << ROSC_DIV_DIV_Pos, ROSC_DIV_DIV_Msk);
io_reg_atomic_set(&ROSC->CTRL.reg, ROSC_CTRL_ENABLE_ENABLE << ROSC_CTRL_ENABLE_Pos);
while (!ROSC->STATUS.bit.STABLE) { }
io_reg_write_dont_corrupt(&ROSC->DIV, 16 << ROSC_DIV_DIV_Pos, ROSC_DIV_DIV_Msk);
io_reg_atomic_set(&ROSC->CTRL, ROSC_CTRL_ENABLE_ENABLE << ROSC_CTRL_ENABLE_Pos);
while (!(ROSC->STATUS & ROSC_STATUS_STABLE_Msk)) { }
}
/**
@ -53,5 +53,5 @@ void rosc_start(void)
*/
void rosc_stop(void)
{
io_reg_atomic_set(&ROSC->CTRL.reg, ROSC_CTRL_ENABLE_DISABLE << ROSC_CTRL_ENABLE_Pos);
io_reg_atomic_set(&ROSC->CTRL, ROSC_CTRL_ENABLE_DISABLE << ROSC_CTRL_ENABLE_Pos);
}

View File

@ -34,15 +34,15 @@ void xosc_start(uint32_t f_ref)
{
assert(f_ref == MHZ(12));
uint32_t delay = _xosc_conf_sartup_delay(f_ref, 1);
io_reg_write_dont_corrupt(&XOSC->STARTUP.reg, delay << XOSC_STARTUP_DELAY_Pos,
io_reg_write_dont_corrupt(&XOSC->STARTUP, delay << XOSC_STARTUP_DELAY_Pos,
XOSC_STARTUP_DELAY_Msk);
io_reg_write_dont_corrupt(&XOSC->CTRL.reg, XOSC_CTRL_ENABLE_ENABLE << XOSC_CTRL_ENABLE_Pos,
io_reg_write_dont_corrupt(&XOSC->CTRL, XOSC_CTRL_ENABLE_ENABLE << XOSC_CTRL_ENABLE_Pos,
XOSC_CTRL_ENABLE_Msk);
while (!XOSC->STATUS.bit.STABLE) { }
while (!(XOSC->STATUS & XOSC_STATUS_STABLE_Msk)) { }
}
void xosc_stop(void)
{
io_reg_write_dont_corrupt(&XOSC->CTRL.reg, XOSC_CTRL_ENABLE_DISABLE << XOSC_CTRL_ENABLE_Pos,
io_reg_write_dont_corrupt(&XOSC->CTRL, XOSC_CTRL_ENABLE_DISABLE << XOSC_CTRL_ENABLE_Pos,
XOSC_CTRL_ENABLE_Msk);
}

View File

@ -131,33 +131,40 @@ typedef struct {
* @brief Number of endpoints available with the OTG FS peripheral
* including the control endpoint
*/
#ifdef STM32_USB_OTG_CID_1x
#define STM32_USB_OTG_FS_NUM_EP (4) /**< OTG FS with 4 endpoints */
#if defined(USB_OTG_FS_MAX_IN_ENDPOINTS)
#define STM32_USB_OTG_FS_NUM_EP (USB_OTG_FS_MAX_IN_ENDPOINTS)
#elif defined(STM32_USB_OTG_CID_1x)
#define STM32_USB_OTG_FS_NUM_EP (4) /**< OTG FS with 4 endpoints */
#elif defined(STM32_USB_OTG_CID_2x)
#define STM32_USB_OTG_FS_NUM_EP (6) /**< OTG FS with 6 endpoints */
#define STM32_USB_OTG_FS_NUM_EP (6) /**< OTG FS with 6 endpoints */
#endif
/**
* @brief Number of endpoints available with the OTG HS peripheral
* including the control endpoint
*/
#ifdef STM32_USB_OTG_CID_1x
#define STM32_USB_OTG_HS_NUM_EP (6) /**< OTG HS with 6 endpoints */
#if defined(USB_OTG_HS_MAX_IN_ENDPOINTS)
#define STM32_USB_OTG_HS_NUM_EP (USB_OTG_HS_MAX_IN_ENDPOINTS)
#elif defined(STM32_USB_OTG_CID_1x)
#define STM32_USB_OTG_HS_NUM_EP (6) /**< OTG HS with 6 endpoints */
#elif defined(STM32_USB_OTG_CID_2x)
#define STM32_USB_OTG_HS_NUM_EP (9) /**< OTG HS with 9 endpoints */
#define STM32_USB_OTG_HS_NUM_EP (9) /**< OTG HS with 9 endpoints */
#endif
/**
* @brief Number of IN/OUT endpoints including EP0 as used by USBUS
*
* @note Since only a single number of EPs can be defined for USBUS that is
* valid for all devices, the smallest number of EPs must be used for
* multiple USB devices.
* @note USBUS allows only one definition of the number of available EPs, which
* is then used for all devices. To be able to use all EPs for devices
* with more EPs, the largest possible number of available EPs for
* several USB devices is defined here. The driver has to ensure that the
* number of allocated EPs does not exceed the number of available EPs if
* a device has less EPs.
*/
#if defined(STM32_USB_OTG_FS_NUM_EP)
#define USBDEV_NUM_ENDPOINTS STM32_USB_OTG_FS_NUM_EP
#elif defined(STM32_USB_OTG_HS_NUM_EP)
#if defined(MODULE_PERIPH_USBDEV_HS) && defined(STM32_USB_OTG_HS_NUM_EP)
#define USBDEV_NUM_ENDPOINTS STM32_USB_OTG_HS_NUM_EP
#elif defined(STM32_USB_OTG_FS_NUM_EP)
#define USBDEV_NUM_ENDPOINTS STM32_USB_OTG_FS_NUM_EP
#else
#define USBDEV_NUM_ENDPOINTS 8
#endif

View File

@ -111,19 +111,6 @@ extern "C" {
*/
#define DWC2_USB_OTG_HS_TOTAL_FIFO_SIZE USB_OTG_HS_TOTAL_FIFO_SIZE
/**
* @brief Use the built-in DMA controller of the HS peripheral when possible
*/
#ifndef STM32_USB_OTG_HS_USE_DMA
#ifdef STM32_USB_OTG_CID_1x
/* FIXME: It should be possible to use DMA with the 1.x version of the *
* peripheral, but somehow it doesn't work. */
#define STM32_USB_OTG_HS_USE_DMA (0)
#else
#define STM32_USB_OTG_HS_USE_DMA (1)
#endif
#endif
/* periph/usbdev.h is included after the definitions above by intention */
#include "periph/usbdev.h"

View File

@ -22,6 +22,16 @@ config MODULE_PERIPH_INIT_USBDEV
bool "Auto initialize USBDEV peripheral"
default y if MODULE_PERIPH_INIT
config MODULE_PERIPH_USBDEV_HS
bool "Use USB HS peripheral"
depends on HAS_PERIPH_USBDEV_HS
default y if MODULE_PERIPH_INIT_USBDEV_HS_ULPI || MODULE_PERIPH_USBDEV_HS_UTMI
config MODULE_PERIPH_INIT_USBDEV_HS
bool
depends on MODULE_PERIPH_USBDEV_HS
default y if MODULE_PERIPH_INIT
config MODULE_PERIPH_USBDEV_HS_ULPI
bool "Use USB HS peripheral with ULPI HS PHY"
depends on HAS_PERIPH_USBDEV_HS_ULPI

View File

@ -130,6 +130,9 @@ typedef struct {
usbdev_ep_t *in; /**< In endpoints */
dwc2_usb_otg_fshs_out_ep_t *out; /**< Out endpoints */
bool suspend; /**< Suspend status */
#ifdef DWC2_USB_OTG_HS_ENABLED
uint8_t *ep0_out_buf; /**< Points to the buffer of EP0 OUT handler */
#endif
} dwc2_usb_otg_fshs_t;
/* List of instantiated USB peripherals */
@ -219,7 +222,7 @@ static bool _uses_dma(const dwc2_usb_otg_fshs_config_t *config)
* request. In this case the enumeration of further interfaces, for example
* CDC ECM is stopped.
* - The Enumeration fails for CDC ECM interface which uses URB support. */
#if 0 /* defined(DWC2_USB_OTG_HS_ENABLED) && STM32_USB_OTG_HS_USE_DMA */
#ifdef DWC2_USB_OTG_HS_ENABLED
return config->type == DWC2_USB_OTG_HS;
#else
(void)config;
@ -982,7 +985,7 @@ static void _usbdev_init(usbdev_t *dev)
/* Unmask the transfer complete interrupts
* Only needed when using DMA, otherwise the RX FIFO not empty
* interrupt is used */
_device_regs(conf)->DOEPMSK |= USB_OTG_DOEPMSK_XFRCM;
_device_regs(conf)->DOEPMSK |= USB_OTG_DOEPMSK_XFRCM | USB_OTG_DOEPMSK_STUPM;
_device_regs(conf)->DIEPMSK |= USB_OTG_DIEPMSK_XFRCM;
}
@ -1172,6 +1175,22 @@ static void _usbdev_ep0_stall(usbdev_t *usbdev)
/* Stall both directions, cleared automatically on SETUP received */
_in_regs(conf, 0)->DIEPCTL |= USB_OTG_DIEPCTL_STALL;
_out_regs(conf, 0)->DOEPCTL |= USB_OTG_DOEPCTL_STALL;
#ifdef DWC2_USB_OTG_HS_ENABLED
if (_uses_dma(conf) && st_usbdev->ep0_out_buf) {
/* The STALL condition is automatically cleared by the hardware as
* specified in the API documentation. However, in DMA mode the
* reception of the next SETUP must be prepared by setting the SETUP
* packet counter (STUPCNT) and enabling the OUT endpoint. Otherwise
* the USB OTG HS core will not generate an interrupt and the USB stack
* cannot respond correctly to the next SETUP received. In addition,
* the DMA address must be reset to the buffer address of the EP0
* OUT handler. */
_out_regs(conf, 0)->DOEPDMA = (uint32_t)(intptr_t)(st_usbdev->ep0_out_buf);
_out_regs(conf, 0)->DOEPTSIZ |= 1 << USB_OTG_DOEPTSIZ_STUPCNT_Pos;
_out_regs(conf, 0)->DOEPCTL |= USB_OTG_DOEPCTL_EPENA;
}
#endif
}
static void _ep_set_stall(usbdev_ep_t *ep, bool enable)
@ -1313,6 +1332,13 @@ static int _usbdev_ep_xmit(usbdev_ep_t *ep, uint8_t *buf, size_t len)
if (_uses_dma(conf)) {
_out_regs(conf, ep->num)->DOEPDMA = (uint32_t)(intptr_t)buf;
/* store the buffer address of the EP0 OUT handler to use it in
* _usbdev_ep0_stall */
#ifdef DWC2_USB_OTG_HS_ENABLED
if (ep->num == 0) {
usbdev->ep0_out_buf = buf;
}
#endif
}
else {
container_of(ep, dwc2_usb_otg_fshs_out_ep_t, ep)->out_buf = buf;
@ -1361,11 +1387,6 @@ static void _read_packet(dwc2_usb_otg_fshs_out_ep_t *st_ep)
* complete status */
if (pkt_status == DWC2_PKTSTS_DATA_UPDT ||
pkt_status == DWC2_PKTSTS_SETUP_UPDT) {
#if defined(MCU_EFM32)
/* TODO For some reason a short delay is required here on EFM32. It has
* to be investigated further. A delay of 1 msec is inserted for now. */
ztimer_sleep(ZTIMER_MSEC, 1);
#endif
_copy_rxfifo(usbdev, st_ep->out_buf, len);
#if !defined(STM32_USB_OTG_CID_1x)
/* CID 2x doesn't signal SETUP_COMP on non-zero length packets, signal
@ -1416,6 +1437,15 @@ static void _usbdev_ep_esr(usbdev_ep_t *ep)
!_uses_dma(conf)) {
_read_packet(container_of(ep, dwc2_usb_otg_fshs_out_ep_t, ep));
}
#ifdef DWC2_USB_OTG_HS_ENABLED
else if (_out_regs(conf, ep->num)->DOEPINT & USB_OTG_DOEPINT_STUP) {
_out_regs(conf, ep->num)->DOEPINT = USB_OTG_DOEPINT_STUP;
_out_regs(conf, ep->num)->DOEPINT = USB_OTG_DOEPINT_XFRC;
if (_uses_dma(conf)) {
usbdev->usbdev.epcb(ep, USBDEV_EVENT_TR_COMPLETE);
}
}
#endif
/* Transfer complete seems only reliable when used with DMA */
else if (_out_regs(conf, ep->num)->DOEPINT & USB_OTG_DOEPINT_XFRC) {
_out_regs(conf, ep->num)->DOEPINT = USB_OTG_DOEPINT_XFRC;

View File

@ -12,7 +12,6 @@ USEMODULE += ps
# Boards that don't have enough endpoints to use CDC ACM together with CDC ECM
ifeq (,$(filter stdio_%,$(filter-out stdio_cdc_acm,$(USEMODULE))))
BOARD_BLACKLIST += \
stm32f429i-disco \
stm32f4discovery \
weact-f401cc \
weact-f401ce \