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:
commit
50cd32fbbf
@ -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)"
|
||||
/** @} */
|
||||
|
||||
|
@ -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- | | | |
|
||||
|
@ -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
|
||||
* @{
|
||||
|
@ -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,
|
||||
|
@ -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"
|
||||
|
@ -1,3 +1,7 @@
|
||||
ifneq (,$(filter periph_usbdev,$(USEMODULE)))
|
||||
USEMODULE += periph_usbdev_hs
|
||||
endif
|
||||
|
||||
ifneq (,$(filter saul_default,$(USEMODULE)))
|
||||
USEMODULE += saul_gpio
|
||||
USEMODULE += l3gxxxx
|
||||
|
@ -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
|
||||
|
@ -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));
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
*/
|
||||
|
@ -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) { }
|
||||
}
|
||||
|
||||
/**
|
||||
|
16466
cpu/rpx0xx/include/vendor/RP2040.h
vendored
16466
cpu/rpx0xx/include/vendor/RP2040.h
vendored
File diff suppressed because it is too large
Load Diff
@ -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
|
||||
|
@ -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 */
|
||||
|
@ -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");
|
||||
}
|
||||
|
@ -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,
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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"
|
||||
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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 \
|
||||
|
Loading…
Reference in New Issue
Block a user