From 74b860fee65ca8feb2a796144976ff6c44e64bcc Mon Sep 17 00:00:00 2001 From: gdisirio Date: Mon, 2 Sep 2013 09:48:38 +0000 Subject: git-svn-id: svn://svn.code.sf.net/p/chibios/svn/branches/kernel_3_dev@6242 35acf78f-673a-0410-8e92-d51de3d6d3f4 --- os/hal/platforms/STM32/GPIOv1/pal_lld.c | 184 ---- os/hal/platforms/STM32/GPIOv1/pal_lld.h | 334 ------- os/hal/platforms/STM32/GPIOv2/pal_lld.c | 237 ----- os/hal/platforms/STM32/GPIOv2/pal_lld.h | 469 ---------- os/hal/platforms/STM32/I2Cv1/i2c_lld.c | 849 ----------------- os/hal/platforms/STM32/I2Cv1/i2c_lld.h | 466 ---------- os/hal/platforms/STM32/I2Cv2/i2c_lld.c | 720 --------------- os/hal/platforms/STM32/I2Cv2/i2c_lld.h | 365 -------- os/hal/platforms/STM32/OTGv1/stm32_otg.h | 916 ------------------- os/hal/platforms/STM32/OTGv1/usb_lld.c | 1300 --------------------------- os/hal/platforms/STM32/OTGv1/usb_lld.h | 534 ----------- os/hal/platforms/STM32/RTCv1/rtc_lld.c | 329 ------- os/hal/platforms/STM32/RTCv1/rtc_lld.h | 187 ---- os/hal/platforms/STM32/RTCv2/rtc_lld.c | 322 ------- os/hal/platforms/STM32/RTCv2/rtc_lld.h | 206 ----- os/hal/platforms/STM32/SPIv1/spi_lld.c | 483 ---------- os/hal/platforms/STM32/SPIv1/spi_lld.h | 407 --------- os/hal/platforms/STM32/SPIv2/spi_lld.c | 501 ----------- os/hal/platforms/STM32/SPIv2/spi_lld.h | 380 -------- os/hal/platforms/STM32/TIMv1/gpt_lld.c | 754 ---------------- os/hal/platforms/STM32/TIMv1/gpt_lld.h | 512 ----------- os/hal/platforms/STM32/TIMv1/icu_lld.c | 634 ------------- os/hal/platforms/STM32/TIMv1/icu_lld.h | 412 --------- os/hal/platforms/STM32/TIMv1/pwm_lld.c | 695 -------------- os/hal/platforms/STM32/TIMv1/pwm_lld.h | 480 ---------- os/hal/platforms/STM32/TIMv1/st_lld.c | 161 ---- os/hal/platforms/STM32/TIMv1/st_lld.h | 147 --- os/hal/platforms/STM32/TIMv1/stm32_tim.h | 448 --------- os/hal/platforms/STM32/USARTv1/serial_lld.c | 524 ----------- os/hal/platforms/STM32/USARTv1/serial_lld.h | 303 ------- os/hal/platforms/STM32/USARTv1/uart_lld.c | 794 ---------------- os/hal/platforms/STM32/USARTv1/uart_lld.h | 680 -------------- os/hal/platforms/STM32/USARTv2/serial_lld.c | 522 ----------- os/hal/platforms/STM32/USARTv2/serial_lld.h | 305 ------- os/hal/platforms/STM32/USARTv2/uart_lld.c | 590 ------------ os/hal/platforms/STM32/USARTv2/uart_lld.h | 417 --------- os/hal/platforms/STM32/USBv1/stm32_usb.h | 243 ----- os/hal/platforms/STM32/USBv1/usb_lld.c | 824 ----------------- os/hal/platforms/STM32/USBv1/usb_lld.h | 437 --------- os/hal/platforms/STM32/can_lld.c | 702 --------------- os/hal/platforms/STM32/can_lld.h | 366 -------- os/hal/platforms/STM32/ext_lld.c | 220 ----- os/hal/platforms/STM32/ext_lld.h | 153 ---- os/hal/platforms/STM32/i2s_lld.c | 161 ---- os/hal/platforms/STM32/i2s_lld.h | 317 ------- os/hal/platforms/STM32/mac_lld.c | 740 --------------- os/hal/platforms/STM32/mac_lld.h | 362 -------- os/hal/platforms/STM32/sdc_lld.c | 788 ---------------- os/hal/platforms/STM32/sdc_lld.h | 310 ------- os/hal/platforms/STM32/stm32.h | 120 --- os/hal/platforms/STM32F0xx/adc_lld.c | 296 ------ os/hal/platforms/STM32F0xx/adc_lld.h | 329 ------- os/hal/platforms/STM32F0xx/ext_lld_isr.c | 197 ---- os/hal/platforms/STM32F0xx/ext_lld_isr.h | 107 --- os/hal/platforms/STM32F0xx/hal_lld.c | 199 ---- os/hal/platforms/STM32F0xx/hal_lld.h | 781 ---------------- os/hal/platforms/STM32F0xx/platform.mk | 28 - os/hal/platforms/STM32F0xx/stm32_dma.c | 291 ------ os/hal/platforms/STM32F0xx/stm32_dma.h | 394 -------- os/hal/platforms/STM32F0xx/stm32_isr.h | 91 -- os/hal/platforms/STM32F0xx/stm32_rcc.h | 596 ------------ os/hal/platforms/STM32F0xx/stm32_registry.h | 168 ---- os/hal/platforms/STM32F30x/adc_lld.c | 548 ----------- os/hal/platforms/STM32F30x/adc_lld.h | 608 ------------- os/hal/platforms/STM32F30x/ext_lld_isr.c | 402 --------- os/hal/platforms/STM32F30x/ext_lld_isr.h | 177 ---- os/hal/platforms/STM32F30x/hal_lld.c | 197 ---- os/hal/platforms/STM32F30x/hal_lld.h | 1105 ----------------------- os/hal/platforms/STM32F30x/platform.mk | 31 - os/hal/platforms/STM32F30x/stm32_dma.c | 449 --------- os/hal/platforms/STM32F30x/stm32_dma.h | 406 --------- os/hal/platforms/STM32F30x/stm32_isr.h | 132 --- os/hal/platforms/STM32F30x/stm32_rcc.h | 835 ----------------- os/hal/platforms/STM32F30x/stm32_registry.h | 194 ---- os/hal/platforms/STM32F4xx/adc_lld.c | 418 --------- os/hal/platforms/STM32F4xx/adc_lld.h | 563 ------------ os/hal/platforms/STM32F4xx/ext_lld_isr.c | 338 ------- os/hal/platforms/STM32F4xx/ext_lld_isr.h | 170 ---- os/hal/platforms/STM32F4xx/hal_lld.c | 225 ----- os/hal/platforms/STM32F4xx/hal_lld.h | 1232 ------------------------- os/hal/platforms/STM32F4xx/platform.mk | 33 - os/hal/platforms/STM32F4xx/stm32_dma.c | 527 ----------- os/hal/platforms/STM32F4xx/stm32_dma.h | 461 ---------- os/hal/platforms/STM32F4xx/stm32_isr.h | 150 ---- os/hal/platforms/STM32F4xx/stm32_rcc.h | 1254 -------------------------- os/hal/platforms/STM32F4xx/stm32_registry.h | 265 ------ os/hal/platforms/common/ARMCMx/nvic.c | 89 -- os/hal/platforms/common/ARMCMx/nvic.h | 69 -- os/hal/ports/STM32/GPIOv1/pal_lld.c | 184 ++++ os/hal/ports/STM32/GPIOv1/pal_lld.h | 334 +++++++ os/hal/ports/STM32/GPIOv2/pal_lld.c | 237 +++++ os/hal/ports/STM32/GPIOv2/pal_lld.h | 469 ++++++++++ os/hal/ports/STM32/I2Cv1/i2c_lld.c | 849 +++++++++++++++++ os/hal/ports/STM32/I2Cv1/i2c_lld.h | 466 ++++++++++ os/hal/ports/STM32/I2Cv2/i2c_lld.c | 720 +++++++++++++++ os/hal/ports/STM32/I2Cv2/i2c_lld.h | 365 ++++++++ os/hal/ports/STM32/OTGv1/stm32_otg.h | 916 +++++++++++++++++++ os/hal/ports/STM32/OTGv1/usb_lld.c | 1300 +++++++++++++++++++++++++++ os/hal/ports/STM32/OTGv1/usb_lld.h | 534 +++++++++++ os/hal/ports/STM32/RTCv1/rtc_lld.c | 329 +++++++ os/hal/ports/STM32/RTCv1/rtc_lld.h | 187 ++++ os/hal/ports/STM32/RTCv2/rtc_lld.c | 322 +++++++ os/hal/ports/STM32/RTCv2/rtc_lld.h | 206 +++++ os/hal/ports/STM32/SPIv1/spi_lld.c | 483 ++++++++++ os/hal/ports/STM32/SPIv1/spi_lld.h | 407 +++++++++ os/hal/ports/STM32/SPIv2/spi_lld.c | 501 +++++++++++ os/hal/ports/STM32/SPIv2/spi_lld.h | 380 ++++++++ os/hal/ports/STM32/TIMv1/gpt_lld.c | 754 ++++++++++++++++ os/hal/ports/STM32/TIMv1/gpt_lld.h | 512 +++++++++++ os/hal/ports/STM32/TIMv1/icu_lld.c | 634 +++++++++++++ os/hal/ports/STM32/TIMv1/icu_lld.h | 412 +++++++++ os/hal/ports/STM32/TIMv1/pwm_lld.c | 695 ++++++++++++++ os/hal/ports/STM32/TIMv1/pwm_lld.h | 480 ++++++++++ os/hal/ports/STM32/TIMv1/st_lld.c | 161 ++++ os/hal/ports/STM32/TIMv1/st_lld.h | 147 +++ os/hal/ports/STM32/TIMv1/stm32_tim.h | 448 +++++++++ os/hal/ports/STM32/USARTv1/serial_lld.c | 524 +++++++++++ os/hal/ports/STM32/USARTv1/serial_lld.h | 303 +++++++ os/hal/ports/STM32/USARTv1/uart_lld.c | 794 ++++++++++++++++ os/hal/ports/STM32/USARTv1/uart_lld.h | 680 ++++++++++++++ os/hal/ports/STM32/USARTv2/serial_lld.c | 522 +++++++++++ os/hal/ports/STM32/USARTv2/serial_lld.h | 305 +++++++ os/hal/ports/STM32/USARTv2/uart_lld.c | 590 ++++++++++++ os/hal/ports/STM32/USARTv2/uart_lld.h | 417 +++++++++ os/hal/ports/STM32/USBv1/stm32_usb.h | 243 +++++ os/hal/ports/STM32/USBv1/usb_lld.c | 824 +++++++++++++++++ os/hal/ports/STM32/USBv1/usb_lld.h | 437 +++++++++ os/hal/ports/STM32/can_lld.c | 702 +++++++++++++++ os/hal/ports/STM32/can_lld.h | 366 ++++++++ os/hal/ports/STM32/ext_lld.c | 220 +++++ os/hal/ports/STM32/ext_lld.h | 153 ++++ os/hal/ports/STM32/i2s_lld.c | 161 ++++ os/hal/ports/STM32/i2s_lld.h | 317 +++++++ os/hal/ports/STM32/mac_lld.c | 740 +++++++++++++++ os/hal/ports/STM32/mac_lld.h | 362 ++++++++ os/hal/ports/STM32/sdc_lld.c | 788 ++++++++++++++++ os/hal/ports/STM32/sdc_lld.h | 310 +++++++ os/hal/ports/STM32/stm32.h | 120 +++ os/hal/ports/STM32F0xx/adc_lld.c | 296 ++++++ os/hal/ports/STM32F0xx/adc_lld.h | 329 +++++++ os/hal/ports/STM32F0xx/ext_lld_isr.c | 197 ++++ os/hal/ports/STM32F0xx/ext_lld_isr.h | 107 +++ os/hal/ports/STM32F0xx/hal_lld.c | 199 ++++ os/hal/ports/STM32F0xx/hal_lld.h | 781 ++++++++++++++++ os/hal/ports/STM32F0xx/platform.mk | 28 + os/hal/ports/STM32F0xx/stm32_dma.c | 291 ++++++ os/hal/ports/STM32F0xx/stm32_dma.h | 394 ++++++++ os/hal/ports/STM32F0xx/stm32_isr.h | 91 ++ os/hal/ports/STM32F0xx/stm32_rcc.h | 596 ++++++++++++ os/hal/ports/STM32F0xx/stm32_registry.h | 168 ++++ os/hal/ports/STM32F30x/adc_lld.c | 548 +++++++++++ os/hal/ports/STM32F30x/adc_lld.h | 608 +++++++++++++ os/hal/ports/STM32F30x/ext_lld_isr.c | 402 +++++++++ os/hal/ports/STM32F30x/ext_lld_isr.h | 177 ++++ os/hal/ports/STM32F30x/hal_lld.c | 197 ++++ os/hal/ports/STM32F30x/hal_lld.h | 1105 +++++++++++++++++++++++ os/hal/ports/STM32F30x/platform.mk | 31 + os/hal/ports/STM32F30x/stm32_dma.c | 449 +++++++++ os/hal/ports/STM32F30x/stm32_dma.h | 406 +++++++++ os/hal/ports/STM32F30x/stm32_isr.h | 132 +++ os/hal/ports/STM32F30x/stm32_rcc.h | 835 +++++++++++++++++ os/hal/ports/STM32F30x/stm32_registry.h | 194 ++++ os/hal/ports/STM32F4xx/adc_lld.c | 418 +++++++++ os/hal/ports/STM32F4xx/adc_lld.h | 563 ++++++++++++ os/hal/ports/STM32F4xx/ext_lld_isr.c | 338 +++++++ os/hal/ports/STM32F4xx/ext_lld_isr.h | 170 ++++ os/hal/ports/STM32F4xx/hal_lld.c | 225 +++++ os/hal/ports/STM32F4xx/hal_lld.h | 1232 +++++++++++++++++++++++++ os/hal/ports/STM32F4xx/platform.mk | 33 + os/hal/ports/STM32F4xx/stm32_dma.c | 527 +++++++++++ os/hal/ports/STM32F4xx/stm32_dma.h | 461 ++++++++++ os/hal/ports/STM32F4xx/stm32_isr.h | 150 ++++ os/hal/ports/STM32F4xx/stm32_rcc.h | 1254 ++++++++++++++++++++++++++ os/hal/ports/STM32F4xx/stm32_registry.h | 265 ++++++ os/hal/ports/common/ARMCMx/nvic.c | 89 ++ os/hal/ports/common/ARMCMx/nvic.h | 69 ++ 176 files changed, 37665 insertions(+), 37665 deletions(-) delete mode 100644 os/hal/platforms/STM32/GPIOv1/pal_lld.c delete mode 100644 os/hal/platforms/STM32/GPIOv1/pal_lld.h delete mode 100644 os/hal/platforms/STM32/GPIOv2/pal_lld.c delete mode 100644 os/hal/platforms/STM32/GPIOv2/pal_lld.h delete mode 100644 os/hal/platforms/STM32/I2Cv1/i2c_lld.c delete mode 100644 os/hal/platforms/STM32/I2Cv1/i2c_lld.h delete mode 100644 os/hal/platforms/STM32/I2Cv2/i2c_lld.c delete mode 100644 os/hal/platforms/STM32/I2Cv2/i2c_lld.h delete mode 100644 os/hal/platforms/STM32/OTGv1/stm32_otg.h delete mode 100644 os/hal/platforms/STM32/OTGv1/usb_lld.c delete mode 100644 os/hal/platforms/STM32/OTGv1/usb_lld.h delete mode 100644 os/hal/platforms/STM32/RTCv1/rtc_lld.c delete mode 100644 os/hal/platforms/STM32/RTCv1/rtc_lld.h delete mode 100644 os/hal/platforms/STM32/RTCv2/rtc_lld.c delete mode 100644 os/hal/platforms/STM32/RTCv2/rtc_lld.h delete mode 100644 os/hal/platforms/STM32/SPIv1/spi_lld.c delete mode 100644 os/hal/platforms/STM32/SPIv1/spi_lld.h delete mode 100644 os/hal/platforms/STM32/SPIv2/spi_lld.c delete mode 100644 os/hal/platforms/STM32/SPIv2/spi_lld.h delete mode 100644 os/hal/platforms/STM32/TIMv1/gpt_lld.c delete mode 100644 os/hal/platforms/STM32/TIMv1/gpt_lld.h delete mode 100644 os/hal/platforms/STM32/TIMv1/icu_lld.c delete mode 100644 os/hal/platforms/STM32/TIMv1/icu_lld.h delete mode 100644 os/hal/platforms/STM32/TIMv1/pwm_lld.c delete mode 100644 os/hal/platforms/STM32/TIMv1/pwm_lld.h delete mode 100644 os/hal/platforms/STM32/TIMv1/st_lld.c delete mode 100644 os/hal/platforms/STM32/TIMv1/st_lld.h delete mode 100644 os/hal/platforms/STM32/TIMv1/stm32_tim.h delete mode 100644 os/hal/platforms/STM32/USARTv1/serial_lld.c delete mode 100644 os/hal/platforms/STM32/USARTv1/serial_lld.h delete mode 100644 os/hal/platforms/STM32/USARTv1/uart_lld.c delete mode 100644 os/hal/platforms/STM32/USARTv1/uart_lld.h delete mode 100644 os/hal/platforms/STM32/USARTv2/serial_lld.c delete mode 100644 os/hal/platforms/STM32/USARTv2/serial_lld.h delete mode 100644 os/hal/platforms/STM32/USARTv2/uart_lld.c delete mode 100644 os/hal/platforms/STM32/USARTv2/uart_lld.h delete mode 100644 os/hal/platforms/STM32/USBv1/stm32_usb.h delete mode 100644 os/hal/platforms/STM32/USBv1/usb_lld.c delete mode 100644 os/hal/platforms/STM32/USBv1/usb_lld.h delete mode 100644 os/hal/platforms/STM32/can_lld.c delete mode 100644 os/hal/platforms/STM32/can_lld.h delete mode 100644 os/hal/platforms/STM32/ext_lld.c delete mode 100644 os/hal/platforms/STM32/ext_lld.h delete mode 100644 os/hal/platforms/STM32/i2s_lld.c delete mode 100644 os/hal/platforms/STM32/i2s_lld.h delete mode 100644 os/hal/platforms/STM32/mac_lld.c delete mode 100644 os/hal/platforms/STM32/mac_lld.h delete mode 100644 os/hal/platforms/STM32/sdc_lld.c delete mode 100644 os/hal/platforms/STM32/sdc_lld.h delete mode 100644 os/hal/platforms/STM32/stm32.h delete mode 100644 os/hal/platforms/STM32F0xx/adc_lld.c delete mode 100644 os/hal/platforms/STM32F0xx/adc_lld.h delete mode 100644 os/hal/platforms/STM32F0xx/ext_lld_isr.c delete mode 100644 os/hal/platforms/STM32F0xx/ext_lld_isr.h delete mode 100644 os/hal/platforms/STM32F0xx/hal_lld.c delete mode 100644 os/hal/platforms/STM32F0xx/hal_lld.h delete mode 100644 os/hal/platforms/STM32F0xx/platform.mk delete mode 100644 os/hal/platforms/STM32F0xx/stm32_dma.c delete mode 100644 os/hal/platforms/STM32F0xx/stm32_dma.h delete mode 100644 os/hal/platforms/STM32F0xx/stm32_isr.h delete mode 100644 os/hal/platforms/STM32F0xx/stm32_rcc.h delete mode 100644 os/hal/platforms/STM32F0xx/stm32_registry.h delete mode 100644 os/hal/platforms/STM32F30x/adc_lld.c delete mode 100644 os/hal/platforms/STM32F30x/adc_lld.h delete mode 100644 os/hal/platforms/STM32F30x/ext_lld_isr.c delete mode 100644 os/hal/platforms/STM32F30x/ext_lld_isr.h delete mode 100644 os/hal/platforms/STM32F30x/hal_lld.c delete mode 100644 os/hal/platforms/STM32F30x/hal_lld.h delete mode 100644 os/hal/platforms/STM32F30x/platform.mk delete mode 100644 os/hal/platforms/STM32F30x/stm32_dma.c delete mode 100644 os/hal/platforms/STM32F30x/stm32_dma.h delete mode 100644 os/hal/platforms/STM32F30x/stm32_isr.h delete mode 100644 os/hal/platforms/STM32F30x/stm32_rcc.h delete mode 100644 os/hal/platforms/STM32F30x/stm32_registry.h delete mode 100644 os/hal/platforms/STM32F4xx/adc_lld.c delete mode 100644 os/hal/platforms/STM32F4xx/adc_lld.h delete mode 100644 os/hal/platforms/STM32F4xx/ext_lld_isr.c delete mode 100644 os/hal/platforms/STM32F4xx/ext_lld_isr.h delete mode 100644 os/hal/platforms/STM32F4xx/hal_lld.c delete mode 100644 os/hal/platforms/STM32F4xx/hal_lld.h delete mode 100644 os/hal/platforms/STM32F4xx/platform.mk delete mode 100644 os/hal/platforms/STM32F4xx/stm32_dma.c delete mode 100644 os/hal/platforms/STM32F4xx/stm32_dma.h delete mode 100644 os/hal/platforms/STM32F4xx/stm32_isr.h delete mode 100644 os/hal/platforms/STM32F4xx/stm32_rcc.h delete mode 100644 os/hal/platforms/STM32F4xx/stm32_registry.h delete mode 100644 os/hal/platforms/common/ARMCMx/nvic.c delete mode 100644 os/hal/platforms/common/ARMCMx/nvic.h create mode 100644 os/hal/ports/STM32/GPIOv1/pal_lld.c create mode 100644 os/hal/ports/STM32/GPIOv1/pal_lld.h create mode 100644 os/hal/ports/STM32/GPIOv2/pal_lld.c create mode 100644 os/hal/ports/STM32/GPIOv2/pal_lld.h create mode 100644 os/hal/ports/STM32/I2Cv1/i2c_lld.c create mode 100644 os/hal/ports/STM32/I2Cv1/i2c_lld.h create mode 100644 os/hal/ports/STM32/I2Cv2/i2c_lld.c create mode 100644 os/hal/ports/STM32/I2Cv2/i2c_lld.h create mode 100644 os/hal/ports/STM32/OTGv1/stm32_otg.h create mode 100644 os/hal/ports/STM32/OTGv1/usb_lld.c create mode 100644 os/hal/ports/STM32/OTGv1/usb_lld.h create mode 100644 os/hal/ports/STM32/RTCv1/rtc_lld.c create mode 100644 os/hal/ports/STM32/RTCv1/rtc_lld.h create mode 100644 os/hal/ports/STM32/RTCv2/rtc_lld.c create mode 100644 os/hal/ports/STM32/RTCv2/rtc_lld.h create mode 100644 os/hal/ports/STM32/SPIv1/spi_lld.c create mode 100644 os/hal/ports/STM32/SPIv1/spi_lld.h create mode 100644 os/hal/ports/STM32/SPIv2/spi_lld.c create mode 100644 os/hal/ports/STM32/SPIv2/spi_lld.h create mode 100644 os/hal/ports/STM32/TIMv1/gpt_lld.c create mode 100644 os/hal/ports/STM32/TIMv1/gpt_lld.h create mode 100644 os/hal/ports/STM32/TIMv1/icu_lld.c create mode 100644 os/hal/ports/STM32/TIMv1/icu_lld.h create mode 100644 os/hal/ports/STM32/TIMv1/pwm_lld.c create mode 100644 os/hal/ports/STM32/TIMv1/pwm_lld.h create mode 100644 os/hal/ports/STM32/TIMv1/st_lld.c create mode 100644 os/hal/ports/STM32/TIMv1/st_lld.h create mode 100644 os/hal/ports/STM32/TIMv1/stm32_tim.h create mode 100644 os/hal/ports/STM32/USARTv1/serial_lld.c create mode 100644 os/hal/ports/STM32/USARTv1/serial_lld.h create mode 100644 os/hal/ports/STM32/USARTv1/uart_lld.c create mode 100644 os/hal/ports/STM32/USARTv1/uart_lld.h create mode 100644 os/hal/ports/STM32/USARTv2/serial_lld.c create mode 100644 os/hal/ports/STM32/USARTv2/serial_lld.h create mode 100644 os/hal/ports/STM32/USARTv2/uart_lld.c create mode 100644 os/hal/ports/STM32/USARTv2/uart_lld.h create mode 100644 os/hal/ports/STM32/USBv1/stm32_usb.h create mode 100644 os/hal/ports/STM32/USBv1/usb_lld.c create mode 100644 os/hal/ports/STM32/USBv1/usb_lld.h create mode 100644 os/hal/ports/STM32/can_lld.c create mode 100644 os/hal/ports/STM32/can_lld.h create mode 100644 os/hal/ports/STM32/ext_lld.c create mode 100644 os/hal/ports/STM32/ext_lld.h create mode 100644 os/hal/ports/STM32/i2s_lld.c create mode 100644 os/hal/ports/STM32/i2s_lld.h create mode 100644 os/hal/ports/STM32/mac_lld.c create mode 100644 os/hal/ports/STM32/mac_lld.h create mode 100644 os/hal/ports/STM32/sdc_lld.c create mode 100644 os/hal/ports/STM32/sdc_lld.h create mode 100644 os/hal/ports/STM32/stm32.h create mode 100644 os/hal/ports/STM32F0xx/adc_lld.c create mode 100644 os/hal/ports/STM32F0xx/adc_lld.h create mode 100644 os/hal/ports/STM32F0xx/ext_lld_isr.c create mode 100644 os/hal/ports/STM32F0xx/ext_lld_isr.h create mode 100644 os/hal/ports/STM32F0xx/hal_lld.c create mode 100644 os/hal/ports/STM32F0xx/hal_lld.h create mode 100644 os/hal/ports/STM32F0xx/platform.mk create mode 100644 os/hal/ports/STM32F0xx/stm32_dma.c create mode 100644 os/hal/ports/STM32F0xx/stm32_dma.h create mode 100644 os/hal/ports/STM32F0xx/stm32_isr.h create mode 100644 os/hal/ports/STM32F0xx/stm32_rcc.h create mode 100644 os/hal/ports/STM32F0xx/stm32_registry.h create mode 100644 os/hal/ports/STM32F30x/adc_lld.c create mode 100644 os/hal/ports/STM32F30x/adc_lld.h create mode 100644 os/hal/ports/STM32F30x/ext_lld_isr.c create mode 100644 os/hal/ports/STM32F30x/ext_lld_isr.h create mode 100644 os/hal/ports/STM32F30x/hal_lld.c create mode 100644 os/hal/ports/STM32F30x/hal_lld.h create mode 100644 os/hal/ports/STM32F30x/platform.mk create mode 100644 os/hal/ports/STM32F30x/stm32_dma.c create mode 100644 os/hal/ports/STM32F30x/stm32_dma.h create mode 100644 os/hal/ports/STM32F30x/stm32_isr.h create mode 100644 os/hal/ports/STM32F30x/stm32_rcc.h create mode 100644 os/hal/ports/STM32F30x/stm32_registry.h create mode 100644 os/hal/ports/STM32F4xx/adc_lld.c create mode 100644 os/hal/ports/STM32F4xx/adc_lld.h create mode 100644 os/hal/ports/STM32F4xx/ext_lld_isr.c create mode 100644 os/hal/ports/STM32F4xx/ext_lld_isr.h create mode 100644 os/hal/ports/STM32F4xx/hal_lld.c create mode 100644 os/hal/ports/STM32F4xx/hal_lld.h create mode 100644 os/hal/ports/STM32F4xx/platform.mk create mode 100644 os/hal/ports/STM32F4xx/stm32_dma.c create mode 100644 os/hal/ports/STM32F4xx/stm32_dma.h create mode 100644 os/hal/ports/STM32F4xx/stm32_isr.h create mode 100644 os/hal/ports/STM32F4xx/stm32_rcc.h create mode 100644 os/hal/ports/STM32F4xx/stm32_registry.h create mode 100644 os/hal/ports/common/ARMCMx/nvic.c create mode 100644 os/hal/ports/common/ARMCMx/nvic.h diff --git a/os/hal/platforms/STM32/GPIOv1/pal_lld.c b/os/hal/platforms/STM32/GPIOv1/pal_lld.c deleted file mode 100644 index 31eec7883..000000000 --- a/os/hal/platforms/STM32/GPIOv1/pal_lld.c +++ /dev/null @@ -1,184 +0,0 @@ -/* - ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file STM32/GPIOv1/pal_lld.c - * @brief STM32F1xx GPIO low level driver code. - * - * @addtogroup PAL - * @{ - */ - -#include "ch.h" -#include "hal.h" - -#if HAL_USE_PAL || defined(__DOXYGEN__) - -/*===========================================================================*/ -/* Driver local definitions. */ -/*===========================================================================*/ - -#if STM32_HAS_GPIOG -#define APB2_EN_MASK (RCC_APB2ENR_IOPAEN | RCC_APB2ENR_IOPBEN | \ - RCC_APB2ENR_IOPCEN | RCC_APB2ENR_IOPDEN | \ - RCC_APB2ENR_IOPEEN | RCC_APB2ENR_IOPFEN | \ - RCC_APB2ENR_IOPGEN | RCC_APB2ENR_AFIOEN) -#elif STM32_HAS_GPIOE -#define APB2_EN_MASK (RCC_APB2ENR_IOPAEN | RCC_APB2ENR_IOPBEN | \ - RCC_APB2ENR_IOPCEN | RCC_APB2ENR_IOPDEN | \ - RCC_APB2ENR_IOPEEN | RCC_APB2ENR_AFIOEN) -#else -#define APB2_EN_MASK (RCC_APB2ENR_IOPAEN | RCC_APB2ENR_IOPBEN | \ - RCC_APB2ENR_IOPCEN | RCC_APB2ENR_IOPDEN | \ - RCC_APB2ENR_AFIOEN) -#endif - -/*===========================================================================*/ -/* Driver exported variables. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver local variables and types. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver local functions. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver interrupt handlers. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver exported functions. */ -/*===========================================================================*/ - -/** - * @brief STM32 I/O ports configuration. - * @details Ports A-D(E, F, G) clocks enabled, AFIO clock enabled. - * - * @param[in] config the STM32 ports configuration - * - * @notapi - */ -void _pal_lld_init(const PALConfig *config) { - - /* - * Enables the GPIO related clocks. - */ - rccEnableAPB2(APB2_EN_MASK, FALSE); - - /* - * Initial GPIO setup. - */ - GPIOA->ODR = config->PAData.odr; - GPIOA->CRH = config->PAData.crh; - GPIOA->CRL = config->PAData.crl; - GPIOB->ODR = config->PBData.odr; - GPIOB->CRH = config->PBData.crh; - GPIOB->CRL = config->PBData.crl; - GPIOC->ODR = config->PCData.odr; - GPIOC->CRH = config->PCData.crh; - GPIOC->CRL = config->PCData.crl; - GPIOD->ODR = config->PDData.odr; - GPIOD->CRH = config->PDData.crh; - GPIOD->CRL = config->PDData.crl; -#if STM32_HAS_GPIOE || defined(__DOXYGEN__) - GPIOE->ODR = config->PEData.odr; - GPIOE->CRH = config->PEData.crh; - GPIOE->CRL = config->PEData.crl; -#if STM32_HAS_GPIOF || defined(__DOXYGEN__) - GPIOF->ODR = config->PFData.odr; - GPIOF->CRH = config->PFData.crh; - GPIOF->CRL = config->PFData.crl; -#if STM32_HAS_GPIOG || defined(__DOXYGEN__) - GPIOG->ODR = config->PGData.odr; - GPIOG->CRH = config->PGData.crh; - GPIOG->CRL = config->PGData.crl; -#endif -#endif -#endif -} - -/** - * @brief Pads mode setup. - * @details This function programs a pads group belonging to the same port - * with the specified mode. - * @note @p PAL_MODE_UNCONNECTED is implemented as push pull output at 2MHz. - * @note Writing on pads programmed as pull-up or pull-down has the side - * effect to modify the resistor setting because the output latched - * data is used for the resistor selection. - * - * @param[in] port the port identifier - * @param[in] mask the group mask - * @param[in] mode the mode - * - * @notapi - */ -void _pal_lld_setgroupmode(ioportid_t port, - ioportmask_t mask, - iomode_t mode) { - static const uint8_t cfgtab[] = { - 4, /* PAL_MODE_RESET, implemented as input.*/ - 2, /* PAL_MODE_UNCONNECTED, implemented as push pull output 2MHz.*/ - 4, /* PAL_MODE_INPUT */ - 8, /* PAL_MODE_INPUT_PULLUP */ - 8, /* PAL_MODE_INPUT_PULLDOWN */ - 0, /* PAL_MODE_INPUT_ANALOG */ - 3, /* PAL_MODE_OUTPUT_PUSHPULL, 50MHz.*/ - 7, /* PAL_MODE_OUTPUT_OPENDRAIN, 50MHz.*/ - 8, /* Reserved.*/ - 8, /* Reserved.*/ - 8, /* Reserved.*/ - 8, /* Reserved.*/ - 8, /* Reserved.*/ - 8, /* Reserved.*/ - 8, /* Reserved.*/ - 8, /* Reserved.*/ - 0xB, /* PAL_MODE_STM32_ALTERNATE_PUSHPULL, 50MHz.*/ - 0xF, /* PAL_MODE_STM32_ALTERNATE_OPENDRAIN, 50MHz.*/ - }; - uint32_t mh, ml, crh, crl, cfg; - unsigned i; - - if (mode == PAL_MODE_INPUT_PULLUP) - port->BSRR = mask; - else if (mode == PAL_MODE_INPUT_PULLDOWN) - port->BRR = mask; - cfg = cfgtab[mode]; - mh = ml = crh = crl = 0; - for (i = 0; i < 8; i++) { - ml <<= 4; - mh <<= 4; - crl <<= 4; - crh <<= 4; - if ((mask & 0x0080) == 0) - ml |= 0xf; - else - crl |= cfg; - if ((mask & 0x8000) == 0) - mh |= 0xf; - else - crh |= cfg; - mask <<= 1; - } - port->CRH = (port->CRH & mh) | crh; - port->CRL = (port->CRL & ml) | crl; -} - -#endif /* HAL_USE_PAL */ - -/** @} */ diff --git a/os/hal/platforms/STM32/GPIOv1/pal_lld.h b/os/hal/platforms/STM32/GPIOv1/pal_lld.h deleted file mode 100644 index 56255ed1a..000000000 --- a/os/hal/platforms/STM32/GPIOv1/pal_lld.h +++ /dev/null @@ -1,334 +0,0 @@ -/* - ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file STM32/GPIOv1/pal_lld.h - * @brief STM32F1xx GPIO low level driver header. - * - * @addtogroup PAL - * @{ - */ - -#ifndef _PAL_LLD_H_ -#define _PAL_LLD_H_ - -#if HAL_USE_PAL || defined(__DOXYGEN__) - -/*===========================================================================*/ -/* Unsupported modes and specific modes */ -/*===========================================================================*/ - -/** - * @name STM32-specific I/O mode flags - * @{ - */ -/** - * @brief STM32 specific alternate push-pull output mode. - */ -#define PAL_MODE_STM32_ALTERNATE_PUSHPULL 16 - -/** - * @brief STM32 specific alternate open-drain output mode. - */ -#define PAL_MODE_STM32_ALTERNATE_OPENDRAIN 17 -/** @} */ - -/*===========================================================================*/ -/* I/O Ports Types and constants. */ -/*===========================================================================*/ - -/** - * @brief GPIO port setup info. - */ -typedef struct { - /** Initial value for ODR register.*/ - uint32_t odr; - /** Initial value for CRL register.*/ - uint32_t crl; - /** Initial value for CRH register.*/ - uint32_t crh; -} stm32_gpio_setup_t; - -/** - * @brief STM32 GPIO static initializer. - * @details An instance of this structure must be passed to @p palInit() at - * system startup time in order to initialize the digital I/O - * subsystem. This represents only the initial setup, specific pads - * or whole ports can be reprogrammed at later time. - */ -typedef struct { - /** @brief Port A setup data.*/ - stm32_gpio_setup_t PAData; - /** @brief Port B setup data.*/ - stm32_gpio_setup_t PBData; - /** @brief Port C setup data.*/ - stm32_gpio_setup_t PCData; - /** @brief Port D setup data.*/ - stm32_gpio_setup_t PDData; -#if STM32_HAS_GPIOE || defined(__DOXYGEN__) - /** @brief Port E setup data.*/ - stm32_gpio_setup_t PEData; -#if STM32_HAS_GPIOF || defined(__DOXYGEN__) - /** @brief Port F setup data.*/ - stm32_gpio_setup_t PFData; -#if STM32_HAS_GPIOG || defined(__DOXYGEN__) - /** @brief Port G setup data.*/ - stm32_gpio_setup_t PGData; -#endif -#endif -#endif -} PALConfig; - -/** - * @brief Width, in bits, of an I/O port. - */ -#define PAL_IOPORTS_WIDTH 16 - -/** - * @brief Whole port mask. - * @details This macro specifies all the valid bits into a port. - */ -#define PAL_WHOLE_PORT ((ioportmask_t)0xFFFF) - -/** - * @brief Digital I/O port sized unsigned type. - */ -typedef uint32_t ioportmask_t; - -/** - * @brief Digital I/O modes. - */ -typedef uint32_t iomode_t; - -/** - * @brief Port Identifier. - * @details This type can be a scalar or some kind of pointer, do not make - * any assumption about it, use the provided macros when populating - * variables of this type. - */ -typedef GPIO_TypeDef * ioportid_t; - -/*===========================================================================*/ -/* I/O Ports Identifiers. */ -/* The low level driver wraps the definitions already present in the STM32 */ -/* firmware library. */ -/*===========================================================================*/ - -/** - * @brief GPIO port A identifier. - */ -#if STM32_HAS_GPIOA || defined(__DOXYGEN__) -#define IOPORT1 GPIOA -#endif - -/** - * @brief GPIO port B identifier. - */ -#if STM32_HAS_GPIOB || defined(__DOXYGEN__) -#define IOPORT2 GPIOB -#endif - -/** - * @brief GPIO port C identifier. - */ -#if STM32_HAS_GPIOC || defined(__DOXYGEN__) -#define IOPORT3 GPIOC -#endif - -/** - * @brief GPIO port D identifier. - */ -#if STM32_HAS_GPIOD || defined(__DOXYGEN__) -#define IOPORT4 GPIOD -#endif - -/** - * @brief GPIO port E identifier. - */ -#if STM32_HAS_GPIOE || defined(__DOXYGEN__) -#define IOPORT5 GPIOE -#endif - -/** - * @brief GPIO port F identifier. - */ -#if STM32_HAS_GPIOF || defined(__DOXYGEN__) -#define IOPORT6 GPIOF -#endif - -/** - * @brief GPIO port G identifier. - */ -#if STM32_HAS_GPIOG || defined(__DOXYGEN__) -#define IOPORT7 GPIOG -#endif - -/*===========================================================================*/ -/* Implementation, some of the following macros could be implemented as */ -/* functions, if so please put them in pal_lld.c. */ -/*===========================================================================*/ - -/** - * @brief GPIO ports subsystem initialization. - * - * @notapi - */ -#define pal_lld_init(config) _pal_lld_init(config) - -/** - * @brief Reads an I/O port. - * @details This function is implemented by reading the GPIO IDR register, the - * implementation has no side effects. - * @note This function is not meant to be invoked directly by the application - * code. - * - * @param[in] port port identifier - * @return The port bits. - * - * @notapi - */ -#define pal_lld_readport(port) ((port)->IDR) - -/** - * @brief Reads the output latch. - * @details This function is implemented by reading the GPIO ODR register, the - * implementation has no side effects. - * @note This function is not meant to be invoked directly by the application - * code. - * - * @param[in] port port identifier - * @return The latched logical states. - * - * @notapi - */ -#define pal_lld_readlatch(port) ((port)->ODR) - -/** - * @brief Writes on a I/O port. - * @details This function is implemented by writing the GPIO ODR register, the - * implementation has no side effects. - * @note Writing on pads programmed as pull-up or pull-down has the side - * effect to modify the resistor setting because the output latched - * data is used for the resistor selection. - * - * @param[in] port port identifier - * @param[in] bits bits to be written on the specified port - * - * @notapi - */ -#define pal_lld_writeport(port, bits) ((port)->ODR = (bits)) - -/** - * @brief Sets a bits mask on a I/O port. - * @details This function is implemented by writing the GPIO BSRR register, the - * implementation has no side effects. - * @note Writing on pads programmed as pull-up or pull-down has the side - * effect to modify the resistor setting because the output latched - * data is used for the resistor selection. - * - * @param[in] port port identifier - * @param[in] bits bits to be ORed on the specified port - * - * @notapi - */ -#define pal_lld_setport(port, bits) ((port)->BSRR = (bits)) - -/** - * @brief Clears a bits mask on a I/O port. - * @details This function is implemented by writing the GPIO BRR register, the - * implementation has no side effects. - * @note Writing on pads programmed as pull-up or pull-down has the side - * effect to modify the resistor setting because the output latched - * data is used for the resistor selection. - * - * @param[in] port port identifier - * @param[in] bits bits to be cleared on the specified port - * - * @notapi - */ -#define pal_lld_clearport(port, bits) ((port)->BRR = (bits)) - -/** - * @brief Writes a group of bits. - * @details This function is implemented by writing the GPIO BSRR register, the - * implementation has no side effects. - * @note Writing on pads programmed as pull-up or pull-down has the side - * effect to modify the resistor setting because the output latched - * data is used for the resistor selection. - * - * @param[in] port port identifier - * @param[in] mask group mask - * @param[in] offset the group bit offset within the port - * @param[in] bits bits to be written. Values exceeding the group - * width are masked. - * - * @notapi - */ -#define pal_lld_writegroup(port, mask, offset, bits) \ - ((port)->BSRR = ((~(bits) & (mask)) << (16 + (offset))) | \ - (((bits) & (mask)) << (offset))) - -/** - * @brief Pads group mode setup. - * @details This function programs a pads group belonging to the same port - * with the specified mode. - * @note Writing on pads programmed as pull-up or pull-down has the side - * effect to modify the resistor setting because the output latched - * data is used for the resistor selection. - * - * @param[in] port port identifier - * @param[in] mask group mask - * @param[in] offset group bit offset within the port - * @param[in] mode group mode - * - * @notapi - */ -#define pal_lld_setgroupmode(port, mask, offset, mode) \ - _pal_lld_setgroupmode(port, mask << offset, mode) - -/** - * @brief Writes a logical state on an output pad. - * @note Writing on pads programmed as pull-up or pull-down has the side - * effect to modify the resistor setting because the output latched - * data is used for the resistor selection. - * - * @param[in] port port identifier - * @param[in] pad pad number within the port - * @param[in] bit logical value, the value must be @p PAL_LOW or - * @p PAL_HIGH - * - * @notapi - */ -#define pal_lld_writepad(port, pad, bit) pal_lld_writegroup(port, 1, pad, bit) - -extern const PALConfig pal_default_config; - -#ifdef __cplusplus -extern "C" { -#endif - void _pal_lld_init(const PALConfig *config); - void _pal_lld_setgroupmode(ioportid_t port, - ioportmask_t mask, - iomode_t mode); -#ifdef __cplusplus -} -#endif - -#endif /* HAL_USE_PAL */ - -#endif /* _PAL_LLD_H_ */ - -/** @} */ diff --git a/os/hal/platforms/STM32/GPIOv2/pal_lld.c b/os/hal/platforms/STM32/GPIOv2/pal_lld.c deleted file mode 100644 index 017b340a0..000000000 --- a/os/hal/platforms/STM32/GPIOv2/pal_lld.c +++ /dev/null @@ -1,237 +0,0 @@ -/* - ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file STM32/GPIOv2/pal_lld.c - * @brief STM32L1xx/STM32F2xx/STM32F4xx GPIO low level driver code. - * - * @addtogroup PAL - * @{ - */ - -#include "hal.h" - -#if HAL_USE_PAL || defined(__DOXYGEN__) - -/*===========================================================================*/ -/* Driver local definitions. */ -/*===========================================================================*/ - -#if defined(STM32L1XX_MD) -#define AHB_EN_MASK (RCC_AHBENR_GPIOAEN | RCC_AHBENR_GPIOBEN | \ - RCC_AHBENR_GPIOCEN | RCC_AHBENR_GPIODEN | \ - RCC_AHBENR_GPIOEEN | RCC_AHBENR_GPIOHEN) -#define AHB_LPEN_MASK AHB_EN_MASK -#elif defined(STM32F0XX) -#define AHB_EN_MASK (RCC_AHBENR_GPIOAEN | RCC_AHBENR_GPIOBEN | \ - RCC_AHBENR_GPIOCEN | RCC_AHBENR_GPIODEN | \ - RCC_AHBENR_GPIOFEN) -#elif defined(STM32F2XX) -#define AHB1_EN_MASK (RCC_AHB1ENR_GPIOAEN | RCC_AHB1ENR_GPIOBEN | \ - RCC_AHB1ENR_GPIOCEN | RCC_AHB1ENR_GPIODEN | \ - RCC_AHB1ENR_GPIOEEN | RCC_AHB1ENR_GPIOFEN | \ - RCC_AHB1ENR_GPIOGEN | RCC_AHB1ENR_GPIOHEN | \ - RCC_AHB1ENR_GPIOIEN) -#define AHB1_LPEN_MASK AHB1_EN_MASK -#elif defined(STM32F30X) || defined(STM32F37X) -#define AHB_EN_MASK (RCC_AHBENR_GPIOAEN | RCC_AHBENR_GPIOBEN | \ - RCC_AHBENR_GPIOCEN | RCC_AHBENR_GPIODEN | \ - RCC_AHBENR_GPIOEEN | RCC_AHBENR_GPIOFEN) -#elif defined(STM32F4XX) -#define AHB1_EN_MASK (RCC_AHB1ENR_GPIOAEN | RCC_AHB1ENR_GPIOBEN | \ - RCC_AHB1ENR_GPIOCEN | RCC_AHB1ENR_GPIODEN | \ - RCC_AHB1ENR_GPIOEEN | RCC_AHB1ENR_GPIOFEN | \ - RCC_AHB1ENR_GPIOGEN | RCC_AHB1ENR_GPIOHEN | \ - RCC_AHB1ENR_GPIOIEN) -#define AHB1_LPEN_MASK AHB1_EN_MASK -#else -#error "missing or unsupported platform for GPIOv2 PAL driver" -#endif - -/*===========================================================================*/ -/* Driver exported variables. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver local variables and types. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver local functions. */ -/*===========================================================================*/ - -static void initgpio(stm32_gpio_t *gpiop, const stm32_gpio_setup_t *config) { - - gpiop->OTYPER = config->otyper; - gpiop->OSPEEDR = config->ospeedr; - gpiop->PUPDR = config->pupdr; - gpiop->ODR = config->odr; - gpiop->AFRL = config->afrl; - gpiop->AFRH = config->afrh; - gpiop->MODER = config->moder; -} - -/*===========================================================================*/ -/* Driver interrupt handlers. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver exported functions. */ -/*===========================================================================*/ - -/** - * @brief STM32 I/O ports configuration. - * @details Ports A-D(E, F, G, H) clocks enabled. - * - * @param[in] config the STM32 ports configuration - * - * @notapi - */ -void _pal_lld_init(const PALConfig *config) { - - /* - * Enables the GPIO related clocks. - */ -#if defined(STM32L1XX_MD) - rccEnableAHB(AHB_EN_MASK, TRUE); - RCC->AHBLPENR |= AHB_LPEN_MASK; -#elif defined(STM32F0XX) - rccEnableAHB(AHB_EN_MASK, TRUE); -#elif defined(STM32F30X) || defined(STM32F37X) - rccEnableAHB(AHB_EN_MASK, TRUE); -#elif defined(STM32F2XX) || defined(STM32F4XX) - RCC->AHB1ENR |= AHB1_EN_MASK; - RCC->AHB1LPENR |= AHB1_LPEN_MASK; -#endif - - /* - * Initial GPIO setup. - */ - initgpio(GPIOA, &config->PAData); - initgpio(GPIOB, &config->PBData); - initgpio(GPIOC, &config->PCData); - initgpio(GPIOD, &config->PDData); -#if STM32_HAS_GPIOE - initgpio(GPIOE, &config->PEData); -#endif -#if STM32_HAS_GPIOF - initgpio(GPIOF, &config->PFData); -#endif -#if STM32_HAS_GPIOG - initgpio(GPIOG, &config->PGData); -#endif -#if STM32_HAS_GPIOH - initgpio(GPIOH, &config->PHData); -#endif -#if STM32_HAS_GPIOI - initgpio(GPIOI, &config->PIData); -#endif -} - -/** - * @brief Pads mode setup. - * @details This function programs a pads group belonging to the same port - * with the specified mode. - * @note @p PAL_MODE_UNCONNECTED is implemented as push pull at minimum - * speed. - * - * @param[in] port the port identifier - * @param[in] mask the group mask - * @param[in] mode the mode - * - * @notapi - */ -#if 1 -void _pal_lld_setgroupmode(ioportid_t port, - ioportmask_t mask, - iomode_t mode) { - - uint32_t moder = (mode & PAL_STM32_MODE_MASK) >> 0; - uint32_t otyper = (mode & PAL_STM32_OTYPE_MASK) >> 2; - uint32_t ospeedr = (mode & PAL_STM32_OSPEED_MASK) >> 3; - uint32_t pupdr = (mode & PAL_STM32_PUDR_MASK) >> 5; - uint32_t altr = (mode & PAL_STM32_ALTERNATE_MASK) >> 7; - uint32_t bit = 0; - while (TRUE) { - if ((mask & 1) != 0) { - uint32_t altrmask, m1, m2, m4; - - altrmask = altr << ((bit & 7) * 4); - m4 = 15 << ((bit & 7) * 4); - if (bit < 8) - port->AFRL = (port->AFRL & ~m4) | altrmask; - else - port->AFRH = (port->AFRH & ~m4) | altrmask; - m1 = 1 << bit; - port->OTYPER = (port->OTYPER & ~m1) | otyper; - m2 = 3 << (bit * 2); - port->OSPEEDR = (port->OSPEEDR & ~m2) | ospeedr; - port->PUPDR = (port->PUPDR & ~m2) | pupdr; - port->MODER = (port->MODER & ~m2) | moder; - } - mask >>= 1; - if (!mask) - return; - otyper <<= 1; - ospeedr <<= 2; - pupdr <<= 2; - moder <<= 2; - bit++; - } -} -#else -void _pal_lld_setgroupmode(ioportid_t port, - ioportmask_t mask, - iomode_t mode) { - uint32_t afrm, moderm, pupdrm, otyperm, ospeedrm; - uint32_t m1 = (uint32_t)mask; - uint32_t m2 = 0; - uint32_t m4l = 0; - uint32_t m4h = 0; - uint32_t bit = 0; - do { - if ((mask & 1) != 0) { - m2 |= 3 << bit; - if (bit < 16) - m4l |= 15 << ((bit & 14) * 2); - else - m4h |= 15 << ((bit & 14) * 2); - } - bit += 2; - mask >>= 1; - } while (mask); - - afrm = ((mode & PAL_STM32_ALTERNATE_MASK) >> 7) * 0x1111; - port->AFRL = (port->AFRL & ~m4l) | (afrm & m4l); - port->AFRH = (port->AFRH & ~m4h) | (afrm & m4h); - - ospeedrm = ((mode & PAL_STM32_OSPEED_MASK) >> 3) * 0x5555; - port->OSPEEDR = (port->OSPEEDR & ~m2) | (ospeedrm & m2); - - otyperm = ((mode & PAL_STM32_OTYPE_MASK) >> 2) * 0xffff; - port->OTYPER = (port->OTYPER & ~m1) | (otyperm & m1); - - pupdrm = ((mode & PAL_STM32_PUDR_MASK) >> 5) * 0x5555; - port->PUPDR = (port->PUPDR & ~m2) | (pupdrm & m2); - - moderm = ((mode & PAL_STM32_MODE_MASK) >> 0) * 0x5555; - port->MODER = (port->MODER & ~m2) | (moderm & m2); -} -#endif - -#endif /* HAL_USE_PAL */ - -/** @} */ diff --git a/os/hal/platforms/STM32/GPIOv2/pal_lld.h b/os/hal/platforms/STM32/GPIOv2/pal_lld.h deleted file mode 100644 index 5349507df..000000000 --- a/os/hal/platforms/STM32/GPIOv2/pal_lld.h +++ /dev/null @@ -1,469 +0,0 @@ -/* - ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file STM32/GPIOv2/pal_lld.h - * @brief STM32L1xx/STM32F2xx/STM32F4xx GPIO low level driver header. - * - * @addtogroup PAL - * @{ - */ - -#ifndef _PAL_LLD_H_ -#define _PAL_LLD_H_ - -#if HAL_USE_PAL || defined(__DOXYGEN__) - -/*===========================================================================*/ -/* Unsupported modes and specific modes */ -/*===========================================================================*/ - -#undef PAL_MODE_RESET -#undef PAL_MODE_UNCONNECTED -#undef PAL_MODE_INPUT -#undef PAL_MODE_INPUT_PULLUP -#undef PAL_MODE_INPUT_PULLDOWN -#undef PAL_MODE_INPUT_ANALOG -#undef PAL_MODE_OUTPUT_PUSHPULL -#undef PAL_MODE_OUTPUT_OPENDRAIN - -/** - * @name STM32-specific I/O mode flags - * @{ - */ -#define PAL_STM32_MODE_MASK (3 << 0) -#define PAL_STM32_MODE_INPUT (0 << 0) -#define PAL_STM32_MODE_OUTPUT (1 << 0) -#define PAL_STM32_MODE_ALTERNATE (2 << 0) -#define PAL_STM32_MODE_ANALOG (3 << 0) - -#define PAL_STM32_OTYPE_MASK (1 << 2) -#define PAL_STM32_OTYPE_PUSHPULL (0 << 2) -#define PAL_STM32_OTYPE_OPENDRAIN (1 << 2) - -#define PAL_STM32_OSPEED_MASK (3 << 3) -#define PAL_STM32_OSPEED_LOWEST (0 << 3) -#if defined(STM32F0XX) || defined(STM32F30X) || defined(STM32F37X) -#define PAL_STM32_OSPEED_MID (1 << 3) -#else -#define PAL_STM32_OSPEED_MID1 (1 << 3) -#define PAL_STM32_OSPEED_MID2 (2 << 3) -#endif -#define PAL_STM32_OSPEED_HIGHEST (3 << 3) - -#define PAL_STM32_PUDR_MASK (3 << 5) -#define PAL_STM32_PUDR_FLOATING (0 << 5) -#define PAL_STM32_PUDR_PULLUP (1 << 5) -#define PAL_STM32_PUDR_PULLDOWN (2 << 5) - -#define PAL_STM32_ALTERNATE_MASK (15 << 7) -#define PAL_STM32_ALTERNATE(n) ((n) << 7) - -/** - * @brief Alternate function. - * - * @param[in] n alternate function selector - */ -#define PAL_MODE_ALTERNATE(n) (PAL_STM32_MODE_ALTERNATE | \ - PAL_STM32_ALTERNATE(n)) -/** @} */ - -/** - * @name Standard I/O mode flags - * @{ - */ -/** - * @brief This mode is implemented as input. - */ -#define PAL_MODE_RESET PAL_STM32_MODE_INPUT - -/** - * @brief This mode is implemented as input with pull-up. - */ -#define PAL_MODE_UNCONNECTED PAL_MODE_INPUT_PULLUP - -/** - * @brief Regular input high-Z pad. - */ -#define PAL_MODE_INPUT PAL_STM32_MODE_INPUT - -/** - * @brief Input pad with weak pull up resistor. - */ -#define PAL_MODE_INPUT_PULLUP (PAL_STM32_MODE_INPUT | \ - PAL_STM32_PUDR_PULLUP) - -/** - * @brief Input pad with weak pull down resistor. - */ -#define PAL_MODE_INPUT_PULLDOWN (PAL_STM32_MODE_INPUT | \ - PAL_STM32_PUDR_PULLDOWN) - -/** - * @brief Analog input mode. - */ -#define PAL_MODE_INPUT_ANALOG PAL_STM32_MODE_ANALOG - -/** - * @brief Push-pull output pad. - */ -#define PAL_MODE_OUTPUT_PUSHPULL (PAL_STM32_MODE_OUTPUT | \ - PAL_STM32_OTYPE_PUSHPULL) - -/** - * @brief Open-drain output pad. - */ -#define PAL_MODE_OUTPUT_OPENDRAIN (PAL_STM32_MODE_OUTPUT | \ - PAL_STM32_OTYPE_OPENDRAIN) -/** @} */ - -/** - * @name GPIO ports definitions - * @{ - */ -#define GPIOA ((stm32_gpio_t *)GPIOA_BASE) -#define GPIOB ((stm32_gpio_t *)GPIOB_BASE) -#define GPIOC ((stm32_gpio_t *)GPIOC_BASE) -#define GPIOD ((stm32_gpio_t *)GPIOD_BASE) -#define GPIOE ((stm32_gpio_t *)GPIOE_BASE) -#define GPIOF ((stm32_gpio_t *)GPIOF_BASE) -#define GPIOG ((stm32_gpio_t *)GPIOG_BASE) -#define GPIOH ((stm32_gpio_t *)GPIOH_BASE) -#define GPIOI ((stm32_gpio_t *)GPIOI_BASE) -/** @} */ - -/*===========================================================================*/ -/* I/O Ports Types and constants. */ -/*===========================================================================*/ - -/** - * @brief STM32 GPIO registers block. - */ -typedef struct { - - volatile uint32_t MODER; - volatile uint32_t OTYPER; - volatile uint32_t OSPEEDR; - volatile uint32_t PUPDR; - volatile uint32_t IDR; - volatile uint32_t ODR; - volatile union { - uint32_t W; - struct { - uint16_t set; - uint16_t clear; - } H; - } BSRR; - volatile uint32_t LCKR; - volatile uint32_t AFRL; - volatile uint32_t AFRH; - volatile uint32_t BRR; -} stm32_gpio_t; - -/** - * @brief GPIO port setup info. - */ -typedef struct { - /** Initial value for MODER register.*/ - uint32_t moder; - /** Initial value for OTYPER register.*/ - uint32_t otyper; - /** Initial value for OSPEEDR register.*/ - uint32_t ospeedr; - /** Initial value for PUPDR register.*/ - uint32_t pupdr; - /** Initial value for ODR register.*/ - uint32_t odr; - /** Initial value for AFRL register.*/ - uint32_t afrl; - /** Initial value for AFRH register.*/ - uint32_t afrh; -} stm32_gpio_setup_t; - -/** - * @brief STM32 GPIO static initializer. - * @details An instance of this structure must be passed to @p palInit() at - * system startup time in order to initialize the digital I/O - * subsystem. This represents only the initial setup, specific pads - * or whole ports can be reprogrammed at later time. - */ -typedef struct { - /** @brief Port A setup data.*/ - stm32_gpio_setup_t PAData; - /** @brief Port B setup data.*/ - stm32_gpio_setup_t PBData; - /** @brief Port C setup data.*/ - stm32_gpio_setup_t PCData; - /** @brief Port D setup data.*/ - stm32_gpio_setup_t PDData; -#if STM32_HAS_GPIOE - /** @brief Port E setup data.*/ - stm32_gpio_setup_t PEData; -#endif -#if STM32_HAS_GPIOF - /** @brief Port F setup data.*/ - stm32_gpio_setup_t PFData; -#endif -#if STM32_HAS_GPIOG - /** @brief Port G setup data.*/ - stm32_gpio_setup_t PGData; -#endif -#if STM32_HAS_GPIOH - /** @brief Port H setup data.*/ - stm32_gpio_setup_t PHData; -#endif -#if STM32_HAS_GPIOI - /** @brief Port I setup data.*/ - stm32_gpio_setup_t PIData; -#endif -} PALConfig; - -/** - * @brief Width, in bits, of an I/O port. - */ -#define PAL_IOPORTS_WIDTH 16 - -/** - * @brief Whole port mask. - * @details This macro specifies all the valid bits into a port. - */ -#define PAL_WHOLE_PORT ((ioportmask_t)0xFFFF) - -/** - * @brief Digital I/O port sized unsigned type. - */ -typedef uint32_t ioportmask_t; - -/** - * @brief Digital I/O modes. - */ -typedef uint32_t iomode_t; - -/** - * @brief Port Identifier. - * @details This type can be a scalar or some kind of pointer, do not make - * any assumption about it, use the provided macros when populating - * variables of this type. - */ -typedef stm32_gpio_t * ioportid_t; - -/*===========================================================================*/ -/* I/O Ports Identifiers. */ -/* The low level driver wraps the definitions already present in the STM32 */ -/* firmware library. */ -/*===========================================================================*/ - -/** - * @brief GPIO port A identifier. - */ -#if STM32_HAS_GPIOA || defined(__DOXYGEN__) -#define IOPORT1 GPIOA -#endif - -/** - * @brief GPIO port B identifier. - */ -#if STM32_HAS_GPIOB || defined(__DOXYGEN__) -#define IOPORT2 GPIOB -#endif - -/** - * @brief GPIO port C identifier. - */ -#if STM32_HAS_GPIOC || defined(__DOXYGEN__) -#define IOPORT3 GPIOC -#endif - -/** - * @brief GPIO port D identifier. - */ -#if STM32_HAS_GPIOD || defined(__DOXYGEN__) -#define IOPORT4 GPIOD -#endif - -/** - * @brief GPIO port E identifier. - */ -#if STM32_HAS_GPIOE || defined(__DOXYGEN__) -#define IOPORT5 GPIOE -#endif - -/** - * @brief GPIO port F identifier. - */ -#if STM32_HAS_GPIOF || defined(__DOXYGEN__) -#define IOPORT6 GPIOF -#endif - -/** - * @brief GPIO port G identifier. - */ -#if STM32_HAS_GPIOG || defined(__DOXYGEN__) -#define IOPORT7 GPIOG -#endif - -/** - * @brief GPIO port H identifier. - */ -#if STM32_HAS_GPIOH || defined(__DOXYGEN__) -#define IOPORT8 GPIOH -#endif - -/** - * @brief GPIO port I identifier. - */ -#if STM32_HAS_GPIOI || defined(__DOXYGEN__) -#define IOPORT9 GPIOI -#endif - -/*===========================================================================*/ -/* Implementation, some of the following macros could be implemented as */ -/* functions, if so please put them in pal_lld.c. */ -/*===========================================================================*/ - -/** - * @brief GPIO ports subsystem initialization. - * - * @notapi - */ -#define pal_lld_init(config) _pal_lld_init(config) - -/** - * @brief Reads an I/O port. - * @details This function is implemented by reading the GPIO IDR register, the - * implementation has no side effects. - * @note This function is not meant to be invoked directly by the application - * code. - * - * @param[in] port port identifier - * @return The port bits. - * - * @notapi - */ -#define pal_lld_readport(port) ((port)->IDR) - -/** - * @brief Reads the output latch. - * @details This function is implemented by reading the GPIO ODR register, the - * implementation has no side effects. - * @note This function is not meant to be invoked directly by the application - * code. - * - * @param[in] port port identifier - * @return The latched logical states. - * - * @notapi - */ -#define pal_lld_readlatch(port) ((port)->ODR) - -/** - * @brief Writes on a I/O port. - * @details This function is implemented by writing the GPIO ODR register, the - * implementation has no side effects. - * - * @param[in] port port identifier - * @param[in] bits bits to be written on the specified port - * - * @notapi - */ -#define pal_lld_writeport(port, bits) ((port)->ODR = (bits)) - -/** - * @brief Sets a bits mask on a I/O port. - * @details This function is implemented by writing the GPIO BSRR register, the - * implementation has no side effects. - * - * @param[in] port port identifier - * @param[in] bits bits to be ORed on the specified port - * - * @notapi - */ -#define pal_lld_setport(port, bits) ((port)->BSRR.H.set = (uint16_t)(bits)) - -/** - * @brief Clears a bits mask on a I/O port. - * @details This function is implemented by writing the GPIO BSRR register, the - * implementation has no side effects. - * - * @param[in] port port identifier - * @param[in] bits bits to be cleared on the specified port - * - * @notapi - */ -#define pal_lld_clearport(port, bits) ((port)->BSRR.H.clear = (uint16_t)(bits)) - -/** - * @brief Writes a group of bits. - * @details This function is implemented by writing the GPIO BSRR register, the - * implementation has no side effects. - * - * @param[in] port port identifier - * @param[in] mask group mask - * @param[in] offset the group bit offset within the port - * @param[in] bits bits to be written. Values exceeding the group - * width are masked. - * - * @notapi - */ -#define pal_lld_writegroup(port, mask, offset, bits) \ - ((port)->BSRR.W = ((~(bits) & (mask)) << (16 + (offset))) | \ - (((bits) & (mask)) << (offset))) - -/** - * @brief Pads group mode setup. - * @details This function programs a pads group belonging to the same port - * with the specified mode. - * - * @param[in] port port identifier - * @param[in] mask group mask - * @param[in] offset group bit offset within the port - * @param[in] mode group mode - * - * @notapi - */ -#define pal_lld_setgroupmode(port, mask, offset, mode) \ - _pal_lld_setgroupmode(port, mask << offset, mode) - -/** - * @brief Writes a logical state on an output pad. - * - * @param[in] port port identifier - * @param[in] pad pad number within the port - * @param[in] bit logical value, the value must be @p PAL_LOW or - * @p PAL_HIGH - * - * @notapi - */ -#define pal_lld_writepad(port, pad, bit) pal_lld_writegroup(port, 1, pad, bit) - -extern const PALConfig pal_default_config; - -#ifdef __cplusplus -extern "C" { -#endif - void _pal_lld_init(const PALConfig *config); - void _pal_lld_setgroupmode(ioportid_t port, - ioportmask_t mask, - iomode_t mode); -#ifdef __cplusplus -} -#endif - -#endif /* HAL_USE_PAL */ - -#endif /* _PAL_LLD_H_ */ - -/** @} */ diff --git a/os/hal/platforms/STM32/I2Cv1/i2c_lld.c b/os/hal/platforms/STM32/I2Cv1/i2c_lld.c deleted file mode 100644 index 35c607330..000000000 --- a/os/hal/platforms/STM32/I2Cv1/i2c_lld.c +++ /dev/null @@ -1,849 +0,0 @@ -/* - ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ -/* - Concepts and parts of this file have been contributed by Uladzimir Pylinsky - aka barthess. - */ - -/** - * @file STM32/I2Cv1/i2c_lld.c - * @brief STM32 I2C subsystem low level driver source. - * - * @addtogroup I2C - * @{ - */ - -#include "hal.h" - -#if HAL_USE_I2C || defined(__DOXYGEN__) - -/*===========================================================================*/ -/* Driver local definitions. */ -/*===========================================================================*/ - -#define I2C1_RX_DMA_CHANNEL \ - STM32_DMA_GETCHANNEL(STM32_I2C_I2C1_RX_DMA_STREAM, \ - STM32_I2C1_RX_DMA_CHN) - -#define I2C1_TX_DMA_CHANNEL \ - STM32_DMA_GETCHANNEL(STM32_I2C_I2C1_TX_DMA_STREAM, \ - STM32_I2C1_TX_DMA_CHN) - -#define I2C2_RX_DMA_CHANNEL \ - STM32_DMA_GETCHANNEL(STM32_I2C_I2C2_RX_DMA_STREAM, \ - STM32_I2C2_RX_DMA_CHN) - -#define I2C2_TX_DMA_CHANNEL \ - STM32_DMA_GETCHANNEL(STM32_I2C_I2C2_TX_DMA_STREAM, \ - STM32_I2C2_TX_DMA_CHN) - -#define I2C3_RX_DMA_CHANNEL \ - STM32_DMA_GETCHANNEL(STM32_I2C_I2C3_RX_DMA_STREAM, \ - STM32_I2C3_RX_DMA_CHN) - -#define I2C3_TX_DMA_CHANNEL \ - STM32_DMA_GETCHANNEL(STM32_I2C_I2C3_TX_DMA_STREAM, \ - STM32_I2C3_TX_DMA_CHN) - -/*===========================================================================*/ -/* Driver constants. */ -/*===========================================================================*/ - -#define I2C_EV5_MASTER_MODE_SELECT \ - ((uint32_t)(((I2C_SR2_MSL | I2C_SR2_BUSY) << 16) | I2C_SR1_SB)) - -#define I2C_EV6_MASTER_TRA_MODE_SELECTED \ - ((uint32_t)(((I2C_SR2_MSL | I2C_SR2_BUSY | I2C_SR2_TRA) << 16) | \ - I2C_SR1_ADDR | I2C_SR1_TXE)) - -#define I2C_EV6_MASTER_REC_MODE_SELECTED \ - ((uint32_t)(((I2C_SR2_MSL | I2C_SR2_BUSY)<< 16) | I2C_SR1_ADDR)) - -#define I2C_EV8_2_MASTER_BYTE_TRANSMITTED \ - ((uint32_t)(((I2C_SR2_MSL | I2C_SR2_BUSY | I2C_SR2_TRA) << 16) | \ - I2C_SR1_BTF | I2C_SR1_TXE)) - -#define I2C_EV_MASK 0x00FFFFFF - -#define I2C_ERROR_MASK \ - ((uint16_t)(I2C_SR1_BERR | I2C_SR1_ARLO | I2C_SR1_AF | I2C_SR1_OVR | \ - I2C_SR1_PECERR | I2C_SR1_TIMEOUT | I2C_SR1_SMBALERT)) - -/*===========================================================================*/ -/* Driver exported variables. */ -/*===========================================================================*/ - -/** @brief I2C1 driver identifier.*/ -#if STM32_I2C_USE_I2C1 || defined(__DOXYGEN__) -I2CDriver I2CD1; -#endif - -/** @brief I2C2 driver identifier.*/ -#if STM32_I2C_USE_I2C2 || defined(__DOXYGEN__) -I2CDriver I2CD2; -#endif - -/** @brief I2C3 driver identifier.*/ -#if STM32_I2C_USE_I2C3 || defined(__DOXYGEN__) -I2CDriver I2CD3; -#endif - -/*===========================================================================*/ -/* Driver local variables and types. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver local functions. */ -/*===========================================================================*/ - -/** - * @brief Aborts an I2C transaction. - * - * @param[in] i2cp pointer to the @p I2CDriver object - * - * @notapi - */ -static void i2c_lld_abort_operation(I2CDriver *i2cp) { - I2C_TypeDef *dp = i2cp->i2c; - - /* Stops the I2C peripheral.*/ - dp->CR1 = I2C_CR1_SWRST; - dp->CR1 = 0; - dp->CR2 = 0; - dp->SR1 = 0; - - /* Stops the associated DMA streams.*/ - dmaStreamDisable(i2cp->dmatx); - dmaStreamDisable(i2cp->dmarx); -} - -/** - * @brief Set clock speed. - * - * @param[in] i2cp pointer to the @p I2CDriver object - * - * @notapi - */ -static void i2c_lld_set_clock(I2CDriver *i2cp) { - I2C_TypeDef *dp = i2cp->i2c; - uint16_t regCCR, clock_div; - int32_t clock_speed = i2cp->config->clock_speed; - i2cdutycycle_t duty = i2cp->config->duty_cycle; - - osalDbgCheck((i2cp != NULL) && - (clock_speed > 0) && - (clock_speed <= 4000000)); - - /* CR2 Configuration.*/ - dp->CR2 &= (uint16_t)~I2C_CR2_FREQ; - dp->CR2 |= (uint16_t)I2C_CLK_FREQ; - - /* CCR Configuration.*/ - regCCR = 0; - clock_div = I2C_CCR_CCR; - - if (clock_speed <= 100000) { - /* Configure clock_div in standard mode.*/ - osalDbgAssert(duty == STD_DUTY_CYCLE, "invalid standard mode duty cycle"); - - /* Standard mode clock_div calculate: Tlow/Thigh = 1/1.*/ - osalDbgAssert((STM32_PCLK1 % (clock_speed * 2)) == 0, - "PCLK1 must be divisible without remainder"); - clock_div = (uint16_t)(STM32_PCLK1 / (clock_speed * 2)); - - osalDbgAssert(clock_div >= 0x04, - "clock divider less then 0x04 not allowed"); - regCCR |= (clock_div & I2C_CCR_CCR); - - /* Sets the Maximum Rise Time for standard mode.*/ - dp->TRISE = I2C_CLK_FREQ + 1; - } - else if (clock_speed <= 400000) { - /* Configure clock_div in fast mode.*/ - osalDbgAssert((duty == FAST_DUTY_CYCLE_2) || - (duty == FAST_DUTY_CYCLE_16_9), - "invalid fast mode duty cycle"); - - if (duty == FAST_DUTY_CYCLE_2) { - /* Fast mode clock_div calculate: Tlow/Thigh = 2/1.*/ - osalDbgAssert((STM32_PCLK1 % (clock_speed * 3)) == 0, - "PCLK1 must be divided without remainder"); - clock_div = (uint16_t)(STM32_PCLK1 / (clock_speed * 3)); - } - else if (duty == FAST_DUTY_CYCLE_16_9) { - /* Fast mode clock_div calculate: Tlow/Thigh = 16/9.*/ - osalDbgAssert((STM32_PCLK1 % (clock_speed * 25)) == 0, - "PCLK1 must be divided without remainder"); - clock_div = (uint16_t)(STM32_PCLK1 / (clock_speed * 25)); - regCCR |= I2C_CCR_DUTY; - } - - osalDbgAssert(clock_div >= 0x01, - "clock divider less then 0x04 not allowed"); - regCCR |= (I2C_CCR_FS | (clock_div & I2C_CCR_CCR)); - - /* Sets the Maximum Rise Time for fast mode.*/ - dp->TRISE = (I2C_CLK_FREQ * 300 / 1000) + 1; - } - - osalDbgAssert((clock_div <= I2C_CCR_CCR), "the selected clock is too low"); - - dp->CCR = regCCR; -} - -/** - * @brief Set operation mode of I2C hardware. - * - * @param[in] i2cp pointer to the @p I2CDriver object - * - * @notapi - */ -static void i2c_lld_set_opmode(I2CDriver *i2cp) { - I2C_TypeDef *dp = i2cp->i2c; - i2copmode_t opmode = i2cp->config->op_mode; - uint16_t regCR1; - - regCR1 = dp->CR1; - switch (opmode) { - case OPMODE_I2C: - regCR1 &= (uint16_t)~(I2C_CR1_SMBUS|I2C_CR1_SMBTYPE); - break; - case OPMODE_SMBUS_DEVICE: - regCR1 |= I2C_CR1_SMBUS; - regCR1 &= (uint16_t)~(I2C_CR1_SMBTYPE); - break; - case OPMODE_SMBUS_HOST: - regCR1 |= (I2C_CR1_SMBUS|I2C_CR1_SMBTYPE); - break; - } - dp->CR1 = regCR1; -} - -/** - * @brief I2C shared ISR code. - * - * @param[in] i2cp pointer to the @p I2CDriver object - * - * @notapi - */ -static void i2c_lld_serve_event_interrupt(I2CDriver *i2cp) { - I2C_TypeDef *dp = i2cp->i2c; - uint32_t regSR2 = dp->SR2; - uint32_t event = dp->SR1; - - /* Interrupts are disabled just before dmaStreamEnable() because there - is no need of interrupts until next transaction begin. All the work is - done by the DMA.*/ - switch (I2C_EV_MASK & (event | (regSR2 << 16))) { - case I2C_EV5_MASTER_MODE_SELECT: - dp->DR = i2cp->addr; - break; - case I2C_EV6_MASTER_REC_MODE_SELECTED: - dp->CR2 &= ~I2C_CR2_ITEVTEN; - dmaStreamEnable(i2cp->dmarx); - dp->CR2 |= I2C_CR2_LAST; /* Needed in receiver mode. */ - if (dmaStreamGetTransactionSize(i2cp->dmarx) < 2) - dp->CR1 &= ~I2C_CR1_ACK; - break; - case I2C_EV6_MASTER_TRA_MODE_SELECTED: - dp->CR2 &= ~I2C_CR2_ITEVTEN; - dmaStreamEnable(i2cp->dmatx); - break; - case I2C_EV8_2_MASTER_BYTE_TRANSMITTED: - /* Catches BTF event after the end of transmission.*/ - if (dmaStreamGetTransactionSize(i2cp->dmarx) > 0) { - /* Starts "read after write" operation, LSB = 1 -> receive.*/ - i2cp->addr |= 0x01; - dp->CR1 |= I2C_CR1_START | I2C_CR1_ACK; - return; - } - dp->CR2 &= ~I2C_CR2_ITEVTEN; - dp->CR1 |= I2C_CR1_STOP; - _i2c_wakeup_isr(i2cp); - break; - default: - break; - } - /* Clear ADDR flag. */ - if (event & (I2C_SR1_ADDR | I2C_SR1_ADD10)) - (void)dp->SR2; -} - -/** - * @brief DMA RX end IRQ handler. - * - * @param[in] i2cp pointer to the @p I2CDriver object - * @param[in] flags pre-shifted content of the ISR register - * - * @notapi - */ -static void i2c_lld_serve_rx_end_irq(I2CDriver *i2cp, uint32_t flags) { - I2C_TypeDef *dp = i2cp->i2c; - - /* DMA errors handling.*/ -#if defined(STM32_I2C_DMA_ERROR_HOOK) - if ((flags & (STM32_DMA_ISR_TEIF | STM32_DMA_ISR_DMEIF)) != 0) { - STM32_I2C_DMA_ERROR_HOOK(i2cp); - } -#else - (void)flags; -#endif - - dmaStreamDisable(i2cp->dmarx); - - dp->CR2 &= ~I2C_CR2_LAST; - dp->CR1 &= ~I2C_CR1_ACK; - dp->CR1 |= I2C_CR1_STOP; - _i2c_wakeup_isr(i2cp); -} - -/** - * @brief DMA TX end IRQ handler. - * - * @param[in] i2cp pointer to the @p I2CDriver object - * - * @notapi - */ -static void i2c_lld_serve_tx_end_irq(I2CDriver *i2cp, uint32_t flags) { - I2C_TypeDef *dp = i2cp->i2c; - - /* DMA errors handling.*/ -#if defined(STM32_I2C_DMA_ERROR_HOOK) - if ((flags & (STM32_DMA_ISR_TEIF | STM32_DMA_ISR_DMEIF)) != 0) { - STM32_I2C_DMA_ERROR_HOOK(i2cp); - } -#else - (void)flags; -#endif - - dmaStreamDisable(i2cp->dmatx); - /* Enables interrupts to catch BTF event meaning transmission part complete. - Interrupt handler will decide to generate STOP or to begin receiving part - of R/W transaction itself.*/ - dp->CR2 |= I2C_CR2_ITEVTEN; -} - -/** - * @brief I2C error handler. - * - * @param[in] i2cp pointer to the @p I2CDriver object - * @param[in] sr content of the SR1 register to be decoded - * - * @notapi - */ -static void i2c_lld_serve_error_interrupt(I2CDriver *i2cp, uint16_t sr) { - - /* Clears interrupt flags just to be safe.*/ - dmaStreamDisable(i2cp->dmatx); - dmaStreamDisable(i2cp->dmarx); - - i2cp->errors = I2C_NO_ERROR; - - if (sr & I2C_SR1_BERR) /* Bus error. */ - i2cp->errors |= I2C_BUS_ERROR; - - if (sr & I2C_SR1_ARLO) /* Arbitration lost. */ - i2cp->errors |= I2C_ARBITRATION_LOST; - - if (sr & I2C_SR1_AF) { /* Acknowledge fail. */ - i2cp->i2c->CR2 &= ~I2C_CR2_ITEVTEN; - i2cp->i2c->CR1 |= I2C_CR1_STOP; /* Setting stop bit. */ - i2cp->errors |= I2C_ACK_FAILURE; - } - - if (sr & I2C_SR1_OVR) /* Overrun. */ - i2cp->errors |= I2C_OVERRUN; - - if (sr & I2C_SR1_TIMEOUT) /* SMBus Timeout. */ - i2cp->errors |= I2C_TIMEOUT; - - if (sr & I2C_SR1_PECERR) /* PEC error. */ - i2cp->errors |= I2C_PEC_ERROR; - - if (sr & I2C_SR1_SMBALERT) /* SMBus alert. */ - i2cp->errors |= I2C_SMB_ALERT; - - /* If some error has been identified then sends wakes the waiting thread.*/ - if (i2cp->errors != I2C_NO_ERROR) - _i2c_wakeup_error_isr(i2cp); -} - -/*===========================================================================*/ -/* Driver interrupt handlers. */ -/*===========================================================================*/ - -#if STM32_I2C_USE_I2C1 || defined(__DOXYGEN__) -/** - * @brief I2C1 event interrupt handler. - * - * @notapi - */ -OSAL_IRQ_HANDLER(I2C1_EV_IRQHandler) { - - OSAL_IRQ_PROLOGUE(); - - i2c_lld_serve_event_interrupt(&I2CD1); - - OSAL_IRQ_EPILOGUE(); -} - -/** - * @brief I2C1 error interrupt handler. - */ -OSAL_IRQ_HANDLER(I2C1_ER_IRQHandler) { - uint16_t sr = I2CD1.i2c->SR1; - - OSAL_IRQ_PROLOGUE(); - - I2CD1.i2c->SR1 = ~(sr & I2C_ERROR_MASK); - i2c_lld_serve_error_interrupt(&I2CD1, sr); - - OSAL_IRQ_EPILOGUE(); -} -#endif /* STM32_I2C_USE_I2C1 */ - -#if STM32_I2C_USE_I2C2 || defined(__DOXYGEN__) -/** - * @brief I2C2 event interrupt handler. - * - * @notapi - */ -OSAL_IRQ_HANDLER(I2C2_EV_IRQHandler) { - - OSAL_IRQ_PROLOGUE(); - - i2c_lld_serve_event_interrupt(&I2CD2); - - OSAL_IRQ_EPILOGUE(); -} - -/** - * @brief I2C2 error interrupt handler. - * - * @notapi - */ -OSAL_IRQ_HANDLER(I2C2_ER_IRQHandler) { - uint16_t sr = I2CD2.i2c->SR1; - - OSAL_IRQ_PROLOGUE(); - - I2CD2.i2c->SR1 = ~(sr & I2C_ERROR_MASK); - i2c_lld_serve_error_interrupt(&I2CD2, sr); - - OSAL_IRQ_EPILOGUE(); -} -#endif /* STM32_I2C_USE_I2C2 */ - -#if STM32_I2C_USE_I2C3 || defined(__DOXYGEN__) -/** - * @brief I2C3 event interrupt handler. - * - * @notapi - */ -OSAL_IRQ_HANDLER(I2C3_EV_IRQHandler) { - - OSAL_IRQ_PROLOGUE(); - - i2c_lld_serve_event_interrupt(&I2CD3); - - OSAL_IRQ_EPILOGUE(); -} - -/** - * @brief I2C3 error interrupt handler. - * - * @notapi - */ -OSAL_IRQ_HANDLER(I2C3_ER_IRQHandler) { - uint16_t sr = I2CD3.i2c->SR1; - - OSAL_IRQ_PROLOGUE(); - - I2CD3.i2c->SR1 = ~(sr & I2C_ERROR_MASK); - i2c_lld_serve_error_interrupt(&I2CD3, sr); - - OSAL_IRQ_EPILOGUE(); -} -#endif /* STM32_I2C_USE_I2C3 */ - -/*===========================================================================*/ -/* Driver exported functions. */ -/*===========================================================================*/ - -/** - * @brief Low level I2C driver initialization. - * - * @notapi - */ -void i2c_lld_init(void) { - -#if STM32_I2C_USE_I2C1 - i2cObjectInit(&I2CD1); - I2CD1.thread = NULL; - I2CD1.i2c = I2C1; - I2CD1.dmarx = STM32_DMA_STREAM(STM32_I2C_I2C1_RX_DMA_STREAM); - I2CD1.dmatx = STM32_DMA_STREAM(STM32_I2C_I2C1_TX_DMA_STREAM); -#endif /* STM32_I2C_USE_I2C1 */ - -#if STM32_I2C_USE_I2C2 - i2cObjectInit(&I2CD2); - I2CD2.thread = NULL; - I2CD2.i2c = I2C2; - I2CD2.dmarx = STM32_DMA_STREAM(STM32_I2C_I2C2_RX_DMA_STREAM); - I2CD2.dmatx = STM32_DMA_STREAM(STM32_I2C_I2C2_TX_DMA_STREAM); -#endif /* STM32_I2C_USE_I2C2 */ - -#if STM32_I2C_USE_I2C3 - i2cObjectInit(&I2CD3); - I2CD3.thread = NULL; - I2CD3.i2c = I2C3; - I2CD3.dmarx = STM32_DMA_STREAM(STM32_I2C_I2C3_RX_DMA_STREAM); - I2CD3.dmatx = STM32_DMA_STREAM(STM32_I2C_I2C3_TX_DMA_STREAM); -#endif /* STM32_I2C_USE_I2C3 */ -} - -/** - * @brief Configures and activates the I2C peripheral. - * - * @param[in] i2cp pointer to the @p I2CDriver object - * - * @notapi - */ -void i2c_lld_start(I2CDriver *i2cp) { - I2C_TypeDef *dp = i2cp->i2c; - - i2cp->txdmamode = STM32_DMA_CR_PSIZE_BYTE | STM32_DMA_CR_MSIZE_BYTE | - STM32_DMA_CR_MINC | STM32_DMA_CR_DMEIE | - STM32_DMA_CR_TEIE | STM32_DMA_CR_TCIE | - STM32_DMA_CR_DIR_M2P; - i2cp->rxdmamode = STM32_DMA_CR_PSIZE_BYTE | STM32_DMA_CR_MSIZE_BYTE | - STM32_DMA_CR_MINC | STM32_DMA_CR_DMEIE | - STM32_DMA_CR_TEIE | STM32_DMA_CR_TCIE | - STM32_DMA_CR_DIR_P2M; - - /* If in stopped state then enables the I2C and DMA clocks.*/ - if (i2cp->state == I2C_STOP) { - -#if STM32_I2C_USE_I2C1 - if (&I2CD1 == i2cp) { - bool b; - - rccResetI2C1(); - b = dmaStreamAllocate(i2cp->dmarx, - STM32_I2C_I2C1_IRQ_PRIORITY, - (stm32_dmaisr_t)i2c_lld_serve_rx_end_irq, - (void *)i2cp); - osalDbgAssert(!b, "stream already allocated"); - b = dmaStreamAllocate(i2cp->dmatx, - STM32_I2C_I2C1_IRQ_PRIORITY, - (stm32_dmaisr_t)i2c_lld_serve_tx_end_irq, - (void *)i2cp); - osalDbgAssert(!b, "stream already allocated"); - rccEnableI2C1(FALSE); - nvicEnableVector(I2C1_EV_IRQn, STM32_I2C_I2C1_IRQ_PRIORITY); - nvicEnableVector(I2C1_ER_IRQn, STM32_I2C_I2C1_IRQ_PRIORITY); - - i2cp->rxdmamode |= STM32_DMA_CR_CHSEL(I2C1_RX_DMA_CHANNEL) | - STM32_DMA_CR_PL(STM32_I2C_I2C1_DMA_PRIORITY); - i2cp->txdmamode |= STM32_DMA_CR_CHSEL(I2C1_TX_DMA_CHANNEL) | - STM32_DMA_CR_PL(STM32_I2C_I2C1_DMA_PRIORITY); - } -#endif /* STM32_I2C_USE_I2C1 */ - -#if STM32_I2C_USE_I2C2 - if (&I2CD2 == i2cp) { - bool b; - - rccResetI2C2(); - b = dmaStreamAllocate(i2cp->dmarx, - STM32_I2C_I2C2_IRQ_PRIORITY, - (stm32_dmaisr_t)i2c_lld_serve_rx_end_irq, - (void *)i2cp); - osalDbgAssert(!b, "stream already allocated"); - b = dmaStreamAllocate(i2cp->dmatx, - STM32_I2C_I2C2_IRQ_PRIORITY, - (stm32_dmaisr_t)i2c_lld_serve_tx_end_irq, - (void *)i2cp); - osalDbgAssert(!b, "stream already allocated"); - rccEnableI2C2(FALSE); - nvicEnableVector(I2C2_EV_IRQn, STM32_I2C_I2C2_IRQ_PRIORITY); - nvicEnableVector(I2C2_ER_IRQn, STM32_I2C_I2C2_IRQ_PRIORITY); - - i2cp->rxdmamode |= STM32_DMA_CR_CHSEL(I2C2_RX_DMA_CHANNEL) | - STM32_DMA_CR_PL(STM32_I2C_I2C2_DMA_PRIORITY); - i2cp->txdmamode |= STM32_DMA_CR_CHSEL(I2C2_TX_DMA_CHANNEL) | - STM32_DMA_CR_PL(STM32_I2C_I2C2_DMA_PRIORITY); - } -#endif /* STM32_I2C_USE_I2C2 */ - -#if STM32_I2C_USE_I2C3 - if (&I2CD3 == i2cp) { - bool b; - - rccResetI2C3(); - b = dmaStreamAllocate(i2cp->dmarx, - STM32_I2C_I2C3_IRQ_PRIORITY, - (stm32_dmaisr_t)i2c_lld_serve_rx_end_irq, - (void *)i2cp); - osalDbgAssert(!b, "stream already allocated"); - b = dmaStreamAllocate(i2cp->dmatx, - STM32_I2C_I2C3_IRQ_PRIORITY, - (stm32_dmaisr_t)i2c_lld_serve_tx_end_irq, - (void *)i2cp); - osalDbgAssert(!b, "stream already allocated"); - rccEnableI2C3(FALSE); - nvicEnableVector(I2C3_EV_IRQn, STM32_I2C_I2C3_IRQ_PRIORITY); - nvicEnableVector(I2C3_ER_IRQn, STM32_I2C_I2C3_IRQ_PRIORITY); - - i2cp->rxdmamode |= STM32_DMA_CR_CHSEL(I2C3_RX_DMA_CHANNEL) | - STM32_DMA_CR_PL(STM32_I2C_I2C3_DMA_PRIORITY); - i2cp->txdmamode |= STM32_DMA_CR_CHSEL(I2C3_TX_DMA_CHANNEL) | - STM32_DMA_CR_PL(STM32_I2C_I2C3_DMA_PRIORITY); - } -#endif /* STM32_I2C_USE_I2C3 */ - } - - /* I2C registers pointed by the DMA.*/ - dmaStreamSetPeripheral(i2cp->dmarx, &dp->DR); - dmaStreamSetPeripheral(i2cp->dmatx, &dp->DR); - - /* Reset i2c peripheral.*/ - dp->CR1 = I2C_CR1_SWRST; - dp->CR1 = 0; - dp->CR2 = I2C_CR2_ITERREN | I2C_CR2_DMAEN; - - /* Setup I2C parameters.*/ - i2c_lld_set_clock(i2cp); - i2c_lld_set_opmode(i2cp); - - /* Ready to go.*/ - dp->CR1 |= I2C_CR1_PE; -} - -/** - * @brief Deactivates the I2C peripheral. - * - * @param[in] i2cp pointer to the @p I2CDriver object - * - * @notapi - */ -void i2c_lld_stop(I2CDriver *i2cp) { - - /* If not in stopped state then disables the I2C clock.*/ - if (i2cp->state != I2C_STOP) { - - /* I2C disable.*/ - i2c_lld_abort_operation(i2cp); - dmaStreamRelease(i2cp->dmatx); - dmaStreamRelease(i2cp->dmarx); - -#if STM32_I2C_USE_I2C1 - if (&I2CD1 == i2cp) { - nvicDisableVector(I2C1_EV_IRQn); - nvicDisableVector(I2C1_ER_IRQn); - rccDisableI2C1(FALSE); - } -#endif - -#if STM32_I2C_USE_I2C2 - if (&I2CD2 == i2cp) { - nvicDisableVector(I2C2_EV_IRQn); - nvicDisableVector(I2C2_ER_IRQn); - rccDisableI2C2(FALSE); - } -#endif - -#if STM32_I2C_USE_I2C3 - if (&I2CD3 == i2cp) { - nvicDisableVector(I2C3_EV_IRQn); - nvicDisableVector(I2C3_ER_IRQn); - rccDisableI2C3(FALSE); - } -#endif - } -} - -/** - * @brief Receives data via the I2C bus as master. - * @details Number of receiving bytes must be more than 1 on STM32F1x. This is - * hardware restriction. - * - * @param[in] i2cp pointer to the @p I2CDriver object - * @param[in] addr slave device address - * @param[out] rxbuf pointer to the receive buffer - * @param[in] rxbytes number of bytes to be received - * @param[in] timeout the number of ticks before the operation timeouts, - * the following special values are allowed: - * - @a TIME_INFINITE no timeout. - * . - * @return The operation status. - * @retval MSG_OK if the function succeeded. - * @retval MSG_RESET if one or more I2C errors occurred, the errors can - * be retrieved using @p i2cGetErrors(). - * @retval MSG_TIMEOUT if a timeout occurred before operation end. After a - * timeout the driver must be stopped and restarted - * because the bus is in an uncertain state. - * - * @notapi - */ -msg_t i2c_lld_master_receive_timeout(I2CDriver *i2cp, i2caddr_t addr, - uint8_t *rxbuf, size_t rxbytes, - systime_t timeout) { - I2C_TypeDef *dp = i2cp->i2c; - systime_t start, end; - -#if defined(STM32F1XX_I2C) - osalDbgCheck((rxbytes > 1), "i2c_lld_master_receive_timeout"); -#endif - - /* Resetting error flags for this transfer.*/ - i2cp->errors = I2C_NO_ERROR; - - /* Initializes driver fields, LSB = 1 -> receive.*/ - i2cp->addr = (addr << 1) | 0x01; - - /* Releases the lock from high level driver.*/ - osalSysUnlock(); - - /* RX DMA setup.*/ - dmaStreamSetMode(i2cp->dmarx, i2cp->rxdmamode); - dmaStreamSetMemory0(i2cp->dmarx, rxbuf); - dmaStreamSetTransactionSize(i2cp->dmarx, rxbytes); - - /* Calculating the time window for the timeout on the busy bus condition.*/ - start = osalOsGetSystemTimeX(); - end = start + OSAL_MS2ST(STM32_I2C_BUSY_TIMEOUT); - - /* Waits until BUSY flag is reset or, alternatively, for a timeout - condition.*/ - while (true) { - osalSysLock(); - - /* If the bus is not busy then the operation can continue, note, the - loop is exited in the locked state.*/ - if (!(dp->SR2 & I2C_SR2_BUSY) && !(dp->CR1 & I2C_CR1_STOP)) - break; - - /* If the system time went outside the allowed window then a timeout - condition is returned.*/ - if (!osalOsIsTimeWithinX(osalOsGetSystemTimeX(), start, end)) - return MSG_TIMEOUT; - - osalSysUnlock(); - } - - /* This lock will be released in high level driver.*/ - osalSysLock(); - - /* Starts the operation.*/ - dp->CR2 |= I2C_CR2_ITEVTEN; - dp->CR1 |= I2C_CR1_START | I2C_CR1_ACK; - - /* Waits for the operation completion or a timeout.*/ - return osalThreadSuspendTimeoutS(&i2cp->thread, timeout); -} - -/** - * @brief Transmits data via the I2C bus as master. - * @details Number of receiving bytes must be 0 or more than 1 on STM32F1x. - * This is hardware restriction. - * - * @param[in] i2cp pointer to the @p I2CDriver object - * @param[in] addr slave device address - * @param[in] txbuf pointer to the transmit buffer - * @param[in] txbytes number of bytes to be transmitted - * @param[out] rxbuf pointer to the receive buffer - * @param[in] rxbytes number of bytes to be received - * @param[in] timeout the number of ticks before the operation timeouts, - * the following special values are allowed: - * - @a TIME_INFINITE no timeout. - * . - * @return The operation status. - * @retval MSG_OK if the function succeeded. - * @retval MSG_RESET if one or more I2C errors occurred, the errors can - * be retrieved using @p i2cGetErrors(). - * @retval MSG_TIMEOUT if a timeout occurred before operation end. After a - * timeout the driver must be stopped and restarted - * because the bus is in an uncertain state. - * - * @notapi - */ -msg_t i2c_lld_master_transmit_timeout(I2CDriver *i2cp, i2caddr_t addr, - const uint8_t *txbuf, size_t txbytes, - uint8_t *rxbuf, size_t rxbytes, - systime_t timeout) { - I2C_TypeDef *dp = i2cp->i2c; - systime_t start, end; - -#if defined(STM32F1XX_I2C) - osalDbgCheck(((rxbytes == 0) || ((rxbytes > 1) && (rxbuf != NULL)))); -#endif - - /* Resetting error flags for this transfer.*/ - i2cp->errors = I2C_NO_ERROR; - - /* Initializes driver fields, LSB = 1 -> receive.*/ - i2cp->addr = (addr << 1) | 0x01; - - /* Releases the lock from high level driver.*/ - osalSysUnlock(); - - /* TX DMA setup.*/ - dmaStreamSetMode(i2cp->dmatx, i2cp->txdmamode); - dmaStreamSetMemory0(i2cp->dmatx, txbuf); - dmaStreamSetTransactionSize(i2cp->dmatx, txbytes); - - /* RX DMA setup.*/ - dmaStreamSetMode(i2cp->dmarx, i2cp->rxdmamode); - dmaStreamSetMemory0(i2cp->dmarx, rxbuf); - dmaStreamSetTransactionSize(i2cp->dmarx, rxbytes); - - /* Calculating the time window for the timeout on the busy bus condition.*/ - start = osalOsGetSystemTimeX(); - end = start + OSAL_MS2ST(STM32_I2C_BUSY_TIMEOUT); - - /* Waits until BUSY flag is reset or, alternatively, for a timeout - condition.*/ - while (true) { - osalSysLock(); - - /* If the bus is not busy then the operation can continue, note, the - loop is exited in the locked state.*/ - if (!(dp->SR2 & I2C_SR2_BUSY) && !(dp->CR1 & I2C_CR1_STOP)) - break; - - /* If the system time went outside the allowed window then a timeout - condition is returned.*/ - if (!osalOsIsTimeWithinX(osalOsGetSystemTimeX(), start, end)) - return MSG_TIMEOUT; - - osalSysUnlock(); - } - - /* This lock will be released in high level driver.*/ - osalSysLock(); - - /* Starts the operation.*/ - dp->CR2 |= I2C_CR2_ITEVTEN; - dp->CR1 |= I2C_CR1_START; - - /* Waits for the operation completion or a timeout.*/ - return osalThreadSuspendTimeoutS(&i2cp->thread, timeout); -} - -#endif /* HAL_USE_I2C */ - -/** @} */ diff --git a/os/hal/platforms/STM32/I2Cv1/i2c_lld.h b/os/hal/platforms/STM32/I2Cv1/i2c_lld.h deleted file mode 100644 index a92e48e26..000000000 --- a/os/hal/platforms/STM32/I2Cv1/i2c_lld.h +++ /dev/null @@ -1,466 +0,0 @@ -/* - ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ -/* - Concepts and parts of this file have been contributed by Uladzimir Pylinsky - aka barthess. - */ - -/** - * @file STM32/I2Cv1/i2c_lld.h - * @brief STM32 I2C subsystem low level driver header. - * - * @addtogroup I2C - * @{ - */ - -#ifndef _I2C_LLD_H_ -#define _I2C_LLD_H_ - -#if HAL_USE_I2C || defined(__DOXYGEN__) - -/*===========================================================================*/ -/* Driver constants. */ -/*===========================================================================*/ - -/** - * @brief Peripheral clock frequency. - */ -#define I2C_CLK_FREQ ((STM32_PCLK1) / 1000000) - -/*===========================================================================*/ -/* Driver pre-compile time settings. */ -/*===========================================================================*/ - -/** - * @name Configuration options - * @{ - */ -/** - * @brief I2C1 driver enable switch. - * @details If set to @p TRUE the support for I2C1 is included. - * @note The default is @p FALSE. - */ -#if !defined(STM32_I2C_USE_I2C1) || defined(__DOXYGEN__) -#define STM32_I2C_USE_I2C1 FALSE -#endif - -/** - * @brief I2C2 driver enable switch. - * @details If set to @p TRUE the support for I2C2 is included. - * @note The default is @p FALSE. - */ -#if !defined(STM32_I2C_USE_I2C2) || defined(__DOXYGEN__) -#define STM32_I2C_USE_I2C2 FALSE -#endif - -/** - * @brief I2C3 driver enable switch. - * @details If set to @p TRUE the support for I2C3 is included. - * @note The default is @p FALSE. - */ -#if !defined(STM32_I2C_USE_I2C3) || defined(__DOXYGEN__) -#define STM32_I2C_USE_I2C3 FALSE -#endif - -/** - * @brief I2C timeout on busy condition in milliseconds. - */ -#if !defined(STM32_I2C_BUSY_TIMEOUT) || defined(__DOXYGEN__) -#define STM32_I2C_BUSY_TIMEOUT 50 -#endif - -/** - * @brief I2C1 interrupt priority level setting. - */ -#if !defined(STM32_I2C_I2C1_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_I2C_I2C1_IRQ_PRIORITY 10 -#endif - -/** - * @brief I2C2 interrupt priority level setting. - */ -#if !defined(STM32_I2C_I2C2_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_I2C_I2C2_IRQ_PRIORITY 10 -#endif - -/** - * @brief I2C3 interrupt priority level setting. - */ -#if !defined(STM32_I2C_I2C3_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_I2C_I2C3_IRQ_PRIORITY 10 -#endif - -/** -* @brief I2C1 DMA priority (0..3|lowest..highest). -* @note The priority level is used for both the TX and RX DMA streams but -* because of the streams ordering the RX stream has always priority -* over the TX stream. -*/ -#if !defined(STM32_I2C_I2C1_DMA_PRIORITY) || defined(__DOXYGEN__) -#define STM32_I2C_I2C1_DMA_PRIORITY 1 -#endif - -/** -* @brief I2C2 DMA priority (0..3|lowest..highest). -* @note The priority level is used for both the TX and RX DMA streams but -* because of the streams ordering the RX stream has always priority -* over the TX stream. -*/ -#if !defined(STM32_I2C_I2C2_DMA_PRIORITY) || defined(__DOXYGEN__) -#define STM32_I2C_I2C2_DMA_PRIORITY 1 -#endif - -/** -* @brief I2C3 DMA priority (0..3|lowest..highest). -* @note The priority level is used for both the TX and RX DMA streams but -* because of the streams ordering the RX stream has always priority -* over the TX stream. -*/ -#if !defined(STM32_I2C_I2C3_DMA_PRIORITY) || defined(__DOXYGEN__) -#define STM32_I2C_I2C3_DMA_PRIORITY 1 -#endif - -/** - * @brief I2C DMA error hook. - * @note The default action for DMA errors is a system halt because DMA - * error can only happen because programming errors. - */ -#if !defined(STM32_I2C_DMA_ERROR_HOOK) || defined(__DOXYGEN__) -#define STM32_I2C_DMA_ERROR_HOOK(i2cp) chSysHalt("DMA failure") -#endif - -#if STM32_ADVANCED_DMA || defined(__DOXYGEN__) - -/** - * @brief DMA stream used for I2C1 RX operations. - * @note This option is only available on platforms with enhanced DMA. - */ -#if !defined(STM32_I2C_I2C1_RX_DMA_STREAM) || defined(__DOXYGEN__) -#define STM32_I2C_I2C1_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 0) -#endif - -/** - * @brief DMA stream used for I2C1 TX operations. - * @note This option is only available on platforms with enhanced DMA. - */ -#if !defined(STM32_I2C_I2C1_TX_DMA_STREAM) || defined(__DOXYGEN__) -#define STM32_I2C_I2C1_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 6) -#endif - -/** - * @brief DMA stream used for I2C2 RX operations. - * @note This option is only available on platforms with enhanced DMA. - */ -#if !defined(STM32_I2C_I2C2_RX_DMA_STREAM) || defined(__DOXYGEN__) -#define STM32_I2C_I2C2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2) -#endif - -/** - * @brief DMA stream used for I2C2 TX operations. - * @note This option is only available on platforms with enhanced DMA. - */ -#if !defined(STM32_I2C_I2C2_TX_DMA_STREAM) || defined(__DOXYGEN__) -#define STM32_I2C_I2C2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7) -#endif - -/** - * @brief DMA stream used for I2C3 RX operations. - * @note This option is only available on platforms with enhanced DMA. - */ -#if !defined(STM32_I2C_I2C3_RX_DMA_STREAM) || defined(__DOXYGEN__) -#define STM32_I2C_I2C3_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2) -#endif - -/** - * @brief DMA stream used for I2C3 TX operations. - * @note This option is only available on platforms with enhanced DMA. - */ -#if !defined(STM32_I2C_I2C3_TX_DMA_STREAM) || defined(__DOXYGEN__) -#define STM32_I2C_I2C3_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) -#endif - -#else /* !STM32_ADVANCED_DMA */ - -/* Fixed streams for platforms using the old DMA peripheral, the values are - valid for both STM32F1xx and STM32L1xx.*/ -#define STM32_I2C_I2C1_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7) -#define STM32_I2C_I2C1_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 6) -#define STM32_I2C_I2C2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 5) -#define STM32_I2C_I2C2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) - -#endif /* !STM32_ADVANCED_DMA*/ - -/* Flag for the whole STM32F1XX family. */ -#if defined(STM32F10X_LD_VL) || defined(STM32F10X_MD_VL) || \ - defined(STM32F10X_LD) || defined(STM32F10X_MD) || \ - defined(STM32F10X_HD) || defined(STM32F10X_XL) || \ - defined(STM32F10X_CL) -#define STM32F1XX_I2C -#endif -/** @} */ - -/*===========================================================================*/ -/* Derived constants and error checks. */ -/*===========================================================================*/ - -/** @brief error checks */ -#if STM32_I2C_USE_I2C1 && !STM32_HAS_I2C1 -#error "I2C1 not present in the selected device" -#endif - -#if STM32_I2C_USE_I2C2 && !STM32_HAS_I2C2 -#error "I2C2 not present in the selected device" -#endif - -#if STM32_I2C_USE_I2C3 && !STM32_HAS_I2C3 -#error "I2C3 not present in the selected device" -#endif - -#if !STM32_I2C_USE_I2C1 && !STM32_I2C_USE_I2C2 && \ - !STM32_I2C_USE_I2C3 -#error "I2C driver activated but no I2C peripheral assigned" -#endif - -#if STM32_I2C_USE_I2C1 && \ - !STM32_DMA_IS_VALID_ID(STM32_I2C_I2C1_RX_DMA_STREAM, \ - STM32_I2C1_RX_DMA_MSK) -#error "invalid DMA stream associated to I2C1 RX" -#endif - -#if STM32_I2C_USE_I2C1 && \ - !STM32_DMA_IS_VALID_ID(STM32_I2C_I2C1_TX_DMA_STREAM, \ - STM32_I2C1_TX_DMA_MSK) -#error "invalid DMA stream associated to I2C1 TX" -#endif - -#if STM32_I2C_USE_I2C2 && \ - !STM32_DMA_IS_VALID_ID(STM32_I2C_I2C2_RX_DMA_STREAM, \ - STM32_I2C2_RX_DMA_MSK) -#error "invalid DMA stream associated to I2C2 RX" -#endif - -#if STM32_I2C_USE_I2C2 && \ - !STM32_DMA_IS_VALID_ID(STM32_I2C_I2C2_TX_DMA_STREAM, \ - STM32_I2C2_TX_DMA_MSK) -#error "invalid DMA stream associated to I2C2 TX" -#endif - -#if STM32_I2C_USE_I2C3 && \ - !STM32_DMA_IS_VALID_ID(STM32_I2C_I2C3_RX_DMA_STREAM, \ - STM32_I2C3_RX_DMA_MSK) -#error "invalid DMA stream associated to I2C3 RX" -#endif - -#if STM32_I2C_USE_I2C3 && \ - !STM32_DMA_IS_VALID_ID(STM32_I2C_I2C3_TX_DMA_STREAM, \ - STM32_I2C3_TX_DMA_MSK) -#error "invalid DMA stream associated to I2C3 TX" -#endif - -#if !defined(STM32_DMA_REQUIRED) -#define STM32_DMA_REQUIRED -#endif - -/* Check clock range. */ -#if defined(STM32F4XX) -#if !(I2C_CLK_FREQ >= 2) && (I2C_CLK_FREQ <= 42) -#error "I2C peripheral clock frequency out of range." -#endif - -#elif defined(STM32L1XX_MD) -#if !(I2C_CLK_FREQ >= 2) && (I2C_CLK_FREQ <= 32) -#error "I2C peripheral clock frequency out of range." -#endif - -#elif defined(STM32F2XX) -#if !(I2C_CLK_FREQ >= 2) && (I2C_CLK_FREQ <= 30) -#error "I2C peripheral clock frequency out of range." -#endif - -#elif defined(STM32F10X_LD_VL) || defined(STM32F10X_MD_VL) || \ - defined(STM32F10X_HD_VL) -#if !(I2C_CLK_FREQ >= 2) && (I2C_CLK_FREQ <= 24) -#error "I2C peripheral clock frequency out of range." -#endif - -#elif defined(STM32F10X_LD) || defined(STM32F10X_MD) || \ - defined(STM32F10X_HD) || defined(STM32F10X_XL) || \ - defined(STM32F10X_CL) -#if !(I2C_CLK_FREQ >= 2) && (I2C_CLK_FREQ <= 36) -#error "I2C peripheral clock frequency out of range." -#endif -#else -#error "unspecified, unsupported or invalid STM32 platform" -#endif - -/*===========================================================================*/ -/* Driver data structures and types. */ -/*===========================================================================*/ - -/** - * @brief Type representing I2C address. - */ -typedef uint16_t i2caddr_t; - -/** - * @brief I2C Driver condition flags type. - */ -typedef uint32_t i2cflags_t; - -/** - * @brief Supported modes for the I2C bus. - */ -typedef enum { - OPMODE_I2C = 1, - OPMODE_SMBUS_DEVICE = 2, - OPMODE_SMBUS_HOST = 3, -} i2copmode_t; - -/** - * @brief Supported duty cycle modes for the I2C bus. - */ -typedef enum { - STD_DUTY_CYCLE = 1, - FAST_DUTY_CYCLE_2 = 2, - FAST_DUTY_CYCLE_16_9 = 3, -} i2cdutycycle_t; - -/** - * @brief Driver configuration structure. - */ -typedef struct { - i2copmode_t op_mode; /**< @brief Specifies the I2C mode. */ - uint32_t clock_speed; /**< @brief Specifies the clock frequency. - @note Must be set to a value lower - than 400kHz. */ - i2cdutycycle_t duty_cycle; /**< @brief Specifies the I2C fast mode - duty cycle. */ -} I2CConfig; - -/** - * @brief Type of a structure representing an I2C driver. - */ -typedef struct I2CDriver I2CDriver; - -/** - * @brief Structure representing an I2C driver. - */ -struct I2CDriver { - /** - * @brief Driver state. - */ - i2cstate_t state; - /** - * @brief Current configuration data. - */ - const I2CConfig *config; - /** - * @brief Error flags. - */ - i2cflags_t errors; -#if I2C_USE_MUTUAL_EXCLUSION || defined(__DOXYGEN__) - /** - * @brief Mutex protecting the bus. - */ - mutex_t mutex; -#endif /* I2C_USE_MUTUAL_EXCLUSION */ -#if defined(I2C_DRIVER_EXT_FIELDS) - I2C_DRIVER_EXT_FIELDS -#endif - /* End of the mandatory fields.*/ - /** - * @brief Thread waiting for I/O completion. - */ - thread_reference_t thread; - /** - * @brief Current slave address without R/W bit. - */ - i2caddr_t addr; - /** - * @brief RX DMA mode bit mask. - */ - uint32_t rxdmamode; - /** - * @brief TX DMA mode bit mask. - */ - uint32_t txdmamode; - /** - * @brief Receive DMA channel. - */ - const stm32_dma_stream_t *dmarx; - /** - * @brief Transmit DMA channel. - */ - const stm32_dma_stream_t *dmatx; - /** - * @brief Pointer to the I2Cx registers block. - */ - I2C_TypeDef *i2c; -}; - -/*===========================================================================*/ -/* Driver macros. */ -/*===========================================================================*/ - -/** - * @brief Get errors from I2C driver. - * - * @param[in] i2cp pointer to the @p I2CDriver object - * - * @notapi - */ -#define i2c_lld_get_errors(i2cp) ((i2cp)->errors) - -/*===========================================================================*/ -/* External declarations. */ -/*===========================================================================*/ - -#if !defined(__DOXYGEN__) -#if STM32_I2C_USE_I2C1 -extern I2CDriver I2CD1; -#endif - -#if STM32_I2C_USE_I2C2 -extern I2CDriver I2CD2; -#endif - -#if STM32_I2C_USE_I2C3 -extern I2CDriver I2CD3; -#endif -#endif /* !defined(__DOXYGEN__) */ - -#ifdef __cplusplus -extern "C" { -#endif - void i2c_lld_init(void); - void i2c_lld_start(I2CDriver *i2cp); - void i2c_lld_stop(I2CDriver *i2cp); - msg_t i2c_lld_master_transmit_timeout(I2CDriver *i2cp, i2caddr_t addr, - const uint8_t *txbuf, size_t txbytes, - uint8_t *rxbuf, size_t rxbytes, - systime_t timeout); - msg_t i2c_lld_master_receive_timeout(I2CDriver *i2cp, i2caddr_t addr, - uint8_t *rxbuf, size_t rxbytes, - systime_t timeout); -#ifdef __cplusplus -} -#endif - -#endif /* HAL_USE_I2C */ - -#endif /* _I2C_LLD_H_ */ - -/** @} */ diff --git a/os/hal/platforms/STM32/I2Cv2/i2c_lld.c b/os/hal/platforms/STM32/I2Cv2/i2c_lld.c deleted file mode 100644 index 249a6f54b..000000000 --- a/os/hal/platforms/STM32/I2Cv2/i2c_lld.c +++ /dev/null @@ -1,720 +0,0 @@ -/* - ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file STM32/I2Cv2/i2c_lld.c - * @brief STM32 I2C subsystem low level driver source. - * - * @addtogroup I2C - * @{ - */ - -#include "hal.h" - -#if HAL_USE_I2C || defined(__DOXYGEN__) - -/*===========================================================================*/ -/* Driver local definitions. */ -/*===========================================================================*/ - -#define DMAMODE_COMMON \ - (STM32_DMA_CR_PSIZE_BYTE | STM32_DMA_CR_MSIZE_BYTE | \ - STM32_DMA_CR_MINC | STM32_DMA_CR_DMEIE | \ - STM32_DMA_CR_TEIE | STM32_DMA_CR_TCIE) - -#define I2C1_RX_DMA_CHANNEL \ - STM32_DMA_GETCHANNEL(STM32_I2C_I2C1_RX_DMA_STREAM, \ - STM32_I2C1_RX_DMA_CHN) - -#define I2C1_TX_DMA_CHANNEL \ - STM32_DMA_GETCHANNEL(STM32_I2C_I2C1_TX_DMA_STREAM, \ - STM32_I2C1_TX_DMA_CHN) - -#define I2C2_RX_DMA_CHANNEL \ - STM32_DMA_GETCHANNEL(STM32_I2C_I2C2_RX_DMA_STREAM, \ - STM32_I2C2_RX_DMA_CHN) - -#define I2C2_TX_DMA_CHANNEL \ - STM32_DMA_GETCHANNEL(STM32_I2C_I2C2_TX_DMA_STREAM, \ - STM32_I2C2_TX_DMA_CHN) - -/*===========================================================================*/ -/* Driver constants. */ -/*===========================================================================*/ - -#define I2C_MASTER_TC \ - ((uint32_t)(I2C_ISR_BUSY | I2C_ISR_TC)) - -#define I2C_ERROR_MASK \ - ((uint32_t)(I2C_ISR_BERR | I2C_ISR_ARLO | I2C_ISR_OVR | I2C_ISR_PECERR | \ - I2C_ISR_TIMEOUT | I2C_ISR_ALERT)) - -#define I2C_INT_MASK \ - ((uint32_t)(I2C_ISR_TCR | I2C_ISR_TC | I2C_ISR_STOPF | I2C_ISR_NACKF | \ - I2C_ISR_ADDR | I2C_ISR_RXNE | I2C_ISR_TXIS)) - -/*===========================================================================*/ -/* Driver exported variables. */ -/*===========================================================================*/ - -/** @brief I2C1 driver identifier.*/ -#if STM32_I2C_USE_I2C1 || defined(__DOXYGEN__) -I2CDriver I2CD1; -#endif - -/** @brief I2C2 driver identifier.*/ -#if STM32_I2C_USE_I2C2 || defined(__DOXYGEN__) -I2CDriver I2CD2; -#endif - -/*===========================================================================*/ -/* Driver local variables. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver local functions. */ -/*===========================================================================*/ - -/** - * @brief Aborts an I2C transaction. - * - * @param[in] i2cp pointer to the @p I2CDriver object - * - * @notapi - */ -static void i2c_lld_abort_operation(I2CDriver *i2cp) { - I2C_TypeDef *dp = i2cp->i2c; - - if (dp->CR1 & I2C_CR1_PE) { - /* Stops the I2C peripheral.*/ - dp->CR1 &= ~I2C_CR1_PE; - while (dp->CR1 & I2C_CR1_PE) - dp->CR1 &= ~I2C_CR1_PE; - dp->CR1 |= I2C_CR1_PE; - } - - /* Stops the associated DMA streams.*/ - dmaStreamDisable(i2cp->dmatx); - dmaStreamDisable(i2cp->dmarx); -} - -/** - * @brief I2C shared ISR code. - * - * @param[in] i2cp pointer to the @p I2CDriver object - * @param[in] isr content of the ISR register to be decoded - * - * @notapi - */ -static void i2c_lld_serve_interrupt(I2CDriver *i2cp, uint32_t isr) { - I2C_TypeDef *dp = i2cp->i2c; - - if ((isr & I2C_ISR_TC) && (i2cp->state == I2C_ACTIVE_TX)) { - size_t rxbytes; - - /* Make sure no more 'Transfer complete' interrupts.*/ - dp->CR1 &= ~I2C_CR1_TCIE; - - rxbytes = dmaStreamGetTransactionSize(i2cp->dmarx); - if (rxbytes > 0) { - i2cp->state = I2C_ACTIVE_RX; - - /* Enable RX DMA */ - dmaStreamEnable(i2cp->dmarx); - - dp->CR2 &= ~I2C_CR2_NBYTES; - dp->CR2 |= rxbytes << 16; - - /* Starts the read operation.*/ - dp->CR2 |= I2C_CR2_RD_WRN; - dp->CR2 |= I2C_CR2_START; - } - else { - /* Nothing to receive - send STOP immediately.*/ - dp->CR2 |= I2C_CR2_STOP; - } - } - if (isr & I2C_ISR_NACKF) { - /* Starts a STOP sequence immediately on error.*/ - dp->CR2 |= I2C_CR2_STOP; - - i2cp->errors |= I2C_ACK_FAILURE; - } - if (isr & I2C_ISR_STOPF) { - /* Stops the associated DMA streams.*/ - dmaStreamDisable(i2cp->dmatx); - dmaStreamDisable(i2cp->dmarx); - - /* The wake up message depends on the presence of errors.*/ - if (i2cp->errors) - _i2c_wakeup_error_isr(i2cp); - else - _i2c_wakeup_isr(i2cp); - } -} - -/** - * @brief DMA RX end IRQ handler. - * - * @param[in] i2cp pointer to the @p I2CDriver object - * @param[in] flags pre-shifted content of the ISR register - * - * @notapi - */ -static void i2c_lld_serve_rx_end_irq(I2CDriver *i2cp, uint32_t flags) { - I2C_TypeDef *dp = i2cp->i2c; - - /* DMA errors handling.*/ -#if defined(STM32_I2C_DMA_ERROR_HOOK) - if ((flags & (STM32_DMA_ISR_TEIF | STM32_DMA_ISR_DMEIF)) != 0) { - STM32_I2C_DMA_ERROR_HOOK(i2cp); - } -#else - (void)flags; -#endif - - dmaStreamDisable(i2cp->dmarx); - dp->CR2 |= I2C_CR2_STOP; - _i2c_wakeup_isr(i2cp); -} - -/** - * @brief DMA TX end IRQ handler. - * - * @param[in] i2cp pointer to the @p I2CDriver object - * - * @notapi - */ -static void i2c_lld_serve_tx_end_irq(I2CDriver *i2cp, uint32_t flags) { - - /* DMA errors handling.*/ -#if defined(STM32_I2C_DMA_ERROR_HOOK) - if ((flags & (STM32_DMA_ISR_TEIF | STM32_DMA_ISR_DMEIF)) != 0) { - STM32_I2C_DMA_ERROR_HOOK(i2cp); - } -#else - (void)flags; -#endif - - dmaStreamDisable(i2cp->dmatx); -} - -/** - * @brief I2C error handler. - * - * @param[in] i2cp pointer to the @p I2CDriver object - * @param[in] isr content of the ISR register to be decoded - * - * @notapi - */ -static void i2c_lld_serve_error_interrupt(I2CDriver *i2cp, uint32_t isr) { - - /* Clears interrupt flags just to be safe.*/ - dmaStreamDisable(i2cp->dmatx); - dmaStreamDisable(i2cp->dmarx); - - if (isr & I2C_ISR_BERR) - i2cp->errors |= I2C_BUS_ERROR; - - if (isr & I2C_ISR_ARLO) - i2cp->errors |= I2C_ARBITRATION_LOST; - - if (isr & I2C_ISR_OVR) - i2cp->errors |= I2C_OVERRUN; - - if (isr & I2C_ISR_TIMEOUT) - i2cp->errors |= I2C_TIMEOUT; - - /* If some error has been identified then sends wakes the waiting thread.*/ - if (i2cp->errors != I2C_NO_ERROR) - _i2c_wakeup_error_isr(i2cp); -} - -/*===========================================================================*/ -/* Driver interrupt handlers. */ -/*===========================================================================*/ - -#if STM32_I2C_USE_I2C1 || defined(__DOXYGEN__) -#if defined(STM32_I2C1_GLOBAL_HANDLER) || defined(__DOXYGEN__) -/** - * @brief I2C1 event interrupt handler. - * - * @notapi - */ -CH_IRQ_HANDLER(STM32_I2C1_GLOBAL_HANDLER) { - uint32_t isr = I2CD1.i2c->ISR; - - CH_IRQ_PROLOGUE(); - - /* Clearing IRQ bits.*/ - I2CD1.i2c->ICR = isr; - - if (isr & I2C_ERROR_MASK) - i2c_lld_serve_error_interrupt(&I2CD1, isr); - else if (isr & I2C_INT_MASK) - i2c_lld_serve_interrupt(&I2CD1, isr); - - CH_IRQ_EPILOGUE(); -} - -#elif defined(STM32_I2C1_EVENT_HANDLER) && defined(STM32_I2C1_ERROR_HANDLER) -CH_IRQ_HANDLER(STM32_I2C1_EVENT_HANDLER) { - uint32_t isr = I2CD1.i2c->ISR; - - CH_IRQ_PROLOGUE(); - - /* Clearing IRQ bits.*/ - I2CD1.i2c->ICR = isr & I2C_INT_MASK; - - i2c_lld_serve_interrupt(&I2CD1, isr); - - CH_IRQ_EPILOGUE(); -} - -CH_IRQ_HANDLER(STM32_I2C1_ERROR_HANDLER) { - uint32_t isr = I2CD1.i2c->ISR; - - CH_IRQ_PROLOGUE(); - - /* Clearing IRQ bits.*/ - I2CD1.i2c->ICR = isr & I2C_ERROR_MASK; - - i2c_lld_serve_error_interrupt(&I2CD1, isr); - - CH_IRQ_EPILOGUE(); -} - -#else -#error "I2C1 interrupt handlers not defined" -#endif -#endif /* STM32_I2C_USE_I2C1 */ - -#if STM32_I2C_USE_I2C2 || defined(__DOXYGEN__) -#if defined(STM32_I2C2_GLOBAL_HANDLER) || defined(__DOXYGEN__) -/** - * @brief I2C2 event interrupt handler. - * - * @notapi - */ -CH_IRQ_HANDLER(STM32_I2C2_GLOBAL_HANDLER) { - uint32_t isr = I2CD2.i2c->ISR; - - CH_IRQ_PROLOGUE(); - - /* Clearing IRQ bits.*/ - I2CD2.i2c->ICR = isr; - - if (isr & I2C_ERROR_MASK) - i2c_lld_serve_error_interrupt(&I2CD2, isr); - else if (isr & I2C_INT_MASK) - i2c_lld_serve_interrupt(&I2CD2, isr); - - CH_IRQ_EPILOGUE(); -} - -#elif defined(STM32_I2C2_EVENT_HANDLER) && defined(STM32_I2C2_ERROR_HANDLER) -CH_IRQ_HANDLER(STM32_I2C2_EVENT_HANDLER) { - uint32_t isr = I2CD2.i2c->ISR; - - CH_IRQ_PROLOGUE(); - - /* Clearing IRQ bits.*/ - I2CD2.i2c->ICR = isr & I2C_INT_MASK; - - i2c_lld_serve_interrupt(&I2CD2, isr); - - CH_IRQ_EPILOGUE(); -} - -CH_IRQ_HANDLER(STM32_I2C2_ERROR_HANDLER) { - uint32_t isr = I2CD2.i2c->ISR; - - CH_IRQ_PROLOGUE(); - - /* Clearing IRQ bits.*/ - I2CD2.i2c->ICR = isr & I2C_ERROR_MASK; - - i2c_lld_serve_error_interrupt(&I2CD2, isr); - - CH_IRQ_EPILOGUE(); -} - -#else -#error "I2C2 interrupt handlers not defined" -#endif -#endif /* STM32_I2C_USE_I2C2 */ - -/*===========================================================================*/ -/* Driver exported functions. */ -/*===========================================================================*/ - -/** - * @brief Low level I2C driver initialization. - * - * @notapi - */ -void i2c_lld_init(void) { - -#if STM32_I2C_USE_I2C1 - i2cObjectInit(&I2CD1); - I2CD1.thread = NULL; - I2CD1.i2c = I2C1; - I2CD1.dmarx = STM32_DMA_STREAM(STM32_I2C_I2C1_RX_DMA_STREAM); - I2CD1.dmatx = STM32_DMA_STREAM(STM32_I2C_I2C1_TX_DMA_STREAM); -#endif /* STM32_I2C_USE_I2C1 */ - -#if STM32_I2C_USE_I2C2 - i2cObjectInit(&I2CD2); - I2CD2.thread = NULL; - I2CD2.i2c = I2C2; - I2CD2.dmarx = STM32_DMA_STREAM(STM32_I2C_I2C2_RX_DMA_STREAM); - I2CD2.dmatx = STM32_DMA_STREAM(STM32_I2C_I2C2_TX_DMA_STREAM); -#endif /* STM32_I2C_USE_I2C2 */ -} - -/** - * @brief Configures and activates the I2C peripheral. - * - * @param[in] i2cp pointer to the @p I2CDriver object - * - * @notapi - */ -void i2c_lld_start(I2CDriver *i2cp) { - I2C_TypeDef *dp = i2cp->i2c; - - i2cp->txdmamode = DMAMODE_COMMON | STM32_DMA_CR_DIR_M2P; - i2cp->rxdmamode = DMAMODE_COMMON | STM32_DMA_CR_DIR_P2M; - - /* Make sure I2C peripheral is disabled */ - dp->CR1 &= ~I2C_CR1_PE; - - /* If in stopped state then enables the I2C and DMA clocks.*/ - if (i2cp->state == I2C_STOP) { - -#if STM32_I2C_USE_I2C1 - if (&I2CD1 == i2cp) { - bool b; - - rccResetI2C1(); - b = dmaStreamAllocate(i2cp->dmarx, - STM32_I2C_I2C1_IRQ_PRIORITY, - (stm32_dmaisr_t)i2c_lld_serve_rx_end_irq, - (void *)i2cp); - osalDbgAssert(!b, "stream already allocated"); - b = dmaStreamAllocate(i2cp->dmatx, - STM32_I2C_I2C1_IRQ_PRIORITY, - (stm32_dmaisr_t)i2c_lld_serve_tx_end_irq, - (void *)i2cp); - osalDbgAssert(!b, "stream already allocated"); - rccEnableI2C1(FALSE); - -#if defined(STM32_I2C1_GLOBAL_NUMBER) || defined(__DOXYGEN__) - nvicEnableVector(STM32_I2C1_GLOBAL_NUMBER, - CORTEX_PRIORITY_MASK(STM32_I2C_I2C1_IRQ_PRIORITY)); -#elif defined(STM32_I2C1_EVENT_NUMBER) && defined(STM32_I2C1_ERROR_NUMBER) - nvicEnableVector(STM32_I2C1_EVENT_NUMBER, STM32_I2C_I2C1_IRQ_PRIORITY); - nvicEnableVector(STM32_I2C1_ERROR_NUMBER, STM32_I2C_I2C1_IRQ_PRIORITY); -#else -#error "I2C1 interrupt numbers not defined" -#endif - - i2cp->rxdmamode |= STM32_DMA_CR_CHSEL(I2C1_RX_DMA_CHANNEL) | - STM32_DMA_CR_PL(STM32_I2C_I2C1_DMA_PRIORITY); - i2cp->txdmamode |= STM32_DMA_CR_CHSEL(I2C1_TX_DMA_CHANNEL) | - STM32_DMA_CR_PL(STM32_I2C_I2C1_DMA_PRIORITY); - } -#endif /* STM32_I2C_USE_I2C1 */ - -#if STM32_I2C_USE_I2C2 - if (&I2CD2 == i2cp) { - bool b; - - rccResetI2C2(); - b = dmaStreamAllocate(i2cp->dmarx, - STM32_I2C_I2C2_IRQ_PRIORITY, - (stm32_dmaisr_t)i2c_lld_serve_rx_end_irq, - (void *)i2cp); - osalDbgAssert(!b, "stream already allocated"); - b = dmaStreamAllocate(i2cp->dmatx, - STM32_I2C_I2C2_IRQ_PRIORITY, - (stm32_dmaisr_t)i2c_lld_serve_tx_end_irq, - (void *)i2cp); - osalDbgAssert(!b, "stream already allocated"); - rccEnableI2C2(FALSE); - -#if defined(STM32_I2C2_GLOBAL_NUMBER) || defined(__DOXYGEN__) - nvicEnableVector(STM32_I2C2_GLOBAL_NUMBER, - CORTEX_PRIORITY_MASK(STM32_I2C_I2C2_IRQ_PRIORITY)); -#elif defined(STM32_I2C2_EVENT_NUMBER) && defined(STM32_I2C2_ERROR_NUMBER) - nvicEnableVector(STM32_I2C2_EVENT_NUMBER, STM32_I2C_I2C2_IRQ_PRIORITY); - nvicEnableVector(STM32_I2C2_ERROR_NUMBER, STM32_I2C_I2C2_IRQ_PRIORITY); -#else -#error "I2C2 interrupt numbers not defined" -#endif - - i2cp->rxdmamode |= STM32_DMA_CR_CHSEL(I2C2_RX_DMA_CHANNEL) | - STM32_DMA_CR_PL(STM32_I2C_I2C2_DMA_PRIORITY); - i2cp->txdmamode |= STM32_DMA_CR_CHSEL(I2C2_TX_DMA_CHANNEL) | - STM32_DMA_CR_PL(STM32_I2C_I2C2_DMA_PRIORITY); - } -#endif /* STM32_I2C_USE_I2C2 */ - } - - /* I2C registers pointed by the DMA.*/ - dmaStreamSetPeripheral(i2cp->dmarx, &dp->RXDR); - dmaStreamSetPeripheral(i2cp->dmatx, &dp->TXDR); - - /* Reset i2c peripheral, the TCIE bit will be handled separately.*/ - dp->CR1 = i2cp->config->cr1 | I2C_CR1_ERRIE | I2C_CR1_STOPIE | - I2C_CR1_NACKIE | I2C_CR1_TXDMAEN | I2C_CR1_RXDMAEN; - - /* Set slave address field (master mode) */ - dp->CR2 = (i2cp->config->cr2 & ~I2C_CR2_SADD); - - /* Setup I2C parameters.*/ - dp->TIMINGR = i2cp->config->timingr; - - /* Ready to go.*/ - dp->CR1 |= I2C_CR1_PE; -} - -/** - * @brief Deactivates the I2C peripheral. - * - * @param[in] i2cp pointer to the @p I2CDriver object - * - * @notapi - */ -void i2c_lld_stop(I2CDriver *i2cp) { - - /* If not in stopped state then disables the I2C clock.*/ - if (i2cp->state != I2C_STOP) { - - /* I2C disable.*/ - i2c_lld_abort_operation(i2cp); - dmaStreamRelease(i2cp->dmatx); - dmaStreamRelease(i2cp->dmarx); - -#if STM32_I2C_USE_I2C1 - if (&I2CD1 == i2cp) { -#if defined(STM32_I2C1_GLOBAL_NUMBER) || defined(__DOXYGEN__) - nvicDisableVector(STM32_I2C1_GLOBAL_NUMBER); -#elif defined(STM32_I2C1_EVENT_NUMBER) && defined(STM32_I2C1_ERROR_NUMBER) - nvicDisableVector(STM32_I2C1_EVENT_NUMBER); - nvicDisableVector(STM32_I2C1_ERROR_NUMBER); -#else -#error "I2C1 interrupt numbers not defined" -#endif - - rccDisableI2C1(FALSE); - } -#endif - -#if STM32_I2C_USE_I2C2 - if (&I2CD2 == i2cp) { -#if defined(STM32_I2C2_GLOBAL_NUMBER) || defined(__DOXYGEN__) - nvicDisableVector(STM32_I2C2_GLOBAL_NUMBER); -#elif defined(STM32_I2C2_EVENT_NUMBER) && defined(STM32_I2C2_ERROR_NUMBER) - nvicDisableVector(STM32_I2C2_EVENT_NUMBER); - nvicDisableVector(STM32_I2C2_ERROR_NUMBER); -#else -#error "I2C2 interrupt numbers not defined" -#endif - - rccDisableI2C2(FALSE); - } -#endif - } -} - -/** - * @brief Receives data via the I2C bus as master. - * @details Number of receiving bytes must be more than 1 on STM32F1x. This is - * hardware restriction. - * - * @param[in] i2cp pointer to the @p I2CDriver object - * @param[in] addr slave device address - * @param[out] rxbuf pointer to the receive buffer - * @param[in] rxbytes number of bytes to be received - * @param[in] timeout the number of ticks before the operation timeouts, - * the following special values are allowed: - * - @a TIME_INFINITE no timeout. - * . - * @return The operation status. - * @retval MSG_OK if the function succeeded. - * @retval MSG_RESET if one or more I2C errors occurred, the errors can - * be retrieved using @p i2cGetErrors(). - * @retval MSG_TIMEOUT if a timeout occurred before operation end. After a - * timeout the driver must be stopped and restarted - * because the bus is in an uncertain state. - * - * @notapi - */ -msg_t i2c_lld_master_receive_timeout(I2CDriver *i2cp, i2caddr_t addr, - uint8_t *rxbuf, size_t rxbytes, - systime_t timeout) { - I2C_TypeDef *dp = i2cp->i2c; - uint32_t addr_cr2 = addr & I2C_CR2_SADD; - systime_t start, end; - - /* Resetting error flags for this transfer.*/ - i2cp->errors = I2C_NO_ERROR; - - /* Releases the lock from high level driver.*/ - osalSysUnlock(); - - /* RX DMA setup.*/ - dmaStreamSetMode(i2cp->dmarx, i2cp->rxdmamode); - dmaStreamSetMemory0(i2cp->dmarx, rxbuf); - dmaStreamSetTransactionSize(i2cp->dmarx, rxbytes); - - /* Calculating the time window for the timeout on the busy bus condition.*/ - start = osalOsGetSystemTimeX(); - end = start + OSAL_MS2ST(STM32_I2C_BUSY_TIMEOUT); - - /* Waits until BUSY flag is reset or, alternatively, for a timeout - condition.*/ - while (true) { - osalSysLock(); - - /* If the bus is not busy then the operation can continue, note, the - loop is exited in the locked state.*/ - if ((dp->ISR & I2C_ISR_BUSY) == 0) - break; - - /* If the system time went outside the allowed window then a timeout - condition is returned.*/ - if (!osalOsIsTimeWithinX(osalOsGetSystemTimeX(), start, end)) - return MSG_TIMEOUT; - - osalSysUnlock(); - } - - /* Adjust slave address (master mode) for 7-bit address mode */ - if ((i2cp->config->cr2 & I2C_CR2_ADD10) == 0) - addr_cr2 = (addr_cr2 & 0x7f) << 1; - - /* Set slave address field (master mode) */ - dp->CR2 &= ~(I2C_CR2_SADD | I2C_CR2_NBYTES); - dp->CR2 |= (rxbytes << 16) | addr_cr2; - - /* Enable RX DMA */ - dmaStreamEnable(i2cp->dmarx); - - /* Starts the operation.*/ - dp->CR2 |= I2C_CR2_RD_WRN; - dp->CR2 |= I2C_CR2_START; - - /* Waits for the operation completion or a timeout.*/ - return osalThreadSuspendTimeoutS(&i2cp->thread, timeout); -} - -/** - * @brief Transmits data via the I2C bus as master. - * @details Number of receiving bytes must be 0 or more than 1 on STM32F1x. - * This is hardware restriction. - * - * @param[in] i2cp pointer to the @p I2CDriver object - * @param[in] addr slave device address - * @param[in] txbuf pointer to the transmit buffer - * @param[in] txbytes number of bytes to be transmitted - * @param[out] rxbuf pointer to the receive buffer - * @param[in] rxbytes number of bytes to be received - * @param[in] timeout the number of ticks before the operation timeouts, - * the following special values are allowed: - * - @a TIME_INFINITE no timeout. - * . - * @return The operation status. - * @retval MSG_OK if the function succeeded. - * @retval MSG_RESET if one or more I2C errors occurred, the errors can - * be retrieved using @p i2cGetErrors(). - * @retval MSG_TIMEOUT if a timeout occurred before operation end. After a - * timeout the driver must be stopped and restarted - * because the bus is in an uncertain state. - * - * @notapi - */ -msg_t i2c_lld_master_transmit_timeout(I2CDriver *i2cp, i2caddr_t addr, - const uint8_t *txbuf, size_t txbytes, - uint8_t *rxbuf, size_t rxbytes, - systime_t timeout) { - I2C_TypeDef *dp = i2cp->i2c; - uint32_t addr_cr2 = addr & I2C_CR2_SADD; - systime_t start, end; - - /* Resetting error flags for this transfer.*/ - i2cp->errors = I2C_NO_ERROR; - - /* Releases the lock from high level driver.*/ - osalSysUnlock(); - - /* TX DMA setup.*/ - dmaStreamSetMode(i2cp->dmatx, i2cp->txdmamode); - dmaStreamSetMemory0(i2cp->dmatx, txbuf); - dmaStreamSetTransactionSize(i2cp->dmatx, txbytes); - - /* RX DMA setup.*/ - dmaStreamSetMode(i2cp->dmarx, i2cp->rxdmamode); - dmaStreamSetMemory0(i2cp->dmarx, rxbuf); - dmaStreamSetTransactionSize(i2cp->dmarx, rxbytes); - - /* Calculating the time window for the timeout on the busy bus condition.*/ - start = osalOsGetSystemTimeX(); - end = start + OSAL_MS2ST(STM32_I2C_BUSY_TIMEOUT); - - /* Waits until BUSY flag is reset or, alternatively, for a timeout - condition.*/ - while (true) { - osalSysLock(); - - /* If the bus is not busy then the operation can continue, note, the - loop is exited in the locked state.*/ - if ((dp->ISR & I2C_ISR_BUSY) == 0) - break; - - /* If the system time went outside the allowed window then a timeout - condition is returned.*/ - if (!osalOsIsTimeWithinX(osalOsGetSystemTimeX(), start, end)) - return MSG_TIMEOUT; - - osalSysUnlock(); - } - - /* Adjust slave address (master mode) for 7-bit address mode */ - if ((i2cp->config->cr2 & I2C_CR2_ADD10) == 0) - addr_cr2 = (addr_cr2 & 0x7f) << 1; - - /* Set slave address field (master mode) */ - dp->CR2 &= ~(I2C_CR2_SADD | I2C_CR2_NBYTES); - dp->CR2 |= (txbytes << 16) | addr_cr2; - - /* Enable TX DMA */ - dmaStreamEnable(i2cp->dmatx); - - /* Transmission complete interrupt enabled.*/ - dp->CR1 |= I2C_CR1_TCIE; - - /* Starts the operation as the very last thing.*/ - dp->CR2 &= ~I2C_CR2_RD_WRN; - dp->CR2 |= I2C_CR2_START; - - /* Waits for the operation completion or a timeout.*/ - return osalThreadSuspendTimeoutS(&i2cp->thread, timeout); -} - -#endif /* HAL_USE_I2C */ - -/** @} */ diff --git a/os/hal/platforms/STM32/I2Cv2/i2c_lld.h b/os/hal/platforms/STM32/I2Cv2/i2c_lld.h deleted file mode 100644 index ca654d582..000000000 --- a/os/hal/platforms/STM32/I2Cv2/i2c_lld.h +++ /dev/null @@ -1,365 +0,0 @@ -/* - ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ -/* - Concepts and parts of this file have been contributed by Uladzimir Pylinsky - aka barthess. - */ - -/** - * @file STM32/I2Cv2/i2c_lld.h - * @brief STM32 I2C subsystem low level driver header. - * - * @addtogroup I2C - * @{ - */ - -#ifndef _I2C_LLD_H_ -#define _I2C_LLD_H_ - -#if HAL_USE_I2C || defined(__DOXYGEN__) - -/*===========================================================================*/ -/* Driver constants. */ -/*===========================================================================*/ - -/** - * @name TIMINGR register definitions - * @{ - */ -#define STM32_TIMINGR_PRESC_MASK (15U << 28) -#define STM32_TIMINGR_PRESC(n) ((n) << 28) -#define STM32_TIMINGR_SCLDEL_MASK (15U << 20) -#define STM32_TIMINGR_SCLDEL(n) ((n) << 20) -#define STM32_TIMINGR_SDADEL_MASK (15U << 16) -#define STM32_TIMINGR_SDADEL(n) ((n) << 16) -#define STM32_TIMINGR_SCLH_MASK (255U << 8) -#define STM32_TIMINGR_SCLH(n) ((n) << 8) -#define STM32_TIMINGR_SCLL_MASK (255U << 0) -#define STM32_TIMINGR_SCLL(n) ((n) << 0) -/** @} */ - -/*===========================================================================*/ -/* Driver pre-compile time settings. */ -/*===========================================================================*/ - -/** - * @name Configuration options - * @{ - */ -/** - * @brief I2C1 driver enable switch. - * @details If set to @p TRUE the support for I2C1 is included. - * @note The default is @p FALSE. - */ -#if !defined(STM32_I2C_USE_I2C1) || defined(__DOXYGEN__) -#define STM32_I2C_USE_I2C1 FALSE -#endif - -/** - * @brief I2C2 driver enable switch. - * @details If set to @p TRUE the support for I2C2 is included. - * @note The default is @p FALSE. - */ -#if !defined(STM32_I2C_USE_I2C2) || defined(__DOXYGEN__) -#define STM32_I2C_USE_I2C2 FALSE -#endif - -/** - * @brief I2C timeout on busy condition in milliseconds. - */ -#if !defined(STM32_I2C_BUSY_TIMEOUT) || defined(__DOXYGEN__) -#define STM32_I2C_BUSY_TIMEOUT 50 -#endif - -/** - * @brief I2C1 interrupt priority level setting. - */ -#if !defined(STM32_I2C_I2C1_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_I2C_I2C1_IRQ_PRIORITY 10 -#endif - -/** - * @brief I2C2 interrupt priority level setting. - */ -#if !defined(STM32_I2C_I2C2_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_I2C_I2C2_IRQ_PRIORITY 10 -#endif - -/** - * @brief I2C1 DMA priority (0..3|lowest..highest). - * @note The priority level is used for both the TX and RX DMA streams but - * because of the streams ordering the RX stream has always priority - * over the TX stream. - */ -#if !defined(STM32_I2C_I2C1_DMA_PRIORITY) || defined(__DOXYGEN__) -#define STM32_I2C_I2C1_DMA_PRIORITY 1 -#endif - -/** - * @brief I2C2 DMA priority (0..3|lowest..highest). - * @note The priority level is used for both the TX and RX DMA streams but - * because of the streams ordering the RX stream has always priority - * over the TX stream. - */ -#if !defined(STM32_I2C_I2C2_DMA_PRIORITY) || defined(__DOXYGEN__) -#define STM32_I2C_I2C2_DMA_PRIORITY 1 -#endif - -/** - * @brief I2C DMA error hook. - * @note The default action for DMA errors is a system halt because DMA - * error can only happen because programming errors. - */ -#if !defined(STM32_I2C_DMA_ERROR_HOOK) || defined(__DOXYGEN__) -#define STM32_I2C_DMA_ERROR_HOOK(i2cp) osalSysHalt("DMA failure") -#endif -/** @} */ - -/*===========================================================================*/ -/* Derived constants and error checks. */ -/*===========================================================================*/ - -/* TODO: Move the following DMA settings in the STM32F37X registry.*/ -#if defined(STM32F37X) -#define STM32_I2C_I2C1_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7) -#define STM32_I2C_I2C1_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 6) -#define STM32_I2C_I2C2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 5) -#define STM32_I2C_I2C2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) -#endif - -/** @brief error checks */ -#if STM32_I2C_USE_I2C1 && !STM32_HAS_I2C1 -#error "I2C1 not present in the selected device" -#endif - -#if STM32_I2C_USE_I2C2 && !STM32_HAS_I2C2 -#error "I2C2 not present in the selected device" -#endif - -#if !STM32_I2C_USE_I2C1 && !STM32_I2C_USE_I2C2 -#error "I2C driver activated but no I2C peripheral assigned" -#endif - -#if STM32_I2C_USE_I2C1 && \ - !CORTEX_IS_VALID_KERNEL_PRIORITY(STM32_I2C_I2C1_IRQ_PRIORITY) -#error "Invalid IRQ priority assigned to I2C1" -#endif - -#if STM32_I2C_USE_I2C2 && \ - !CORTEX_IS_VALID_KERNEL_PRIORITY(STM32_I2C_I2C2_IRQ_PRIORITY) -#error "Invalid IRQ priority assigned to I2C2" -#endif - -#if STM32_I2C_USE_I2C1 && \ - !STM32_DMA_IS_VALID_PRIORITY(STM32_I2C_I2C1_DMA_PRIORITY) -#error "Invalid DMA priority assigned to I2C1" -#endif - -#if STM32_I2C_USE_I2C2 && \ - !STM32_DMA_IS_VALID_PRIORITY(STM32_I2C_I2C2_DMA_PRIORITY) -#error "Invalid DMA priority assigned to I2C2" -#endif - -/* The following checks are only required when there is a DMA able to - reassign streams to different channels.*/ -#if STM32_ADVANCED_DMA -/* Check on the presence of the DMA streams settings in mcuconf.h.*/ -#if STM32_I2C_USE_I2C1 && (!defined(STM32_I2C_I2C1_RX_DMA_STREAM) || \ - !defined(STM32_I2C_I2C1_TX_DMA_STREAM)) -#error "I2C1 DMA streams not defined" -#endif - -#if STM32_I2C_USE_I2C2 && (!defined(STM32_I2C_I2C2_RX_DMA_STREAM) || \ - !defined(STM32_I2C_I2C2_TX_DMA_STREAM)) -#error "I2C2 DMA streams not defined" -#endif - -/* Check on the validity of the assigned DMA channels.*/ -#if STM32_I2C_USE_I2C1 && \ - !STM32_DMA_IS_VALID_ID(STM32_I2C_I2C1_RX_DMA_STREAM, \ - STM32_I2C1_RX_DMA_MSK) -#error "invalid DMA stream associated to I2C1 RX" -#endif - -#if STM32_I2C_USE_I2C1 && \ - !STM32_DMA_IS_VALID_ID(STM32_I2C_I2C1_TX_DMA_STREAM, \ - STM32_I2C1_TX_DMA_MSK) -#error "invalid DMA stream associated to I2C1 TX" -#endif - -#if STM32_I2C_USE_I2C2 && \ - !STM32_DMA_IS_VALID_ID(STM32_I2C_I2C2_RX_DMA_STREAM, \ - STM32_I2C2_RX_DMA_MSK) -#error "invalid DMA stream associated to I2C2 RX" -#endif - -#if STM32_I2C_USE_I2C2 && \ - !STM32_DMA_IS_VALID_ID(STM32_I2C_I2C2_TX_DMA_STREAM, \ - STM32_I2C2_TX_DMA_MSK) -#error "invalid DMA stream associated to I2C2 TX" -#endif -#endif /* STM32_ADVANCED_DMA */ - -#if !defined(STM32_DMA_REQUIRED) -#define STM32_DMA_REQUIRED -#endif - -/* Check clock range. */ - -/*===========================================================================*/ -/* Driver data structures and types. */ -/*===========================================================================*/ - -/** - * @brief Type representing I2C address. - */ -typedef uint16_t i2caddr_t; - -/** - * @brief I2C Driver condition flags type. - */ -typedef uint32_t i2cflags_t; - -/** - * @brief Driver configuration structure. - */ -typedef struct { - /** - * @brief TIMINGR register initialization. - * @note Refer to the STM32 reference manual, the values are affected - * by the system clock settings in mcuconf.h. - */ - uint32_t timingr; - /** - * @brief CR1 register initialization. - * @note Leave to zero unless you know what you are doing. - */ - uint32_t cr1; - /** - * @brief CR2 register initialization. - * @note Only the ADD10 bit can eventually be specified here. - */ - uint32_t cr2; -} I2CConfig; - -/** - * @brief Type of a structure representing an I2C driver. - */ -typedef struct I2CDriver I2CDriver; - -/** - * @brief Structure representing an I2C driver. - */ -struct I2CDriver{ - /** - * @brief Driver state. - */ - i2cstate_t state; - /** - * @brief Current configuration data. - */ - const I2CConfig *config; - /** - * @brief Error flags. - */ - i2cflags_t errors; -#if I2C_USE_MUTUAL_EXCLUSION || defined(__DOXYGEN__) - mutex_t mutex; -#endif /* I2C_USE_MUTUAL_EXCLUSION */ -#if defined(I2C_DRIVER_EXT_FIELDS) - I2C_DRIVER_EXT_FIELDS -#endif - /* End of the mandatory fields.*/ - /** - * @brief Thread waiting for I/O completion. - */ - thread_reference_t thread; - /** - * @brief Current slave address without R/W bit. - */ - i2caddr_t addr; - /** - * @brief RX DMA mode bit mask. - */ - uint32_t rxdmamode; - /** - * @brief TX DMA mode bit mask. - */ - uint32_t txdmamode; - /** - * @brief Receive DMA channel. - */ - const stm32_dma_stream_t *dmarx; - /** - * @brief Transmit DMA channel. - */ - const stm32_dma_stream_t *dmatx; - /** - * @brief Pointer to the I2Cx registers block. - */ - I2C_TypeDef *i2c; -}; - -/*===========================================================================*/ -/* Driver macros. */ -/*===========================================================================*/ - -/** - * @brief Get errors from I2C driver. - * - * @param[in] i2cp pointer to the @p I2CDriver object - * - * @notapi - */ -#define i2c_lld_get_errors(i2cp) ((i2cp)->errors) - -/*===========================================================================*/ -/* External declarations. */ -/*===========================================================================*/ - -#if !defined(__DOXYGEN__) -#if STM32_I2C_USE_I2C1 -extern I2CDriver I2CD1; -#endif - -#if STM32_I2C_USE_I2C2 -extern I2CDriver I2CD2; -#endif - -#endif /* !defined(__DOXYGEN__) */ - -#ifdef __cplusplus -extern "C" { -#endif - void i2c_lld_init(void); - void i2c_lld_start(I2CDriver *i2cp); - void i2c_lld_stop(I2CDriver *i2cp); - msg_t i2c_lld_master_transmit_timeout(I2CDriver *i2cp, i2caddr_t addr, - const uint8_t *txbuf, size_t txbytes, - uint8_t *rxbuf, size_t rxbytes, - systime_t timeout); - msg_t i2c_lld_master_receive_timeout(I2CDriver *i2cp, i2caddr_t addr, - uint8_t *rxbuf, size_t rxbytes, - systime_t timeout); -#ifdef __cplusplus -} -#endif - -#endif /* HAL_USE_I2C */ - -#endif /* _I2C_LLD_H_ */ - -/** @} */ diff --git a/os/hal/platforms/STM32/OTGv1/stm32_otg.h b/os/hal/platforms/STM32/OTGv1/stm32_otg.h deleted file mode 100644 index a78ba57e4..000000000 --- a/os/hal/platforms/STM32/OTGv1/stm32_otg.h +++ /dev/null @@ -1,916 +0,0 @@ -/* - ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file stm32_otg.h - * @brief STM32 OTG registers layout header. - * - * @addtogroup USB - * @{ - */ - -#ifndef _STM32_OTG_H_ -#define _STM32_OTG_H_ - -/** - * @brief Number of the implemented endpoints in OTG_FS. - * @details This value does not include the endpoint 0 that is always present. - */ -#define STM32_OTG1_ENDOPOINTS_NUMBER 3 - -/** - * @brief Number of the implemented endpoints in OTG_HS. - * @details This value does not include the endpoint 0 that is always present. - */ -#define STM32_OTG2_ENDOPOINTS_NUMBER 5 - -/** - * @brief OTG_FS FIFO memory size in words. - */ -#define STM32_OTG1_FIFO_MEM_SIZE 384 - -/** - * @brief OTG_HS FIFO memory size in words. - */ -#define STM32_OTG2_FIFO_MEM_SIZE 1024 - -/** - * @brief Host channel registers group. - */ -typedef struct { - volatile uint32_t HCCHAR; /**< @brief Host channel characteristics - register. */ - volatile uint32_t resvd8; - volatile uint32_t HCINT; /**< @brief Host channel interrupt register.*/ - volatile uint32_t HCINTMSK; /**< @brief Host channel interrupt mask - register. */ - volatile uint32_t HCTSIZ; /**< @brief Host channel transfer size - register. */ - volatile uint32_t resvd14; - volatile uint32_t resvd18; - volatile uint32_t resvd1c; -} stm32_otg_host_chn_t; - -/** - * @brief Device input endpoint registers group. - */ -typedef struct { - volatile uint32_t DIEPCTL; /**< @brief Device control IN endpoint - control register. */ - volatile uint32_t resvd4; - volatile uint32_t DIEPINT; /**< @brief Device IN endpoint interrupt - register. */ - volatile uint32_t resvdC; - volatile uint32_t DIEPTSIZ; /**< @brief Device IN endpoint transfer size - register. */ - volatile uint32_t resvd14; - volatile uint32_t DTXFSTS; /**< @brief Device IN endpoint transmit FIFO - status register. */ - volatile uint32_t resvd1C; -} stm32_otg_in_ep_t; - -/** - * @brief Device output endpoint registers group. - */ -typedef struct { - volatile uint32_t DOEPCTL; /**< @brief Device control OUT endpoint - control register. */ - volatile uint32_t resvd4; - volatile uint32_t DOEPINT; /**< @brief Device OUT endpoint interrupt - register. */ - volatile uint32_t resvdC; - volatile uint32_t DOEPTSIZ; /**< @brief Device OUT endpoint transfer - size register. */ - volatile uint32_t resvd14; - volatile uint32_t resvd18; - volatile uint32_t resvd1C; -} stm32_otg_out_ep_t; - -/** - * @brief USB registers memory map. - */ -typedef struct { - volatile uint32_t GOTGCTL; /**< @brief OTG control and status register.*/ - volatile uint32_t GOTGINT; /**< @brief OTG interrupt register. */ - volatile uint32_t GAHBCFG; /**< @brief AHB configuration register. */ - volatile uint32_t GUSBCFG; /**< @brief USB configuration register. */ - volatile uint32_t GRSTCTL; /**< @brief Reset register size. */ - volatile uint32_t GINTSTS; /**< @brief Interrupt register. */ - volatile uint32_t GINTMSK; /**< @brief Interrupt mask register. */ - volatile uint32_t GRXSTSR; /**< @brief Receive status debug read - register. */ - volatile uint32_t GRXSTSP; /**< @brief Receive status read/pop - register. */ - volatile uint32_t GRXFSIZ; /**< @brief Receive FIFO size register. */ - volatile uint32_t DIEPTXF0; /**< @brief Endpoint 0 transmit FIFO size - register. */ - volatile uint32_t HNPTXSTS; /**< @brief Non-periodic transmit FIFO/queue - status register. */ - volatile uint32_t resvd30; - volatile uint32_t resvd34; - volatile uint32_t GCCFG; /**< @brief General core configuration. */ - volatile uint32_t CID; /**< @brief Core ID register. */ - volatile uint32_t resvd58[48]; - volatile uint32_t HPTXFSIZ; /**< @brief Host periodic transmit FIFO size - register. */ - volatile uint32_t DIEPTXF[15];/**< @brief Device IN endpoint transmit FIFO - size registers. */ - volatile uint32_t resvd140[176]; - volatile uint32_t HCFG; /**< @brief Host configuration register. */ - volatile uint32_t HFIR; /**< @brief Host frame interval register. */ - volatile uint32_t HFNUM; /**< @brief Host frame number/frame time - Remaining register. */ - volatile uint32_t resvd40C; - volatile uint32_t HPTXSTS; /**< @brief Host periodic transmit FIFO/queue - status register. */ - volatile uint32_t HAINT; /**< @brief Host all channels interrupt - register. */ - volatile uint32_t HAINTMSK; /**< @brief Host all channels interrupt mask - register. */ - volatile uint32_t resvd41C[9]; - volatile uint32_t HPRT; /**< @brief Host port control and status - register. */ - volatile uint32_t resvd444[47]; - stm32_otg_host_chn_t hc[16]; /**< @brief Host channels array. */ - volatile uint32_t resvd700[64]; - volatile uint32_t DCFG; /**< @brief Device configuration register. */ - volatile uint32_t DCTL; /**< @brief Device control register. */ - volatile uint32_t DSTS; /**< @brief Device status register. */ - volatile uint32_t resvd80C; - volatile uint32_t DIEPMSK; /**< @brief Device IN endpoint common - interrupt mask register. */ - volatile uint32_t DOEPMSK; /**< @brief Device OUT endpoint common - interrupt mask register. */ - volatile uint32_t DAINT; /**< @brief Device all endpoints interrupt - register. */ - volatile uint32_t DAINTMSK; /**< @brief Device all endpoints interrupt - mask register. */ - volatile uint32_t resvd820; - volatile uint32_t resvd824; - volatile uint32_t DVBUSDIS; /**< @brief Device VBUS discharge time - register. */ - volatile uint32_t DVBUSPULSE; /**< @brief Device VBUS pulsing time - register. */ - volatile uint32_t resvd830; - volatile uint32_t DIEPEMPMSK; /**< @brief Device IN endpoint FIFO empty - interrupt mask register. */ - volatile uint32_t resvd838; - volatile uint32_t resvd83C; - volatile uint32_t resvd840[16]; - volatile uint32_t resvd880[16]; - volatile uint32_t resvd8C0[16]; - stm32_otg_in_ep_t ie[16]; /**< @brief Input endpoints. */ - stm32_otg_out_ep_t oe[16]; /**< @brief Output endpoints. */ - volatile uint32_t resvdD00[64]; - volatile uint32_t PCGCCTL; /**< @brief Power and clock gating control - register. */ - volatile uint32_t resvdE04[127]; - volatile uint32_t FIFO[16][1024]; -} stm32_otg_t; - -/** - * @name GOTGCTL register bit definitions - * @{ - */ -#define GOTGCTL_BSVLD (1U<<19) /**< B-Session Valid. */ -#define GOTGCTL_ASVLD (1U<<18) /**< A-Session Valid. */ -#define GOTGCTL_DBCT (1U<<17) /**< Long/Short debounce time. */ -#define GOTGCTL_CIDSTS (1U<<16) /**< Connector ID status. */ -#define GOTGCTL_DHNPEN (1U<<11) /**< Device HNP enabled. */ -#define GOTGCTL_HSHNPEN (1U<<10) /**< Host Set HNP enable. */ -#define GOTGCTL_HNPRQ (1U<<9) /**< HNP request. */ -#define GOTGCTL_HNGSCS (1U<<8) /**< Host negotiation success. */ -#define GOTGCTL_SRQ (1U<<1) /**< Session request. */ -#define GOTGCTL_SRQSCS (1U<<0) /**< Session request success. */ -/** @} */ - -/** - * @name GOTGINT register bit definitions - * @{ - */ -#define GOTGINT_DBCDNE (1U<<19) /**< Debounce done. */ -#define GOTGINT_ADTOCHG (1U<<18) /**< A-Device timeout change. */ -#define GOTGINT_HNGDET (1U<<17) /**< Host negotiation detected. */ -#define GOTGINT_HNSSCHG (1U<<9) /**< Host negotiation success - status change. */ -#define GOTGINT_SRSSCHG (1U<<8) /**< Session request success - status change. */ -#define GOTGINT_SEDET (1U<<2) /**< Session end detected. */ -/** @} */ - -/** - * @name GAHBCFG register bit definitions - * @{ - */ -#define GAHBCFG_PTXFELVL (1U<<8) /**< Periodic TxFIFO empty - level. */ -#define GAHBCFG_TXFELVL (1U<<7) /**< Non-periodic TxFIFO empty - level. */ -#define GAHBCFG_DMAEN (1U<<5) /**< DMA enable (HS only). */ -#define GAHBCFG_HBSTLEN_MASK (15U<<1) /**< Burst length/type mask (HS - only). */ -#define GAHBCFG_HBSTLEN(n) ((n)<<1) /**< Burst length/type (HS - only). */ -#define GAHBCFG_GINTMSK (1U<<0) /**< Global interrupt mask. */ -/** @} */ - -/** - * @name GUSBCFG register bit definitions - * @{ - */ -#define GUSBCFG_CTXPKT (1U<<31) /**< Corrupt Tx packet. */ -#define GUSBCFG_FDMOD (1U<<30) /**< Force Device Mode. */ -#define GUSBCFG_FHMOD (1U<<29) /**< Force Host Mode. */ -#define GUSBCFG_TRDT_MASK (15U<<10) /**< USB Turnaround time field - mask. */ -#define GUSBCFG_TRDT(n) ((n)<<10) /**< USB Turnaround time field - value. */ -#define GUSBCFG_HNPCAP (1U<<9) /**< HNP-Capable. */ -#define GUSBCFG_SRPCAP (1U<<8) /**< SRP-Capable. */ -#define GUSBCFG_PHYSEL (1U<<6) /**< USB 2.0 High-Speed PHY or - USB 1.1 Full-Speed serial - transceiver Select. */ -#define GUSBCFG_TOCAL_MASK (7U<<0) /**< HS/FS timeout calibration - field mask. */ -#define GUSBCFG_TOCAL(n) ((n)<<0) /**< HS/FS timeout calibration - field value. */ -/** @} */ - -/** - * @name GRSTCTL register bit definitions - * @{ - */ -#define GRSTCTL_AHBIDL (1U<<31) /**< AHB Master Idle. */ -#define GRSTCTL_TXFNUM_MASK (31U<<6) /**< TxFIFO number field mask. */ -#define GRSTCTL_TXFNUM(n) ((n)<<6) /**< TxFIFO number field value. */ -#define GRSTCTL_TXFFLSH (1U<<5) /**< TxFIFO flush. */ -#define GRSTCTL_RXFFLSH (1U<<4) /**< RxFIFO flush. */ -#define GRSTCTL_FCRST (1U<<2) /**< Host frame counter reset. */ -#define GRSTCTL_HSRST (1U<<1) /**< HClk soft reset. */ -#define GRSTCTL_CSRST (1U<<0) /**< Core soft reset. */ -/** @} */ - -/** - * @name GINTSTS register bit definitions - * @{ - */ -#define GINTSTS_WKUPINT (1U<<31) /**< Resume/Remote wakeup - detected interrupt. */ -#define GINTSTS_SRQINT (1U<<30) /**< Session request/New session - detected interrupt. */ -#define GINTSTS_DISCINT (1U<<29) /**< Disconnect detected - interrupt. */ -#define GINTSTS_CIDSCHG (1U<<28) /**< Connector ID status change.*/ -#define GINTSTS_PTXFE (1U<<26) /**< Periodic TxFIFO empty. */ -#define GINTSTS_HCINT (1U<<25) /**< Host channels interrupt. */ -#define GINTSTS_HPRTINT (1U<<24) /**< Host port interrupt. */ -#define GINTSTS_IPXFR (1U<<21) /**< Incomplete periodic - transfer. */ -#define GINTSTS_IISOOXFR (1U<<21) /**< Incomplete isochronous OUT - transfer. */ -#define GINTSTS_IISOIXFR (1U<<20) /**< Incomplete isochronous IN - transfer. */ -#define GINTSTS_OEPINT (1U<<19) /**< OUT endpoints interrupt. */ -#define GINTSTS_IEPINT (1U<<18) /**< IN endpoints interrupt. */ -#define GINTSTS_EOPF (1U<<15) /**< End of periodic frame - interrupt. */ -#define GINTSTS_ISOODRP (1U<<14) /**< Isochronous OUT packet - dropped interrupt. */ -#define GINTSTS_ENUMDNE (1U<<13) /**< Enumeration done. */ -#define GINTSTS_USBRST (1U<<12) /**< USB reset. */ -#define GINTSTS_USBSUSP (1U<<11) /**< USB suspend. */ -#define GINTSTS_ESUSP (1U<<10) /**< Early suspend. */ -#define GINTSTS_GONAKEFF (1U<<7) /**< Global OUT NAK effective. */ -#define GINTSTS_GINAKEFF (1U<<6) /**< Global IN non-periodic NAK - effective. */ -#define GINTSTS_NPTXFE (1U<<5) /**< Non-periodic TxFIFO empty. */ -#define GINTSTS_RXFLVL (1U<<4) /**< RxFIFO non-empty. */ -#define GINTSTS_SOF (1U<<3) /**< Start of frame. */ -#define GINTSTS_OTGINT (1U<<2) /**< OTG interrupt. */ -#define GINTSTS_MMIS (1U<<1) /**< Mode Mismatch interrupt. */ -#define GINTSTS_CMOD (1U<<0) /**< Current mode of operation. */ -/** @} */ - -/** - * @name GINTMSK register bit definitions - * @{ - */ -#define GINTMSK_WKUM (1U<<31) /**< Resume/remote wakeup - detected interrupt mask. */ -#define GINTMSK_SRQM (1U<<30) /**< Session request/New session - detected interrupt mask. */ -#define GINTMSK_DISCM (1U<<29) /**< Disconnect detected - interrupt mask. */ -#define GINTMSK_CIDSCHGM (1U<<28) /**< Connector ID status change - mask. */ -#define GINTMSK_PTXFEM (1U<<26) /**< Periodic TxFIFO empty mask.*/ -#define GINTMSK_HCM (1U<<25) /**< Host channels interrupt - mask. */ -#define GINTMSK_HPRTM (1U<<24) /**< Host port interrupt mask. */ -#define GINTMSK_IPXFRM (1U<<21) /**< Incomplete periodic - transfer mask. */ -#define GINTMSK_IISOOXFRM (1U<<21) /**< Incomplete isochronous OUT - transfer mask. */ -#define GINTMSK_IISOIXFRM (1U<<20) /**< Incomplete isochronous IN - transfer mask. */ -#define GINTMSK_OEPM (1U<<19) /**< OUT endpoints interrupt - mask. */ -#define GINTMSK_IEPM (1U<<18) /**< IN endpoints interrupt - mask. */ -#define GINTMSK_EOPFM (1U<<15) /**< End of periodic frame - interrupt mask. */ -#define GINTMSK_ISOODRPM (1U<<14) /**< Isochronous OUT packet - dropped interrupt mask. */ -#define GINTMSK_ENUMDNEM (1U<<13) /**< Enumeration done mask. */ -#define GINTMSK_USBRSTM (1U<<12) /**< USB reset mask. */ -#define GINTMSK_USBSUSPM (1U<<11) /**< USB suspend mask. */ -#define GINTMSK_ESUSPM (1U<<10) /**< Early suspend mask. */ -#define GINTMSK_GONAKEFFM (1U<<7) /**< Global OUT NAK effective - mask. */ -#define GINTMSK_GINAKEFFM (1U<<6) /**< Global non-periodic IN NAK - effective mask. */ -#define GINTMSK_NPTXFEM (1U<<5) /**< Non-periodic TxFIFO empty - mask. */ -#define GINTMSK_RXFLVLM (1U<<4) /**< Receive FIFO non-empty - mask. */ -#define GINTMSK_SOFM (1U<<3) /**< Start of (micro)frame mask.*/ -#define GINTMSK_OTGM (1U<<2) /**< OTG interrupt mask. */ -#define GINTMSK_MMISM (1U<<1) /**< Mode Mismatch interrupt - mask. */ -/** @} */ - -/** - * @name GRXSTSR register bit definitions - * @{ - */ -#define GRXSTSR_PKTSTS_MASK (15U<<17) /**< Packet status mask. */ -#define GRXSTSR_PKTSTS(n) ((n)<<17) /**< Packet status value. */ -#define GRXSTSR_OUT_GLOBAL_NAK GRXSTSR_PKTSTS(1) -#define GRXSTSR_OUT_DATA GRXSTSR_PKTSTS(2) -#define GRXSTSR_OUT_COMP GRXSTSR_PKTSTS(3) -#define GRXSTSR_SETUP_COMP GRXSTSR_PKTSTS(4) -#define GRXSTSR_SETUP_DATA GRXSTSR_PKTSTS(6) -#define GRXSTSR_DPID_MASK (3U<<15) /**< Data PID mask. */ -#define GRXSTSR_DPID(n) ((n)<<15) /**< Data PID value. */ -#define GRXSTSR_BCNT_MASK (0x7FF<<4) /**< Byte count mask. */ -#define GRXSTSR_BCNT(n) ((n)<<4) /**< Byte count value. */ -#define GRXSTSR_CHNUM_MASK (15U<<0) /**< Channel number mask. */ -#define GRXSTSR_CHNUM(n) ((n)<<0) /**< Channel number value. */ -#define GRXSTSR_EPNUM_MASK (15U<<0) /**< Endpoint number mask. */ -#define GRXSTSR_EPNUM(n) ((n)<<0) /**< Endpoint number value. */ -/** @} */ - -/** - * @name GRXSTSP register bit definitions - * @{ - */ -#define GRXSTSP_PKTSTS_MASK (15<<17) /**< Packet status mask. */ -#define GRXSTSP_PKTSTS(n) ((n)<<17) /**< Packet status value. */ -#define GRXSTSP_OUT_GLOBAL_NAK GRXSTSP_PKTSTS(1) -#define GRXSTSP_OUT_DATA GRXSTSP_PKTSTS(2) -#define GRXSTSP_OUT_COMP GRXSTSP_PKTSTS(3) -#define GRXSTSP_SETUP_COMP GRXSTSP_PKTSTS(4) -#define GRXSTSP_SETUP_DATA GRXSTSP_PKTSTS(6) -#define GRXSTSP_DPID_MASK (3U<<15) /**< Data PID mask. */ -#define GRXSTSP_DPID(n) ((n)<<15) /**< Data PID value. */ -#define GRXSTSP_BCNT_MASK (0x7FF<<4) /**< Byte count mask. */ -#define GRXSTSP_BCNT_OFF 4 /**< Byte count offset. */ -#define GRXSTSP_BCNT(n) ((n)<<4) /**< Byte count value. */ -#define GRXSTSP_CHNUM_MASK (15U<<0) /**< Channel number mask. */ -#define GRXSTSP_CHNUM(n) ((n)<<0) /**< Channel number value. */ -#define GRXSTSP_EPNUM_MASK (15U<<0) /**< Endpoint number mask. */ -#define GRXSTSP_EPNUM_OFF 0 /**< Endpoint number offset. */ -#define GRXSTSP_EPNUM(n) ((n)<<0) /**< Endpoint number value. */ -/** @} */ - -/** - * @name GRXFSIZ register bit definitions - * @{ - */ -#define GRXFSIZ_RXFD_MASK (0xFFFF<<0) /**< RxFIFO depth mask. */ -#define GRXFSIZ_RXFD(n) ((n)<<0) /**< RxFIFO depth value. */ -/** @} */ - -/** - * @name DIEPTXFx register bit definitions - * @{ - */ -#define DIEPTXF_INEPTXFD_MASK (0xFFFFU<<16)/**< IN endpoint TxFIFO depth - mask. */ -#define DIEPTXF_INEPTXFD(n) ((n)<<16) /**< IN endpoint TxFIFO depth - value. */ -#define DIEPTXF_INEPTXSA_MASK (0xFFFF<<0) /**< IN endpoint FIFOx transmit - RAM start address mask. */ -#define DIEPTXF_INEPTXSA(n) ((n)<<0) /**< IN endpoint FIFOx transmit - RAM start address value. */ -/** @} */ - -/** - * @name GCCFG register bit definitions - * @{ - */ -#define GCCFG_NOVBUSSENS (1U<<21) /**< VBUS sensing disable. */ -#define GCCFG_SOFOUTEN (1U<<20) /**< SOF output enable. */ -#define GCCFG_VBUSBSEN (1U<<19) /**< Enable the VBUS sensing "B" - device. */ -#define GCCFG_VBUSASEN (1U<<18) /**< Enable the VBUS sensing "A" - device. */ -#define GCCFG_PWRDWN (1U<<16) /**< Power down. */ -/** @} */ - -/** - * @name HPTXFSIZ register bit definitions - * @{ - */ -#define HPTXFSIZ_PTXFD_MASK (0xFFFFU<<16)/**< Host periodic TxFIFO - depth mask. */ -#define HPTXFSIZ_PTXFD(n) ((n)<<16) /**< Host periodic TxFIFO - depth value. */ -#define HPTXFSIZ_PTXSA_MASK (0xFFFFU<<0)/**< Host periodic TxFIFO - Start address mask. */ -#define HPTXFSIZ_PTXSA(n) ((n)<<0) /**< Host periodic TxFIFO - start address value. */ -/** @} */ - -/** - * @name HCFG register bit definitions - * @{ - */ -#define HCFG_FSLSS (1U<<2) /**< FS- and LS-only support. */ -#define HCFG_FSLSPCS_MASK (3U<<0) /**< FS/LS PHY clock select - mask. */ -#define HCFG_FSLSPCS_48 (1U<<0) /**< PHY clock is running at - 48 MHz. */ -#define HCFG_FSLSPCS_6 (2U<<0) /**< PHY clock is running at - 6 MHz. */ -/** @} */ - -/** - * @name HFIR register bit definitions - * @{ - */ -#define HFIR_FRIVL_MASK (0xFFFFU<<0)/**< Frame interval mask. */ -#define HFIR_FRIVL(n) ((n)<<0) /**< Frame interval value. */ -/** @} */ - -/** - * @name HFNUM register bit definitions - * @{ - */ -#define HFNUM_FTREM_MASK (0xFFFFU<<16)/**< Frame time Remaining mask.*/ -#define HFNUM_FTREM(n) ((n)<<16) /**< Frame time Remaining value.*/ -#define HFNUM_FRNUM_MASK (0xFFFFU<<0)/**< Frame number mask. */ -#define HFNUM_FRNUM(n) ((n)<<0) /**< Frame number value. */ -/** @} */ - -/** - * @name HPTXSTS register bit definitions - * @{ - */ -#define HPTXSTS_PTXQTOP_MASK (0xFFU<<24) /**< Top of the periodic - transmit request queue - mask. */ -#define HPTXSTS_PTXQTOP(n) ((n)<<24) /**< Top of the periodic - transmit request queue - value. */ -#define HPTXSTS_PTXQSAV_MASK (0xFF<<16) /**< Periodic transmit request - queue Space Available - mask. */ -#define HPTXSTS_PTXQSAV(n) ((n)<<16) /**< Periodic transmit request - queue Space Available - value. */ -#define HPTXSTS_PTXFSAVL_MASK (0xFFFF<<0) /**< Periodic transmit Data - FIFO Space Available - mask. */ -#define HPTXSTS_PTXFSAVL(n) ((n)<<0) /**< Periodic transmit Data - FIFO Space Available - value. */ -/** @} */ - -/** - * @name HAINT register bit definitions - * @{ - */ -#define HAINT_HAINT_MASK (0xFFFFU<<0)/**< Channel interrupts mask. */ -#define HAINT_HAINT(n) ((n)<<0) /**< Channel interrupts value. */ -/** @} */ - -/** - * @name HAINTMSK register bit definitions - * @{ - */ -#define HAINTMSK_HAINTM_MASK (0xFFFFU<<0)/**< Channel interrupt mask - mask. */ -#define HAINTMSK_HAINTM(n) ((n)<<0) /**< Channel interrupt mask - value. */ -/** @} */ - -/** - * @name HPRT register bit definitions - * @{ - */ -#define HPRT_PSPD_MASK (3U<<17) /**< Port speed mask. */ -#define HPRT_PSPD_FS (1U<<17) /**< Full speed value. */ -#define HPRT_PSPD_LS (2U<<17) /**< Low speed value. */ -#define HPRT_PTCTL_MASK (15<<13) /**< Port Test control mask. */ -#define HPRT_PTCTL(n) ((n)<<13) /**< Port Test control value. */ -#define HPRT_PPWR (1U<<12) /**< Port power. */ -#define HPRT_PLSTS_MASK (3U<<11) /**< Port Line status mask. */ -#define HPRT_PLSTS_DM (1U<<11) /**< Logic level of D-. */ -#define HPRT_PLSTS_DP (1U<<10) /**< Logic level of D+. */ -#define HPRT_PRST (1U<<8) /**< Port reset. */ -#define HPRT_PSUSP (1U<<7) /**< Port suspend. */ -#define HPRT_PRES (1U<<6) /**< Port Resume. */ -#define HPRT_POCCHNG (1U<<5) /**< Port overcurrent change. */ -#define HPRT_POCA (1U<<4) /**< Port overcurrent active. */ -#define HPRT_PENCHNG (1U<<3) /**< Port enable/disable change.*/ -#define HPRT_PENA (1U<<2) /**< Port enable. */ -#define HPRT_PCDET (1U<<1) /**< Port Connect detected. */ -#define HPRT_PCSTS (1U<<0) /**< Port connect status. */ -/** @} */ - -/** - * @name HCCHAR register bit definitions - * @{ - */ -#define HCCHAR_CHENA (1U<<31) /**< Channel enable. */ -#define HCCHAR_CHDIS (1U<<30) /**< Channel Disable. */ -#define HCCHAR_ODDFRM (1U<<29) /**< Odd frame. */ -#define HCCHAR_DAD_MASK (0x7FU<<22) /**< Device Address mask. */ -#define HCCHAR_DAD(n) ((n)<<22) /**< Device Address value. */ -#define HCCHAR_MCNT_MASK (3U<<20) /**< Multicount mask. */ -#define HCCHAR_MCNT(n) ((n)<<20) /**< Multicount value. */ -#define HCCHAR_EPTYP_MASK (3U<<18) /**< Endpoint type mask. */ -#define HCCHAR_EPTYP(n) ((n)<<18) /**< Endpoint type value. */ -#define HCCHAR_EPTYP_CTL (0U<<18) /**< Control endpoint value. */ -#define HCCHAR_EPTYP_ISO (1U<<18) /**< Isochronous endpoint value.*/ -#define HCCHAR_EPTYP_BULK (2U<<18) /**< Bulk endpoint value. */ -#define HCCHAR_EPTYP_INTR (3U<<18) /**< Interrupt endpoint value. */ -#define HCCHAR_LSDEV (1U<<17) /**< Low-Speed device. */ -#define HCCHAR_EPDIR (1U<<15) /**< Endpoint direction. */ -#define HCCHAR_EPNUM_MASK (15U<<11) /**< Endpoint number mask. */ -#define HCCHAR_EPNUM(n) ((n)<<11) /**< Endpoint number value. */ -#define HCCHAR_MPS_MASK (11U<<0) /**< Maximum packet size mask. */ -#define HCCHAR_MPS(n) (11U<<0) /**< Maximum packet size value. */ -/** @} */ - -/** - * @name HCINT register bit definitions - * @{ - */ -#define HCINT_DTERR (1U<<10) /**< Data toggle error. */ -#define HCINT_FRMOR (1U<<9) /**< Frame overrun. */ -#define HCINT_BBERR (1U<<8) /**< Babble error. */ -#define HCINT_TRERR (1U<<7) /**< Transaction Error. */ -#define HCINT_ACK (1U<<5) /**< ACK response - received/transmitted - interrupt. */ -#define HCINT_NAK (1U<<4) /**< NAK response received - interrupt. */ -#define HCINT_STALL (1U<<3) /**< STALL response received - interrupt. */ -#define HCINT_CHH (1U<<1) /**< Channel halted. */ -#define HCINT_XFRC (1U<<0) /**< Transfer completed. */ -/** @} */ - -/** - * @name HCINTMSK register bit definitions - * @{ - */ -#define HCINTMSK_DTERRM (1U<<10) /**< Data toggle error mask. */ -#define HCINTMSK_FRMORM (1U<<9) /**< Frame overrun mask. */ -#define HCINTMSK_BBERRM (1U<<8) /**< Babble error mask. */ -#define HCINTMSK_TRERRM (1U<<7) /**< Transaction error mask. */ -#define HCINTMSK_NYET (1U<<6) /**< NYET response received - interrupt mask. */ -#define HCINTMSK_ACKM (1U<<5) /**< ACK Response - received/transmitted - interrupt mask. */ -#define HCINTMSK_NAKM (1U<<4) /**< NAK response received - interrupt mask. */ -#define HCINTMSK_STALLM (1U<<3) /**< STALL response received - interrupt mask. */ -#define HCINTMSK_CHHM (1U<<1) /**< Channel halted mask. */ -#define HCINTMSK_XFRCM (1U<<0) /**< Transfer completed mask. */ -/** @} */ - -/** - * @name HCTSIZ register bit definitions - * @{ - */ -#define HCTSIZ_DPID_MASK (3U<<29) /**< PID mask. */ -#define HCTSIZ_DPID_DATA0 (0U<<29) /**< DATA0. */ -#define HCTSIZ_DPID_DATA2 (1U<<29) /**< DATA2. */ -#define HCTSIZ_DPID_DATA1 (2U<<29) /**< DATA1. */ -#define HCTSIZ_DPID_MDATA (3U<<29) /**< MDATA. */ -#define HCTSIZ_PKTCNT_MASK (0x3FFU<<19)/**< Packet count mask. */ -#define HCTSIZ_PKTCNT(n) ((n)<<19) /**< Packet count value. */ -#define HCTSIZ_XFRSIZ_MASK (0x7FFFF<<0)/**< Transfer size mask. */ -#define HCTSIZ_XFRSIZ(n) ((n)<<0) /**< Transfer size value. */ -/** @} */ - -/** - * @name DCFG register bit definitions - * @{ - */ -#define DCFG_PFIVL_MASK (3U<<11) /**< Periodic frame interval - mask. */ -#define DCFG_PFIVL(n) ((n)<<11) /**< Periodic frame interval - value. */ -#define DCFG_DAD_MASK (0x7FU<<4) /**< Device address mask. */ -#define DCFG_DAD(n) ((n)<<4) /**< Device address value. */ -#define DCFG_NZLSOHSK (1U<<2) /**< Non-Zero-Length status - OUT handshake. */ -#define DCFG_DSPD_MASK (3U<<0) /**< Device speed mask. */ -#define DCFG_DSPD_HS (0U<<0) /**< High speed (USB 2.0). */ -#define DCFG_DSPD_HS_FS (1U<<0) /**< High speed (USB 2.0) in FS - mode. */ -#define DCFG_DSPD_FS11 (3U<<0) /**< Full speed (USB 1.1 - transceiver clock is 48 - MHz). */ -/** @} */ - -/** - * @name DCTL register bit definitions - * @{ - */ -#define DCTL_POPRGDNE (1U<<11) /**< Power-on programming done. */ -#define DCTL_CGONAK (1U<<10) /**< Clear global OUT NAK. */ -#define DCTL_SGONAK (1U<<9) /**< Set global OUT NAK. */ -#define DCTL_CGINAK (1U<<8) /**< Clear global non-periodic - IN NAK. */ -#define DCTL_SGINAK (1U<<7) /**< Set global non-periodic - IN NAK. */ -#define DCTL_TCTL_MASK (7U<<4) /**< Test control mask. */ -#define DCTL_TCTL(n) ((n)<<4 /**< Test control value. */ -#define DCTL_GONSTS (1U<<3) /**< Global OUT NAK status. */ -#define DCTL_GINSTS (1U<<2) /**< Global non-periodic IN - NAK status. */ -#define DCTL_SDIS (1U<<1) /**< Soft disconnect. */ -#define DCTL_RWUSIG (1U<<0) /**< Remote wakeup signaling. */ -/** @} */ - -/** - * @name DSTS register bit definitions - * @{ - */ -#define DSTS_FNSOF_MASK (0x3FFU<<8) /**< Frame number of the received - SOF mask. */ -#define DSTS_FNSOF(n) ((n)<<8) /**< Frame number of the received - SOF value. */ -#define DSTS_EERR (1U<<3) /**< Erratic error. */ -#define DSTS_ENUMSPD_MASK (3U<<1) /**< Enumerated speed mask. */ -#define DSTS_ENUMSPD_FS_48 (3U<<1) /**< Full speed (PHY clock is - running at 48 MHz). */ -#define DSTS_SUSPSTS (1U<<0) /**< Suspend status. */ -/** @} */ - -/** - * @name DIEPMSK register bit definitions - * @{ - */ -#define DIEPMSK_TXFEM (1U<<6) /**< Transmit FIFO empty mask. */ -#define DIEPMSK_INEPNEM (1U<<6) /**< IN endpoint NAK effective - mask. */ -#define DIEPMSK_ITTXFEMSK (1U<<4) /**< IN token received when - TxFIFO empty mask. */ -#define DIEPMSK_TOCM (1U<<3) /**< Timeout condition mask. */ -#define DIEPMSK_EPDM (1U<<1) /**< Endpoint disabled - interrupt mask. */ -#define DIEPMSK_XFRCM (1U<<0) /**< Transfer completed - interrupt mask. */ -/** @} */ - -/** - * @name DOEPMSK register bit definitions - * @{ - */ -#define DOEPMSK_OTEPDM (1U<<4) /**< OUT token received when - endpoint disabled mask. */ -#define DOEPMSK_STUPM (1U<<3) /**< SETUP phase done mask. */ -#define DOEPMSK_EPDM (1U<<1) /**< Endpoint disabled - interrupt mask. */ -#define DOEPMSK_XFRCM (1U<<0) /**< Transfer completed - interrupt mask. */ -/** @} */ - -/** - * @name DAINT register bit definitions - * @{ - */ -#define DAINT_OEPINT_MASK (0xFFFFU<<16)/**< OUT endpoint interrupt - bits mask. */ -#define DAINT_OEPINT(n) ((n)<<16) /**< OUT endpoint interrupt - bits value. */ -#define DAINT_IEPINT_MASK (0xFFFFU<<0)/**< IN endpoint interrupt - bits mask. */ -#define DAINT_IEPINT(n) ((n)<<0) /**< IN endpoint interrupt - bits value. */ -/** @} */ - -/** - * @name DAINTMSK register bit definitions - * @{ - */ -#define DAINTMSK_OEPM_MASK (0xFFFFU<<16)/**< OUT EP interrupt mask - bits mask. */ -#define DAINTMSK_OEPM(n) (1U<<(16+(n)))/**< OUT EP interrupt mask - bits value. */ -#define DAINTMSK_IEPM_MASK (0xFFFFU<<0)/**< IN EP interrupt mask - bits mask. */ -#define DAINTMSK_IEPM(n) (1U<<(n)) /**< IN EP interrupt mask - bits value. */ -/** @} */ - -/** - * @name DVBUSDIS register bit definitions - * @{ - */ -#define DVBUSDIS_VBUSDT_MASK (0xFFFFU<<0)/**< Device VBUS discharge - time mask. */ -#define DVBUSDIS_VBUSDT(n) ((n)<<0) /**< Device VBUS discharge - time value. */ -/** @} */ - -/** - * @name DVBUSPULSE register bit definitions - * @{ - */ -#define DVBUSPULSE_DVBUSP_MASK (0xFFFU<<0) /**< Device VBUSpulsing time - mask. */ -#define DVBUSPULSE_DVBUSP(n) ((n)<<0) /**< Device VBUS pulsing time - value. */ -/** @} */ - -/** - * @name DIEPEMPMSK register bit definitions - * @{ - */ -#define DIEPEMPMSK_INEPTXFEM(n) (1U<<(n)) /**< IN EP Tx FIFO empty - interrupt mask bit. */ -/** @} */ - -/** - * @name DIEPCTL register bit definitions - * @{ - */ -#define DIEPCTL_EPENA (1U<<31) /**< Endpoint enable. */ -#define DIEPCTL_EPDIS (1U<<30) /**< Endpoint disable. */ -#define DIEPCTL_SD1PID (1U<<29) /**< Set DATA1 PID. */ -#define DIEPCTL_SODDFRM (1U<<29) /**< Set odd frame. */ -#define DIEPCTL_SD0PID (1U<<28) /**< Set DATA0 PID. */ -#define DIEPCTL_SEVNFRM (1U<<28) /**< Set even frame. */ -#define DIEPCTL_SNAK (1U<<27) /**< Set NAK. */ -#define DIEPCTL_CNAK (1U<<26) /**< Clear NAK. */ -#define DIEPCTL_TXFNUM_MASK (15U<<22) /**< TxFIFO number mask. */ -#define DIEPCTL_TXFNUM(n) ((n)<<22) /**< TxFIFO number value. */ -#define DIEPCTL_STALL (1U<<21) /**< STALL handshake. */ -#define DIEPCTL_SNPM (1U<<20) /**< Snoop mode. */ -#define DIEPCTL_EPTYP_MASK (3<<18) /**< Endpoint type mask. */ -#define DIEPCTL_EPTYP_CTRL (0U<<18) /**< Control. */ -#define DIEPCTL_EPTYP_ISO (1U<<18) /**< Isochronous. */ -#define DIEPCTL_EPTYP_BULK (2U<<18) /**< Bulk. */ -#define DIEPCTL_EPTYP_INTR (3U<<18) /**< Interrupt. */ -#define DIEPCTL_NAKSTS (1U<<17) /**< NAK status. */ -#define DIEPCTL_EONUM (1U<<16) /**< Even/odd frame. */ -#define DIEPCTL_DPID (1U<<16) /**< Endpoint data PID. */ -#define DIEPCTL_USBAEP (1U<<15) /**< USB active endpoint. */ -#define DIEPCTL_MPSIZ_MASK (0x3FFU<<0) /**< Maximum Packet size mask. */ -#define DIEPCTL_MPSIZ(n) ((n)<<0) /**< Maximum Packet size value. */ -/** @} */ - -/** - * @name DIEPINT register bit definitions - * @{ - */ -#define DIEPINT_TXFE (1U<<7) /**< Transmit FIFO empty. */ -#define DIEPINT_INEPNE (1U<<6) /**< IN endpoint NAK effective. */ -#define DIEPINT_ITTXFE (1U<<4) /**< IN Token received when - TxFIFO is empty. */ -#define DIEPINT_TOC (1U<<3) /**< Timeout condition. */ -#define DIEPINT_EPDISD (1U<<1) /**< Endpoint disabled - interrupt. */ -#define DIEPINT_XFRC (1U<<0) /**< Transfer completed. */ -/** @} */ - -/** - * @name DIEPTSIZ register bit definitions - * @{ - */ -#define DIEPTSIZ_MCNT_MASK (3U<<29) /**< Multi count mask. */ -#define DIEPTSIZ_MCNT(n) ((n)<<29) /**< Multi count value. */ -#define DIEPTSIZ_PKTCNT_MASK (0x3FF<<19) /**< Packet count mask. */ -#define DIEPTSIZ_PKTCNT(n) ((n)<<19) /**< Packet count value. */ -#define DIEPTSIZ_XFRSIZ_MASK (0x7FFFFU<<0)/**< Transfer size mask. */ -#define DIEPTSIZ_XFRSIZ(n) ((n)<<0) /**< Transfer size value. */ -/** @} */ - -/** - * @name DTXFSTS register bit definitions. - * @{ - */ -#define DTXFSTS_INEPTFSAV_MASK (0xFFFF<<0) /**< IN endpoint TxFIFO space - available. */ -/** @} */ - -/** - * @name DOEPCTL register bit definitions. - * @{ - */ -#define DOEPCTL_EPENA (1U<<31) /**< Endpoint enable. */ -#define DOEPCTL_EPDIS (1U<<30) /**< Endpoint disable. */ -#define DOEPCTL_SD1PID (1U<<29) /**< Set DATA1 PID. */ -#define DOEPCTL_SODDFRM (1U<<29) /**< Set odd frame. */ -#define DOEPCTL_SD0PID (1U<<28) /**< Set DATA0 PID. */ -#define DOEPCTL_SEVNFRM (1U<<28) /**< Set even frame. */ -#define DOEPCTL_SNAK (1U<<27) /**< Set NAK. */ -#define DOEPCTL_CNAK (1U<<26) /**< Clear NAK. */ -#define DOEPCTL_STALL (1U<<21) /**< STALL handshake. */ -#define DOEPCTL_SNPM (1U<<20) /**< Snoop mode. */ -#define DOEPCTL_EPTYP_MASK (3U<<18) /**< Endpoint type mask. */ -#define DOEPCTL_EPTYP_CTRL (0U<<18) /**< Control. */ -#define DOEPCTL_EPTYP_ISO (1U<<18) /**< Isochronous. */ -#define DOEPCTL_EPTYP_BULK (2U<<18) /**< Bulk. */ -#define DOEPCTL_EPTYP_INTR (3U<<18) /**< Interrupt. */ -#define DOEPCTL_NAKSTS (1U<<17) /**< NAK status. */ -#define DOEPCTL_EONUM (1U<<16) /**< Even/odd frame. */ -#define DOEPCTL_DPID (1U<<16) /**< Endpoint data PID. */ -#define DOEPCTL_USBAEP (1U<<15) /**< USB active endpoint. */ -#define DOEPCTL_MPSIZ_MASK (0x3FFU<<0) /**< Maximum Packet size mask. */ -#define DOEPCTL_MPSIZ(n) ((n)<<0) /**< Maximum Packet size value. */ -/** @} */ - -/** - * @name DOEPINT register bit definitions - * @{ - */ -#define DOEPINT_B2BSTUP (1U<<6) /**< Back-to-back SETUP packets - received. */ -#define DOEPINT_OTEPDIS (1U<<4) /**< OUT token received when - endpoint disabled. */ -#define DOEPINT_STUP (1U<<3) /**< SETUP phase done. */ -#define DOEPINT_EPDISD (1U<<1) /**< Endpoint disabled - interrupt. */ -#define DOEPINT_XFRC (1U<<0) /**< Transfer completed - interrupt. */ -/** @} */ - -/** - * @name DOEPTSIZ register bit definitions - * @{ - */ -#define DOEPTSIZ_RXDPID_MASK (3U<<29) /**< Received data PID mask. */ -#define DOEPTSIZ_RXDPID(n) ((n)<<29) /**< Received data PID value. */ -#define DOEPTSIZ_STUPCNT_MASK (3U<<29) /**< SETUP packet count mask. */ -#define DOEPTSIZ_STUPCNT(n) ((n)<<29) /**< SETUP packet count value. */ -#define DOEPTSIZ_PKTCNT_MASK (0x3FFU<<19)/**< Packet count mask. */ -#define DOEPTSIZ_PKTCNT(n) ((n)<<19) /**< Packet count value. */ -#define DOEPTSIZ_XFRSIZ_MASK (0x7FFFFU<<0)/**< Transfer size mask. */ -#define DOEPTSIZ_XFRSIZ(n) ((n)<<0) /**< Transfer size value. */ -/** @} */ - -/** - * @name PCGCCTL register bit definitions - * @{ - */ -#define PCGCCTL_PHYSUSP (1U<<4) /**< PHY Suspended. */ -#define PCGCCTL_GATEHCLK (1U<<1) /**< Gate HCLK. */ -#define PCGCCTL_STPPCLK (1U<<0) /**< Stop PCLK. */ -/** @} */ - -/** - * @brief OTG_FS registers block memory address. - */ -#define OTG_FS_ADDR 0x50000000 - -/** - * @brief OTG_HS registers block memory address. - */ -#define OTG_HS_ADDR 0x40040000 - -/** - * @brief Accesses to the OTG_FS registers block. - */ -#define OTG_FS ((stm32_otg_t *)OTG_FS_ADDR) - -/** - * @brief Accesses to the OTG_HS registers block. - */ -#define OTG_HS ((stm32_otg_t *)OTG_HS_ADDR) - -#endif /* _STM32_OTG_H_ */ - -/** @} */ diff --git a/os/hal/platforms/STM32/OTGv1/usb_lld.c b/os/hal/platforms/STM32/OTGv1/usb_lld.c deleted file mode 100644 index f6287a49c..000000000 --- a/os/hal/platforms/STM32/OTGv1/usb_lld.c +++ /dev/null @@ -1,1300 +0,0 @@ -/* - ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file STM32/OTGv1/usb_lld.c - * @brief STM32 USB subsystem low level driver source. - * - * @addtogroup USB - * @{ - */ - -#include - -#include "ch.h" -#include "hal.h" - -#if HAL_USE_USB || defined(__DOXYGEN__) - -/*===========================================================================*/ -/* Driver local definitions. */ -/*===========================================================================*/ - -#define TRDT_VALUE 5 - -/*===========================================================================*/ -/* Driver exported variables. */ -/*===========================================================================*/ - -/** @brief OTG_FS driver identifier.*/ -#if STM32_USB_USE_OTG1 || defined(__DOXYGEN__) -USBDriver USBD1; -#endif - -/** @brief OTG_HS driver identifier.*/ -#if STM32_USB_USE_OTG2 || defined(__DOXYGEN__) -USBDriver USBD2; -#endif - -/*===========================================================================*/ -/* Driver local variables and types. */ -/*===========================================================================*/ - -/** - * @brief EP0 state. - * @note It is an union because IN and OUT endpoints are never used at the - * same time for EP0. - */ -static union { - /** - * @brief IN EP0 state. - */ - USBInEndpointState in; - /** - * @brief OUT EP0 state. - */ - USBOutEndpointState out; -} ep0_state; - -/** - * @brief Buffer for the EP0 setup packets. - */ -static uint8_t ep0setup_buffer[8]; - -/** - * @brief EP0 initialization structure. - */ -static const USBEndpointConfig ep0config = { - USB_EP_MODE_TYPE_CTRL, - _usb_ep0setup, - _usb_ep0in, - _usb_ep0out, - 0x40, - 0x40, - &ep0_state.in, - &ep0_state.out, - 1, - ep0setup_buffer -}; - -#if STM32_USB_USE_OTG1 -static const stm32_otg_params_t fsparams = { - STM32_USB_OTG1_RX_FIFO_SIZE / 4, - STM32_OTG1_FIFO_MEM_SIZE, - STM32_OTG1_ENDOPOINTS_NUMBER -}; -#endif - -#if STM32_USB_USE_OTG2 -static const stm32_otg_params_t hsparams = { - STM32_USB_OTG2_RX_FIFO_SIZE / 4, - STM32_OTG2_FIFO_MEM_SIZE, - STM32_OTG2_ENDOPOINTS_NUMBER -}; -#endif - -/*===========================================================================*/ -/* Driver local functions. */ -/*===========================================================================*/ - -/** - * @brief Wakes up the pump thread. - * - * @param[in] usbp pointer to the @p USBDriver object - * - * @notapi - */ -static void usb_lld_wakeup_pump(USBDriver *usbp) { - - if (usbp->thd_wait != NULL) { - chThdResumeI(usbp->thd_wait); - usbp->thd_wait = NULL; - } -} - -static void otg_core_reset(USBDriver *usbp) { - stm32_otg_t *otgp = usbp->otg; - - /* Core reset and delay of at least 3 PHY cycles.*/ - otgp->GRSTCTL = GRSTCTL_CSRST; - while ((otgp->GRSTCTL & GRSTCTL_CSRST) != 0) - ; - halPolledDelay(12); - /* Wait AHB idle condition.*/ - while ((otgp->GRSTCTL & GRSTCTL_AHBIDL) == 0) - ; -} - -static void otg_disable_ep(USBDriver *usbp) { - stm32_otg_t *otgp = usbp->otg; - unsigned i; - - for (i = 0; i <= usbp->otgparams->num_endpoints; i++) { - /* Disable only if enabled because this sentence in the manual: - "The application must set this bit only if Endpoint Enable is - already set for this endpoint".*/ - if ((otgp->ie[i].DIEPCTL & DIEPCTL_EPENA) != 0) { - otgp->ie[i].DIEPCTL = DIEPCTL_EPDIS; - /* Wait for endpoint disable.*/ - while (!(otgp->ie[i].DIEPINT & DIEPINT_EPDISD)) - ; - } - else - otgp->ie[i].DIEPCTL = 0; - otgp->ie[i].DIEPTSIZ = 0; - otgp->ie[i].DIEPINT = 0xFFFFFFFF; - /* Disable only if enabled because this sentence in the manual: - "The application must set this bit only if Endpoint Enable is - already set for this endpoint". - Note that the attempt to disable the OUT EP0 is ignored by the - hardware but the code is simpler this way.*/ - if ((otgp->oe[i].DOEPCTL & DOEPCTL_EPENA) != 0) { - otgp->oe[i].DOEPCTL = DOEPCTL_EPDIS; - /* Wait for endpoint disable.*/ - while (!(otgp->oe[i].DOEPINT & DOEPINT_OTEPDIS)) - ; - } - else - otgp->oe[i].DOEPCTL = 0; - otgp->oe[i].DOEPTSIZ = 0; - otgp->oe[i].DOEPINT = 0xFFFFFFFF; - } - otgp->DAINTMSK = DAINTMSK_OEPM(0) | DAINTMSK_IEPM(0); -} - -static void otg_rxfifo_flush(USBDriver *usbp) { - stm32_otg_t *otgp = usbp->otg; - - otgp->GRSTCTL = GRSTCTL_RXFFLSH; - while ((otgp->GRSTCTL & GRSTCTL_RXFFLSH) != 0) - ; - /* Wait for 3 PHY Clocks.*/ - halPolledDelay(12); -} - -static void otg_txfifo_flush(USBDriver *usbp, uint32_t fifo) { - stm32_otg_t *otgp = usbp->otg; - - otgp->GRSTCTL = GRSTCTL_TXFNUM(fifo) | GRSTCTL_TXFFLSH; - while ((otgp->GRSTCTL & GRSTCTL_TXFFLSH) != 0) - ; - /* Wait for 3 PHY Clocks.*/ - halPolledDelay(12); -} - -/** - * @brief Resets the FIFO RAM memory allocator. - * - * @param[in] usbp pointer to the @p USBDriver object - * - * @notapi - */ -static void otg_ram_reset(USBDriver *usbp) { - - usbp->pmnext = usbp->otgparams->rx_fifo_size; -} - -/** - * @brief Allocates a block from the FIFO RAM memory. - * - * @param[in] usbp pointer to the @p USBDriver object - * @param[in] size size of the packet buffer to allocate in words - * - * @notapi - */ -static uint32_t otg_ram_alloc(USBDriver *usbp, size_t size) { - uint32_t next; - - next = usbp->pmnext; - usbp->pmnext += size; - chDbgAssert(usbp->pmnext <= usbp->otgparams->otg_ram_size, - "otg_fifo_alloc(), #1", "OTG FIFO memory overflow"); - return next; -} - -/** - * @brief Pushes a series of words into a FIFO. - * - * @param[in] fifop pointer to the FIFO register - * @param[in] buf pointer to the words buffer, not necessarily word - * aligned - * @param[in] n number of words to push - * - * @return A pointer after the last word pushed. - * - * @notapi - */ -static uint8_t *otg_do_push(volatile uint32_t *fifop, uint8_t *buf, size_t n) { - - while (n > 0) { - /* Note, this line relies on the Cortex-M3/M4 ability to perform - unaligned word accesses and on the LSB-first memory organization.*/ - *fifop = *((uint32_t *)buf); - buf += 4; - n--; - } - return buf; -} - -/** - * @brief Writes to a TX FIFO. - * - * @param[in] fifop pointer to the FIFO register - * @param[in] buf buffer where to copy the endpoint data - * @param[in] n maximum number of bytes to copy - * - * @notapi - */ -static void otg_fifo_write_from_buffer(volatile uint32_t *fifop, - const uint8_t *buf, - size_t n) { - - otg_do_push(fifop, (uint8_t *)buf, (n + 3) / 4); -} - -/** - * @brief Writes to a TX FIFO fetching data from a queue. - * - * @param[in] fifop pointer to the FIFO register - * @param[in] oqp pointer to an @p OutputQueue object - * @param[in] n maximum number of bytes to copy - * - * @notapi - */ -static void otg_fifo_write_from_queue(volatile uint32_t *fifop, - OutputQueue *oqp, - size_t n) { - size_t ntogo; - - ntogo = n; - while (ntogo > 0) { - uint32_t w, i; - size_t nw = ntogo / 4; - - if (nw > 0) { - size_t streak; - uint32_t nw2end = (oqp->q_top - oqp->q_rdptr) / 4; - - ntogo -= (streak = nw <= nw2end ? nw : nw2end) * 4; - oqp->q_rdptr = otg_do_push(fifop, oqp->q_rdptr, streak); - if (oqp->q_rdptr >= oqp->q_top) { - oqp->q_rdptr = oqp->q_buffer; - continue; - } - } - - /* If this condition is not satisfied then there is a word lying across - queue circular buffer boundary or there are some remaining bytes.*/ - if (ntogo <= 0) - break; - - /* One byte at time.*/ - w = 0; - i = 0; - while ((ntogo > 0) && (i < 4)) { - w |= (uint32_t)*oqp->q_rdptr++ << (i * 8); - if (oqp->q_rdptr >= oqp->q_top) - oqp->q_rdptr = oqp->q_buffer; - ntogo--; - i++; - } - *fifop = w; - } - - /* Updating queue.*/ - chSysLock(); - oqp->q_counter += n; - while (notempty(&oqp->q_waiting)) - chSchReadyI(fifo_remove(&oqp->q_waiting))->p_u.rdymsg = Q_OK; - chSchRescheduleS(); - chSysUnlock(); -} - -/** - * @brief Pops a series of words from a FIFO. - * - * @param[in] fifop pointer to the FIFO register - * @param[in] buf pointer to the words buffer, not necessarily word - * aligned - * @param[in] n number of words to push - * - * @return A pointer after the last word pushed. - * - * @notapi - */ -static uint8_t *otg_do_pop(volatile uint32_t *fifop, uint8_t *buf, size_t n) { - - while (n > 0) { - uint32_t w = *fifop; - /* Note, this line relies on the Cortex-M3/M4 ability to perform - unaligned word accesses and on the LSB-first memory organization.*/ - *((uint32_t *)buf) = w; - buf += 4; - n--; - } - return buf; -} - -/** - * @brief Reads a packet from the RXFIFO. - * - * @param[in] fifop pointer to the FIFO register - * @param[out] buf buffer where to copy the endpoint data - * @param[in] n number of bytes to pull from the FIFO - * @param[in] max number of bytes to copy into the buffer - * - * @notapi - */ -static void otg_fifo_read_to_buffer(volatile uint32_t *fifop, - uint8_t *buf, - size_t n, - size_t max) { - - n = (n + 3) / 4; - max = (max + 3) / 4; - while (n) { - uint32_t w = *fifop; - if (max) { - /* Note, this line relies on the Cortex-M3/M4 ability to perform - unaligned word accesses and on the LSB-first memory organization.*/ - *((uint32_t *)buf) = w; - buf += 4; - max--; - } - n--; - } -} - -/** - * @brief Reads a packet from the RXFIFO. - * - * @param[in] fifop pointer to the FIFO register - * @param[in] iqp pointer to an @p InputQueue object - * @param[in] n number of bytes to pull from the FIFO - * - * @notapi - */ -static void otg_fifo_read_to_queue(volatile uint32_t *fifop, - InputQueue *iqp, - size_t n) { - size_t ntogo; - - ntogo = n; - while (ntogo > 0) { - uint32_t w, i; - size_t nw = ntogo / 4; - - if (nw > 0) { - size_t streak; - uint32_t nw2end = (iqp->q_wrptr - iqp->q_wrptr) / 4; - - ntogo -= (streak = nw <= nw2end ? nw : nw2end) * 4; - iqp->q_wrptr = otg_do_pop(fifop, iqp->q_wrptr, streak); - if (iqp->q_wrptr >= iqp->q_top) { - iqp->q_wrptr = iqp->q_buffer; - continue; - } - } - - /* If this condition is not satisfied then there is a word lying across - queue circular buffer boundary or there are some remaining bytes.*/ - if (ntogo <= 0) - break; - - /* One byte at time.*/ - w = *fifop; - i = 0; - while ((ntogo > 0) && (i < 4)) { - *iqp->q_wrptr++ = (uint8_t)(w >> (i * 8)); - if (iqp->q_wrptr >= iqp->q_top) - iqp->q_wrptr = iqp->q_buffer; - ntogo--; - i++; - } - } - - /* Updating queue.*/ - chSysLock(); - iqp->q_counter += n; - while (notempty(&iqp->q_waiting)) - chSchReadyI(fifo_remove(&iqp->q_waiting))->p_u.rdymsg = Q_OK; - chSchRescheduleS(); - chSysUnlock(); -} - -/** - * @brief Incoming packets handler. - * - * @param[in] usbp pointer to the @p USBDriver object - * - * @notapi - */ -static void otg_rxfifo_handler(USBDriver *usbp) { - uint32_t sts, cnt, ep; - - sts = usbp->otg->GRXSTSP; - switch (sts & GRXSTSP_PKTSTS_MASK) { - case GRXSTSP_SETUP_COMP: - break; - case GRXSTSP_SETUP_DATA: - cnt = (sts & GRXSTSP_BCNT_MASK) >> GRXSTSP_BCNT_OFF; - ep = (sts & GRXSTSP_EPNUM_MASK) >> GRXSTSP_EPNUM_OFF; - otg_fifo_read_to_buffer(usbp->otg->FIFO[0], usbp->epc[ep]->setup_buf, - cnt, 8); - break; - case GRXSTSP_OUT_DATA: - cnt = (sts & GRXSTSP_BCNT_MASK) >> GRXSTSP_BCNT_OFF; - ep = (sts & GRXSTSP_EPNUM_MASK) >> GRXSTSP_EPNUM_OFF; - if (usbp->epc[ep]->out_state->rxqueued) { - /* Queue associated.*/ - otg_fifo_read_to_queue(usbp->otg->FIFO[0], - usbp->epc[ep]->out_state->mode.queue.rxqueue, - cnt); - } - else { - otg_fifo_read_to_buffer(usbp->otg->FIFO[0], - usbp->epc[ep]->out_state->mode.linear.rxbuf, - cnt, - usbp->epc[ep]->out_state->rxsize - - usbp->epc[ep]->out_state->rxcnt); - usbp->epc[ep]->out_state->mode.linear.rxbuf += cnt; - } - usbp->epc[ep]->out_state->rxcnt += cnt; - break; - case GRXSTSP_OUT_GLOBAL_NAK: - case GRXSTSP_OUT_COMP: - default: - ; - } -} - -/** - * @brief Outgoing packets handler. - * - * @param[in] usbp pointer to the @p USBDriver object - * @param[in] ep endpoint number - * - * @notapi - */ -static bool_t otg_txfifo_handler(USBDriver *usbp, usbep_t ep) { - - /* The TXFIFO is filled until there is space and data to be transmitted.*/ - while (TRUE) { - uint32_t n; - - /* Transaction end condition.*/ - if (usbp->epc[ep]->in_state->txcnt >= usbp->epc[ep]->in_state->txsize) - return TRUE; - - /* Number of bytes remaining in current transaction.*/ - n = usbp->epc[ep]->in_state->txsize - usbp->epc[ep]->in_state->txcnt; - if (n > usbp->epc[ep]->in_maxsize) - n = usbp->epc[ep]->in_maxsize; - - /* Checks if in the TXFIFO there is enough space to accommodate the - next packet.*/ - if (((usbp->otg->ie[ep].DTXFSTS & DTXFSTS_INEPTFSAV_MASK) * 4) < n) - return FALSE; - -#if STM32_USB_OTGFIFO_FILL_BASEPRI - __set_BASEPRI(CORTEX_PRIORITY_MASK(STM32_USB_OTGFIFO_FILL_BASEPRI)); -#endif - /* Handles the two cases: linear buffer or queue.*/ - if (usbp->epc[ep]->in_state->txqueued) { - /* Queue associated.*/ - otg_fifo_write_from_queue(usbp->otg->FIFO[ep], - usbp->epc[ep]->in_state->mode.queue.txqueue, - n); - } - else { - /* Linear buffer associated.*/ - otg_fifo_write_from_buffer(usbp->otg->FIFO[ep], - usbp->epc[ep]->in_state->mode.linear.txbuf, - n); - usbp->epc[ep]->in_state->mode.linear.txbuf += n; - } - usbp->epc[ep]->in_state->txcnt += n; - } -#if STM32_USB_OTGFIFO_FILL_BASEPRI - __set_BASEPRI(0); -#endif -} - -/** - * @brief Generic endpoint IN handler. - * - * @param[in] usbp pointer to the @p USBDriver object - * @param[in] ep endpoint number - * - * @notapi - */ -static void otg_epin_handler(USBDriver *usbp, usbep_t ep) { - stm32_otg_t *otgp = usbp->otg; - uint32_t epint = otgp->ie[ep].DIEPINT; - - otgp->ie[ep].DIEPINT = 0xFFFFFFFF; - - if (epint & DIEPINT_TOC) { - /* Timeouts not handled yet, not sure how to handle.*/ - } - if ((epint & DIEPINT_XFRC) && (otgp->DIEPMSK & DIEPMSK_XFRCM)) { - /* Transmit transfer complete.*/ - _usb_isr_invoke_in_cb(usbp, ep); - } - if ((epint & DIEPINT_TXFE) && - (otgp->DIEPEMPMSK & DIEPEMPMSK_INEPTXFEM(ep))) { - /* The thread is made ready, it will be scheduled on ISR exit.*/ - chSysLockFromIsr(); - usbp->txpending |= (1 << ep); - otgp->DIEPEMPMSK &= ~(1 << ep); - usb_lld_wakeup_pump(usbp); - chSysUnlockFromIsr(); - } -} - -/** - * @brief Generic endpoint OUT handler. - * - * @param[in] usbp pointer to the @p USBDriver object - * @param[in] ep endpoint number - * - * @notapi - */ -static void otg_epout_handler(USBDriver *usbp, usbep_t ep) { - stm32_otg_t *otgp = usbp->otg; - uint32_t epint = otgp->oe[ep].DOEPINT; - - /* Resets all EP IRQ sources.*/ - otgp->oe[ep].DOEPINT = 0xFFFFFFFF; - - if ((epint & DOEPINT_STUP) && (otgp->DOEPMSK & DOEPMSK_STUPM)) { - /* Setup packets handling, setup packets are handled using a - specific callback.*/ - _usb_isr_invoke_setup_cb(usbp, ep); - - } - if ((epint & DOEPINT_XFRC) && (otgp->DOEPMSK & DOEPMSK_XFRCM)) { - /* Receive transfer complete.*/ - _usb_isr_invoke_out_cb(usbp, ep); - } -} - -/** - * @brief OTG shared ISR. - * - * @param[in] usbp pointer to the @p USBDriver object - * - * @notapi - */ -static void usb_lld_serve_interrupt(USBDriver *usbp) { - stm32_otg_t *otgp = usbp->otg; - uint32_t sts, src; - - sts = otgp->GINTSTS & otgp->GINTMSK; - otgp->GINTSTS = sts; - - /* Reset interrupt handling.*/ - if (sts & GINTSTS_USBRST) { - _usb_reset(usbp); - _usb_isr_invoke_event_cb(usbp, USB_EVENT_RESET); - } - - /* Enumeration done.*/ - if (sts & GINTSTS_ENUMDNE) { - (void)otgp->DSTS; - } - - /* SOF interrupt handling.*/ - if (sts & GINTSTS_SOF) { - _usb_isr_invoke_sof_cb(usbp); - } - - /* RX FIFO not empty handling.*/ - if (sts & GINTSTS_RXFLVL) { - /* The interrupt is masked while the thread has control or it would - be triggered again.*/ - chSysLockFromIsr(); - otgp->GINTMSK &= ~GINTMSK_RXFLVLM; - usb_lld_wakeup_pump(usbp); - chSysUnlockFromIsr(); - } - - /* IN/OUT endpoints event handling.*/ - src = otgp->DAINT; - if (sts & GINTSTS_IEPINT) { - if (src & (1 << 0)) - otg_epin_handler(usbp, 0); - if (src & (1 << 1)) - otg_epin_handler(usbp, 1); - if (src & (1 << 2)) - otg_epin_handler(usbp, 2); - if (src & (1 << 3)) - otg_epin_handler(usbp, 3); -#if STM32_USB_USE_OTG2 - if (src & (1 << 4)) - otg_epin_handler(usbp, 4); - if (src & (1 << 5)) - otg_epin_handler(usbp, 5); -#endif - } - if (sts & GINTSTS_OEPINT) { - if (src & (1 << 16)) - otg_epout_handler(usbp, 0); - if (src & (1 << 17)) - otg_epout_handler(usbp, 1); - if (src & (1 << 18)) - otg_epout_handler(usbp, 2); - if (src & (1 << 19)) - otg_epout_handler(usbp, 3); -#if STM32_USB_USE_OTG2 - if (src & (1 << 20)) - otg_epout_handler(usbp, 4); - if (src & (1 << 21)) - otg_epout_handler(usbp, 5); -#endif - } -} - -/*===========================================================================*/ -/* Driver interrupt handlers and threads. */ -/*===========================================================================*/ - -static msg_t usb_lld_pump(void *p) { - USBDriver *usbp = (USBDriver *)p; - stm32_otg_t *otgp = usbp->otg; - - chRegSetThreadName("usb_lld_pump"); - chSysLock(); - while (TRUE) { - usbep_t ep; - uint32_t epmask; - - /* Nothing to do, going to sleep.*/ - if ((usbp->state == USB_STOP) || - ((usbp->txpending == 0) && !(otgp->GINTSTS & GINTSTS_RXFLVL))) { - otgp->GINTMSK |= GINTMSK_RXFLVLM; - usbp->thd_wait = chThdSelf(); - chSchGoSleepS(THD_STATE_SUSPENDED); - } - chSysUnlock(); - - /* Checks if there are TXFIFOs to be filled.*/ - for (ep = 0; ep <= usbp->otgparams->num_endpoints; ep++) { - - /* Empties the RX FIFO.*/ - while (otgp->GINTSTS & GINTSTS_RXFLVL) { - otg_rxfifo_handler(usbp); - } - - epmask = (1 << ep); - if (usbp->txpending & epmask) { - bool_t done; - - chSysLock(); - /* USB interrupts are globally *suspended* because the peripheral - does not allow any interference during the TX FIFO filling - operation. - Synopsys document: DesignWare Cores USB 2.0 Hi-Speed On-The-Go (OTG) - "The application has to finish writing one complete packet before - switching to a different channel/endpoint FIFO. Violating this - rule results in an error.".*/ - otgp->GAHBCFG &= ~GAHBCFG_GINTMSK; - usbp->txpending &= ~epmask; - chSysUnlock(); - - done = otg_txfifo_handler(usbp, ep); - - chSysLock(); - otgp->GAHBCFG |= GAHBCFG_GINTMSK; - if (!done) - otgp->DIEPEMPMSK |= epmask; - chSysUnlock(); - } - } - chSysLock(); - } - chSysUnlock(); - return 0; -} - -#if STM32_USB_USE_OTG1 || defined(__DOXYGEN__) -#if !defined(STM32_OTG1_HANDLER) -#error "STM32_OTG1_HANDLER not defined" -#endif -/** - * @brief OTG1 interrupt handler. - * - * @isr - */ -CH_IRQ_HANDLER(STM32_OTG1_HANDLER) { - - CH_IRQ_PROLOGUE(); - - usb_lld_serve_interrupt(&USBD1); - - CH_IRQ_EPILOGUE(); -} -#endif - -#if STM32_USB_USE_OTG2 || defined(__DOXYGEN__) -#if !defined(STM32_OTG2_HANDLER) -#error "STM32_OTG2_HANDLER not defined" -#endif -/** - * @brief OTG2 interrupt handler. - * - * @isr - */ -CH_IRQ_HANDLER(STM32_OTG2_HANDLER) { - - CH_IRQ_PROLOGUE(); - - usb_lld_serve_interrupt(&USBD2); - - CH_IRQ_EPILOGUE(); -} -#endif - -/*===========================================================================*/ -/* Driver exported functions. */ -/*===========================================================================*/ - -/** - * @brief Low level USB driver initialization. - * - * @notapi - */ -void usb_lld_init(void) { - - /* Driver initialization.*/ -#if STM32_USB_USE_OTG1 - usbObjectInit(&USBD1); - USBD1.thd_ptr = NULL; - USBD1.thd_wait = NULL; - USBD1.otg = OTG_FS; - USBD1.otgparams = &fsparams; - - /* Filling the thread working area here because the function - @p chThdCreateI() does not do it.*/ -#if CH_DBG_FILL_THREADS - { - void *wsp = USBD1.wa_pump; - _thread_memfill((uint8_t *)wsp, - (uint8_t *)wsp + sizeof(Thread), - CH_THREAD_FILL_VALUE); - _thread_memfill((uint8_t *)wsp + sizeof(Thread), - (uint8_t *)wsp + sizeof(USBD1.wa_pump) - sizeof(Thread), - CH_STACK_FILL_VALUE); - } -#endif -#endif - -#if STM32_USB_USE_OTG2 - usbObjectInit(&USBD2); - USBD2.thd_ptr = NULL; - USBD2.thd_wait = NULL; - USBD2.otg = OTG_HS; - USBD2.otgparams = &hsparams; - - /* Filling the thread working area here because the function - @p chThdCreateI() does not do it.*/ -#if CH_DBG_FILL_THREADS - { - void *wsp = USBD2.wa_pump; - _thread_memfill((uint8_t *)wsp, - (uint8_t *)wsp + sizeof(Thread), - CH_THREAD_FILL_VALUE); - _thread_memfill((uint8_t *)wsp + sizeof(Thread), - (uint8_t *)wsp + sizeof(USBD2.wa_pump) - sizeof(Thread), - CH_STACK_FILL_VALUE); - } -#endif -#endif -} - -/** - * @brief Configures and activates the USB peripheral. - * @note Starting the OTG cell can be a slow operation carried out with - * interrupts disabled, perform it before starting time-critical - * operations. - * - * @param[in] usbp pointer to the @p USBDriver object - * - * @notapi - */ -void usb_lld_start(USBDriver *usbp) { - stm32_otg_t *otgp = usbp->otg; - - if (usbp->state == USB_STOP) { - /* Clock activation.*/ -#if STM32_USB_USE_OTG1 - if (&USBD1 == usbp) { - /* OTG FS clock enable and reset.*/ - rccEnableOTG_FS(FALSE); - rccResetOTG_FS(); - - /* Enables IRQ vector.*/ - nvicEnableVector(STM32_OTG1_NUMBER, - CORTEX_PRIORITY_MASK(STM32_USB_OTG1_IRQ_PRIORITY)); - } -#endif -#if STM32_USB_USE_OTG2 - if (&USBD2 == usbp) { - /* OTG HS clock enable and reset.*/ - rccEnableOTG_HS(FALSE); - rccResetOTG_HS(); - - /* Enables IRQ vector.*/ - nvicEnableVector(STM32_OTG2_NUMBER, - CORTEX_PRIORITY_MASK(STM32_USB_OTG2_IRQ_PRIORITY)); - } -#endif - - /* Creates the data pump threads in a suspended state. Note, it is - created only once, the first time @p usbStart() is invoked.*/ - usbp->txpending = 0; - if (usbp->thd_ptr == NULL) - usbp->thd_ptr = usbp->thd_wait = chThdCreateI(usbp->wa_pump, - sizeof usbp->wa_pump, - STM32_USB_OTG_THREAD_PRIO, - usb_lld_pump, - usbp); - - /* - Forced device mode. - - USB turn-around time = TRDT_VALUE. - - Full Speed 1.1 PHY.*/ - otgp->GUSBCFG = GUSBCFG_FDMOD | GUSBCFG_TRDT(TRDT_VALUE) | GUSBCFG_PHYSEL; - - /* 48MHz 1.1 PHY.*/ - otgp->DCFG = 0x02200000 | DCFG_DSPD_FS11; - - /* PHY enabled.*/ - otgp->PCGCCTL = 0; - - /* Internal FS PHY activation.*/ - otgp->GCCFG = GCCFG_VBUSASEN | GCCFG_VBUSBSEN | GCCFG_PWRDWN; - - /* Soft core reset.*/ - otg_core_reset(usbp); - - /* Interrupts on TXFIFOs half empty.*/ - otgp->GAHBCFG = 0; - - /* Endpoints re-initialization.*/ - otg_disable_ep(usbp); - - /* Clear all pending Device Interrupts, only the USB Reset interrupt - is required initially.*/ - otgp->DIEPMSK = 0; - otgp->DOEPMSK = 0; - otgp->DAINTMSK = 0; - if (usbp->config->sof_cb == NULL) - otgp->GINTMSK = GINTMSK_ENUMDNEM | GINTMSK_USBRSTM /*| GINTMSK_USBSUSPM | - GINTMSK_ESUSPM |*/; - else - otgp->GINTMSK = GINTMSK_ENUMDNEM | GINTMSK_USBRSTM /*| GINTMSK_USBSUSPM | - GINTMSK_ESUSPM */ | GINTMSK_SOFM; - otgp->GINTSTS = 0xFFFFFFFF; /* Clears all pending IRQs, if any. */ - - /* Global interrupts enable.*/ - otgp->GAHBCFG |= GAHBCFG_GINTMSK; - } -} - -/** - * @brief Deactivates the USB peripheral. - * - * @param[in] usbp pointer to the @p USBDriver object - * - * @notapi - */ -void usb_lld_stop(USBDriver *usbp) { - stm32_otg_t *otgp = usbp->otg; - - /* If in ready state then disables the USB clock.*/ - if (usbp->state != USB_STOP) { - - /* Disabling all endpoints in case the driver has been stopped while - active.*/ - otg_disable_ep(usbp); - - usbp->txpending = 0; - - otgp->DAINTMSK = 0; - otgp->GAHBCFG = 0; - otgp->GCCFG = 0; - -#if STM32_USB_USE_USB1 - if (&USBD1 == usbp) { - nvicDisableVector(STM32_OTG1_NUMBER); - rccDisableOTG1(FALSE); - } -#endif - -#if STM32_USB_USE_USB2 - if (&USBD2 == usbp) { - nvicDisableVector(STM32_OTG2_NUMBER); - rccDisableOTG2(FALSE); - } -#endif - } -} - -/** - * @brief USB low level reset routine. - * - * @param[in] usbp pointer to the @p USBDriver object - * - * @notapi - */ -void usb_lld_reset(USBDriver *usbp) { - unsigned i; - stm32_otg_t *otgp = usbp->otg; - - /* Flush the Tx FIFO.*/ - otg_txfifo_flush(usbp, 0); - - /* All endpoints in NAK mode, interrupts cleared.*/ - for (i = 0; i <= usbp->otgparams->num_endpoints; i++) { - otgp->ie[i].DIEPCTL = DIEPCTL_SNAK; - otgp->oe[i].DOEPCTL = DOEPCTL_SNAK; - otgp->ie[i].DIEPINT = 0xFF; - otgp->oe[i].DOEPINT = 0xFF; - } - - /* Endpoint interrupts all disabled and cleared.*/ - otgp->DAINT = 0xFFFFFFFF; - otgp->DAINTMSK = DAINTMSK_OEPM(0) | DAINTMSK_IEPM(0); - - /* Resets the FIFO memory allocator.*/ - otg_ram_reset(usbp); - - /* Receive FIFO size initialization, the address is always zero.*/ - otgp->GRXFSIZ = usbp->otgparams->rx_fifo_size; - otg_rxfifo_flush(usbp); - - /* Resets the device address to zero.*/ - otgp->DCFG = (otgp->DCFG & ~DCFG_DAD_MASK) | DCFG_DAD(0); - - /* Enables also EP-related interrupt sources.*/ - otgp->GINTMSK |= GINTMSK_RXFLVLM | GINTMSK_OEPM | GINTMSK_IEPM; - otgp->DIEPMSK = DIEPMSK_TOCM | DIEPMSK_XFRCM; - otgp->DOEPMSK = DOEPMSK_STUPM | DOEPMSK_XFRCM; - - /* EP0 initialization, it is a special case.*/ - usbp->epc[0] = &ep0config; - otgp->oe[0].DOEPTSIZ = 0; - otgp->oe[0].DOEPCTL = DOEPCTL_SD0PID | DOEPCTL_USBAEP | DOEPCTL_EPTYP_CTRL | - DOEPCTL_MPSIZ(ep0config.out_maxsize); - otgp->ie[0].DIEPTSIZ = 0; - otgp->ie[0].DIEPCTL = DIEPCTL_SD0PID | DIEPCTL_USBAEP | DIEPCTL_EPTYP_CTRL | - DIEPCTL_TXFNUM(0) | DIEPCTL_MPSIZ(ep0config.in_maxsize); - otgp->DIEPTXF0 = DIEPTXF_INEPTXFD(ep0config.in_maxsize / 4) | - DIEPTXF_INEPTXSA(otg_ram_alloc(usbp, - ep0config.in_maxsize / 4)); -} - -/** - * @brief Sets the USB address. - * - * @param[in] usbp pointer to the @p USBDriver object - * - * @notapi - */ -void usb_lld_set_address(USBDriver *usbp) { - stm32_otg_t *otgp = usbp->otg; - - otgp->DCFG = (otgp->DCFG & ~DCFG_DAD_MASK) | DCFG_DAD(usbp->address); -} - -/** - * @brief Enables an endpoint. - * - * @param[in] usbp pointer to the @p USBDriver object - * @param[in] ep endpoint number - * - * @notapi - */ -void usb_lld_init_endpoint(USBDriver *usbp, usbep_t ep) { - uint32_t ctl, fsize; - stm32_otg_t *otgp = usbp->otg; - - /* IN and OUT common parameters.*/ - switch (usbp->epc[ep]->ep_mode & USB_EP_MODE_TYPE) { - case USB_EP_MODE_TYPE_CTRL: - ctl = DIEPCTL_SD0PID | DIEPCTL_USBAEP | DIEPCTL_EPTYP_CTRL; - break; - case USB_EP_MODE_TYPE_ISOC: - ctl = DIEPCTL_SD0PID | DIEPCTL_USBAEP | DIEPCTL_EPTYP_ISO; - break; - case USB_EP_MODE_TYPE_BULK: - ctl = DIEPCTL_SD0PID | DIEPCTL_USBAEP | DIEPCTL_EPTYP_BULK; - break; - case USB_EP_MODE_TYPE_INTR: - ctl = DIEPCTL_SD0PID | DIEPCTL_USBAEP | DIEPCTL_EPTYP_INTR; - break; - default: - return; - } - - /* OUT endpoint activation or deactivation.*/ - otgp->oe[ep].DOEPTSIZ = 0; - if (usbp->epc[ep]->out_cb != NULL) { - otgp->oe[ep].DOEPCTL = ctl | DOEPCTL_MPSIZ(usbp->epc[ep]->out_maxsize); - otgp->DAINTMSK |= DAINTMSK_OEPM(ep); - } - else { - otgp->oe[ep].DOEPCTL &= ~DOEPCTL_USBAEP; - otgp->DAINTMSK &= ~DAINTMSK_OEPM(ep); - } - - /* IN endpoint activation or deactivation.*/ - otgp->ie[ep].DIEPTSIZ = 0; - if (usbp->epc[ep]->in_cb != NULL) { - /* FIFO allocation for the IN endpoint.*/ - fsize = usbp->epc[ep]->in_maxsize / 4; - if (usbp->epc[ep]->in_multiplier > 1) - fsize *= usbp->epc[ep]->in_multiplier; - otgp->DIEPTXF[ep - 1] = DIEPTXF_INEPTXFD(fsize) | - DIEPTXF_INEPTXSA(otg_ram_alloc(usbp, fsize)); - otg_txfifo_flush(usbp, ep); - - otgp->ie[ep].DIEPCTL = ctl | - DIEPCTL_TXFNUM(ep) | - DIEPCTL_MPSIZ(usbp->epc[ep]->in_maxsize); - otgp->DAINTMSK |= DAINTMSK_IEPM(ep); - } - else { - otgp->DIEPTXF[ep - 1] = 0x02000400; /* Reset value.*/ - otg_txfifo_flush(usbp, ep); - otgp->ie[ep].DIEPCTL &= ~DIEPCTL_USBAEP; - otgp->DAINTMSK &= ~DAINTMSK_IEPM(ep); - } -} - -/** - * @brief Disables all the active endpoints except the endpoint zero. - * - * @param[in] usbp pointer to the @p USBDriver object - * - * @notapi - */ -void usb_lld_disable_endpoints(USBDriver *usbp) { - - /* Resets the FIFO memory allocator.*/ - otg_ram_reset(usbp); - - /* Disabling all endpoints.*/ - otg_disable_ep(usbp); -} - -/** - * @brief Returns the status of an OUT endpoint. - * - * @param[in] usbp pointer to the @p USBDriver object - * @param[in] ep endpoint number - * @return The endpoint status. - * @retval EP_STATUS_DISABLED The endpoint is not active. - * @retval EP_STATUS_STALLED The endpoint is stalled. - * @retval EP_STATUS_ACTIVE The endpoint is active. - * - * @notapi - */ -usbepstatus_t usb_lld_get_status_out(USBDriver *usbp, usbep_t ep) { - uint32_t ctl; - - (void)usbp; - - ctl = usbp->otg->oe[ep].DOEPCTL; - if (!(ctl & DOEPCTL_USBAEP)) - return EP_STATUS_DISABLED; - if (ctl & DOEPCTL_STALL) - return EP_STATUS_STALLED; - return EP_STATUS_ACTIVE; -} - -/** - * @brief Returns the status of an IN endpoint. - * - * @param[in] usbp pointer to the @p USBDriver object - * @param[in] ep endpoint number - * @return The endpoint status. - * @retval EP_STATUS_DISABLED The endpoint is not active. - * @retval EP_STATUS_STALLED The endpoint is stalled. - * @retval EP_STATUS_ACTIVE The endpoint is active. - * - * @notapi - */ -usbepstatus_t usb_lld_get_status_in(USBDriver *usbp, usbep_t ep) { - uint32_t ctl; - - (void)usbp; - - ctl = usbp->otg->ie[ep].DIEPCTL; - if (!(ctl & DIEPCTL_USBAEP)) - return EP_STATUS_DISABLED; - if (ctl & DIEPCTL_STALL) - return EP_STATUS_STALLED; - return EP_STATUS_ACTIVE; -} - -/** - * @brief Reads a setup packet from the dedicated packet buffer. - * @details This function must be invoked in the context of the @p setup_cb - * callback in order to read the received setup packet. - * @pre In order to use this function the endpoint must have been - * initialized as a control endpoint. - * @post The endpoint is ready to accept another packet. - * - * @param[in] usbp pointer to the @p USBDriver object - * @param[in] ep endpoint number - * @param[out] buf buffer where to copy the packet data - * - * @notapi - */ -void usb_lld_read_setup(USBDriver *usbp, usbep_t ep, uint8_t *buf) { - - memcpy(buf, usbp->epc[ep]->setup_buf, 8); -} - -/** - * @brief Prepares for a receive operation. - * - * @param[in] usbp pointer to the @p USBDriver object - * @param[in] ep endpoint number - * - * @notapi - */ -void usb_lld_prepare_receive(USBDriver *usbp, usbep_t ep) { - uint32_t pcnt; - USBOutEndpointState *osp = usbp->epc[ep]->out_state; - - /* Transfer initialization.*/ - pcnt = (osp->rxsize + usbp->epc[ep]->out_maxsize - 1) / - usbp->epc[ep]->out_maxsize; - usbp->otg->oe[ep].DOEPTSIZ = DOEPTSIZ_STUPCNT(3) | DOEPTSIZ_PKTCNT(pcnt) | - DOEPTSIZ_XFRSIZ(usbp->epc[ep]->out_maxsize); - -} - -/** - * @brief Prepares for a transmit operation. - * - * @param[in] usbp pointer to the @p USBDriver object - * @param[in] ep endpoint number - * - * @notapi - */ -void usb_lld_prepare_transmit(USBDriver *usbp, usbep_t ep) { - USBInEndpointState *isp = usbp->epc[ep]->in_state; - - /* Transfer initialization.*/ - if (isp->txsize == 0) { - /* Special case, sending zero size packet.*/ - usbp->otg->ie[ep].DIEPTSIZ = DIEPTSIZ_PKTCNT(1) | DIEPTSIZ_XFRSIZ(0); - } - else { - /* Normal case.*/ - uint32_t pcnt = (isp->txsize + usbp->epc[ep]->in_maxsize - 1) / - usbp->epc[ep]->in_maxsize; - usbp->otg->ie[ep].DIEPTSIZ = DIEPTSIZ_PKTCNT(pcnt) | - DIEPTSIZ_XFRSIZ(usbp->epc[ep]->in_state->txsize); - } - -} - -/** - * @brief Starts a receive operation on an OUT endpoint. - * - * @param[in] usbp pointer to the @p USBDriver object - * @param[in] ep endpoint number - * - * @notapi - */ -void usb_lld_start_out(USBDriver *usbp, usbep_t ep) { - - usbp->otg->oe[ep].DOEPCTL |= DOEPCTL_CNAK; -} - -/** - * @brief Starts a transmit operation on an IN endpoint. - * - * @param[in] usbp pointer to the @p USBDriver object - * @param[in] ep endpoint number - * - * @notapi - */ -void usb_lld_start_in(USBDriver *usbp, usbep_t ep) { - - usbp->otg->ie[ep].DIEPCTL |= DIEPCTL_EPENA | DIEPCTL_CNAK; - usbp->otg->DIEPEMPMSK |= DIEPEMPMSK_INEPTXFEM(ep); -} - -/** - * @brief Brings an OUT endpoint in the stalled state. - * - * @param[in] usbp pointer to the @p USBDriver object - * @param[in] ep endpoint number - * - * @notapi - */ -void usb_lld_stall_out(USBDriver *usbp, usbep_t ep) { - - usbp->otg->oe[ep].DOEPCTL |= DOEPCTL_STALL; -} - -/** - * @brief Brings an IN endpoint in the stalled state. - * - * @param[in] usbp pointer to the @p USBDriver object - * @param[in] ep endpoint number - * - * @notapi - */ -void usb_lld_stall_in(USBDriver *usbp, usbep_t ep) { - - usbp->otg->ie[ep].DIEPCTL |= DIEPCTL_STALL; -} - -/** - * @brief Brings an OUT endpoint in the active state. - * - * @param[in] usbp pointer to the @p USBDriver object - * @param[in] ep endpoint number - * - * @notapi - */ -void usb_lld_clear_out(USBDriver *usbp, usbep_t ep) { - - usbp->otg->oe[ep].DOEPCTL &= ~DOEPCTL_STALL; -} - -/** - * @brief Brings an IN endpoint in the active state. - * - * @param[in] usbp pointer to the @p USBDriver object - * @param[in] ep endpoint number - * - * @notapi - */ -void usb_lld_clear_in(USBDriver *usbp, usbep_t ep) { - - usbp->otg->ie[ep].DIEPCTL &= ~DIEPCTL_STALL; -} - -#endif /* HAL_USE_USB */ - -/** @} */ diff --git a/os/hal/platforms/STM32/OTGv1/usb_lld.h b/os/hal/platforms/STM32/OTGv1/usb_lld.h deleted file mode 100644 index 570309750..000000000 --- a/os/hal/platforms/STM32/OTGv1/usb_lld.h +++ /dev/null @@ -1,534 +0,0 @@ -/* - ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file STM32/OTGv1/usb_lld.h - * @brief STM32 USB subsystem low level driver header. - * - * @addtogroup USB - * @{ - */ - -#ifndef _USB_LLD_H_ -#define _USB_LLD_H_ - -#if HAL_USE_USB || defined(__DOXYGEN__) - -#include "stm32_otg.h" - -/*===========================================================================*/ -/* Driver constants. */ -/*===========================================================================*/ - -/** - * @brief Maximum endpoint address. - */ -#if !STM32_USB_USE_OTG2 || defined(__DOXYGEN__) -#define USB_MAX_ENDPOINTS 3 -#else -#define USB_MAX_ENDPOINTS 5 -#endif - -/** - * @brief The address can be changed immediately upon packet reception. - */ -#define USB_SET_ADDRESS_MODE USB_EARLY_SET_ADDRESS - -/*===========================================================================*/ -/* Driver pre-compile time settings. */ -/*===========================================================================*/ - -/** - * @brief OTG1 driver enable switch. - * @details If set to @p TRUE the support for OTG_FS is included. - * @note The default is @p TRUE. - */ -#if !defined(STM32_USB_USE_OTG1) || defined(__DOXYGEN__) -#define STM32_USB_USE_OTG1 FALSE -#endif - -/** - * @brief OTG2 driver enable switch. - * @details If set to @p TRUE the support for OTG_HS is included. - * @note The default is @p TRUE. - */ -#if !defined(STM32_USB_USE_OTG2) || defined(__DOXYGEN__) -#define STM32_USB_USE_OTG2 FALSE -#endif - -/** - * @brief OTG1 interrupt priority level setting. - */ -#if !defined(STM32_USB_OTG1_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_USB_OTG1_IRQ_PRIORITY 14 -#endif - -/** - * @brief OTG2 interrupt priority level setting. - */ -#if !defined(STM32_USB_OTG2_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_USB_OTG2_IRQ_PRIORITY 14 -#endif - -/** - * @brief OTG1 RX shared FIFO size. - * @note Must be a multiple of 4. - */ -#if !defined(STM32_USB_OTG1_RX_FIFO_SIZE) || defined(__DOXYGEN__) -#define STM32_USB_OTG1_RX_FIFO_SIZE 512 -#endif - -/** - * @brief OTG2 RX shared FIFO size. - * @note Must be a multiple of 4. - */ -#if !defined(STM32_USB_OTG2_RX_FIFO_SIZE) || defined(__DOXYGEN__) -#define STM32_USB_OTG2_RX_FIFO_SIZE 1024 -#endif - -/** - * @brief Dedicated data pump threads priority. - */ -#if !defined(STM32_USB_OTG_THREAD_PRIO) || defined(__DOXYGEN__) -#define STM32_USB_OTG_THREAD_PRIO LOWPRIO -#endif - -/** - * @brief Dedicated data pump threads stack size. - */ -#if !defined(STM32_USB_OTG_THREAD_STACK_SIZE) || defined(__DOXYGEN__) -#define STM32_USB_OTG_THREAD_STACK_SIZE 128 -#endif - -/** - * @brief Exception priority level during TXFIFOs operations. - * @note Because an undocumented silicon behavior the operation of - * copying a packet into a TXFIFO must not be interrupted by - * any other operation on the OTG peripheral. - * This parameter represents the priority mask during copy - * operations. The default value only allows to call USB - * functions from callbacks invoked from USB ISR handlers. - * If you need to invoke USB functions from other handlers - * then raise this priority mast to the same level of the - * handler you need to use. - * @note The value zero means disabled, when disabled calling USB - * functions is only safe from thread level or from USB - * callbacks. - */ -#if !defined(STM32_USB_OTGFIFO_FILL_BASEPRI) || defined(__DOXYGEN__) -#define STM32_USB_OTGFIFO_FILL_BASEPRI 0 -#endif - -/*===========================================================================*/ -/* Derived constants and error checks. */ -/*===========================================================================*/ - -#if STM32_USB_USE_OTG1 && !STM32_HAS_OTG1 -#error "OTG1 not present in the selected device" -#endif - -#if STM32_USB_USE_OTG2 && !STM32_HAS_OTG2 -#error "OTG2 not present in the selected device" -#endif - -#if !STM32_USB_USE_OTG1 && !STM32_USB_USE_OTG2 -#error "USB driver activated but no USB peripheral assigned" -#endif - -#if STM32_USB_USE_OTG1 && \ - !CORTEX_IS_VALID_KERNEL_PRIORITY(STM32_USB_OTG1_IRQ_PRIORITY) -#error "Invalid IRQ priority assigned to OTG1" -#endif - -#if STM32_USB_USE_OTG2 && \ - !CORTEX_IS_VALID_KERNEL_PRIORITY(STM32_USB_OTG2_IRQ_PRIORITY) -#error "Invalid IRQ priority assigned to OTG2" -#endif - -#if (STM32_USB_OTG1_RX_FIFO_SIZE & 3) != 0 -#error "OTG1 RX FIFO size must be a multiple of 4" -#endif - -#if (STM32_USB_OTG2_RX_FIFO_SIZE & 3) != 0 -#error "OTG2 RX FIFO size must be a multiple of 4" -#endif - -#if defined(STM32F4XX) || defined(STM32F2XX) -#define STM32_USBCLK STM32_PLL48CLK -#elif defined(STM32F10X_CL) -#define STM32_USBCLK STM32_OTGFSCLK -#else -#error "unsupported STM32 platform for OTG functionality" -#endif - -#if STM32_USBCLK != 48000000 -#error "the USB OTG driver requires a 48MHz clock" -#endif - -/*===========================================================================*/ -/* Driver data structures and types. */ -/*===========================================================================*/ - -/** - * @brief Peripheral-specific parameters block. - */ -typedef struct { - uint32_t rx_fifo_size; - uint32_t otg_ram_size; - uint32_t num_endpoints; -} stm32_otg_params_t; - -/** - * @brief Type of an IN endpoint state structure. - */ -typedef struct { - /** - * @brief Buffer mode, queue or linear. - */ - bool_t txqueued; - /** - * @brief Requested transmit transfer size. - */ - size_t txsize; - /** - * @brief Transmitted bytes so far. - */ - size_t txcnt; - union { - struct { - /** - * @brief Pointer to the transmission linear buffer. - */ - const uint8_t *txbuf; - } linear; - struct { - /** - * @brief Pointer to the output queue. - */ - OutputQueue *txqueue; - } queue; - } mode; -} USBInEndpointState; - -/** - * @brief Type of an OUT endpoint state structure. - */ -typedef struct { - /** - * @brief Buffer mode, queue or linear. - */ - bool_t rxqueued; - /** - * @brief Requested receive transfer size. - */ - size_t rxsize; - /** - * @brief Received bytes so far. - */ - size_t rxcnt; - union { - struct { - /** - * @brief Pointer to the receive linear buffer. - */ - uint8_t *rxbuf; - } linear; - struct { - /** - * @brief Pointer to the input queue. - */ - InputQueue *rxqueue; - } queue; - } mode; -} USBOutEndpointState; - -/** - * @brief Type of an USB endpoint configuration structure. - * @note Platform specific restrictions may apply to endpoints. - */ -typedef struct { - /** - * @brief Type and mode of the endpoint. - */ - uint32_t ep_mode; - /** - * @brief Setup packet notification callback. - * @details This callback is invoked when a setup packet has been - * received. - * @post The application must immediately call @p usbReadPacket() in - * order to access the received packet. - * @note This field is only valid for @p USB_EP_MODE_TYPE_CTRL - * endpoints, it should be set to @p NULL for other endpoint - * types. - */ - usbepcallback_t setup_cb; - /** - * @brief IN endpoint notification callback. - * @details This field must be set to @p NULL if the IN endpoint is not - * used. - */ - usbepcallback_t in_cb; - /** - * @brief OUT endpoint notification callback. - * @details This field must be set to @p NULL if the OUT endpoint is not - * used. - */ - usbepcallback_t out_cb; - /** - * @brief IN endpoint maximum packet size. - * @details This field must be set to zero if the IN endpoint is not - * used. - */ - uint16_t in_maxsize; - /** - * @brief OUT endpoint maximum packet size. - * @details This field must be set to zero if the OUT endpoint is not - * used. - */ - uint16_t out_maxsize; - /** - * @brief @p USBEndpointState associated to the IN endpoint. - * @details This structure maintains the state of the IN endpoint. - */ - USBInEndpointState *in_state; - /** - * @brief @p USBEndpointState associated to the OUT endpoint. - * @details This structure maintains the state of the OUT endpoint. - */ - USBOutEndpointState *out_state; - /* End of the mandatory fields.*/ - /** - * @brief Determines the space allocated for the TXFIFO as multiples of - * the packet size (@p in_maxsize). Note that zero is interpreted - * as one for simplicity and robustness. - */ - uint16_t in_multiplier; - /** - * @brief Pointer to a buffer for setup packets. - * @details Setup packets require a dedicated 8-bytes buffer, set this - * field to @p NULL for non-control endpoints. - */ - uint8_t *setup_buf; -} USBEndpointConfig; - -/** - * @brief Type of an USB driver configuration structure. - */ -typedef struct { - /** - * @brief USB events callback. - * @details This callback is invoked when an USB driver event is registered. - */ - usbeventcb_t event_cb; - /** - * @brief Device GET_DESCRIPTOR request callback. - * @note This callback is mandatory and cannot be set to @p NULL. - */ - usbgetdescriptor_t get_descriptor_cb; - /** - * @brief Requests hook callback. - * @details This hook allows to be notified of standard requests or to - * handle non standard requests. - */ - usbreqhandler_t requests_hook_cb; - /** - * @brief Start Of Frame callback. - */ - usbcallback_t sof_cb; - /* End of the mandatory fields.*/ -} USBConfig; - -/** - * @brief Structure representing an USB driver. - */ -struct USBDriver { - /** - * @brief Driver state. - */ - usbstate_t state; - /** - * @brief Current configuration data. - */ - const USBConfig *config; - /** - * @brief Bit map of the transmitting IN endpoints. - */ - uint16_t transmitting; - /** - * @brief Bit map of the receiving OUT endpoints. - */ - uint16_t receiving; - /** - * @brief Active endpoints configurations. - */ - const USBEndpointConfig *epc[USB_MAX_ENDPOINTS + 1]; - /** - * @brief Fields available to user, it can be used to associate an - * application-defined handler to an IN endpoint. - * @note The base index is one, the endpoint zero does not have a - * reserved element in this array. - */ - void *in_params[USB_MAX_ENDPOINTS]; - /** - * @brief Fields available to user, it can be used to associate an - * application-defined handler to an OUT endpoint. - * @note The base index is one, the endpoint zero does not have a - * reserved element in this array. - */ - void *out_params[USB_MAX_ENDPOINTS]; - /** - * @brief Endpoint 0 state. - */ - usbep0state_t ep0state; - /** - * @brief Next position in the buffer to be transferred through endpoint 0. - */ - uint8_t *ep0next; - /** - * @brief Number of bytes yet to be transferred through endpoint 0. - */ - size_t ep0n; - /** - * @brief Endpoint 0 end transaction callback. - */ - usbcallback_t ep0endcb; - /** - * @brief Setup packet buffer. - */ - uint8_t setup[8]; - /** - * @brief Current USB device status. - */ - uint16_t status; - /** - * @brief Assigned USB address. - */ - uint8_t address; - /** - * @brief Current USB device configuration. - */ - uint8_t configuration; -#if defined(USB_DRIVER_EXT_FIELDS) - USB_DRIVER_EXT_FIELDS -#endif - /* End of the mandatory fields.*/ - /** - * @brief Pointer to the OTG peripheral associated to this driver. - */ - stm32_otg_t *otg; - /** - * @brief Peripheral-specific parameters. - */ - const stm32_otg_params_t *otgparams; - /** - * @brief Pointer to the next address in the packet memory. - */ - uint32_t pmnext; - /** - * @brief Mask of TXFIFOs to be filled by the pump thread. - */ - uint32_t txpending; - /** - * @brief Pointer to the thread. - */ - Thread *thd_ptr; - /** - * @brief Pointer to the thread when it is sleeping or @p NULL. - */ - Thread *thd_wait; - /** - * @brief Working area for the dedicated data pump thread; - */ - WORKING_AREA(wa_pump, STM32_USB_OTG_THREAD_STACK_SIZE); -}; - -/*===========================================================================*/ -/* Driver macros. */ -/*===========================================================================*/ - -/** - * @brief Returns the exact size of a receive transaction. - * @details The received size can be different from the size specified in - * @p usbStartReceiveI() because the last packet could have a size - * different from the expected one. - * @pre The OUT endpoint must have been configured in transaction mode - * in order to use this function. - * - * @param[in] usbp pointer to the @p USBDriver object - * @param[in] ep endpoint number - * @return Received data size. - * - * @notapi - */ -#define usb_lld_get_transaction_size(usbp, ep) \ - ((usbp)->epc[ep]->out_state->rxcnt) - -/** - * @brief Connects the USB device. - * - * @api - */ -#define usb_lld_connect_bus(usbp) ((usbp)->otg->GCCFG |= GCCFG_VBUSBSEN) - -/** - * @brief Disconnect the USB device. - * - * @api - */ -#define usb_lld_disconnect_bus(usbp) ((usbp)->otg->GCCFG &= ~GCCFG_VBUSBSEN) - -/*===========================================================================*/ -/* External declarations. */ -/*===========================================================================*/ - -#if STM32_USB_USE_OTG1 && !defined(__DOXYGEN__) -extern USBDriver USBD1; -#endif - -#if STM32_USB_USE_OTG2 && !defined(__DOXYGEN__) -extern USBDriver USBD2; -#endif - -#ifdef __cplusplus -extern "C" { -#endif - void usb_lld_init(void); - void usb_lld_start(USBDriver *usbp); - void usb_lld_stop(USBDriver *usbp); - void usb_lld_reset(USBDriver *usbp); - void usb_lld_set_address(USBDriver *usbp); - void usb_lld_init_endpoint(USBDriver *usbp, usbep_t ep); - void usb_lld_disable_endpoints(USBDriver *usbp); - usbepstatus_t usb_lld_get_status_in(USBDriver *usbp, usbep_t ep); - usbepstatus_t usb_lld_get_status_out(USBDriver *usbp, usbep_t ep); - void usb_lld_read_setup(USBDriver *usbp, usbep_t ep, uint8_t *buf); - void usb_lld_prepare_receive(USBDriver *usbp, usbep_t ep); - void usb_lld_prepare_transmit(USBDriver *usbp, usbep_t ep); - void usb_lld_start_out(USBDriver *usbp, usbep_t ep); - void usb_lld_start_in(USBDriver *usbp, usbep_t ep); - void usb_lld_stall_out(USBDriver *usbp, usbep_t ep); - void usb_lld_stall_in(USBDriver *usbp, usbep_t ep); - void usb_lld_clear_out(USBDriver *usbp, usbep_t ep); - void usb_lld_clear_in(USBDriver *usbp, usbep_t ep); -#ifdef __cplusplus -} -#endif - -#endif /* HAL_USE_USB */ - -#endif /* _USB_LLD_H_ */ - -/** @} */ diff --git a/os/hal/platforms/STM32/RTCv1/rtc_lld.c b/os/hal/platforms/STM32/RTCv1/rtc_lld.c deleted file mode 100644 index 108d94fb6..000000000 --- a/os/hal/platforms/STM32/RTCv1/rtc_lld.c +++ /dev/null @@ -1,329 +0,0 @@ -/* - ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ -/* - Concepts and parts of this file have been contributed by Uladzimir Pylinsky - aka barthess. - */ - -/** - * @file STM32/RTCv1/rtc_lld.c - * @brief STM32 RTC subsystem low level driver header. - * - * @addtogroup RTC - * @{ - */ - -#include "ch.h" -#include "hal.h" - -#if HAL_USE_RTC || defined(__DOXYGEN__) - -/*===========================================================================*/ -/* Driver local definitions. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver exported variables. */ -/*===========================================================================*/ - -/** - * @brief RTC driver identifier. - */ -RTCDriver RTCD1; - -/*===========================================================================*/ -/* Driver local variables and types. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver local functions. */ -/*===========================================================================*/ - -/** - * @brief Wait for synchronization of RTC registers with APB1 bus. - * @details This function must be invoked before trying to read RTC registers - * in the backup domain: DIV, CNT, ALR. CR registers can always - * be read. - * - * @notapi - */ -#define rtc_lld_apb1_sync() {while ((RTC->CRL & RTC_CRL_RSF) == 0);} - -/** - * @brief Wait for for previous write operation complete. - * @details This function must be invoked before writing to any RTC registers - * - * @notapi - */ -#define rtc_lld_wait_write() {while ((RTC->CRL & RTC_CRL_RTOFF) == 0);} - -/** - * @brief Acquires write access to RTC registers. - * @details Before writing to the backup domain RTC registers the previous - * write operation must be completed. Use this function before - * writing to PRL, CNT, ALR registers. - * - * @notapi - */ -#define rtc_lld_acquire() {rtc_lld_wait_write(); RTC->CRL |= RTC_CRL_CNF;} - -/** - * @brief Releases write access to RTC registers. - * - * @notapi - */ -#define rtc_lld_release() {RTC->CRL &= ~RTC_CRL_CNF;} - -/*===========================================================================*/ -/* Driver interrupt handlers. */ -/*===========================================================================*/ - -/** - * @brief RTC interrupt handler. - * - * @isr - */ -CH_IRQ_HANDLER(RTC_IRQHandler) { - uint16_t flags; - - CH_IRQ_PROLOGUE(); - - /* This wait works only when AHB1 bus was previously powered off by any - reason (standby, reset, etc). In other cases it does nothing.*/ - rtc_lld_apb1_sync(); - - /* Mask of all enabled and pending sources.*/ - flags = RTC->CRH & RTC->CRL; - RTC->CRL &= ~(RTC_CRL_SECF | RTC_CRL_ALRF | RTC_CRL_OWF); - - if (flags & RTC_CRL_SECF) - RTCD1.callback(&RTCD1, RTC_EVENT_SECOND); - - if (flags & RTC_CRL_ALRF) - RTCD1.callback(&RTCD1, RTC_EVENT_ALARM); - - if (flags & RTC_CRL_OWF) - RTCD1.callback(&RTCD1, RTC_EVENT_OVERFLOW); - - CH_IRQ_EPILOGUE(); -} - -/*===========================================================================*/ -/* Driver exported functions. */ -/*===========================================================================*/ - -/** - * @brief Load value of RTCCLK to prescaler registers. - * @note The pre-scaler must not be set on every reset as RTC clock - * counts are lost when it is set. - * @note This function designed to be called from - * hal_lld_backup_domain_init(). Because there is only place - * where possible to detect BKP domain reset event reliably. - * - * @notapi - */ -void rtc_lld_set_prescaler(void){ - rtc_lld_acquire(); - RTC->PRLH = (uint16_t)((STM32_RTCCLK - 1) >> 16) & 0x000F; - RTC->PRLL = (uint16_t)(((STM32_RTCCLK - 1)) & 0xFFFF); - rtc_lld_release(); -} - -/** - * @brief Initialize RTC. - * - * @notapi - */ -void rtc_lld_init(void){ - - /* RSF bit must be cleared by software after an APB1 reset or an APB1 clock - stop. Otherwise its value will not be actual. */ - RTC->CRL &= ~RTC_CRL_RSF; - - /* Required because access to PRL.*/ - rtc_lld_apb1_sync(); - - /* All interrupts initially disabled.*/ - rtc_lld_wait_write(); - RTC->CRH = 0; - - /* Callback initially disabled.*/ - RTCD1.callback = NULL; - - /* IRQ vector permanently assigned to this driver.*/ - nvicEnableVector(RTC_IRQn, CORTEX_PRIORITY_MASK(STM32_RTC_IRQ_PRIORITY)); -} - -/** - * @brief Set current time. - * @note Fractional part will be silently ignored. There is no possibility - * to change it on STM32F1xx platform. - * - * @param[in] rtcp pointer to RTC driver structure - * @param[in] timespec pointer to a @p RTCTime structure - * - * @notapi - */ -void rtc_lld_set_time(RTCDriver *rtcp, const RTCTime *timespec) { - - (void)rtcp; - - rtc_lld_acquire(); - RTC->CNTH = (uint16_t)(timespec->tv_sec >> 16); - RTC->CNTL = (uint16_t)(timespec->tv_sec & 0xFFFF); - rtc_lld_release(); -} - -/** - * @brief Get current time. - * - * @param[in] rtcp pointer to RTC driver structure - * @param[in] timespec pointer to a @p RTCTime structure - * - * @notapi - */ -void rtc_lld_get_time(RTCDriver *rtcp, RTCTime *timespec) { - (void)rtcp; - - uint32_t time_frac; - - /* Required because access to CNT and DIV.*/ - rtc_lld_apb1_sync(); - - /* Loops until two consecutive read returning the same value.*/ - do { - timespec->tv_sec = ((uint32_t)(RTC->CNTH) << 16) + RTC->CNTL; - time_frac = (((uint32_t)RTC->DIVH) << 16) + (uint32_t)RTC->DIVL; - } while ((timespec->tv_sec) != (((uint32_t)(RTC->CNTH) << 16) + RTC->CNTL)); - - timespec->tv_msec = (uint16_t)(((STM32_RTCCLK - 1 - time_frac) * 1000) / - STM32_RTCCLK); -} - -/** - * @brief Set alarm time. - * - * @note Default value after BKP domain reset is 0xFFFFFFFF - * - * @param[in] rtcp pointer to RTC driver structure - * @param[in] alarm alarm identifier - * @param[in] alarmspec pointer to a @p RTCAlarm structure - * - * @notapi - */ -void rtc_lld_set_alarm(RTCDriver *rtcp, - rtcalarm_t alarm, - const RTCAlarm *alarmspec) { - - (void)rtcp; - (void)alarm; - - rtc_lld_acquire(); - if (alarmspec != NULL) { - RTC->ALRH = (uint16_t)(alarmspec->tv_sec >> 16); - RTC->ALRL = (uint16_t)(alarmspec->tv_sec & 0xFFFF); - } - else { - RTC->ALRH = 0; - RTC->ALRL = 0; - } - rtc_lld_release(); -} - -/** - * @brief Get current alarm. - * @note If an alarm has not been set then the returned alarm specification - * is not meaningful. - * - * @note Default value after BKP domain reset is 0xFFFFFFFF. - * - * @param[in] rtcp pointer to RTC driver structure - * @param[in] alarm alarm identifier - * @param[out] alarmspec pointer to a @p RTCAlarm structure - * - * @notapi - */ -void rtc_lld_get_alarm(RTCDriver *rtcp, - rtcalarm_t alarm, - RTCAlarm *alarmspec) { - - (void)rtcp; - (void)alarm; - - /* Required because access to ALR.*/ - rtc_lld_apb1_sync(); - - alarmspec->tv_sec = ((RTC->ALRH << 16) + RTC->ALRL); -} - -/** - * @brief Enables or disables RTC callbacks. - * @details This function enables or disables callbacks, use a @p NULL pointer - * in order to disable a callback. - * - * @param[in] rtcp pointer to RTC driver structure - * @param[in] callback callback function pointer or @p NULL - * - * @notapi - */ -void rtc_lld_set_callback(RTCDriver *rtcp, rtccb_t callback) { - - if (callback != NULL) { - - /* IRQ sources enabled only after setting up the callback.*/ - rtcp->callback = callback; - - rtc_lld_wait_write(); - RTC->CRL &= ~(RTC_CRL_OWF | RTC_CRL_ALRF | RTC_CRL_SECF); - RTC->CRH = RTC_CRH_OWIE | RTC_CRH_ALRIE | RTC_CRH_SECIE; - } - else { - rtc_lld_wait_write(); - RTC->CRH = 0; - - /* Callback set to NULL only after disabling the IRQ sources.*/ - rtcp->callback = NULL; - } -} - -#include "chrtclib.h" - -/** - * @brief Get current time in format suitable for usage in FatFS. - * - * @param[in] rtcp pointer to RTC driver structure - * @return FAT time value. - * - * @api - */ -uint32_t rtc_lld_get_time_fat(RTCDriver *rtcp) { - uint32_t fattime; - struct tm timp; - - rtcGetTimeTm(rtcp, &timp); - - fattime = (timp.tm_sec) >> 1; - fattime |= (timp.tm_min) << 5; - fattime |= (timp.tm_hour) << 11; - fattime |= (timp.tm_mday) << 16; - fattime |= (timp.tm_mon + 1) << 21; - fattime |= (timp.tm_year - 80) << 25; - - return fattime; -} -#endif /* HAL_USE_RTC */ - -/** @} */ diff --git a/os/hal/platforms/STM32/RTCv1/rtc_lld.h b/os/hal/platforms/STM32/RTCv1/rtc_lld.h deleted file mode 100644 index 62b74cc46..000000000 --- a/os/hal/platforms/STM32/RTCv1/rtc_lld.h +++ /dev/null @@ -1,187 +0,0 @@ -/* - ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ -/* - Concepts and parts of this file have been contributed by Uladzimir Pylinsky - aka barthess. - */ - -/** - * @file STM32/RTCv1/rtc_lld.h - * @brief STM32F1xx RTC subsystem low level driver header. - * - * @addtogroup RTC - * @{ - */ - -#ifndef _RTC_LLD_H_ -#define _RTC_LLD_H_ - -#if HAL_USE_RTC || defined(__DOXYGEN__) - -/*===========================================================================*/ -/* Driver constants. */ -/*===========================================================================*/ - -/** - * @brief This RTC implementation supports callbacks. - */ -#define RTC_SUPPORTS_CALLBACKS TRUE - -/** - * @brief One alarm comparator available. - */ -#define RTC_ALARMS 1 - -/*===========================================================================*/ -/* Driver pre-compile time settings. */ -/*===========================================================================*/ - -/** - * @name Configuration options - * @{ - */ -/* - * RTC driver system settings. - */ -#define STM32_RTC_IRQ_PRIORITY 15 -/** @} */ - -/*===========================================================================*/ -/* Derived constants and error checks. */ -/*===========================================================================*/ - -#if HAL_USE_RTC && !STM32_HAS_RTC -#error "RTC not present in the selected device" -#endif - -#if STM32_RTCCLK == 0 -#error "RTC clock not enabled" -#endif - -/*===========================================================================*/ -/* Driver data structures and types. */ -/*===========================================================================*/ - -/** - * @brief Type of a structure representing an RTC alarm time stamp. - */ -typedef struct RTCAlarm RTCAlarm; - -/** - * @brief Type of a structure representing an RTC callbacks config. - */ -typedef struct RTCCallbackConfig RTCCallbackConfig; - -/** - * @brief Type of an RTC alarm. - * @details Meaningful on platforms with more than 1 alarm comparator. - */ -typedef uint32_t rtcalarm_t; - -/** - * @brief Type of an RTC event. - */ -typedef enum { - RTC_EVENT_SECOND = 0, /** Triggered every second. */ - RTC_EVENT_ALARM = 1, /** Triggered on alarm. */ - RTC_EVENT_OVERFLOW = 2 /** Triggered on counter overflow. */ -} rtcevent_t; - -/** - * @brief Type of a generic RTC callback. - */ -typedef void (*rtccb_t)(RTCDriver *rtcp, rtcevent_t event); - -/** - * @brief Structure representing an RTC callbacks config. - */ -struct RTCCallbackConfig{ - /** - * @brief Generic RTC callback pointer. - */ - rtccb_t callback; -}; - -/** - * @brief Structure representing an RTC time stamp. - */ -struct RTCTime { - /** - * @brief Seconds since UNIX epoch. - */ - uint32_t tv_sec; - /** - * @brief Fractional part. - */ - uint32_t tv_msec; -}; - -/** - * @brief Structure representing an RTC alarm time stamp. - */ -struct RTCAlarm { - /** - * @brief Seconds since UNIX epoch. - */ - uint32_t tv_sec; -}; - -/** - * @brief Structure representing an RTC driver. - */ -struct RTCDriver{ - /** - * @brief Callback pointer. - */ - rtccb_t callback; -}; - -/*===========================================================================*/ -/* Driver macros. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* External declarations. */ -/*===========================================================================*/ - -#if !defined(__DOXYGEN__) -extern RTCDriver RTCD1; -#endif - -#ifdef __cplusplus -extern "C" { -#endif - void rtc_lld_set_prescaler(void); - void rtc_lld_init(void); - void rtc_lld_set_time(RTCDriver *rtcp, const RTCTime *timespec); - void rtc_lld_get_time(RTCDriver *rtcp, RTCTime *timespec); - void rtc_lld_set_alarm(RTCDriver *rtcp, - rtcalarm_t alarm, - const RTCAlarm *alarmspec); - void rtc_lld_get_alarm(RTCDriver *rtcp, - rtcalarm_t alarm, - RTCAlarm *alarmspec); - void rtc_lld_set_callback(RTCDriver *rtcp, rtccb_t callback); - uint32_t rtc_lld_get_time_fat(RTCDriver *rtcp); -#ifdef __cplusplus -} -#endif - -#endif /* HAL_USE_RTC */ - -#endif /* _RTC_LLD_H_ */ - -/** @} */ diff --git a/os/hal/platforms/STM32/RTCv2/rtc_lld.c b/os/hal/platforms/STM32/RTCv2/rtc_lld.c deleted file mode 100644 index 17ae46ccf..000000000 --- a/os/hal/platforms/STM32/RTCv2/rtc_lld.c +++ /dev/null @@ -1,322 +0,0 @@ -/* - ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ -/* - Concepts and parts of this file have been contributed by Uladzimir Pylinsky - aka barthess. - */ - -/** - * @file STM32/RTCv2/rtc_lld.c - * @brief STM32L1xx/STM32F2xx/STM32F4xx RTC low level driver. - * - * @addtogroup RTC - * @{ - */ - -#include "ch.h" -#include "hal.h" - -#if HAL_USE_RTC || defined(__DOXYGEN__) - -/*===========================================================================*/ -/* Driver local definitions. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver exported variables. */ -/*===========================================================================*/ - -/** - * @brief RTC driver identifier. - */ -RTCDriver RTCD1; - -/*===========================================================================*/ -/* Driver local variables and types. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver local functions. */ -/*===========================================================================*/ -/** - * @brief Wait for synchronization of RTC registers with APB1 bus. - * @details This function must be invoked before trying to read RTC registers. - * - * @notapi - */ -#define rtc_lld_apb1_sync() {while ((RTCD1.id_rtc->ISR & RTC_ISR_RSF) == 0);} - -/** - * @brief Beginning of configuration procedure. - * - * @notapi - */ -#define rtc_lld_enter_init() { \ - RTCD1.id_rtc->ISR |= RTC_ISR_INIT; \ - while ((RTCD1.id_rtc->ISR & RTC_ISR_INITF) == 0) \ - ; \ -} - -/** - * @brief Finalizing of configuration procedure. - * - * @notapi - */ -#define rtc_lld_exit_init() {RTCD1.id_rtc->ISR &= ~RTC_ISR_INIT;} - -/*===========================================================================*/ -/* Driver interrupt handlers. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver exported functions. */ -/*===========================================================================*/ - -/** - * @brief Enable access to registers. - * - * @api - */ -void rtc_lld_init(void){ - RTCD1.id_rtc = RTC; - - /* Asynchronous part of preloader. Set it to maximum value. */ - uint32_t prediv_a = 0x7F; - - /* Disable write protection. */ - RTCD1.id_rtc->WPR = 0xCA; - RTCD1.id_rtc->WPR = 0x53; - - /* If calendar not init yet. */ - if (!(RTC->ISR & RTC_ISR_INITS)){ - rtc_lld_enter_init(); - - /* Prescaler register must be written in two SEPARATE writes. */ - prediv_a = (prediv_a << 16) | - (((STM32_RTCCLK / (prediv_a + 1)) - 1) & 0x7FFF); - RTCD1.id_rtc->PRER = prediv_a; - RTCD1.id_rtc->PRER = prediv_a; - rtc_lld_exit_init(); - } -} - -/** - * @brief Set current time. - * @note Fractional part will be silently ignored. There is no possibility - * to set it on STM32 platform. - * - * @param[in] rtcp pointer to RTC driver structure - * @param[in] timespec pointer to a @p RTCTime structure - * - * @api - */ -void rtc_lld_set_time(RTCDriver *rtcp, const RTCTime *timespec) { - (void)rtcp; - - rtc_lld_enter_init(); - if (timespec->h12) - RTCD1.id_rtc->CR |= RTC_CR_FMT; - else - RTCD1.id_rtc->CR &= ~RTC_CR_FMT; - RTCD1.id_rtc->TR = timespec->tv_time; - RTCD1.id_rtc->DR = timespec->tv_date; - rtc_lld_exit_init(); -} - -/** - * @brief Get current time. - * - * @param[in] rtcp pointer to RTC driver structure - * @param[out] timespec pointer to a @p RTCTime structure - * - * @api - */ -void rtc_lld_get_time(RTCDriver *rtcp, RTCTime *timespec) { - (void)rtcp; - - rtc_lld_apb1_sync(); - -#if STM32_RTC_HAS_SUBSECONDS - timespec->tv_msec = - (1000 * ((RTCD1.id_rtc->PRER & 0x7FFF) - RTCD1.id_rtc->SSR)) / - ((RTCD1.id_rtc->PRER & 0x7FFF) + 1); -#endif /* STM32_RTC_HAS_SUBSECONDS */ - timespec->tv_time = RTCD1.id_rtc->TR; - timespec->tv_date = RTCD1.id_rtc->DR; -} - -/** - * @brief Set alarm time. - * - * @note Default value after BKP domain reset for both comparators is 0. - * @note Function does not performs any checks of alarm time validity. - * - * @param[in] rtcp Pointer to RTC driver structure. - * @param[in] alarm Alarm identifier. Can be 1 or 2. - * @param[in] alarmspec Pointer to a @p RTCAlarm structure. - * - * @api - */ -void rtc_lld_set_alarm(RTCDriver *rtcp, - rtcalarm_t alarm, - const RTCAlarm *alarmspec) { - if (alarm == 1){ - if (alarmspec != NULL){ - rtcp->id_rtc->CR &= ~RTC_CR_ALRAE; - while(!(rtcp->id_rtc->ISR & RTC_ISR_ALRAWF)) - ; - rtcp->id_rtc->ALRMAR = alarmspec->tv_datetime; - rtcp->id_rtc->CR |= RTC_CR_ALRAE; - rtcp->id_rtc->CR |= RTC_CR_ALRAIE; - } - else { - rtcp->id_rtc->CR &= ~RTC_CR_ALRAIE; - rtcp->id_rtc->CR &= ~RTC_CR_ALRAE; - } - } - else{ - if (alarmspec != NULL){ - rtcp->id_rtc->CR &= ~RTC_CR_ALRBE; - while(!(rtcp->id_rtc->ISR & RTC_ISR_ALRBWF)) - ; - rtcp->id_rtc->ALRMBR = alarmspec->tv_datetime; - rtcp->id_rtc->CR |= RTC_CR_ALRBE; - rtcp->id_rtc->CR |= RTC_CR_ALRBIE; - } - else { - rtcp->id_rtc->CR &= ~RTC_CR_ALRBIE; - rtcp->id_rtc->CR &= ~RTC_CR_ALRBE; - } - } -} - -/** - * @brief Get alarm time. - * - * @param[in] rtcp pointer to RTC driver structure - * @param[in] alarm alarm identifier - * @param[out] alarmspec pointer to a @p RTCAlarm structure - * - * @api - */ -void rtc_lld_get_alarm(RTCDriver *rtcp, - rtcalarm_t alarm, - RTCAlarm *alarmspec) { - if (alarm == 1) - alarmspec->tv_datetime = rtcp->id_rtc->ALRMAR; - else - alarmspec->tv_datetime = rtcp->id_rtc->ALRMBR; -} - -/** - * @brief Sets time of periodic wakeup. - * - * @note Default value after BKP domain reset is 0x0000FFFF - * - * @param[in] rtcp pointer to RTC driver structure - * @param[in] wakeupspec pointer to a @p RTCWakeup structure - * - * @api - */ -void rtcSetPeriodicWakeup_v2(RTCDriver *rtcp, RTCWakeup *wakeupspec){ - chDbgCheck((wakeupspec->wakeup != 0x30000), - "rtc_lld_set_periodic_wakeup, forbidden combination"); - - if (wakeupspec != NULL){ - rtcp->id_rtc->CR &= ~RTC_CR_WUTE; - while(!(rtcp->id_rtc->ISR & RTC_ISR_WUTWF)) - ; - rtcp->id_rtc->WUTR = wakeupspec->wakeup & 0xFFFF; - rtcp->id_rtc->CR = (wakeupspec->wakeup >> 16) & 0x7; - rtcp->id_rtc->CR |= RTC_CR_WUTIE; - rtcp->id_rtc->CR |= RTC_CR_WUTE; - } - else { - rtcp->id_rtc->CR &= ~RTC_CR_WUTIE; - rtcp->id_rtc->CR &= ~RTC_CR_WUTE; - } -} - -/** - * @brief Gets time of periodic wakeup. - * - * @note Default value after BKP domain reset is 0x0000FFFF - * - * @param[in] rtcp pointer to RTC driver structure - * @param[out] wakeupspec pointer to a @p RTCWakeup structure - * - * @api - */ -void rtcGetPeriodicWakeup_v2(RTCDriver *rtcp, RTCWakeup *wakeupspec){ - wakeupspec->wakeup = 0; - wakeupspec->wakeup |= rtcp->id_rtc->WUTR; - wakeupspec->wakeup |= (((uint32_t)rtcp->id_rtc->CR) & 0x7) << 16; -} - -/** - * @brief Get current time in format suitable for usage in FatFS. - * - * @param[in] rtcp pointer to RTC driver structure - * @return FAT time value. - * - * @api - */ -uint32_t rtc_lld_get_time_fat(RTCDriver *rtcp) { - uint32_t fattime; - RTCTime timespec; - uint32_t tv_time; - uint32_t tv_date; - uint32_t v; - - chSysLock(); - rtcGetTimeI(rtcp, ×pec); - chSysUnlock(); - - tv_time = timespec.tv_time; - tv_date = timespec.tv_date; - - v = (tv_time & RTC_TR_SU) >> RTC_TR_SU_OFFSET; - v += ((tv_time & RTC_TR_ST) >> RTC_TR_ST_OFFSET) * 10; - fattime = v >> 1; - - v = (tv_time & RTC_TR_MNU) >> RTC_TR_MNU_OFFSET; - v += ((tv_time & RTC_TR_MNT) >> RTC_TR_MNT_OFFSET) * 10; - fattime |= v << 5; - - v = (tv_time & RTC_TR_HU) >> RTC_TR_HU_OFFSET; - v += ((tv_time & RTC_TR_HT) >> RTC_TR_HT_OFFSET) * 10; - v += 12 * ((tv_time & RTC_TR_PM) >> RTC_TR_PM_OFFSET); - fattime |= v << 11; - - v = (tv_date & RTC_DR_DU) >> RTC_DR_DU_OFFSET; - v += ((tv_date & RTC_DR_DT) >> RTC_DR_DT_OFFSET) * 10; - fattime |= v << 16; - - v = (tv_date & RTC_DR_MU) >> RTC_DR_MU_OFFSET; - v += ((tv_date & RTC_DR_MT) >> RTC_DR_MT_OFFSET) * 10; - fattime |= v << 21; - - v = (tv_date & RTC_DR_YU) >> RTC_DR_YU_OFFSET; - v += ((tv_date & RTC_DR_YT) >> RTC_DR_YT_OFFSET) * 10; - v += 2000 - 1900 - 80; - fattime |= v << 25; - - return fattime; -} - -#endif /* HAL_USE_RTC */ - -/** @} */ diff --git a/os/hal/platforms/STM32/RTCv2/rtc_lld.h b/os/hal/platforms/STM32/RTCv2/rtc_lld.h deleted file mode 100644 index 8e0ce8dd0..000000000 --- a/os/hal/platforms/STM32/RTCv2/rtc_lld.h +++ /dev/null @@ -1,206 +0,0 @@ -/* - ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ -/* - Concepts and parts of this file have been contributed by Uladzimir Pylinsky - aka barthess. - */ - -/** - * @file STM32/RTCv2/rtc_lld.h - * @brief STM32L1xx/STM32F2xx/STM32F4xx RTC low level driver header. - * - * @addtogroup RTC - * @{ - */ - -#ifndef _RTC_LLD_H_ -#define _RTC_LLD_H_ - -#if HAL_USE_RTC || defined(__DOXYGEN__) - -/*===========================================================================*/ -/* Driver constants. */ -/*===========================================================================*/ - -/** - * @brief Two alarm comparators available on STM32F4x. - */ -#define RTC_ALARMS 2 - -/** - * @brief Data offsets in RTC date and time registers. - */ -#define RTC_TR_PM_OFFSET 22 -#define RTC_TR_HT_OFFSET 20 -#define RTC_TR_HU_OFFSET 16 -#define RTC_TR_MNT_OFFSET 12 -#define RTC_TR_MNU_OFFSET 8 -#define RTC_TR_ST_OFFSET 4 -#define RTC_TR_SU_OFFSET 0 - -#define RTC_DR_YT_OFFSET 20 -#define RTC_DR_YU_OFFSET 16 -#define RTC_DR_WDU_OFFSET 13 -#define RTC_DR_MT_OFFSET 12 -#define RTC_DR_MU_OFFSET 8 -#define RTC_DR_DT_OFFSET 4 -#define RTC_DR_DU_OFFSET 0 - -/*===========================================================================*/ -/* Driver pre-compile time settings. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Derived constants and error checks. */ -/*===========================================================================*/ - -#if HAL_USE_RTC && !STM32_HAS_RTC -#error "RTC not present in the selected device" -#endif - -#if !(STM32_RTCSEL == STM32_RTCSEL_LSE) && \ - !(STM32_RTCSEL == STM32_RTCSEL_LSI) && \ - !(STM32_RTCSEL == STM32_RTCSEL_HSEDIV) -#error "invalid source selected for RTC clock" -#endif - -#if !defined(RTC_USE_INTERRUPTS) || defined(__DOXYGEN__) -#define RTC_USE_INTERRUPTS FALSE -#endif - -#if STM32_PCLK1 < (STM32_RTCCLK * 7) -#error "STM32_PCLK1 frequency is too low to handle RTC without ugly workaround" -#endif - -/*===========================================================================*/ -/* Driver data structures and types. */ -/*===========================================================================*/ - -/** - * @brief Type of a structure representing an RTC alarm time stamp. - */ -typedef struct RTCAlarm RTCAlarm; - -/** - * @brief Type of a structure representing an RTC wakeup period. - */ -typedef struct RTCWakeup RTCWakeup; - -/** - * @brief Type of a structure representing an RTC callbacks config. - */ -typedef struct RTCCallbackConfig RTCCallbackConfig; - -/** - * @brief Type of an RTC alarm. - * @details Meaningful on platforms with more than 1 alarm comparator. - */ -typedef uint32_t rtcalarm_t; - -/** - * @brief Structure representing an RTC time stamp. - */ -struct RTCTime { - /** - * @brief RTC date register in STM32 BCD format. - */ - uint32_t tv_date; - /** - * @brief RTC time register in STM32 BCD format. - */ - uint32_t tv_time; - /** - * @brief Set this to TRUE to use 12 hour notation. - */ - bool_t h12; - /** - * @brief Fractional part of time. - */ -#if STM32_RTC_HAS_SUBSECONDS - uint32_t tv_msec; -#endif -}; - -/** - * @brief Structure representing an RTC alarm time stamp. - */ -struct RTCAlarm { - /** - * @brief Date and time of alarm in STM32 BCD. - */ - uint32_t tv_datetime; -}; - -/** - * @brief Structure representing an RTC periodic wakeup period. - */ -struct RTCWakeup { - /** - * @brief RTC WUTR register. - * @details Bits [15:0] contain value of WUTR register - * Bits [18:16] contain value of WUCKSEL bits in CR register - * - * @note ((WUTR == 0) || (WUCKSEL == 3)) is forbidden combination. - */ - uint32_t wakeup; -}; - -/** - * @brief Structure representing an RTC driver. - */ -struct RTCDriver{ - /** - * @brief Pointer to the RTC registers block. - */ - RTC_TypeDef *id_rtc; -}; - -/*===========================================================================*/ -/* Driver macros. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* External declarations. */ -/*===========================================================================*/ - -#if !defined(__DOXYGEN__) -extern RTCDriver RTCD1; -#endif - -#ifdef __cplusplus -extern "C" { -#endif - void rtc_lld_init(void); - void rtc_lld_set_time(RTCDriver *rtcp, const RTCTime *timespec); - void rtc_lld_get_time(RTCDriver *rtcp, RTCTime *timespec); - void rtc_lld_set_alarm(RTCDriver *rtcp, - rtcalarm_t alarm, - const RTCAlarm *alarmspec); - void rtc_lld_get_alarm(RTCDriver *rtcp, - rtcalarm_t alarm, - RTCAlarm *alarmspec); - void rtcSetPeriodicWakeup_v2(RTCDriver *rtcp, RTCWakeup *wakeupspec); - void rtcGetPeriodicWakeup_v2(RTCDriver *rtcp, RTCWakeup *wakeupspec); - uint32_t rtc_lld_get_time_fat(RTCDriver *rtcp); -#ifdef __cplusplus -} -#endif - -#endif /* HAL_USE_RTC */ - -#endif /* _RTC_LLD_H_ */ - -/** @} */ diff --git a/os/hal/platforms/STM32/SPIv1/spi_lld.c b/os/hal/platforms/STM32/SPIv1/spi_lld.c deleted file mode 100644 index 74d21273a..000000000 --- a/os/hal/platforms/STM32/SPIv1/spi_lld.c +++ /dev/null @@ -1,483 +0,0 @@ -/* - ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file STM32/SPIv1/spi_lld.c - * @brief STM32 SPI subsystem low level driver source. - * - * @addtogroup SPI - * @{ - */ - -#include "ch.h" -#include "hal.h" - -#if HAL_USE_SPI || defined(__DOXYGEN__) - -/*===========================================================================*/ -/* Driver local definitions. */ -/*===========================================================================*/ - -#define SPI1_RX_DMA_CHANNEL \ - STM32_DMA_GETCHANNEL(STM32_SPI_SPI1_RX_DMA_STREAM, \ - STM32_SPI1_RX_DMA_CHN) - -#define SPI1_TX_DMA_CHANNEL \ - STM32_DMA_GETCHANNEL(STM32_SPI_SPI1_TX_DMA_STREAM, \ - STM32_SPI1_TX_DMA_CHN) - -#define SPI2_RX_DMA_CHANNEL \ - STM32_DMA_GETCHANNEL(STM32_SPI_SPI2_RX_DMA_STREAM, \ - STM32_SPI2_RX_DMA_CHN) - -#define SPI2_TX_DMA_CHANNEL \ - STM32_DMA_GETCHANNEL(STM32_SPI_SPI2_TX_DMA_STREAM, \ - STM32_SPI2_TX_DMA_CHN) - -#define SPI3_RX_DMA_CHANNEL \ - STM32_DMA_GETCHANNEL(STM32_SPI_SPI3_RX_DMA_STREAM, \ - STM32_SPI3_RX_DMA_CHN) - -#define SPI3_TX_DMA_CHANNEL \ - STM32_DMA_GETCHANNEL(STM32_SPI_SPI3_TX_DMA_STREAM, \ - STM32_SPI3_TX_DMA_CHN) - -/*===========================================================================*/ -/* Driver exported variables. */ -/*===========================================================================*/ - -/** @brief SPI1 driver identifier.*/ -#if STM32_SPI_USE_SPI1 || defined(__DOXYGEN__) -SPIDriver SPID1; -#endif - -/** @brief SPI2 driver identifier.*/ -#if STM32_SPI_USE_SPI2 || defined(__DOXYGEN__) -SPIDriver SPID2; -#endif - -/** @brief SPI3 driver identifier.*/ -#if STM32_SPI_USE_SPI3 || defined(__DOXYGEN__) -SPIDriver SPID3; -#endif - -/*===========================================================================*/ -/* Driver local variables and types. */ -/*===========================================================================*/ - -static uint16_t dummytx; -static uint16_t dummyrx; - -/*===========================================================================*/ -/* Driver local functions. */ -/*===========================================================================*/ - -/** - * @brief Shared end-of-rx service routine. - * - * @param[in] spip pointer to the @p SPIDriver object - * @param[in] flags pre-shifted content of the ISR register - */ -static void spi_lld_serve_rx_interrupt(SPIDriver *spip, uint32_t flags) { - - /* DMA errors handling.*/ -#if defined(STM32_SPI_DMA_ERROR_HOOK) - if ((flags & (STM32_DMA_ISR_TEIF | STM32_DMA_ISR_DMEIF)) != 0) { - STM32_SPI_DMA_ERROR_HOOK(spip); - } -#else - (void)flags; -#endif - - /* Stop everything.*/ - dmaStreamDisable(spip->dmatx); - dmaStreamDisable(spip->dmarx); - - /* Portable SPI ISR code defined in the high level driver, note, it is - a macro.*/ - _spi_isr_code(spip); -} - -/** - * @brief Shared end-of-tx service routine. - * - * @param[in] spip pointer to the @p SPIDriver object - * @param[in] flags pre-shifted content of the ISR register - */ -static void spi_lld_serve_tx_interrupt(SPIDriver *spip, uint32_t flags) { - - /* DMA errors handling.*/ -#if defined(STM32_SPI_DMA_ERROR_HOOK) - (void)spip; - if ((flags & (STM32_DMA_ISR_TEIF | STM32_DMA_ISR_DMEIF)) != 0) { - STM32_SPI_DMA_ERROR_HOOK(spip); - } -#else - (void)spip; - (void)flags; -#endif -} - -/*===========================================================================*/ -/* Driver interrupt handlers. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver exported functions. */ -/*===========================================================================*/ - -/** - * @brief Low level SPI driver initialization. - * - * @notapi - */ -void spi_lld_init(void) { - - dummytx = 0xFFFF; - -#if STM32_SPI_USE_SPI1 - spiObjectInit(&SPID1); - SPID1.spi = SPI1; - SPID1.dmarx = STM32_DMA_STREAM(STM32_SPI_SPI1_RX_DMA_STREAM); - SPID1.dmatx = STM32_DMA_STREAM(STM32_SPI_SPI1_TX_DMA_STREAM); - SPID1.rxdmamode = STM32_DMA_CR_CHSEL(SPI1_RX_DMA_CHANNEL) | - STM32_DMA_CR_PL(STM32_SPI_SPI1_DMA_PRIORITY) | - STM32_DMA_CR_DIR_P2M | - STM32_DMA_CR_TCIE | - STM32_DMA_CR_DMEIE | - STM32_DMA_CR_TEIE; - SPID1.txdmamode = STM32_DMA_CR_CHSEL(SPI1_TX_DMA_CHANNEL) | - STM32_DMA_CR_PL(STM32_SPI_SPI1_DMA_PRIORITY) | - STM32_DMA_CR_DIR_M2P | - STM32_DMA_CR_DMEIE | - STM32_DMA_CR_TEIE; -#endif - -#if STM32_SPI_USE_SPI2 - spiObjectInit(&SPID2); - SPID2.spi = SPI2; - SPID2.dmarx = STM32_DMA_STREAM(STM32_SPI_SPI2_RX_DMA_STREAM); - SPID2.dmatx = STM32_DMA_STREAM(STM32_SPI_SPI2_TX_DMA_STREAM); - SPID2.rxdmamode = STM32_DMA_CR_CHSEL(SPI2_RX_DMA_CHANNEL) | - STM32_DMA_CR_PL(STM32_SPI_SPI2_DMA_PRIORITY) | - STM32_DMA_CR_DIR_P2M | - STM32_DMA_CR_TCIE | - STM32_DMA_CR_DMEIE | - STM32_DMA_CR_TEIE; - SPID2.txdmamode = STM32_DMA_CR_CHSEL(SPI2_TX_DMA_CHANNEL) | - STM32_DMA_CR_PL(STM32_SPI_SPI2_DMA_PRIORITY) | - STM32_DMA_CR_DIR_M2P | - STM32_DMA_CR_DMEIE | - STM32_DMA_CR_TEIE; -#endif - -#if STM32_SPI_USE_SPI3 - spiObjectInit(&SPID3); - SPID3.spi = SPI3; - SPID3.dmarx = STM32_DMA_STREAM(STM32_SPI_SPI3_RX_DMA_STREAM); - SPID3.dmatx = STM32_DMA_STREAM(STM32_SPI_SPI3_TX_DMA_STREAM); - SPID3.rxdmamode = STM32_DMA_CR_CHSEL(SPI3_RX_DMA_CHANNEL) | - STM32_DMA_CR_PL(STM32_SPI_SPI3_DMA_PRIORITY) | - STM32_DMA_CR_DIR_P2M | - STM32_DMA_CR_TCIE | - STM32_DMA_CR_DMEIE | - STM32_DMA_CR_TEIE; - SPID3.txdmamode = STM32_DMA_CR_CHSEL(SPI3_TX_DMA_CHANNEL) | - STM32_DMA_CR_PL(STM32_SPI_SPI3_DMA_PRIORITY) | - STM32_DMA_CR_DIR_M2P | - STM32_DMA_CR_DMEIE | - STM32_DMA_CR_TEIE; -#endif -} - -/** - * @brief Configures and activates the SPI peripheral. - * - * @param[in] spip pointer to the @p SPIDriver object - * - * @notapi - */ -void spi_lld_start(SPIDriver *spip) { - - /* If in stopped state then enables the SPI and DMA clocks.*/ - if (spip->state == SPI_STOP) { -#if STM32_SPI_USE_SPI1 - if (&SPID1 == spip) { - bool b; - b = dmaStreamAllocate(spip->dmarx, - STM32_SPI_SPI1_IRQ_PRIORITY, - (stm32_dmaisr_t)spi_lld_serve_rx_interrupt, - (void *)spip); - osalDbgAssert(!b, "stream already allocated"); - b = dmaStreamAllocate(spip->dmatx, - STM32_SPI_SPI1_IRQ_PRIORITY, - (stm32_dmaisr_t)spi_lld_serve_tx_interrupt, - (void *)spip); - osalDbgAssert(!b, "stream already allocated"); - rccEnableSPI1(FALSE); - } -#endif -#if STM32_SPI_USE_SPI2 - if (&SPID2 == spip) { - bool b; - b = dmaStreamAllocate(spip->dmarx, - STM32_SPI_SPI2_IRQ_PRIORITY, - (stm32_dmaisr_t)spi_lld_serve_rx_interrupt, - (void *)spip); - osalDbgAssert(!b, "stream already allocated"); - b = dmaStreamAllocate(spip->dmatx, - STM32_SPI_SPI2_IRQ_PRIORITY, - (stm32_dmaisr_t)spi_lld_serve_tx_interrupt, - (void *)spip); - osalDbgAssert(!b, "stream already allocated"); - rccEnableSPI2(FALSE); - } -#endif -#if STM32_SPI_USE_SPI3 - if (&SPID3 == spip) { - bool b; - b = dmaStreamAllocate(spip->dmarx, - STM32_SPI_SPI3_IRQ_PRIORITY, - (stm32_dmaisr_t)spi_lld_serve_rx_interrupt, - (void *)spip); - osalDbgAssert(!b, "stream already allocated"); - b = dmaStreamAllocate(spip->dmatx, - STM32_SPI_SPI3_IRQ_PRIORITY, - (stm32_dmaisr_t)spi_lld_serve_tx_interrupt, - (void *)spip); - osalDbgAssert(!b, "stream already allocated"); - rccEnableSPI3(FALSE); - } -#endif - - /* DMA setup.*/ - dmaStreamSetPeripheral(spip->dmarx, &spip->spi->DR); - dmaStreamSetPeripheral(spip->dmatx, &spip->spi->DR); - } - - /* Configuration-specific DMA setup.*/ - if ((spip->config->cr1 & SPI_CR1_DFF) == 0) { - /* Frame width is 8 bits or smaller.*/ - spip->rxdmamode = (spip->rxdmamode & ~STM32_DMA_CR_SIZE_MASK) | - STM32_DMA_CR_PSIZE_BYTE | STM32_DMA_CR_MSIZE_BYTE; - spip->txdmamode = (spip->txdmamode & ~STM32_DMA_CR_SIZE_MASK) | - STM32_DMA_CR_PSIZE_BYTE | STM32_DMA_CR_MSIZE_BYTE; - } - else { - /* Frame width is larger than 8 bits.*/ - spip->rxdmamode = (spip->rxdmamode & ~STM32_DMA_CR_SIZE_MASK) | - STM32_DMA_CR_PSIZE_HWORD | STM32_DMA_CR_MSIZE_HWORD; - spip->txdmamode = (spip->txdmamode & ~STM32_DMA_CR_SIZE_MASK) | - STM32_DMA_CR_PSIZE_HWORD | STM32_DMA_CR_MSIZE_HWORD; - } - /* SPI setup and enable.*/ - spip->spi->CR1 = 0; - spip->spi->CR1 = spip->config->cr1 | SPI_CR1_MSTR | SPI_CR1_SSM | - SPI_CR1_SSI; - spip->spi->CR2 = SPI_CR2_SSOE | SPI_CR2_RXDMAEN | SPI_CR2_TXDMAEN; - spip->spi->CR1 |= SPI_CR1_SPE; -} - -/** - * @brief Deactivates the SPI peripheral. - * - * @param[in] spip pointer to the @p SPIDriver object - * - * @notapi - */ -void spi_lld_stop(SPIDriver *spip) { - - /* If in ready state then disables the SPI clock.*/ - if (spip->state == SPI_READY) { - - /* SPI disable.*/ - spip->spi->CR1 = 0; - spip->spi->CR2 = 0; - dmaStreamRelease(spip->dmarx); - dmaStreamRelease(spip->dmatx); - -#if STM32_SPI_USE_SPI1 - if (&SPID1 == spip) - rccDisableSPI1(FALSE); -#endif -#if STM32_SPI_USE_SPI2 - if (&SPID2 == spip) - rccDisableSPI2(FALSE); -#endif -#if STM32_SPI_USE_SPI3 - if (&SPID3 == spip) - rccDisableSPI3(FALSE); -#endif - } -} - -/** - * @brief Asserts the slave select signal and prepares for transfers. - * - * @param[in] spip pointer to the @p SPIDriver object - * - * @notapi - */ -void spi_lld_select(SPIDriver *spip) { - - palClearPad(spip->config->ssport, spip->config->sspad); -} - -/** - * @brief Deasserts the slave select signal. - * @details The previously selected peripheral is unselected. - * - * @param[in] spip pointer to the @p SPIDriver object - * - * @notapi - */ -void spi_lld_unselect(SPIDriver *spip) { - - palSetPad(spip->config->ssport, spip->config->sspad); -} - -/** - * @brief Ignores data on the SPI bus. - * @details This asynchronous function starts the transmission of a series of - * idle words on the SPI bus and ignores the received data. - * @post At the end of the operation the configured callback is invoked. - * - * @param[in] spip pointer to the @p SPIDriver object - * @param[in] n number of words to be ignored - * - * @notapi - */ -void spi_lld_ignore(SPIDriver *spip, size_t n) { - - dmaStreamSetMemory0(spip->dmarx, &dummyrx); - dmaStreamSetTransactionSize(spip->dmarx, n); - dmaStreamSetMode(spip->dmarx, spip->rxdmamode); - - dmaStreamSetMemory0(spip->dmatx, &dummytx); - dmaStreamSetTransactionSize(spip->dmatx, n); - dmaStreamSetMode(spip->dmatx, spip->txdmamode); - - dmaStreamEnable(spip->dmarx); - dmaStreamEnable(spip->dmatx); -} - -/** - * @brief Exchanges data on the SPI bus. - * @details This asynchronous function starts a simultaneous transmit/receive - * operation. - * @post At the end of the operation the configured callback is invoked. - * @note The buffers are organized as uint8_t arrays for data sizes below or - * equal to 8 bits else it is organized as uint16_t arrays. - * - * @param[in] spip pointer to the @p SPIDriver object - * @param[in] n number of words to be exchanged - * @param[in] txbuf the pointer to the transmit buffer - * @param[out] rxbuf the pointer to the receive buffer - * - * @notapi - */ -void spi_lld_exchange(SPIDriver *spip, size_t n, - const void *txbuf, void *rxbuf) { - - dmaStreamSetMemory0(spip->dmarx, rxbuf); - dmaStreamSetTransactionSize(spip->dmarx, n); - dmaStreamSetMode(spip->dmarx, spip->rxdmamode| STM32_DMA_CR_MINC); - - dmaStreamSetMemory0(spip->dmatx, txbuf); - dmaStreamSetTransactionSize(spip->dmatx, n); - dmaStreamSetMode(spip->dmatx, spip->txdmamode | STM32_DMA_CR_MINC); - - dmaStreamEnable(spip->dmarx); - dmaStreamEnable(spip->dmatx); -} - -/** - * @brief Sends data over the SPI bus. - * @details This asynchronous function starts a transmit operation. - * @post At the end of the operation the configured callback is invoked. - * @note The buffers are organized as uint8_t arrays for data sizes below or - * equal to 8 bits else it is organized as uint16_t arrays. - * - * @param[in] spip pointer to the @p SPIDriver object - * @param[in] n number of words to send - * @param[in] txbuf the pointer to the transmit buffer - * - * @notapi - */ -void spi_lld_send(SPIDriver *spip, size_t n, const void *txbuf) { - - dmaStreamSetMemory0(spip->dmarx, &dummyrx); - dmaStreamSetTransactionSize(spip->dmarx, n); - dmaStreamSetMode(spip->dmarx, spip->rxdmamode); - - dmaStreamSetMemory0(spip->dmatx, txbuf); - dmaStreamSetTransactionSize(spip->dmatx, n); - dmaStreamSetMode(spip->dmatx, spip->txdmamode | STM32_DMA_CR_MINC); - - dmaStreamEnable(spip->dmarx); - dmaStreamEnable(spip->dmatx); -} - -/** - * @brief Receives data from the SPI bus. - * @details This asynchronous function starts a receive operation. - * @post At the end of the operation the configured callback is invoked. - * @note The buffers are organized as uint8_t arrays for data sizes below or - * equal to 8 bits else it is organized as uint16_t arrays. - * - * @param[in] spip pointer to the @p SPIDriver object - * @param[in] n number of words to receive - * @param[out] rxbuf the pointer to the receive buffer - * - * @notapi - */ -void spi_lld_receive(SPIDriver *spip, size_t n, void *rxbuf) { - - dmaStreamSetMemory0(spip->dmarx, rxbuf); - dmaStreamSetTransactionSize(spip->dmarx, n); - dmaStreamSetMode(spip->dmarx, spip->rxdmamode | STM32_DMA_CR_MINC); - - dmaStreamSetMemory0(spip->dmatx, &dummytx); - dmaStreamSetTransactionSize(spip->dmatx, n); - dmaStreamSetMode(spip->dmatx, spip->txdmamode); - - dmaStreamEnable(spip->dmarx); - dmaStreamEnable(spip->dmatx); -} - -/** - * @brief Exchanges one frame using a polled wait. - * @details This synchronous function exchanges one frame using a polled - * synchronization method. This function is useful when exchanging - * small amount of data on high speed channels, usually in this - * situation is much more efficient just wait for completion using - * polling than suspending the thread waiting for an interrupt. - * - * @param[in] spip pointer to the @p SPIDriver object - * @param[in] frame the data frame to send over the SPI bus - * @return The received data frame from the SPI bus. - */ -uint16_t spi_lld_polled_exchange(SPIDriver *spip, uint16_t frame) { - - spip->spi->DR = frame; - while ((spip->spi->SR & SPI_SR_RXNE) == 0) - ; - return spip->spi->DR; -} - -#endif /* HAL_USE_SPI */ - -/** @} */ diff --git a/os/hal/platforms/STM32/SPIv1/spi_lld.h b/os/hal/platforms/STM32/SPIv1/spi_lld.h deleted file mode 100644 index b0a65d7cd..000000000 --- a/os/hal/platforms/STM32/SPIv1/spi_lld.h +++ /dev/null @@ -1,407 +0,0 @@ -/* - ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file STM32/SPIv1/spi_lld.h - * @brief STM32 SPI subsystem low level driver header. - * - * @addtogroup SPI - * @{ - */ - -#ifndef _SPI_LLD_H_ -#define _SPI_LLD_H_ - -#if HAL_USE_SPI || defined(__DOXYGEN__) - -/*===========================================================================*/ -/* Driver constants. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver pre-compile time settings. */ -/*===========================================================================*/ - -/** - * @name Configuration options - * @{ - */ -/** - * @brief SPI1 driver enable switch. - * @details If set to @p TRUE the support for SPI1 is included. - * @note The default is @p TRUE. - */ -#if !defined(STM32_SPI_USE_SPI1) || defined(__DOXYGEN__) -#define STM32_SPI_USE_SPI1 FALSE -#endif - -/** - * @brief SPI2 driver enable switch. - * @details If set to @p TRUE the support for SPI2 is included. - * @note The default is @p TRUE. - */ -#if !defined(STM32_SPI_USE_SPI2) || defined(__DOXYGEN__) -#define STM32_SPI_USE_SPI2 FALSE -#endif - -/** - * @brief SPI3 driver enable switch. - * @details If set to @p TRUE the support for SPI3 is included. - * @note The default is @p TRUE. - */ -#if !defined(STM32_SPI_USE_SPI3) || defined(__DOXYGEN__) -#define STM32_SPI_USE_SPI3 FALSE -#endif - -/** - * @brief SPI1 interrupt priority level setting. - */ -#if !defined(STM32_SPI_SPI1_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_SPI_SPI1_IRQ_PRIORITY 10 -#endif - -/** - * @brief SPI2 interrupt priority level setting. - */ -#if !defined(STM32_SPI_SPI2_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_SPI_SPI2_IRQ_PRIORITY 10 -#endif - -/** - * @brief SPI3 interrupt priority level setting. - */ -#if !defined(STM32_SPI_SPI3_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_SPI_SPI3_IRQ_PRIORITY 10 -#endif - -/** - * @brief SPI1 DMA priority (0..3|lowest..highest). - * @note The priority level is used for both the TX and RX DMA streams but - * because of the streams ordering the RX stream has always priority - * over the TX stream. - */ -#if !defined(STM32_SPI_SPI1_DMA_PRIORITY) || defined(__DOXYGEN__) -#define STM32_SPI_SPI1_DMA_PRIORITY 1 -#endif - -/** - * @brief SPI2 DMA priority (0..3|lowest..highest). - * @note The priority level is used for both the TX and RX DMA streams but - * because of the streams ordering the RX stream has always priority - * over the TX stream. - */ -#if !defined(STM32_SPI_SPI2_DMA_PRIORITY) || defined(__DOXYGEN__) -#define STM32_SPI_SPI2_DMA_PRIORITY 1 -#endif - -/** - * @brief SPI3 DMA priority (0..3|lowest..highest). - * @note The priority level is used for both the TX and RX DMA streams but - * because of the streams ordering the RX stream has always priority - * over the TX stream. - */ -#if !defined(STM32_SPI_SPI3_DMA_PRIORITY) || defined(__DOXYGEN__) -#define STM32_SPI_SPI3_DMA_PRIORITY 1 -#endif - -/** - * @brief SPI DMA error hook. - */ -#if !defined(STM32_SPI_DMA_ERROR_HOOK) || defined(__DOXYGEN__) -#define STM32_SPI_DMA_ERROR_HOOK(spip) chSysHalt() -#endif - -#if STM32_ADVANCED_DMA || defined(__DOXYGEN__) - -/** - * @brief DMA stream used for SPI1 RX operations. - * @note This option is only available on platforms with enhanced DMA. - */ -#if !defined(STM32_SPI_SPI1_RX_DMA_STREAM) || defined(__DOXYGEN__) -#define STM32_SPI_SPI1_RX_DMA_STREAM STM32_DMA_STREAM_ID(2, 0) -#endif - -/** - * @brief DMA stream used for SPI1 TX operations. - * @note This option is only available on platforms with enhanced DMA. - */ -#if !defined(STM32_SPI_SPI1_TX_DMA_STREAM) || defined(__DOXYGEN__) -#define STM32_SPI_SPI1_TX_DMA_STREAM STM32_DMA_STREAM_ID(2, 3) -#endif - -/** - * @brief DMA stream used for SPI2 RX operations. - * @note This option is only available on platforms with enhanced DMA. - */ -#if !defined(STM32_SPI_SPI2_RX_DMA_STREAM) || defined(__DOXYGEN__) -#define STM32_SPI_SPI2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 3) -#endif - -/** - * @brief DMA stream used for SPI2 TX operations. - * @note This option is only available on platforms with enhanced DMA. - */ -#if !defined(STM32_SPI_SPI2_TX_DMA_STREAM) || defined(__DOXYGEN__) -#define STM32_SPI_SPI2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) -#endif - -/** - * @brief DMA stream used for SPI3 RX operations. - * @note This option is only available on platforms with enhanced DMA. - */ -#if !defined(STM32_SPI_SPI3_RX_DMA_STREAM) || defined(__DOXYGEN__) -#define STM32_SPI_SPI3_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 0) -#endif - -/** - * @brief DMA stream used for SPI3 TX operations. - * @note This option is only available on platforms with enhanced DMA. - */ -#if !defined(STM32_SPI_SPI3_TX_DMA_STREAM) || defined(__DOXYGEN__) -#define STM32_SPI_SPI3_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7) -#endif - -#else /* !STM32_ADVANCED_DMA */ - -/* Fixed streams for platforms using the old DMA peripheral, the values are - valid for both STM32F1xx and STM32L1xx.*/ -#define STM32_SPI_SPI1_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2) -#define STM32_SPI_SPI1_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 3) -#define STM32_SPI_SPI2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) -#define STM32_SPI_SPI2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 5) -#define STM32_SPI_SPI3_RX_DMA_STREAM STM32_DMA_STREAM_ID(2, 1) -#define STM32_SPI_SPI3_TX_DMA_STREAM STM32_DMA_STREAM_ID(2, 2) - -#endif /* !STM32_ADVANCED_DMA*/ -/** @} */ - -/*===========================================================================*/ -/* Derived constants and error checks. */ -/*===========================================================================*/ - -#if STM32_SPI_USE_SPI1 && !STM32_HAS_SPI1 -#error "SPI1 not present in the selected device" -#endif - -#if STM32_SPI_USE_SPI2 && !STM32_HAS_SPI2 -#error "SPI2 not present in the selected device" -#endif - -#if STM32_SPI_USE_SPI3 && !STM32_HAS_SPI3 -#error "SPI3 not present in the selected device" -#endif - -#if !STM32_SPI_USE_SPI1 && !STM32_SPI_USE_SPI2 && !STM32_SPI_USE_SPI3 -#error "SPI driver activated but no SPI peripheral assigned" -#endif - -#if STM32_SPI_USE_SPI1 && \ - !CORTEX_IS_VALID_KERNEL_PRIORITY(STM32_SPI_SPI1_IRQ_PRIORITY) -#error "Invalid IRQ priority assigned to SPI1" -#endif - -#if STM32_SPI_USE_SPI2 && \ - !CORTEX_IS_VALID_KERNEL_PRIORITY(STM32_SPI_SPI2_IRQ_PRIORITY) -#error "Invalid IRQ priority assigned to SPI2" -#endif - -#if STM32_SPI_USE_SPI3 && \ - !CORTEX_IS_VALID_KERNEL_PRIORITY(STM32_SPI_SPI3_IRQ_PRIORITY) -#error "Invalid IRQ priority assigned to SPI3" -#endif - -#if STM32_SPI_USE_SPI1 && \ - !STM32_DMA_IS_VALID_PRIORITY(STM32_SPI_SPI1_DMA_PRIORITY) -#error "Invalid DMA priority assigned to SPI1" -#endif - -#if STM32_SPI_USE_SPI2 && \ - !STM32_DMA_IS_VALID_PRIORITY(STM32_SPI_SPI2_DMA_PRIORITY) -#error "Invalid DMA priority assigned to SPI2" -#endif - -#if STM32_SPI_USE_SPI3 && \ - !STM32_DMA_IS_VALID_PRIORITY(STM32_SPI_SPI3_DMA_PRIORITY) -#error "Invalid DMA priority assigned to SPI3" -#endif - -#if STM32_SPI_USE_SPI1 && \ - !STM32_DMA_IS_VALID_ID(STM32_SPI_SPI1_RX_DMA_STREAM, STM32_SPI1_RX_DMA_MSK) -#error "invalid DMA stream associated to SPI1 RX" -#endif - -#if STM32_SPI_USE_SPI1 && \ - !STM32_DMA_IS_VALID_ID(STM32_SPI_SPI1_TX_DMA_STREAM, STM32_SPI1_TX_DMA_MSK) -#error "invalid DMA stream associated to SPI1 TX" -#endif - -#if STM32_SPI_USE_SPI2 && \ - !STM32_DMA_IS_VALID_ID(STM32_SPI_SPI2_RX_DMA_STREAM, STM32_SPI2_RX_DMA_MSK) -#error "invalid DMA stream associated to SPI2 RX" -#endif - -#if STM32_SPI_USE_SPI2 && \ - !STM32_DMA_IS_VALID_ID(STM32_SPI_SPI2_TX_DMA_STREAM, STM32_SPI2_TX_DMA_MSK) -#error "invalid DMA stream associated to SPI2 TX" -#endif - -#if STM32_SPI_USE_SPI3 && \ - !STM32_DMA_IS_VALID_ID(STM32_SPI_SPI3_RX_DMA_STREAM, STM32_SPI3_RX_DMA_MSK) -#error "invalid DMA stream associated to SPI3 RX" -#endif - -#if STM32_SPI_USE_SPI3 && \ - !STM32_DMA_IS_VALID_ID(STM32_SPI_SPI3_TX_DMA_STREAM, STM32_SPI3_TX_DMA_MSK) -#error "invalid DMA stream associated to SPI3 TX" -#endif - -#if !defined(STM32_DMA_REQUIRED) -#define STM32_DMA_REQUIRED -#endif - -/*===========================================================================*/ -/* Driver data structures and types. */ -/*===========================================================================*/ - -/** - * @brief Type of a structure representing an SPI driver. - */ -typedef struct SPIDriver SPIDriver; - -/** - * @brief SPI notification callback type. - * - * @param[in] spip pointer to the @p SPIDriver object triggering the - * callback - */ -typedef void (*spicallback_t)(SPIDriver *spip); - -/** - * @brief Driver configuration structure. - */ -typedef struct { - /** - * @brief Operation complete callback or @p NULL. - */ - spicallback_t end_cb; - /* End of the mandatory fields.*/ - /** - * @brief The chip select line port. - */ - ioportid_t ssport; - /** - * @brief The chip select line pad number. - */ - uint16_t sspad; - /** - * @brief SPI initialization data. - */ - uint16_t cr1; -} SPIConfig; - -/** - * @brief Structure representing a SPI driver. - */ -struct SPIDriver{ - /** - * @brief Driver state. - */ - spistate_t state; - /** - * @brief Current configuration data. - */ - const SPIConfig *config; -#if SPI_USE_WAIT || defined(__DOXYGEN__) - /** - * @brief Waiting thread. - */ - thread_reference_t thread; -#endif /* SPI_USE_WAIT */ -#if SPI_USE_MUTUAL_EXCLUSION || defined(__DOXYGEN__) - /** - * @brief Mutex protecting the bus. - */ - mutex_t mutex; -#endif /* SPI_USE_MUTUAL_EXCLUSION */ -#if defined(SPI_DRIVER_EXT_FIELDS) - SPI_DRIVER_EXT_FIELDS -#endif - /* End of the mandatory fields.*/ - /** - * @brief Pointer to the SPIx registers block. - */ - SPI_TypeDef *spi; - /** - * @brief Receive DMA stream. - */ - const stm32_dma_stream_t *dmarx; - /** - * @brief Transmit DMA stream. - */ - const stm32_dma_stream_t *dmatx; - /** - * @brief RX DMA mode bit mask. - */ - uint32_t rxdmamode; - /** - * @brief TX DMA mode bit mask. - */ - uint32_t txdmamode; -}; - -/*===========================================================================*/ -/* Driver macros. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* External declarations. */ -/*===========================================================================*/ - -#if STM32_SPI_USE_SPI1 && !defined(__DOXYGEN__) -extern SPIDriver SPID1; -#endif - -#if STM32_SPI_USE_SPI2 && !defined(__DOXYGEN__) -extern SPIDriver SPID2; -#endif - -#if STM32_SPI_USE_SPI3 && !defined(__DOXYGEN__) -extern SPIDriver SPID3; -#endif - -#ifdef __cplusplus -extern "C" { -#endif - void spi_lld_init(void); - void spi_lld_start(SPIDriver *spip); - void spi_lld_stop(SPIDriver *spip); - void spi_lld_select(SPIDriver *spip); - void spi_lld_unselect(SPIDriver *spip); - void spi_lld_ignore(SPIDriver *spip, size_t n); - void spi_lld_exchange(SPIDriver *spip, size_t n, - const void *txbuf, void *rxbuf); - void spi_lld_send(SPIDriver *spip, size_t n, const void *txbuf); - void spi_lld_receive(SPIDriver *spip, size_t n, void *rxbuf); - uint16_t spi_lld_polled_exchange(SPIDriver *spip, uint16_t frame); -#ifdef __cplusplus -} -#endif - -#endif /* HAL_USE_SPI */ - -#endif /* _SPI_LLD_H_ */ - -/** @} */ diff --git a/os/hal/platforms/STM32/SPIv2/spi_lld.c b/os/hal/platforms/STM32/SPIv2/spi_lld.c deleted file mode 100644 index 3cbcc0fc0..000000000 --- a/os/hal/platforms/STM32/SPIv2/spi_lld.c +++ /dev/null @@ -1,501 +0,0 @@ -/* - ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file STM32/SPIv2/spi_lld.c - * @brief STM32 SPI subsystem low level driver source. - * - * @addtogroup SPI - * @{ - */ - -#include "hal.h" - -#if HAL_USE_SPI || defined(__DOXYGEN__) - -/*===========================================================================*/ -/* Driver local definitions. */ -/*===========================================================================*/ - -#define SPI1_RX_DMA_CHANNEL \ - STM32_DMA_GETCHANNEL(STM32_SPI_SPI1_RX_DMA_STREAM, \ - STM32_SPI1_RX_DMA_CHN) - -#define SPI1_TX_DMA_CHANNEL \ - STM32_DMA_GETCHANNEL(STM32_SPI_SPI1_TX_DMA_STREAM, \ - STM32_SPI1_TX_DMA_CHN) - -#define SPI2_RX_DMA_CHANNEL \ - STM32_DMA_GETCHANNEL(STM32_SPI_SPI2_RX_DMA_STREAM, \ - STM32_SPI2_RX_DMA_CHN) - -#define SPI2_TX_DMA_CHANNEL \ - STM32_DMA_GETCHANNEL(STM32_SPI_SPI2_TX_DMA_STREAM, \ - STM32_SPI2_TX_DMA_CHN) - -#define SPI3_RX_DMA_CHANNEL \ - STM32_DMA_GETCHANNEL(STM32_SPI_SPI3_RX_DMA_STREAM, \ - STM32_SPI3_RX_DMA_CHN) - -#define SPI3_TX_DMA_CHANNEL \ - STM32_DMA_GETCHANNEL(STM32_SPI_SPI3_TX_DMA_STREAM, \ - STM32_SPI3_TX_DMA_CHN) - -/*===========================================================================*/ -/* Driver exported variables. */ -/*===========================================================================*/ - -/** @brief SPI1 driver identifier.*/ -#if STM32_SPI_USE_SPI1 || defined(__DOXYGEN__) -SPIDriver SPID1; -#endif - -/** @brief SPI2 driver identifier.*/ -#if STM32_SPI_USE_SPI2 || defined(__DOXYGEN__) -SPIDriver SPID2; -#endif - -/** @brief SPI3 driver identifier.*/ -#if STM32_SPI_USE_SPI3 || defined(__DOXYGEN__) -SPIDriver SPID3; -#endif - -/*===========================================================================*/ -/* Driver local variables and types. */ -/*===========================================================================*/ - -static uint16_t dummytx; -static uint16_t dummyrx; - -/*===========================================================================*/ -/* Driver local functions. */ -/*===========================================================================*/ - -/** - * @brief Shared end-of-rx service routine. - * - * @param[in] spip pointer to the @p SPIDriver object - * @param[in] flags pre-shifted content of the ISR register - */ -static void spi_lld_serve_rx_interrupt(SPIDriver *spip, uint32_t flags) { - - /* DMA errors handling.*/ -#if defined(STM32_SPI_DMA_ERROR_HOOK) - if ((flags & (STM32_DMA_ISR_TEIF | STM32_DMA_ISR_DMEIF)) != 0) { - STM32_SPI_DMA_ERROR_HOOK(spip); - } -#else - (void)flags; -#endif - - /* Stop everything.*/ - dmaStreamDisable(spip->dmatx); - dmaStreamDisable(spip->dmarx); - - /* Portable SPI ISR code defined in the high level driver, note, it is - a macro.*/ - _spi_isr_code(spip); -} - -/** - * @brief Shared end-of-tx service routine. - * - * @param[in] spip pointer to the @p SPIDriver object - * @param[in] flags pre-shifted content of the ISR register - */ -static void spi_lld_serve_tx_interrupt(SPIDriver *spip, uint32_t flags) { - - /* DMA errors handling.*/ -#if defined(STM32_SPI_DMA_ERROR_HOOK) - (void)spip; - if ((flags & (STM32_DMA_ISR_TEIF | STM32_DMA_ISR_DMEIF)) != 0) { - STM32_SPI_DMA_ERROR_HOOK(spip); - } -#else - (void)spip; - (void)flags; -#endif -} - -/*===========================================================================*/ -/* Driver interrupt handlers. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver exported functions. */ -/*===========================================================================*/ - -/** - * @brief Low level SPI driver initialization. - * - * @notapi - */ -void spi_lld_init(void) { - - dummytx = 0xFFFF; - -#if STM32_SPI_USE_SPI1 - spiObjectInit(&SPID1); - SPID1.spi = SPI1; - SPID1.dmarx = STM32_DMA_STREAM(STM32_SPI_SPI1_RX_DMA_STREAM); - SPID1.dmatx = STM32_DMA_STREAM(STM32_SPI_SPI1_TX_DMA_STREAM); - SPID1.rxdmamode = STM32_DMA_CR_CHSEL(SPI1_RX_DMA_CHANNEL) | - STM32_DMA_CR_PL(STM32_SPI_SPI1_DMA_PRIORITY) | - STM32_DMA_CR_DIR_P2M | - STM32_DMA_CR_TCIE | - STM32_DMA_CR_DMEIE | - STM32_DMA_CR_TEIE; - SPID1.txdmamode = STM32_DMA_CR_CHSEL(SPI1_TX_DMA_CHANNEL) | - STM32_DMA_CR_PL(STM32_SPI_SPI1_DMA_PRIORITY) | - STM32_DMA_CR_DIR_M2P | - STM32_DMA_CR_DMEIE | - STM32_DMA_CR_TEIE; -#endif - -#if STM32_SPI_USE_SPI2 - spiObjectInit(&SPID2); - SPID2.spi = SPI2; - SPID2.dmarx = STM32_DMA_STREAM(STM32_SPI_SPI2_RX_DMA_STREAM); - SPID2.dmatx = STM32_DMA_STREAM(STM32_SPI_SPI2_TX_DMA_STREAM); - SPID2.rxdmamode = STM32_DMA_CR_CHSEL(SPI2_RX_DMA_CHANNEL) | - STM32_DMA_CR_PL(STM32_SPI_SPI2_DMA_PRIORITY) | - STM32_DMA_CR_DIR_P2M | - STM32_DMA_CR_TCIE | - STM32_DMA_CR_DMEIE | - STM32_DMA_CR_TEIE; - SPID2.txdmamode = STM32_DMA_CR_CHSEL(SPI2_TX_DMA_CHANNEL) | - STM32_DMA_CR_PL(STM32_SPI_SPI2_DMA_PRIORITY) | - STM32_DMA_CR_DIR_M2P | - STM32_DMA_CR_DMEIE | - STM32_DMA_CR_TEIE; -#endif - -#if STM32_SPI_USE_SPI3 - spiObjectInit(&SPID3); - SPID3.spi = SPI3; - SPID3.dmarx = STM32_DMA_STREAM(STM32_SPI_SPI3_RX_DMA_STREAM); - SPID3.dmatx = STM32_DMA_STREAM(STM32_SPI_SPI3_TX_DMA_STREAM); - SPID3.rxdmamode = STM32_DMA_CR_CHSEL(SPI3_RX_DMA_CHANNEL) | - STM32_DMA_CR_PL(STM32_SPI_SPI3_DMA_PRIORITY) | - STM32_DMA_CR_DIR_P2M | - STM32_DMA_CR_TCIE | - STM32_DMA_CR_DMEIE | - STM32_DMA_CR_TEIE; - SPID3.txdmamode = STM32_DMA_CR_CHSEL(SPI3_TX_DMA_CHANNEL) | - STM32_DMA_CR_PL(STM32_SPI_SPI3_DMA_PRIORITY) | - STM32_DMA_CR_DIR_M2P | - STM32_DMA_CR_DMEIE | - STM32_DMA_CR_TEIE; -#endif -} - -/** - * @brief Configures and activates the SPI peripheral. - * - * @param[in] spip pointer to the @p SPIDriver object - * - * @notapi - */ -void spi_lld_start(SPIDriver *spip) { - uint32_t ds; - - /* If in stopped state then enables the SPI and DMA clocks.*/ - if (spip->state == SPI_STOP) { -#if STM32_SPI_USE_SPI1 - if (&SPID1 == spip) { - bool_t b; - b = dmaStreamAllocate(spip->dmarx, - STM32_SPI_SPI1_IRQ_PRIORITY, - (stm32_dmaisr_t)spi_lld_serve_rx_interrupt, - (void *)spip); - osalDbgAssert(!b, "stream already allocated"); - b = dmaStreamAllocate(spip->dmatx, - STM32_SPI_SPI1_IRQ_PRIORITY, - (stm32_dmaisr_t)spi_lld_serve_tx_interrupt, - (void *)spip); - osalDbgAssert(!b, "stream already allocated"); - rccEnableSPI1(FALSE); - } -#endif -#if STM32_SPI_USE_SPI2 - if (&SPID2 == spip) { - bool_t b; - b = dmaStreamAllocate(spip->dmarx, - STM32_SPI_SPI2_IRQ_PRIORITY, - (stm32_dmaisr_t)spi_lld_serve_rx_interrupt, - (void *)spip); - osalDbgAssert(!b, "stream already allocated"); - b = dmaStreamAllocate(spip->dmatx, - STM32_SPI_SPI2_IRQ_PRIORITY, - (stm32_dmaisr_t)spi_lld_serve_tx_interrupt, - (void *)spip); - osalDbgAssert(!b, "stream already allocated"); - rccEnableSPI2(FALSE); - } -#endif -#if STM32_SPI_USE_SPI3 - if (&SPID3 == spip) { - bool_t b; - b = dmaStreamAllocate(spip->dmarx, - STM32_SPI_SPI3_IRQ_PRIORITY, - (stm32_dmaisr_t)spi_lld_serve_rx_interrupt, - (void *)spip); - osalDbgAssert(!b, "stream already allocated"); - b = dmaStreamAllocate(spip->dmatx, - STM32_SPI_SPI3_IRQ_PRIORITY, - (stm32_dmaisr_t)spi_lld_serve_tx_interrupt, - (void *)spip); - osalDbgAssert(!b, "stream already allocated"); - rccEnableSPI3(FALSE); - } -#endif - - /* DMA setup.*/ - dmaStreamSetPeripheral(spip->dmarx, &spip->spi->DR); - dmaStreamSetPeripheral(spip->dmatx, &spip->spi->DR); - } - - /* Configuration-specific DMA setup.*/ - ds = spip->config->cr2 & SPI_CR2_DS; - if (!ds || (ds <= (SPI_CR2_DS_2 | SPI_CR2_DS_1 | SPI_CR2_DS_0))) { - /* Frame width is 8 bits or smaller.*/ - spip->rxdmamode = (spip->rxdmamode & ~STM32_DMA_CR_SIZE_MASK) | - STM32_DMA_CR_PSIZE_BYTE | STM32_DMA_CR_MSIZE_BYTE; - spip->txdmamode = (spip->txdmamode & ~STM32_DMA_CR_SIZE_MASK) | - STM32_DMA_CR_PSIZE_BYTE | STM32_DMA_CR_MSIZE_BYTE; - } - else { - /* Frame width is larger than 8 bits.*/ - spip->rxdmamode = (spip->rxdmamode & ~STM32_DMA_CR_SIZE_MASK) | - STM32_DMA_CR_PSIZE_HWORD | STM32_DMA_CR_MSIZE_HWORD; - spip->txdmamode = (spip->txdmamode & ~STM32_DMA_CR_SIZE_MASK) | - STM32_DMA_CR_PSIZE_HWORD | STM32_DMA_CR_MSIZE_HWORD; - } - /* SPI setup and enable.*/ - spip->spi->CR1 = 0; - spip->spi->CR1 = spip->config->cr1 | SPI_CR1_MSTR | SPI_CR1_SSM | - SPI_CR1_SSI; - spip->spi->CR2 = spip->config->cr2 | SPI_CR2_FRXTH | SPI_CR2_SSOE | - SPI_CR2_RXDMAEN | SPI_CR2_TXDMAEN; - spip->spi->CR1 |= SPI_CR1_SPE; -} - -/** - * @brief Deactivates the SPI peripheral. - * - * @param[in] spip pointer to the @p SPIDriver object - * - * @notapi - */ -void spi_lld_stop(SPIDriver *spip) { - - /* If in ready state then disables the SPI clock.*/ - if (spip->state == SPI_READY) { - - /* SPI disable.*/ - spip->spi->CR1 = 0; - spip->spi->CR2 = 0; - dmaStreamRelease(spip->dmarx); - dmaStreamRelease(spip->dmatx); - -#if STM32_SPI_USE_SPI1 - if (&SPID1 == spip) - rccDisableSPI1(FALSE); -#endif -#if STM32_SPI_USE_SPI2 - if (&SPID2 == spip) - rccDisableSPI2(FALSE); -#endif -#if STM32_SPI_USE_SPI3 - if (&SPID3 == spip) - rccDisableSPI3(FALSE); -#endif - } -} - -/** - * @brief Asserts the slave select signal and prepares for transfers. - * - * @param[in] spip pointer to the @p SPIDriver object - * - * @notapi - */ -void spi_lld_select(SPIDriver *spip) { - - palClearPad(spip->config->ssport, spip->config->sspad); -} - -/** - * @brief Deasserts the slave select signal. - * @details The previously selected peripheral is unselected. - * - * @param[in] spip pointer to the @p SPIDriver object - * - * @notapi - */ -void spi_lld_unselect(SPIDriver *spip) { - - palSetPad(spip->config->ssport, spip->config->sspad); -} - -/** - * @brief Ignores data on the SPI bus. - * @details This asynchronous function starts the transmission of a series of - * idle words on the SPI bus and ignores the received data. - * @post At the end of the operation the configured callback is invoked. - * - * @param[in] spip pointer to the @p SPIDriver object - * @param[in] n number of words to be ignored - * - * @notapi - */ -void spi_lld_ignore(SPIDriver *spip, size_t n) { - - dmaStreamSetMemory0(spip->dmarx, &dummyrx); - dmaStreamSetTransactionSize(spip->dmarx, n); - dmaStreamSetMode(spip->dmarx, spip->rxdmamode); - - dmaStreamSetMemory0(spip->dmatx, &dummytx); - dmaStreamSetTransactionSize(spip->dmatx, n); - dmaStreamSetMode(spip->dmatx, spip->txdmamode); - - dmaStreamEnable(spip->dmarx); - dmaStreamEnable(spip->dmatx); -} - -/** - * @brief Exchanges data on the SPI bus. - * @details This asynchronous function starts a simultaneous transmit/receive - * operation. - * @post At the end of the operation the configured callback is invoked. - * @note The buffers are organized as uint8_t arrays for data sizes below or - * equal to 8 bits else it is organized as uint16_t arrays. - * - * @param[in] spip pointer to the @p SPIDriver object - * @param[in] n number of words to be exchanged - * @param[in] txbuf the pointer to the transmit buffer - * @param[out] rxbuf the pointer to the receive buffer - * - * @notapi - */ -void spi_lld_exchange(SPIDriver *spip, size_t n, - const void *txbuf, void *rxbuf) { - - dmaStreamSetMemory0(spip->dmarx, rxbuf); - dmaStreamSetTransactionSize(spip->dmarx, n); - dmaStreamSetMode(spip->dmarx, spip->rxdmamode| STM32_DMA_CR_MINC); - - dmaStreamSetMemory0(spip->dmatx, txbuf); - dmaStreamSetTransactionSize(spip->dmatx, n); - dmaStreamSetMode(spip->dmatx, spip->txdmamode | STM32_DMA_CR_MINC); - - dmaStreamEnable(spip->dmarx); - dmaStreamEnable(spip->dmatx); -} - -/** - * @brief Sends data over the SPI bus. - * @details This asynchronous function starts a transmit operation. - * @post At the end of the operation the configured callback is invoked. - * @note The buffers are organized as uint8_t arrays for data sizes below or - * equal to 8 bits else it is organized as uint16_t arrays. - * - * @param[in] spip pointer to the @p SPIDriver object - * @param[in] n number of words to send - * @param[in] txbuf the pointer to the transmit buffer - * - * @notapi - */ -void spi_lld_send(SPIDriver *spip, size_t n, const void *txbuf) { - - dmaStreamSetMemory0(spip->dmarx, &dummyrx); - dmaStreamSetTransactionSize(spip->dmarx, n); - dmaStreamSetMode(spip->dmarx, spip->rxdmamode); - - dmaStreamSetMemory0(spip->dmatx, txbuf); - dmaStreamSetTransactionSize(spip->dmatx, n); - dmaStreamSetMode(spip->dmatx, spip->txdmamode | STM32_DMA_CR_MINC); - - dmaStreamEnable(spip->dmarx); - dmaStreamEnable(spip->dmatx); -} - -/** - * @brief Receives data from the SPI bus. - * @details This asynchronous function starts a receive operation. - * @post At the end of the operation the configured callback is invoked. - * @note The buffers are organized as uint8_t arrays for data sizes below or - * equal to 8 bits else it is organized as uint16_t arrays. - * - * @param[in] spip pointer to the @p SPIDriver object - * @param[in] n number of words to receive - * @param[out] rxbuf the pointer to the receive buffer - * - * @notapi - */ -void spi_lld_receive(SPIDriver *spip, size_t n, void *rxbuf) { - - dmaStreamSetMemory0(spip->dmarx, rxbuf); - dmaStreamSetTransactionSize(spip->dmarx, n); - dmaStreamSetMode(spip->dmarx, spip->rxdmamode | STM32_DMA_CR_MINC); - - dmaStreamSetMemory0(spip->dmatx, &dummytx); - dmaStreamSetTransactionSize(spip->dmatx, n); - dmaStreamSetMode(spip->dmatx, spip->txdmamode); - - dmaStreamEnable(spip->dmarx); - dmaStreamEnable(spip->dmatx); -} - -/** - * @brief Exchanges one frame using a polled wait. - * @details This synchronous function exchanges one frame using a polled - * synchronization method. This function is useful when exchanging - * small amount of data on high speed channels, usually in this - * situation is much more efficient just wait for completion using - * polling than suspending the thread waiting for an interrupt. - * - * @param[in] spip pointer to the @p SPIDriver object - * @param[in] frame the data frame to send over the SPI bus - * @return The received data frame from the SPI bus. - */ -uint16_t spi_lld_polled_exchange(SPIDriver *spip, uint16_t frame) { - - /* - * Data register must be accessed with the appropriate data size. - * Byte size access (uint8_t *) for transactions that are <= 8-bit. - * Halfword size access (uint16_t) for transactions that are <= 8-bit. - */ - if ((spip->config->cr2 & SPI_CR2_DS) <= (SPI_CR2_DS_2 | - SPI_CR2_DS_1 | - SPI_CR2_DS_0)) { - volatile uint8_t *spidr = (volatile uint8_t *)&spip->spi->DR; - *spidr = (uint8_t)frame; - while ((spip->spi->SR & SPI_SR_RXNE) == 0) - ; - return (uint16_t)*spidr; - } - else { - spip->spi->DR = frame; - while ((spip->spi->SR & SPI_SR_RXNE) == 0) - ; - return spip->spi->DR; - } -} - -#endif /* HAL_USE_SPI */ - -/** @} */ diff --git a/os/hal/platforms/STM32/SPIv2/spi_lld.h b/os/hal/platforms/STM32/SPIv2/spi_lld.h deleted file mode 100644 index 07123df12..000000000 --- a/os/hal/platforms/STM32/SPIv2/spi_lld.h +++ /dev/null @@ -1,380 +0,0 @@ -/* - ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file STM32/SPIv2/spi_lld.h - * @brief STM32 SPI subsystem low level driver header. - * - * @addtogroup SPI - * @{ - */ - -#ifndef _SPI_LLD_H_ -#define _SPI_LLD_H_ - -#if HAL_USE_SPI || defined(__DOXYGEN__) - -/*===========================================================================*/ -/* Driver constants. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver pre-compile time settings. */ -/*===========================================================================*/ - -/** - * @name Configuration options - * @{ - */ -/** - * @brief SPI1 driver enable switch. - * @details If set to @p TRUE the support for SPI1 is included. - * @note The default is @p TRUE. - */ -#if !defined(STM32_SPI_USE_SPI1) || defined(__DOXYGEN__) -#define STM32_SPI_USE_SPI1 FALSE -#endif - -/** - * @brief SPI2 driver enable switch. - * @details If set to @p TRUE the support for SPI2 is included. - * @note The default is @p TRUE. - */ -#if !defined(STM32_SPI_USE_SPI2) || defined(__DOXYGEN__) -#define STM32_SPI_USE_SPI2 FALSE -#endif - -/** - * @brief SPI3 driver enable switch. - * @details If set to @p TRUE the support for SPI3 is included. - * @note The default is @p TRUE. - */ -#if !defined(STM32_SPI_USE_SPI3) || defined(__DOXYGEN__) -#define STM32_SPI_USE_SPI3 FALSE -#endif - -/** - * @brief SPI1 interrupt priority level setting. - */ -#if !defined(STM32_SPI_SPI1_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_SPI_SPI1_IRQ_PRIORITY 10 -#endif - -/** - * @brief SPI2 interrupt priority level setting. - */ -#if !defined(STM32_SPI_SPI2_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_SPI_SPI2_IRQ_PRIORITY 10 -#endif - -/** - * @brief SPI3 interrupt priority level setting. - */ -#if !defined(STM32_SPI_SPI3_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_SPI_SPI3_IRQ_PRIORITY 10 -#endif - -/** - * @brief SPI1 DMA priority (0..3|lowest..highest). - * @note The priority level is used for both the TX and RX DMA streams but - * because of the streams ordering the RX stream has always priority - * over the TX stream. - */ -#if !defined(STM32_SPI_SPI1_DMA_PRIORITY) || defined(__DOXYGEN__) -#define STM32_SPI_SPI1_DMA_PRIORITY 1 -#endif - -/** - * @brief SPI2 DMA priority (0..3|lowest..highest). - * @note The priority level is used for both the TX and RX DMA streams but - * because of the streams ordering the RX stream has always priority - * over the TX stream. - */ -#if !defined(STM32_SPI_SPI2_DMA_PRIORITY) || defined(__DOXYGEN__) -#define STM32_SPI_SPI2_DMA_PRIORITY 1 -#endif - -/** - * @brief SPI3 DMA priority (0..3|lowest..highest). - * @note The priority level is used for both the TX and RX DMA streams but - * because of the streams ordering the RX stream has always priority - * over the TX stream. - */ -#if !defined(STM32_SPI_SPI3_DMA_PRIORITY) || defined(__DOXYGEN__) -#define STM32_SPI_SPI3_DMA_PRIORITY 1 -#endif - -/** - * @brief SPI DMA error hook. - */ -#if !defined(STM32_SPI_DMA_ERROR_HOOK) || defined(__DOXYGEN__) -#define STM32_SPI_DMA_ERROR_HOOK(spip) osalSysHalt("DMA failure") -#endif - -/* TODO: Move the following DMA settings in the STM32F37X registry.*/ -#if defined(STM32F37X) -/* Fixed values for STM32F3xx devices.*/ -#define STM32_SPI_SPI1_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2) -#define STM32_SPI_SPI1_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 3) -#define STM32_SPI_SPI2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) -#define STM32_SPI_SPI2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 5) -#define STM32_SPI_SPI3_RX_DMA_STREAM STM32_DMA_STREAM_ID(2, 1) -#define STM32_SPI_SPI3_TX_DMA_STREAM STM32_DMA_STREAM_ID(2, 2) -#endif /* defined(STM32F30X) */ -/** @} */ - -/*===========================================================================*/ -/* Derived constants and error checks. */ -/*===========================================================================*/ - -#if STM32_SPI_USE_SPI1 && !STM32_HAS_SPI1 -#error "SPI1 not present in the selected device" -#endif - -#if STM32_SPI_USE_SPI2 && !STM32_HAS_SPI2 -#error "SPI2 not present in the selected device" -#endif - -#if STM32_SPI_USE_SPI3 && !STM32_HAS_SPI3 -#error "SPI3 not present in the selected device" -#endif - -#if !STM32_SPI_USE_SPI1 && !STM32_SPI_USE_SPI2 && !STM32_SPI_USE_SPI3 -#error "SPI driver activated but no SPI peripheral assigned" -#endif - -#if STM32_SPI_USE_SPI1 && \ - !CORTEX_IS_VALID_KERNEL_PRIORITY(STM32_SPI_SPI1_IRQ_PRIORITY) -#error "Invalid IRQ priority assigned to SPI1" -#endif - -#if STM32_SPI_USE_SPI2 && \ - !CORTEX_IS_VALID_KERNEL_PRIORITY(STM32_SPI_SPI2_IRQ_PRIORITY) -#error "Invalid IRQ priority assigned to SPI2" -#endif - -#if STM32_SPI_USE_SPI3 && \ - !CORTEX_IS_VALID_KERNEL_PRIORITY(STM32_SPI_SPI3_IRQ_PRIORITY) -#error "Invalid IRQ priority assigned to SPI3" -#endif - -#if STM32_SPI_USE_SPI1 && \ - !STM32_DMA_IS_VALID_PRIORITY(STM32_SPI_SPI1_DMA_PRIORITY) -#error "Invalid DMA priority assigned to SPI1" -#endif - -#if STM32_SPI_USE_SPI2 && \ - !STM32_DMA_IS_VALID_PRIORITY(STM32_SPI_SPI2_DMA_PRIORITY) -#error "Invalid DMA priority assigned to SPI2" -#endif - -#if STM32_SPI_USE_SPI3 && \ - !STM32_DMA_IS_VALID_PRIORITY(STM32_SPI_SPI3_DMA_PRIORITY) -#error "Invalid DMA priority assigned to SPI3" -#endif - -/* The following checks are only required when there is a DMA able to - reassign streams to different channels.*/ -#if STM32_ADVANCED_DMA -/* Check on the presence of the DMA streams settings in mcuconf.h.*/ -#if STM32_SPI_USE_SPI1 && (!defined(STM32_SPI_SPI1_RX_DMA_STREAM) || \ - !defined(STM32_SPI_SPI1_TX_DMA_STREAM)) -#error "SPI1 DMA streams not defined" -#endif - -#if STM32_SPI_USE_SPI2 && (!defined(STM32_SPI_SPI2_RX_DMA_STREAM) || \ - !defined(STM32_SPI_SPI2_TX_DMA_STREAM)) -#error "SPI2 DMA streams not defined" -#endif - -#if STM32_SPI_USE_SPI3 && (!defined(STM32_SPI_SPI3_RX_DMA_STREAM) || \ - !defined(STM32_SPI_SPI3_TX_DMA_STREAM)) -#error "SPI3 DMA streams not defined" -#endif - -/* Check on the validity of the assigned DMA channels.*/ -#if STM32_SPI_USE_SPI1 && \ - !STM32_DMA_IS_VALID_ID(STM32_SPI_SPI1_RX_DMA_STREAM, STM32_SPI1_RX_DMA_MSK) -#error "invalid DMA stream associated to SPI1 RX" -#endif - -#if STM32_SPI_USE_SPI1 && \ - !STM32_DMA_IS_VALID_ID(STM32_SPI_SPI1_TX_DMA_STREAM, STM32_SPI1_TX_DMA_MSK) -#error "invalid DMA stream associated to SPI1 TX" -#endif - -#if STM32_SPI_USE_SPI2 && \ - !STM32_DMA_IS_VALID_ID(STM32_SPI_SPI2_RX_DMA_STREAM, STM32_SPI2_RX_DMA_MSK) -#error "invalid DMA stream associated to SPI2 RX" -#endif - -#if STM32_SPI_USE_SPI2 && \ - !STM32_DMA_IS_VALID_ID(STM32_SPI_SPI2_TX_DMA_STREAM, STM32_SPI2_TX_DMA_MSK) -#error "invalid DMA stream associated to SPI2 TX" -#endif - -#if STM32_SPI_USE_SPI3 && \ - !STM32_DMA_IS_VALID_ID(STM32_SPI_SPI3_RX_DMA_STREAM, STM32_SPI3_RX_DMA_MSK) -#error "invalid DMA stream associated to SPI3 RX" -#endif - -#if STM32_SPI_USE_SPI3 && \ - !STM32_DMA_IS_VALID_ID(STM32_SPI_SPI3_TX_DMA_STREAM, STM32_SPI3_TX_DMA_MSK) -#error "invalid DMA stream associated to SPI3 TX" -#endif -#endif /* STM32_ADVANCED_DMA */ - -#if !defined(STM32_DMA_REQUIRED) -#define STM32_DMA_REQUIRED -#endif - -/*===========================================================================*/ -/* Driver data structures and types. */ -/*===========================================================================*/ - -/** - * @brief Type of a structure representing an SPI driver. - */ -typedef struct SPIDriver SPIDriver; - -/** - * @brief SPI notification callback type. - * - * @param[in] spip pointer to the @p SPIDriver object triggering the - * callback - */ -typedef void (*spicallback_t)(SPIDriver *spip); - -/** - * @brief Driver configuration structure. - */ -typedef struct { - /** - * @brief Operation complete callback or @p NULL. - */ - spicallback_t end_cb; - /* End of the mandatory fields.*/ - /** - * @brief The chip select line port. - */ - ioportid_t ssport; - /** - * @brief The chip select line pad number. - */ - uint16_t sspad; - /** - * @brief SPI CR1 register initialization data. - */ - uint16_t cr1; - /** - * @brief SPI CR2 register initialization data. - */ - uint16_t cr2; -} SPIConfig; - -/** - * @brief Structure representing a SPI driver. - */ -struct SPIDriver{ - /** - * @brief Driver state. - */ - spistate_t state; - /** - * @brief Current configuration data. - */ - const SPIConfig *config; -#if SPI_USE_WAIT || defined(__DOXYGEN__) - /** - * @brief Waiting thread. - */ - thread_reference_t thread; -#endif /* SPI_USE_WAIT */ -#if SPI_USE_MUTUAL_EXCLUSION || defined(__DOXYGEN__) - /** - * @brief Mutex protecting the peripheral. - */ - mutex_t mutex; -#endif /* SPI_USE_MUTUAL_EXCLUSION */ -#if defined(SPI_DRIVER_EXT_FIELDS) - SPI_DRIVER_EXT_FIELDS -#endif - /* End of the mandatory fields.*/ - /** - * @brief Pointer to the SPIx registers block. - */ - SPI_TypeDef *spi; - /** - * @brief Receive DMA stream. - */ - const stm32_dma_stream_t *dmarx; - /** - * @brief Transmit DMA stream. - */ - const stm32_dma_stream_t *dmatx; - /** - * @brief RX DMA mode bit mask. - */ - uint32_t rxdmamode; - /** - * @brief TX DMA mode bit mask. - */ - uint32_t txdmamode; -}; - -/*===========================================================================*/ -/* Driver macros. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* External declarations. */ -/*===========================================================================*/ - -#if STM32_SPI_USE_SPI1 && !defined(__DOXYGEN__) -extern SPIDriver SPID1; -#endif - -#if STM32_SPI_USE_SPI2 && !defined(__DOXYGEN__) -extern SPIDriver SPID2; -#endif - -#if STM32_SPI_USE_SPI3 && !defined(__DOXYGEN__) -extern SPIDriver SPID3; -#endif - -#ifdef __cplusplus -extern "C" { -#endif - void spi_lld_init(void); - void spi_lld_start(SPIDriver *spip); - void spi_lld_stop(SPIDriver *spip); - void spi_lld_select(SPIDriver *spip); - void spi_lld_unselect(SPIDriver *spip); - void spi_lld_ignore(SPIDriver *spip, size_t n); - void spi_lld_exchange(SPIDriver *spip, size_t n, - const void *txbuf, void *rxbuf); - void spi_lld_send(SPIDriver *spip, size_t n, const void *txbuf); - void spi_lld_receive(SPIDriver *spip, size_t n, void *rxbuf); - uint16_t spi_lld_polled_exchange(SPIDriver *spip, uint16_t frame); -#ifdef __cplusplus -} -#endif - -#endif /* HAL_USE_SPI */ - -#endif /* _SPI_LLD_H_ */ - -/** @} */ diff --git a/os/hal/platforms/STM32/TIMv1/gpt_lld.c b/os/hal/platforms/STM32/TIMv1/gpt_lld.c deleted file mode 100644 index f9e144417..000000000 --- a/os/hal/platforms/STM32/TIMv1/gpt_lld.c +++ /dev/null @@ -1,754 +0,0 @@ -/* - ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file STM32/gpt_lld.c - * @brief STM32 GPT subsystem low level driver source. - * - * @addtogroup GPT - * @{ - */ - -#include "hal.h" - -#if HAL_USE_GPT || defined(__DOXYGEN__) - -/*===========================================================================*/ -/* Driver local definitions. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver exported variables. */ -/*===========================================================================*/ - -/** - * @brief GPTD1 driver identifier. - * @note The driver GPTD1 allocates the complex timer TIM1 when enabled. - */ -#if STM32_GPT_USE_TIM1 || defined(__DOXYGEN__) -GPTDriver GPTD1; -#endif - -/** - * @brief GPTD2 driver identifier. - * @note The driver GPTD2 allocates the timer TIM2 when enabled. - */ -#if STM32_GPT_USE_TIM2 || defined(__DOXYGEN__) -GPTDriver GPTD2; -#endif - -/** - * @brief GPTD3 driver identifier. - * @note The driver GPTD3 allocates the timer TIM3 when enabled. - */ -#if STM32_GPT_USE_TIM3 || defined(__DOXYGEN__) -GPTDriver GPTD3; -#endif - -/** - * @brief GPTD4 driver identifier. - * @note The driver GPTD4 allocates the timer TIM4 when enabled. - */ -#if STM32_GPT_USE_TIM4 || defined(__DOXYGEN__) -GPTDriver GPTD4; -#endif - -/** - * @brief GPTD5 driver identifier. - * @note The driver GPTD5 allocates the timer TIM5 when enabled. - */ -#if STM32_GPT_USE_TIM5 || defined(__DOXYGEN__) -GPTDriver GPTD5; -#endif - -/** - * @brief GPTD6 driver identifier. - * @note The driver GPTD6 allocates the timer TIM6 when enabled. - */ -#if STM32_GPT_USE_TIM6 || defined(__DOXYGEN__) -GPTDriver GPTD6; -#endif - -/** - * @brief GPTD7 driver identifier. - * @note The driver GPTD7 allocates the timer TIM7 when enabled. - */ -#if STM32_GPT_USE_TIM7 || defined(__DOXYGEN__) -GPTDriver GPTD7; -#endif - -/** - * @brief GPTD8 driver identifier. - * @note The driver GPTD8 allocates the timer TIM8 when enabled. - */ -#if STM32_GPT_USE_TIM8 || defined(__DOXYGEN__) -GPTDriver GPTD8; -#endif - -/** - * @brief GPTD9 driver identifier. - * @note The driver GPTD9 allocates the timer TIM9 when enabled. - */ -#if STM32_GPT_USE_TIM9 || defined(__DOXYGEN__) -GPTDriver GPTD9; -#endif - -/** - * @brief GPTD11 driver identifier. - * @note The driver GPTD11 allocates the timer TIM11 when enabled. - */ -#if STM32_GPT_USE_TIM11 || defined(__DOXYGEN__) -GPTDriver GPTD11; -#endif - -/** - * @brief GPTD12 driver identifier. - * @note The driver GPTD12 allocates the timer TIM12 when enabled. - */ -#if STM32_GPT_USE_TIM12 || defined(__DOXYGEN__) -GPTDriver GPTD12; -#endif - -/** - * @brief GPTD14 driver identifier. - * @note The driver GPTD14 allocates the timer TIM14 when enabled. - */ -#if STM32_GPT_USE_TIM14 || defined(__DOXYGEN__) -GPTDriver GPTD14; -#endif - -/*===========================================================================*/ -/* Driver local variables and types. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver local functions. */ -/*===========================================================================*/ - -/** - * @brief Shared IRQ handler. - * - * @param[in] gptp pointer to a @p GPTDriver object - */ -static void gpt_lld_serve_interrupt(GPTDriver *gptp) { - - gptp->tim->SR = 0; - if (gptp->state == GPT_ONESHOT) { - gptp->state = GPT_READY; /* Back in GPT_READY state. */ - gpt_lld_stop_timer(gptp); /* Timer automatically stopped. */ - } - gptp->config->callback(gptp); -} - -/*===========================================================================*/ -/* Driver interrupt handlers. */ -/*===========================================================================*/ - -#if STM32_GPT_USE_TIM1 -#if !defined(STM32_TIM1_UP_HANDLER) -#error "STM32_TIM1_UP_HANDLER not defined" -#endif -/** - * @brief TIM2 interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(STM32_TIM1_UP_HANDLER) { - - OSAL_IRQ_PROLOGUE(); - - gpt_lld_serve_interrupt(&GPTD1); - - OSAL_IRQ_EPILOGUE(); -} -#endif /* STM32_GPT_USE_TIM1 */ - -#if STM32_GPT_USE_TIM2 -#if !defined(STM32_TIM2_HANDLER) -#error "STM32_TIM2_HANDLER not defined" -#endif -/** - * @brief TIM2 interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(STM32_TIM2_HANDLER) { - - OSAL_IRQ_PROLOGUE(); - - gpt_lld_serve_interrupt(&GPTD2); - - OSAL_IRQ_EPILOGUE(); -} -#endif /* STM32_GPT_USE_TIM2 */ - -#if STM32_GPT_USE_TIM3 -#if !defined(STM32_TIM3_HANDLER) -#error "STM32_TIM3_HANDLER not defined" -#endif -/** - * @brief TIM3 interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(STM32_TIM3_HANDLER) { - - OSAL_IRQ_PROLOGUE(); - - gpt_lld_serve_interrupt(&GPTD3); - - OSAL_IRQ_EPILOGUE(); -} -#endif /* STM32_GPT_USE_TIM3 */ - -#if STM32_GPT_USE_TIM4 -#if !defined(STM32_TIM4_HANDLER) -#error "STM32_TIM4_HANDLER not defined" -#endif -/** - * @brief TIM4 interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(STM32_TIM4_HANDLER) { - - OSAL_IRQ_PROLOGUE(); - - gpt_lld_serve_interrupt(&GPTD4); - - OSAL_IRQ_EPILOGUE(); -} -#endif /* STM32_GPT_USE_TIM4 */ - -#if STM32_GPT_USE_TIM5 -#if !defined(STM32_TIM5_HANDLER) -#error "STM32_TIM5_HANDLER not defined" -#endif -/** - * @brief TIM5 interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(STM32_TIM5_HANDLER) { - - OSAL_IRQ_PROLOGUE(); - - gpt_lld_serve_interrupt(&GPTD5); - - OSAL_IRQ_EPILOGUE(); -} -#endif /* STM32_GPT_USE_TIM5 */ - -#if STM32_GPT_USE_TIM6 -#if !defined(STM32_TIM6_HANDLER) -#error "STM32_TIM6_HANDLER not defined" -#endif -/** - * @brief TIM6 interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(STM32_TIM6_HANDLER) { - - OSAL_IRQ_PROLOGUE(); - - gpt_lld_serve_interrupt(&GPTD6); - - OSAL_IRQ_EPILOGUE(); -} -#endif /* STM32_GPT_USE_TIM6 */ - -#if STM32_GPT_USE_TIM7 -#if !defined(STM32_TIM7_HANDLER) -#error "STM32_TIM7_HANDLER not defined" -#endif -/** - * @brief TIM7 interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(STM32_TIM7_HANDLER) { - - OSAL_IRQ_PROLOGUE(); - - gpt_lld_serve_interrupt(&GPTD7); - - OSAL_IRQ_EPILOGUE(); -} -#endif /* STM32_GPT_USE_TIM7 */ - -#if STM32_GPT_USE_TIM8 -#if !defined(STM32_TIM8_UP_HANDLER) -#error "STM32_TIM8_UP_HANDLER not defined" -#endif -/** - * @brief TIM8 interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(STM32_TIM8_UP_HANDLER) { - - OSAL_IRQ_PROLOGUE(); - - gpt_lld_serve_interrupt(&GPTD8); - - OSAL_IRQ_EPILOGUE(); -} -#endif /* STM32_GPT_USE_TIM8 */ - -#if STM32_GPT_USE_TIM9 -#if !defined(STM32_TIM9_HANDLER) -#error "STM32_TIM9_HANDLER not defined" -#endif -/** - * @brief TIM9 interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(STM32_TIM9_HANDLER) { - - OSAL_IRQ_PROLOGUE(); - - gpt_lld_serve_interrupt(&GPTD9); - - OSAL_IRQ_EPILOGUE(); -} -#endif /* STM32_GPT_USE_TIM9 */ - -#if STM32_GPT_USE_TIM11 -#if !defined(STM32_TIM11_HANDLER) -#error "STM32_TIM11_HANDLER not defined" -#endif -/** - * @brief TIM11 interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(STM32_TIM11_HANDLER) { - - OSAL_IRQ_PROLOGUE(); - - gpt_lld_serve_interrupt(&GPTD11); - - OSAL_IRQ_EPILOGUE(); -} -#endif /* STM32_GPT_USE_TIM11 */ - -#if STM32_GPT_USE_TIM12 -#if !defined(STM32_TIM12_HANDLER) -#error "STM32_TIM12_HANDLER not defined" -#endif -/** - * @brief TIM12 interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(STM32_TIM12_HANDLER) { - - OSAL_IRQ_PROLOGUE(); - - gpt_lld_serve_interrupt(&GPTD12); - - OSAL_IRQ_EPILOGUE(); -} -#endif /* STM32_GPT_USE_TIM12 */ - -#if STM32_GPT_USE_TIM14 -#if !defined(STM32_TIM14_HANDLER) -#error "STM32_TIM14_HANDLER not defined" -#endif -/** - * @brief TIM14 interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(STM32_TIM14_HANDLER) { - - OSAL_IRQ_PROLOGUE(); - - gpt_lld_serve_interrupt(&GPTD14); - - OSAL_IRQ_EPILOGUE(); -} -#endif /* STM32_GPT_USE_TIM14 */ - -/*===========================================================================*/ -/* Driver exported functions. */ -/*===========================================================================*/ - -/** - * @brief Low level GPT driver initialization. - * - * @notapi - */ -void gpt_lld_init(void) { - -#if STM32_GPT_USE_TIM1 - /* Driver initialization.*/ - GPTD1.tim = STM32_TIM1; - gptObjectInit(&GPTD1); -#endif - -#if STM32_GPT_USE_TIM2 - /* Driver initialization.*/ - GPTD2.tim = STM32_TIM2; - gptObjectInit(&GPTD2); -#endif - -#if STM32_GPT_USE_TIM3 - /* Driver initialization.*/ - GPTD3.tim = STM32_TIM3; - gptObjectInit(&GPTD3); -#endif - -#if STM32_GPT_USE_TIM4 - /* Driver initialization.*/ - GPTD4.tim = STM32_TIM4; - gptObjectInit(&GPTD4); -#endif - -#if STM32_GPT_USE_TIM5 - /* Driver initialization.*/ - GPTD5.tim = STM32_TIM5; - gptObjectInit(&GPTD5); -#endif - -#if STM32_GPT_USE_TIM6 - /* Driver initialization.*/ - GPTD6.tim = STM32_TIM6; - gptObjectInit(&GPTD6); -#endif - -#if STM32_GPT_USE_TIM7 - /* Driver initialization.*/ - GPTD7.tim = STM32_TIM7; - gptObjectInit(&GPTD7); -#endif - -#if STM32_GPT_USE_TIM8 - /* Driver initialization.*/ - GPTD8.tim = STM32_TIM8; - gptObjectInit(&GPTD8); -#endif - -#if STM32_GPT_USE_TIM9 - /* Driver initialization.*/ - GPTD9.tim = STM32_TIM9; - gptObjectInit(&GPTD9); -#endif - -#if STM32_GPT_USE_TIM11 - /* Driver initialization.*/ - GPTD11.tim = STM32_TIM11; - gptObjectInit(&GPTD11); -#endif - -#if STM32_GPT_USE_TIM12 - /* Driver initialization.*/ - GPTD12.tim = STM32_TIM12; - gptObjectInit(&GPTD12); -#endif - -#if STM32_GPT_USE_TIM14 - /* Driver initialization.*/ - GPTD14.tim = STM32_TIM14; - gptObjectInit(&GPTD14); -#endif -} - -/** - * @brief Configures and activates the GPT peripheral. - * - * @param[in] gptp pointer to the @p GPTDriver object - * - * @notapi - */ -void gpt_lld_start(GPTDriver *gptp) { - uint16_t psc; - - if (gptp->state == GPT_STOP) { - /* Clock activation.*/ -#if STM32_GPT_USE_TIM1 - if (&GPTD1 == gptp) { - rccEnableTIM1(FALSE); - rccResetTIM1(); - nvicEnableVector(STM32_TIM1_UP_NUMBER, STM32_GPT_TIM1_IRQ_PRIORITY); - gptp->clock = STM32_TIMCLK2; - } -#endif -#if STM32_GPT_USE_TIM2 - if (&GPTD2 == gptp) { - rccEnableTIM2(FALSE); - rccResetTIM2(); - nvicEnableVector(STM32_TIM2_NUMBER, STM32_GPT_TIM2_IRQ_PRIORITY); - gptp->clock = STM32_TIMCLK1; - } -#endif -#if STM32_GPT_USE_TIM3 - if (&GPTD3 == gptp) { - rccEnableTIM3(FALSE); - rccResetTIM3(); - nvicEnableVector(STM32_TIM3_NUMBER, STM32_GPT_TIM3_IRQ_PRIORITY); - gptp->clock = STM32_TIMCLK1; - } -#endif -#if STM32_GPT_USE_TIM4 - if (&GPTD4 == gptp) { - rccEnableTIM4(FALSE); - rccResetTIM4(); - nvicEnableVector(STM32_TIM4_NUMBER, STM32_GPT_TIM4_IRQ_PRIORITY); - gptp->clock = STM32_TIMCLK1; - } -#endif - -#if STM32_GPT_USE_TIM5 - if (&GPTD5 == gptp) { - rccEnableTIM5(FALSE); - rccResetTIM5(); - nvicEnableVector(STM32_TIM5_NUMBER, STM32_GPT_TIM5_IRQ_PRIORITY); - gptp->clock = STM32_TIMCLK1; - } -#endif - -#if STM32_GPT_USE_TIM6 - if (&GPTD6 == gptp) { - rccEnableTIM6(FALSE); - rccResetTIM6(); - nvicEnableVector(STM32_TIM6_NUMBER, STM32_GPT_TIM6_IRQ_PRIORITY); - gptp->clock = STM32_TIMCLK1; - } -#endif - -#if STM32_GPT_USE_TIM7 - if (&GPTD7 == gptp) { - rccEnableTIM7(FALSE); - rccResetTIM7(); - nvicEnableVector(STM32_TIM7_NUMBER, STM32_GPT_TIM7_IRQ_PRIORITY); - gptp->clock = STM32_TIMCLK1; - } -#endif - -#if STM32_GPT_USE_TIM8 - if (&GPTD8 == gptp) { - rccEnableTIM8(FALSE); - rccResetTIM8(); - nvicEnableVector(STM32_TIM8_UP_NUMBER, STM32_GPT_TIM8_IRQ_PRIORITY); - gptp->clock = STM32_TIMCLK2; - } -#endif - -#if STM32_GPT_USE_TIM9 - if (&GPTD9 == gptp) { - rccEnableTIM9(FALSE); - rccResetTIM9(); - nvicEnableVector(STM32_TIM9_NUMBER, STM32_GPT_TIM9_IRQ_PRIORITY); - gptp->clock = STM32_TIMCLK2; - } -#endif - -#if STM32_GPT_USE_TIM11 - if (&GPTD11 == gptp) { - rccEnableTIM11(FALSE); - rccResetTIM11(); - nvicEnableVector(STM32_TIM11_NUMBER, STM32_GPT_TIM11_IRQ_PRIORITY); - gptp->clock = STM32_TIMCLK2; - } -#endif - -#if STM32_GPT_USE_TIM12 - if (&GPTD12 == gptp) { - rccEnableTIM12(FALSE); - rccResetTIM12(); - nvicEnableVector(STM32_TIM12_NUMBER, STM32_GPT_TIM12_IRQ_PRIORITY); - gptp->clock = STM32_TIMCLK1; - } -#endif - -#if STM32_GPT_USE_TIM14 - if (&GPTD14 == gptp) { - rccEnableTIM14(FALSE); - rccResetTIM14(); - nvicEnableVector(STM32_TIM14_NUMBER, STM32_GPT_TIM14_IRQ_PRIORITY); - gptp->clock = STM32_TIMCLK1; - } -#endif - } - - /* Prescaler value calculation.*/ - psc = (uint16_t)((gptp->clock / gptp->config->frequency) - 1); - osalDbgAssert(((uint32_t)(psc + 1) * gptp->config->frequency) == gptp->clock, - "invalid frequency"); - - /* Timer configuration.*/ - gptp->tim->CR1 = 0; /* Initially stopped. */ - gptp->tim->CR2 = STM32_TIM_CR2_CCDS; /* DMA on UE (if any). */ - gptp->tim->PSC = psc; /* Prescaler value. */ - gptp->tim->DIER = gptp->config->dier & /* DMA-related DIER bits. */ - STM32_TIM_DIER_IRQ_MASK; - gptp->tim->SR = 0; /* Clear pending IRQs. */ -} - -/** - * @brief Deactivates the GPT peripheral. - * - * @param[in] gptp pointer to the @p GPTDriver object - * - * @notapi - */ -void gpt_lld_stop(GPTDriver *gptp) { - - if (gptp->state == GPT_READY) { - gptp->tim->CR1 = 0; /* Timer disabled. */ - gptp->tim->DIER = 0; /* All IRQs disabled. */ - gptp->tim->SR = 0; /* Clear pending IRQs. */ - -#if STM32_GPT_USE_TIM1 - if (&GPTD1 == gptp) { - nvicDisableVector(STM32_TIM1_UP_NUMBER); - rccDisableTIM1(FALSE); - } -#endif -#if STM32_GPT_USE_TIM2 - if (&GPTD2 == gptp) { - nvicDisableVector(STM32_TIM2_NUMBER); - rccDisableTIM2(FALSE); - } -#endif -#if STM32_GPT_USE_TIM3 - if (&GPTD3 == gptp) { - nvicDisableVector(STM32_TIM3_NUMBER); - rccDisableTIM3(FALSE); - } -#endif -#if STM32_GPT_USE_TIM4 - if (&GPTD4 == gptp) { - nvicDisableVector(STM32_TIM4_NUMBER); - rccDisableTIM4(FALSE); - } -#endif -#if STM32_GPT_USE_TIM5 - if (&GPTD5 == gptp) { - nvicDisableVector(STM32_TIM5_NUMBER); - rccDisableTIM5(FALSE); - } -#endif -#if STM32_GPT_USE_TIM6 - if (&GPTD6 == gptp) { - nvicDisableVector(STM32_TIM6_NUMBER); - rccDisableTIM6(FALSE); - } -#endif -#if STM32_GPT_USE_TIM7 - if (&GPTD7 == gptp) { - nvicDisableVector(STM32_TIM7_NUMBER); - rccDisableTIM7(FALSE); - } -#endif -#if STM32_GPT_USE_TIM8 - if (&GPTD8 == gptp) { - nvicDisableVector(STM32_TIM8_UP_NUMBER); - rccDisableTIM8(FALSE); - } -#endif -#if STM32_GPT_USE_TIM9 - if (&GPTD9 == gptp) { - nvicDisableVector(STM32_TIM9_NUMBER); - rccDisableTIM9(FALSE); - } -#endif -#if STM32_GPT_USE_TIM11 - if (&GPTD11 == gptp) { - nvicDisableVector(STM32_TIM11_NUMBER); - rccDisableTIM11(FALSE); - } -#endif -#if STM32_GPT_USE_TIM12 - if (&GPTD12 == gptp) { - nvicDisableVector(STM32_TIM12_NUMBER); - rccDisableTIM12(FALSE); - } -#endif -#if STM32_GPT_USE_TIM14 - if (&GPTD14 == gptp) { - nvicDisableVector(STM32_TIM14_NUMBER); - rccDisableTIM14(FALSE); - } -#endif - } -} - -/** - * @brief Starts the timer in continuous mode. - * - * @param[in] gptp pointer to the @p GPTDriver object - * @param[in] interval period in ticks - * - * @notapi - */ -void gpt_lld_start_timer(GPTDriver *gptp, gptcnt_t interval) { - - gptp->tim->ARR = (uint32_t)(interval - 1); /* Time constant. */ - gptp->tim->EGR = STM32_TIM_EGR_UG; /* Update event. */ - gptp->tim->CNT = 0; /* Reset counter. */ - - /* NOTE: After generating the UG event it takes several clock cycles before - SR bit 0 goes to 1. This is because the clearing of CNT has been inserted - before the clearing of SR, to give it some time.*/ - gptp->tim->SR = 0; /* Clear pending IRQs. */ - gptp->tim->DIER |= STM32_TIM_DIER_UIE; /* Update Event IRQ enabled.*/ - gptp->tim->CR1 = STM32_TIM_CR1_URS | STM32_TIM_CR1_CEN; -} - -/** - * @brief Stops the timer. - * - * @param[in] gptp pointer to the @p GPTDriver object - * - * @notapi - */ -void gpt_lld_stop_timer(GPTDriver *gptp) { - - gptp->tim->CR1 = 0; /* Initially stopped. */ - gptp->tim->SR = 0; /* Clear pending IRQs. */ - - /* All interrupts disabled.*/ - gptp->tim->DIER &= ~STM32_TIM_DIER_IRQ_MASK; -} - -/** - * @brief Starts the timer in one shot mode and waits for completion. - * @details This function specifically polls the timer waiting for completion - * in order to not have extra delays caused by interrupt servicing, - * this function is only recommended for short delays. - * - * @param[in] gptp pointer to the @p GPTDriver object - * @param[in] interval time interval in ticks - * - * @notapi - */ -void gpt_lld_polled_delay(GPTDriver *gptp, gptcnt_t interval) { - - gptp->tim->ARR = (uint32_t)(interval - 1); /* Time constant. */ - gptp->tim->EGR = STM32_TIM_EGR_UG; /* Update event. */ - gptp->tim->SR = 0; /* Clear pending IRQs. */ - gptp->tim->CR1 = STM32_TIM_CR1_OPM | STM32_TIM_CR1_URS | STM32_TIM_CR1_CEN; - while (!(gptp->tim->SR & STM32_TIM_SR_UIF)) - ; -} - -#endif /* HAL_USE_GPT */ - -/** @} */ diff --git a/os/hal/platforms/STM32/TIMv1/gpt_lld.h b/os/hal/platforms/STM32/TIMv1/gpt_lld.h deleted file mode 100644 index 56dc04f6b..000000000 --- a/os/hal/platforms/STM32/TIMv1/gpt_lld.h +++ /dev/null @@ -1,512 +0,0 @@ -/* - ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file STM32/gpt_lld.h - * @brief STM32 GPT subsystem low level driver header. - * - * @addtogroup GPT - * @{ - */ - -#ifndef _GPT_LLD_H_ -#define _GPT_LLD_H_ - -#include "stm32_tim.h" - -#if HAL_USE_GPT || defined(__DOXYGEN__) - -/*===========================================================================*/ -/* Driver constants. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver pre-compile time settings. */ -/*===========================================================================*/ - -/** - * @name Configuration options - * @{ - */ -/** - * @brief GPTD1 driver enable switch. - * @details If set to @p TRUE the support for GPTD1 is included. - * @note The default is @p TRUE. - */ -#if !defined(STM32_GPT_USE_TIM1) || defined(__DOXYGEN__) -#define STM32_GPT_USE_TIM1 FALSE -#endif - -/** - * @brief GPTD2 driver enable switch. - * @details If set to @p TRUE the support for GPTD2 is included. - * @note The default is @p TRUE. - */ -#if !defined(STM32_GPT_USE_TIM2) || defined(__DOXYGEN__) -#define STM32_GPT_USE_TIM2 FALSE -#endif - -/** - * @brief GPTD3 driver enable switch. - * @details If set to @p TRUE the support for GPTD3 is included. - * @note The default is @p TRUE. - */ -#if !defined(STM32_GPT_USE_TIM3) || defined(__DOXYGEN__) -#define STM32_GPT_USE_TIM3 FALSE -#endif - -/** - * @brief GPTD4 driver enable switch. - * @details If set to @p TRUE the support for GPTD4 is included. - * @note The default is @p TRUE. - */ -#if !defined(STM32_GPT_USE_TIM4) || defined(__DOXYGEN__) -#define STM32_GPT_USE_TIM4 FALSE -#endif - -/** - * @brief GPTD5 driver enable switch. - * @details If set to @p TRUE the support for GPTD5 is included. - * @note The default is @p TRUE. - */ -#if !defined(STM32_GPT_USE_TIM5) || defined(__DOXYGEN__) -#define STM32_GPT_USE_TIM5 FALSE -#endif - -/** - * @brief GPTD6 driver enable switch. - * @details If set to @p TRUE the support for GPTD6 is included. - * @note The default is @p TRUE. - */ -#if !defined(STM32_GPT_USE_TIM6) || defined(__DOXYGEN__) -#define STM32_GPT_USE_TIM6 FALSE -#endif - -/** - * @brief GPTD7 driver enable switch. - * @details If set to @p TRUE the support for GPTD7 is included. - * @note The default is @p TRUE. - */ -#if !defined(STM32_GPT_USE_TIM7) || defined(__DOXYGEN__) -#define STM32_GPT_USE_TIM7 FALSE -#endif - -/** - * @brief GPTD8 driver enable switch. - * @details If set to @p TRUE the support for GPTD8 is included. - * @note The default is @p TRUE. - */ -#if !defined(STM32_GPT_USE_TIM8) || defined(__DOXYGEN__) -#define STM32_GPT_USE_TIM8 FALSE -#endif - -/** - * @brief GPTD9 driver enable switch. - * @details If set to @p TRUE the support for GPTD9 is included. - * @note The default is @p TRUE. - */ -#if !defined(STM32_GPT_USE_TIM9) || defined(__DOXYGEN__) -#define STM32_GPT_USE_TIM9 FALSE -#endif - -/** - * @brief GPTD11 driver enable switch. - * @details If set to @p TRUE the support for GPTD11 is included. - * @note The default is @p TRUE. - */ -#if !defined(STM32_GPT_USE_TIM11) || defined(__DOXYGEN__) -#define STM32_GPT_USE_TIM11 FALSE -#endif - -/** - * @brief GPTD12 driver enable switch. - * @details If set to @p TRUE the support for GPTD12 is included. - * @note The default is @p TRUE. - */ -#if !defined(STM32_GPT_USE_TIM12) || defined(__DOXYGEN__) -#define STM32_GPT_USE_TIM12 FALSE -#endif - -/** - * @brief GPTD14 driver enable switch. - * @details If set to @p TRUE the support for GPTD14 is included. - * @note The default is @p TRUE. - */ -#if !defined(STM32_GPT_USE_TIM14) || defined(__DOXYGEN__) -#define STM32_GPT_USE_TIM14 FALSE -#endif - -/** - * @brief GPTD1 interrupt priority level setting. - */ -#if !defined(STM32_GPT_TIM1_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_GPT_TIM1_IRQ_PRIORITY 7 -#endif - -/** - * @brief GPTD2 interrupt priority level setting. - */ -#if !defined(STM32_GPT_TIM2_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_GPT_TIM2_IRQ_PRIORITY 7 -#endif - -/** - * @brief GPTD3 interrupt priority level setting. - */ -#if !defined(STM32_GPT_TIM3_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_GPT_TIM3_IRQ_PRIORITY 7 -#endif - -/** - * @brief GPTD4 interrupt priority level setting. - */ -#if !defined(STM32_GPT_TIM4_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_GPT_TIM4_IRQ_PRIORITY 7 -#endif - -/** - * @brief GPTD5 interrupt priority level setting. - */ -#if !defined(STM32_GPT_TIM5_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_GPT_TIM5_IRQ_PRIORITY 7 -#endif - -/** - * @brief GPTD6 interrupt priority level setting. - */ -#if !defined(STM32_GPT_TIM6_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_GPT_TIM6_IRQ_PRIORITY 7 -#endif - -/** - * @brief GPTD7 interrupt priority level setting. - */ -#if !defined(STM32_GPT_TIM7_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_GPT_TIM7_IRQ_PRIORITY 7 -#endif - -/** - * @brief GPTD8 interrupt priority level setting. - */ -#if !defined(STM32_GPT_TIM8_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_GPT_TIM8_IRQ_PRIORITY 7 -#endif - -/** - * @brief GPTD9 interrupt priority level setting. - */ -#if !defined(STM32_GPT_TIM9_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_GPT_TIM9_IRQ_PRIORITY 7 -#endif - -/** - * @brief GPTD11 interrupt priority level setting. - */ -#if !defined(STM32_GPT_TIM11_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_GPT_TIM11_IRQ_PRIORITY 7 -#endif - -/** - * @brief GPTD12 interrupt priority level setting. - */ -#if !defined(STM32_GPT_TIM12_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_GPT_TIM12_IRQ_PRIORITY 7 -#endif - -/** - * @brief GPTD14 interrupt priority level setting. - */ -#if !defined(STM32_GPT_TIM14_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_GPT_TIM14_IRQ_PRIORITY 7 -#endif -/** @} */ - -/*===========================================================================*/ -/* Derived constants and error checks. */ -/*===========================================================================*/ - -#if STM32_GPT_USE_TIM1 && !STM32_HAS_TIM1 -#error "TIM1 not present in the selected device" -#endif - -#if STM32_GPT_USE_TIM2 && !STM32_HAS_TIM2 -#error "TIM2 not present in the selected device" -#endif - -#if STM32_GPT_USE_TIM3 && !STM32_HAS_TIM3 -#error "TIM3 not present in the selected device" -#endif - -#if STM32_GPT_USE_TIM4 && !STM32_HAS_TIM4 -#error "TIM4 not present in the selected device" -#endif - -#if STM32_GPT_USE_TIM5 && !STM32_HAS_TIM5 -#error "TIM5 not present in the selected device" -#endif - -#if STM32_GPT_USE_TIM6 && !STM32_HAS_TIM6 -#error "TIM6 not present in the selected device" -#endif - -#if STM32_GPT_USE_TIM7 && !STM32_HAS_TIM7 -#error "TIM7 not present in the selected device" -#endif - -#if STM32_GPT_USE_TIM8 && !STM32_HAS_TIM8 -#error "TIM8 not present in the selected device" -#endif - -#if STM32_GPT_USE_TIM9 && !STM32_HAS_TIM9 -#error "TIM9 not present in the selected device" -#endif - -#if STM32_GPT_USE_TIM11 && !STM32_HAS_TIM11 -#error "TIM11 not present in the selected device" -#endif - -#if STM32_GPT_USE_TIM12 && !STM32_HAS_TIM12 -#error "TIM12 not present in the selected device" -#endif - -#if STM32_GPT_USE_TIM14 && !STM32_HAS_TIM14 -#error "TIM14 not present in the selected device" -#endif - -#if !STM32_GPT_USE_TIM1 && !STM32_GPT_USE_TIM2 && \ - !STM32_GPT_USE_TIM3 && !STM32_GPT_USE_TIM4 && \ - !STM32_GPT_USE_TIM5 && !STM32_GPT_USE_TIM6 && \ - !STM32_GPT_USE_TIM7 && !STM32_GPT_USE_TIM8 && \ - !STM32_GPT_USE_TIM9 && !STM32_GPT_USE_TIM11 && \ - !STM32_GPT_USE_TIM12 && !STM32_GPT_USE_TIM14 -#error "GPT driver activated but no TIM peripheral assigned" -#endif - -#if STM32_GPT_USE_TIM1 && \ - !CORTEX_IS_VALID_KERNEL_PRIORITY(STM32_GPT_TIM1_IRQ_PRIORITY) -#error "Invalid IRQ priority assigned to TIM1" -#endif - -#if STM32_GPT_USE_TIM2 && \ - !CORTEX_IS_VALID_KERNEL_PRIORITY(STM32_GPT_TIM2_IRQ_PRIORITY) -#error "Invalid IRQ priority assigned to TIM2" -#endif - -#if STM32_GPT_USE_TIM3 && \ - !CORTEX_IS_VALID_KERNEL_PRIORITY(STM32_GPT_TIM3_IRQ_PRIORITY) -#error "Invalid IRQ priority assigned to TIM3" -#endif - -#if STM32_GPT_USE_TIM4 && \ - !CORTEX_IS_VALID_KERNEL_PRIORITY(STM32_GPT_TIM4_IRQ_PRIORITY) -#error "Invalid IRQ priority assigned to TIM4" -#endif - -#if STM32_GPT_USE_TIM5 && \ - !CORTEX_IS_VALID_KERNEL_PRIORITY(STM32_GPT_TIM5_IRQ_PRIORITY) -#error "Invalid IRQ priority assigned to TIM5" -#endif - -#if STM32_GPT_USE_TIM6 && \ - !CORTEX_IS_VALID_KERNEL_PRIORITY(STM32_GPT_TIM6_IRQ_PRIORITY) -#error "Invalid IRQ priority assigned to TIM6" -#endif - -#if STM32_GPT_USE_TIM7 && \ - !CORTEX_IS_VALID_KERNEL_PRIORITY(STM32_GPT_TIM7_IRQ_PRIORITY) -#error "Invalid IRQ priority assigned to TIM7" -#endif - -#if STM32_GPT_USE_TIM8 && \ - !CORTEX_IS_VALID_KERNEL_PRIORITY(STM32_GPT_TIM8_IRQ_PRIORITY) -#error "Invalid IRQ priority assigned to TIM8" -#endif - -#if STM32_GPT_USE_TIM9 && \ - !CORTEX_IS_VALID_KERNEL_PRIORITY(STM32_GPT_TIM9_IRQ_PRIORITY) -#error "Invalid IRQ priority assigned to TIM9" -#endif - -#if STM32_GPT_USE_TIM11 && \ - !CORTEX_IS_VALID_KERNEL_PRIORITY(STM32_GPT_TIM11_IRQ_PRIORITY) -#error "Invalid IRQ priority assigned to TIM11" -#endif - -#if STM32_GPT_USE_TIM12 && \ - !CORTEX_IS_VALID_KERNEL_PRIORITY(STM32_GPT_TIM12_IRQ_PRIORITY) -#error "Invalid IRQ priority assigned to TIM12" -#endif - -#if STM32_GPT_USE_TIM14 && \ - !CORTEX_IS_VALID_KERNEL_PRIORITY(STM32_GPT_TIM14_IRQ_PRIORITY) -#error "Invalid IRQ priority assigned to TIM14" -#endif - -/*===========================================================================*/ -/* Driver data structures and types. */ -/*===========================================================================*/ - -/** - * @brief GPT frequency type. - */ -typedef uint32_t gptfreq_t; - -/** - * @brief GPT counter type. - */ -typedef uint32_t gptcnt_t; - -/** - * @brief Driver configuration structure. - * @note It could be empty on some architectures. - */ -typedef struct { - /** - * @brief Timer clock in Hz. - * @note The low level can use assertions in order to catch invalid - * frequency specifications. - */ - gptfreq_t frequency; - /** - * @brief Timer callback pointer. - * @note This callback is invoked on GPT counter events. - */ - gptcallback_t callback; - /* End of the mandatory fields.*/ - /** - * @brief TIM DIER register initialization data. - * @note The value of this field should normally be equal to zero. - * @note Only the DMA-related bits can be specified in this field. - */ - uint32_t dier; -} GPTConfig; - -/** - * @brief Structure representing a GPT driver. - */ -struct GPTDriver { - /** - * @brief Driver state. - */ - gptstate_t state; - /** - * @brief Current configuration data. - */ - const GPTConfig *config; -#if defined(GPT_DRIVER_EXT_FIELDS) - GPT_DRIVER_EXT_FIELDS -#endif - /* End of the mandatory fields.*/ - /** - * @brief Timer base clock. - */ - uint32_t clock; - /** - * @brief Pointer to the TIMx registers block. - */ - stm32_tim_t *tim; -}; - -/*===========================================================================*/ -/* Driver macros. */ -/*===========================================================================*/ - -/** - * @brief Changes the interval of GPT peripheral. - * @details This function changes the interval of a running GPT unit. - * @pre The GPT unit must have been activated using @p gptStart(). - * @pre The GPT unit must have been running in continuous mode using - * @p gptStartContinuous(). - * @post The GPT unit interval is changed to the new value. - * @note The function has effect at the next cycle start. - * - * @param[in] gptp pointer to a @p GPTDriver object - * @param[in] interval new cycle time in timer ticks - * @notapi - */ -#define gpt_lld_change_interval(gptp, interval) \ - ((gptp)->tim->ARR = (uint32_t)((interval) - 1)) - -/*===========================================================================*/ -/* External declarations. */ -/*===========================================================================*/ - -#if STM32_GPT_USE_TIM1 && !defined(__DOXYGEN__) -extern GPTDriver GPTD1; -#endif - -#if STM32_GPT_USE_TIM2 && !defined(__DOXYGEN__) -extern GPTDriver GPTD2; -#endif - -#if STM32_GPT_USE_TIM3 && !defined(__DOXYGEN__) -extern GPTDriver GPTD3; -#endif - -#if STM32_GPT_USE_TIM4 && !defined(__DOXYGEN__) -extern GPTDriver GPTD4; -#endif - -#if STM32_GPT_USE_TIM5 && !defined(__DOXYGEN__) -extern GPTDriver GPTD5; -#endif - -#if STM32_GPT_USE_TIM6 && !defined(__DOXYGEN__) -extern GPTDriver GPTD6; -#endif - -#if STM32_GPT_USE_TIM7 && !defined(__DOXYGEN__) -extern GPTDriver GPTD7; -#endif - -#if STM32_GPT_USE_TIM8 && !defined(__DOXYGEN__) -extern GPTDriver GPTD8; -#endif - -#if STM32_GPT_USE_TIM9 && !defined(__DOXYGEN__) -extern GPTDriver GPTD9; -#endif - -#if STM32_GPT_USE_TIM11 && !defined(__DOXYGEN__) -extern GPTDriver GPTD11; -#endif - -#if STM32_GPT_USE_TIM12 && !defined(__DOXYGEN__) -extern GPTDriver GPTD12; -#endif - -#if STM32_GPT_USE_TIM14 && !defined(__DOXYGEN__) -extern GPTDriver GPTD14; -#endif - -#ifdef __cplusplus -extern "C" { -#endif - void gpt_lld_init(void); - void gpt_lld_start(GPTDriver *gptp); - void gpt_lld_stop(GPTDriver *gptp); - void gpt_lld_start_timer(GPTDriver *gptp, gptcnt_t period); - void gpt_lld_stop_timer(GPTDriver *gptp); - void gpt_lld_polled_delay(GPTDriver *gptp, gptcnt_t interval); -#ifdef __cplusplus -} -#endif - -#endif /* HAL_USE_GPT */ - -#endif /* _GPT_LLD_H_ */ - -/** @} */ diff --git a/os/hal/platforms/STM32/TIMv1/icu_lld.c b/os/hal/platforms/STM32/TIMv1/icu_lld.c deleted file mode 100644 index 09be838a6..000000000 --- a/os/hal/platforms/STM32/TIMv1/icu_lld.c +++ /dev/null @@ -1,634 +0,0 @@ -/* - ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ -/* - Concepts and parts of this file have been contributed by Fabio Utzig and - Xo Wang. - */ - -/** - * @file STM32/icu_lld.c - * @brief STM32 ICU subsystem low level driver header. - * - * @addtogroup ICU - * @{ - */ - -#include "hal.h" - -#if HAL_USE_ICU || defined(__DOXYGEN__) - -/*===========================================================================*/ -/* Driver local definitions. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver exported variables. */ -/*===========================================================================*/ - -/** - * @brief ICUD1 driver identifier. - * @note The driver ICUD1 allocates the complex timer TIM1 when enabled. - */ -#if STM32_ICU_USE_TIM1 || defined(__DOXYGEN__) -ICUDriver ICUD1; -#endif - -/** - * @brief ICUD2 driver identifier. - * @note The driver ICUD1 allocates the timer TIM2 when enabled. - */ -#if STM32_ICU_USE_TIM2 || defined(__DOXYGEN__) -ICUDriver ICUD2; -#endif - -/** - * @brief ICUD3 driver identifier. - * @note The driver ICUD1 allocates the timer TIM3 when enabled. - */ -#if STM32_ICU_USE_TIM3 || defined(__DOXYGEN__) -ICUDriver ICUD3; -#endif - -/** - * @brief ICUD4 driver identifier. - * @note The driver ICUD4 allocates the timer TIM4 when enabled. - */ -#if STM32_ICU_USE_TIM4 || defined(__DOXYGEN__) -ICUDriver ICUD4; -#endif - -/** - * @brief ICUD5 driver identifier. - * @note The driver ICUD5 allocates the timer TIM5 when enabled. - */ -#if STM32_ICU_USE_TIM5 || defined(__DOXYGEN__) -ICUDriver ICUD5; -#endif - -/** - * @brief ICUD8 driver identifier. - * @note The driver ICUD8 allocates the timer TIM8 when enabled. - */ -#if STM32_ICU_USE_TIM8 || defined(__DOXYGEN__) -ICUDriver ICUD8; -#endif - -/** - * @brief ICUD9 driver identifier. - * @note The driver ICUD9 allocates the timer TIM9 when enabled. - */ -#if STM32_ICU_USE_TIM9 || defined(__DOXYGEN__) -ICUDriver ICUD9; -#endif - -/*===========================================================================*/ -/* Driver local variables and types. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver local functions. */ -/*===========================================================================*/ - -/** - * @brief Shared IRQ handler. - * - * @param[in] icup pointer to the @p ICUDriver object - */ -static void icu_lld_serve_interrupt(ICUDriver *icup) { - uint16_t sr; - - sr = icup->tim->SR; - sr &= icup->tim->DIER & STM32_TIM_DIER_IRQ_MASK; - icup->tim->SR = ~sr; - if (icup->config->channel == ICU_CHANNEL_1) { - if ((sr & STM32_TIM_SR_CC1IF) != 0) - _icu_isr_invoke_period_cb(icup); - if ((sr & STM32_TIM_SR_CC2IF) != 0) - _icu_isr_invoke_width_cb(icup); - } else { - if ((sr & STM32_TIM_SR_CC1IF) != 0) - _icu_isr_invoke_width_cb(icup); - if ((sr & STM32_TIM_SR_CC2IF) != 0) - _icu_isr_invoke_period_cb(icup); - } - if ((sr & STM32_TIM_SR_UIF) != 0) - _icu_isr_invoke_overflow_cb(icup); -} - -/*===========================================================================*/ -/* Driver interrupt handlers. */ -/*===========================================================================*/ - -#if STM32_ICU_USE_TIM1 -#if !defined(STM32_TIM1_UP_HANDLER) -#error "STM32_TIM1_UP_HANDLER not defined" -#endif -/** - * @brief TIM1 compare interrupt handler. - * @note It is assumed that the various sources are only activated if the - * associated callback pointer is not equal to @p NULL in order to not - * perform an extra check in a potentially critical interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(STM32_TIM1_UP_HANDLER) { - - OSAL_IRQ_PROLOGUE(); - - icu_lld_serve_interrupt(&ICUD1); - - OSAL_IRQ_EPILOGUE(); -} - -#if !defined(STM32_TIM1_CC_HANDLER) -#error "STM32_TIM1_CC_HANDLER not defined" -#endif -/** - * @brief TIM1 compare interrupt handler. - * @note It is assumed that the various sources are only activated if the - * associated callback pointer is not equal to @p NULL in order to not - * perform an extra check in a potentially critical interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(STM32_TIM1_CC_HANDLER) { - - OSAL_IRQ_PROLOGUE(); - - icu_lld_serve_interrupt(&ICUD1); - - OSAL_IRQ_EPILOGUE(); -} -#endif /* STM32_ICU_USE_TIM1 */ - -#if STM32_ICU_USE_TIM2 -#if !defined(STM32_TIM2_HANDLER) -#error "STM32_TIM2_HANDLER not defined" -#endif -/** - * @brief TIM2 interrupt handler. - * @note It is assumed that the various sources are only activated if the - * associated callback pointer is not equal to @p NULL in order to not - * perform an extra check in a potentially critical interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(STM32_TIM2_HANDLER) { - - OSAL_IRQ_PROLOGUE(); - - icu_lld_serve_interrupt(&ICUD2); - - OSAL_IRQ_EPILOGUE(); -} -#endif /* STM32_ICU_USE_TIM2 */ - -#if STM32_ICU_USE_TIM3 -#if !defined(STM32_TIM3_HANDLER) -#error "STM32_TIM3_HANDLER not defined" -#endif -/** - * @brief TIM3 interrupt handler. - * @note It is assumed that the various sources are only activated if the - * associated callback pointer is not equal to @p NULL in order to not - * perform an extra check in a potentially critical interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(STM32_TIM3_HANDLER) { - - OSAL_IRQ_PROLOGUE(); - - icu_lld_serve_interrupt(&ICUD3); - - OSAL_IRQ_EPILOGUE(); -} -#endif /* STM32_ICU_USE_TIM3 */ - -#if STM32_ICU_USE_TIM4 -#if !defined(STM32_TIM4_HANDLER) -#error "STM32_TIM4_HANDLER not defined" -#endif -/** - * @brief TIM4 interrupt handler. - * @note It is assumed that the various sources are only activated if the - * associated callback pointer is not equal to @p NULL in order to not - * perform an extra check in a potentially critical interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(STM32_TIM4_HANDLER) { - - OSAL_IRQ_PROLOGUE(); - - icu_lld_serve_interrupt(&ICUD4); - - OSAL_IRQ_EPILOGUE(); -} -#endif /* STM32_ICU_USE_TIM4 */ - -#if STM32_ICU_USE_TIM5 -#if !defined(STM32_TIM5_HANDLER) -#error "STM32_TIM5_HANDLER not defined" -#endif -/** - * @brief TIM5 interrupt handler. - * @note It is assumed that the various sources are only activated if the - * associated callback pointer is not equal to @p NULL in order to not - * perform an extra check in a potentially critical interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(STM32_TIM5_HANDLER) { - - OSAL_IRQ_PROLOGUE(); - - icu_lld_serve_interrupt(&ICUD5); - - OSAL_IRQ_EPILOGUE(); -} -#endif /* STM32_ICU_USE_TIM5 */ - -#if STM32_ICU_USE_TIM8 -#if !defined(STM32_TIM8_UP_HANDLER) -#error "STM32_TIM8_UP_HANDLER not defined" -#endif -/** - * @brief TIM8 compare interrupt handler. - * @note It is assumed that the various sources are only activated if the - * associated callback pointer is not equal to @p NULL in order to not - * perform an extra check in a potentially critical interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(STM32_TIM8_UP_HANDLER) { - - OSAL_IRQ_PROLOGUE(); - - icu_lld_serve_interrupt(&ICUD8); - - OSAL_IRQ_EPILOGUE(); -} - -#if !defined(STM32_TIM8_CC_HANDLER) -#error "STM32_TIM8_CC_HANDLER not defined" -#endif -/** - * @brief TIM8 compare interrupt handler. - * @note It is assumed that the various sources are only activated if the - * associated callback pointer is not equal to @p NULL in order to not - * perform an extra check in a potentially critical interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(STM32_TIM8_CC_HANDLER) { - - OSAL_IRQ_PROLOGUE(); - - icu_lld_serve_interrupt(&ICUD8); - - OSAL_IRQ_EPILOGUE(); -} -#endif /* STM32_ICU_USE_TIM8 */ - -#if STM32_ICU_USE_TIM9 -#if !defined(STM32_TIM9_HANDLER) -#error "STM32_TIM9_HANDLER not defined" -#endif -/** - * @brief TIM9 interrupt handler. - * @note It is assumed that the various sources are only activated if the - * associated callback pointer is not equal to @p NULL in order to not - * perform an extra check in a potentially critical interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(STM32_TIM9_HANDLER) { - - OSAL_IRQ_PROLOGUE(); - - icu_lld_serve_interrupt(&ICUD9); - - OSAL_IRQ_EPILOGUE(); -} -#endif /* STM32_ICU_USE_TIM9 */ - -/*===========================================================================*/ -/* Driver exported functions. */ -/*===========================================================================*/ - -/** - * @brief Low level ICU driver initialization. - * - * @notapi - */ -void icu_lld_init(void) { - -#if STM32_ICU_USE_TIM1 - /* Driver initialization.*/ - icuObjectInit(&ICUD1); - ICUD1.tim = STM32_TIM1; -#endif - -#if STM32_ICU_USE_TIM2 - /* Driver initialization.*/ - icuObjectInit(&ICUD2); - ICUD2.tim = STM32_TIM2; -#endif - -#if STM32_ICU_USE_TIM3 - /* Driver initialization.*/ - icuObjectInit(&ICUD3); - ICUD3.tim = STM32_TIM3; -#endif - -#if STM32_ICU_USE_TIM4 - /* Driver initialization.*/ - icuObjectInit(&ICUD4); - ICUD4.tim = STM32_TIM4; -#endif - -#if STM32_ICU_USE_TIM5 - /* Driver initialization.*/ - icuObjectInit(&ICUD5); - ICUD5.tim = STM32_TIM5; -#endif - -#if STM32_ICU_USE_TIM8 - /* Driver initialization.*/ - icuObjectInit(&ICUD8); - ICUD8.tim = STM32_TIM8; -#endif - -#if STM32_ICU_USE_TIM9 - /* Driver initialization.*/ - icuObjectInit(&ICUD9); - ICUD9.tim = STM32_TIM9; -#endif -} - -/** - * @brief Configures and activates the ICU peripheral. - * - * @param[in] icup pointer to the @p ICUDriver object - * - * @notapi - */ -void icu_lld_start(ICUDriver *icup) { - uint32_t psc; - - osalDbgAssert((icup->config->channel == ICU_CHANNEL_1) || - (icup->config->channel == ICU_CHANNEL_2), - "invalid input"); - - if (icup->state == ICU_STOP) { - /* Clock activation and timer reset.*/ -#if STM32_ICU_USE_TIM1 - if (&ICUD1 == icup) { - rccEnableTIM1(FALSE); - rccResetTIM1(); - nvicEnableVector(STM32_TIM1_UP_NUMBER, STM32_ICU_TIM1_IRQ_PRIORITY); - nvicEnableVector(STM32_TIM1_CC_NUMBER, STM32_ICU_TIM1_IRQ_PRIORITY); - icup->clock = STM32_TIMCLK2; - } -#endif -#if STM32_ICU_USE_TIM2 - if (&ICUD2 == icup) { - rccEnableTIM2(FALSE); - rccResetTIM2(); - nvicEnableVector(STM32_TIM2_NUMBER, STM32_ICU_TIM2_IRQ_PRIORITY); - icup->clock = STM32_TIMCLK1; - } -#endif -#if STM32_ICU_USE_TIM3 - if (&ICUD3 == icup) { - rccEnableTIM3(FALSE); - rccResetTIM3(); - nvicEnableVector(STM32_TIM3_NUMBER, STM32_ICU_TIM3_IRQ_PRIORITY); - icup->clock = STM32_TIMCLK1; - } -#endif -#if STM32_ICU_USE_TIM4 - if (&ICUD4 == icup) { - rccEnableTIM4(FALSE); - rccResetTIM4(); - nvicEnableVector(STM32_TIM4_NUMBER, STM32_ICU_TIM4_IRQ_PRIORITY); - icup->clock = STM32_TIMCLK1; - } -#endif -#if STM32_ICU_USE_TIM5 - if (&ICUD5 == icup) { - rccEnableTIM5(FALSE); - rccResetTIM5(); - nvicEnableVector(STM32_TIM5_NUMBER, STM32_ICU_TIM5_IRQ_PRIORITY); - icup->clock = STM32_TIMCLK1; - } -#endif -#if STM32_ICU_USE_TIM8 - if (&ICUD8 == icup) { - rccEnableTIM8(FALSE); - rccResetTIM8(); - nvicEnableVector(STM32_TIM8_UP_NUMBER, STM32_ICU_TIM8_IRQ_PRIORITY); - nvicEnableVector(STM32_TIM8_CC_NUMBER, STM32_ICU_TIM8_IRQ_PRIORITY); - icup->clock = STM32_TIMCLK2; - } -#endif -#if STM32_ICU_USE_TIM9 - if (&ICUD9 == icup) { - rccEnableTIM9(FALSE); - rccResetTIM9(); - nvicEnableVector(STM32_TIM9_NUMBER, STM32_ICU_TIM9_IRQ_PRIORITY); - icup->clock = STM32_TIMCLK1; - } -#endif - } - else { - /* Driver re-configuration scenario, it must be stopped first.*/ - icup->tim->CR1 = 0; /* Timer disabled. */ - icup->tim->DIER = icup->config->dier &/* DMA-related DIER settings. */ - ~STM32_TIM_DIER_IRQ_MASK; - icup->tim->SR = 0; /* Clear eventual pending IRQs. */ - icup->tim->CCR[0] = 0; /* Comparator 1 disabled. */ - icup->tim->CCR[1] = 0; /* Comparator 2 disabled. */ - icup->tim->CNT = 0; /* Counter reset to zero. */ - } - - /* Timer configuration.*/ - psc = (icup->clock / icup->config->frequency) - 1; - osalDbgAssert((psc <= 0xFFFF) && - ((psc + 1) * icup->config->frequency) == icup->clock, - "invalid frequency"); - icup->tim->PSC = (uint16_t)psc; - icup->tim->ARR = 0xFFFF; - - if (icup->config->channel == ICU_CHANNEL_1) { - /* Selected input 1. - CCMR1_CC1S = 01 = CH1 Input on TI1. - CCMR1_CC2S = 10 = CH2 Input on TI1.*/ - icup->tim->CCMR1 = STM32_TIM_CCMR1_CC1S(1) | STM32_TIM_CCMR1_CC2S(2); - - /* SMCR_TS = 101, input is TI1FP1. - SMCR_SMS = 100, reset on rising edge.*/ - icup->tim->SMCR = STM32_TIM_SMCR_TS(5) | STM32_TIM_SMCR_SMS(4); - - /* The CCER settings depend on the selected trigger mode. - ICU_INPUT_ACTIVE_HIGH: Active on rising edge, idle on falling edge. - ICU_INPUT_ACTIVE_LOW: Active on falling edge, idle on rising edge.*/ - if (icup->config->mode == ICU_INPUT_ACTIVE_HIGH) - icup->tim->CCER = STM32_TIM_CCER_CC1E | - STM32_TIM_CCER_CC2E | STM32_TIM_CCER_CC2P; - else - icup->tim->CCER = STM32_TIM_CCER_CC1E | STM32_TIM_CCER_CC1P | - STM32_TIM_CCER_CC2E; - - /* Direct pointers to the capture registers in order to make reading - data faster from within callbacks.*/ - icup->wccrp = &icup->tim->CCR[1]; - icup->pccrp = &icup->tim->CCR[0]; - } else { - /* Selected input 2. - CCMR1_CC1S = 10 = CH1 Input on TI2. - CCMR1_CC2S = 01 = CH2 Input on TI2.*/ - icup->tim->CCMR1 = STM32_TIM_CCMR1_CC1S(2) | STM32_TIM_CCMR1_CC2S(1); - - /* SMCR_TS = 110, input is TI2FP2. - SMCR_SMS = 100, reset on rising edge.*/ - icup->tim->SMCR = STM32_TIM_SMCR_TS(6) | STM32_TIM_SMCR_SMS(4); - - /* The CCER settings depend on the selected trigger mode. - ICU_INPUT_ACTIVE_HIGH: Active on rising edge, idle on falling edge. - ICU_INPUT_ACTIVE_LOW: Active on falling edge, idle on rising edge.*/ - if (icup->config->mode == ICU_INPUT_ACTIVE_HIGH) - icup->tim->CCER = STM32_TIM_CCER_CC1E | STM32_TIM_CCER_CC1P | - STM32_TIM_CCER_CC2E; - else - icup->tim->CCER = STM32_TIM_CCER_CC1E | - STM32_TIM_CCER_CC2E | STM32_TIM_CCER_CC2P; - - /* Direct pointers to the capture registers in order to make reading - data faster from within callbacks.*/ - icup->wccrp = &icup->tim->CCR[0]; - icup->pccrp = &icup->tim->CCR[1]; - } -} - -/** - * @brief Deactivates the ICU peripheral. - * - * @param[in] icup pointer to the @p ICUDriver object - * - * @notapi - */ -void icu_lld_stop(ICUDriver *icup) { - - if (icup->state == ICU_READY) { - /* Clock deactivation.*/ - icup->tim->CR1 = 0; /* Timer disabled. */ - icup->tim->DIER = 0; /* All IRQs disabled. */ - icup->tim->SR = 0; /* Clear eventual pending IRQs. */ - -#if STM32_ICU_USE_TIM1 - if (&ICUD1 == icup) { - nvicDisableVector(STM32_TIM1_UP_NUMBER); - nvicDisableVector(STM32_TIM1_CC_NUMBER); - rccDisableTIM1(FALSE); - } -#endif -#if STM32_ICU_USE_TIM2 - if (&ICUD2 == icup) { - nvicDisableVector(STM32_TIM2_NUMBER); - rccDisableTIM2(FALSE); - } -#endif -#if STM32_ICU_USE_TIM3 - if (&ICUD3 == icup) { - nvicDisableVector(STM32_TIM3_NUMBER); - rccDisableTIM3(FALSE); - } -#endif -#if STM32_ICU_USE_TIM4 - if (&ICUD4 == icup) { - nvicDisableVector(STM32_TIM4_NUMBER); - rccDisableTIM4(FALSE); - } -#endif -#if STM32_ICU_USE_TIM5 - if (&ICUD5 == icup) { - nvicDisableVector(STM32_TIM5_NUMBER); - rccDisableTIM5(FALSE); - } -#endif -#if STM32_ICU_USE_TIM8 - if (&ICUD8 == icup) { - nvicDisableVector(STM32_TIM8_UP_NUMBER); - nvicDisableVector(STM32_TIM8_CC_NUMBER); - rccDisableTIM8(FALSE); - } -#endif -#if STM32_ICU_USE_TIM9 - if (&ICUD9 == icup) { - nvicDisableVector(STM32_TIM9_NUMBER); - rccDisableTIM9(FALSE); - } -#endif - } -} - -/** - * @brief Enables the input capture. - * - * @param[in] icup pointer to the @p ICUDriver object - * - * @notapi - */ -void icu_lld_enable(ICUDriver *icup) { - - icup->tim->SR = 0; /* Clear pending IRQs (if any). */ - if (icup->config->channel == ICU_CHANNEL_1) { - if (icup->config->period_cb != NULL) - icup->tim->DIER |= STM32_TIM_DIER_CC1IE; - if (icup->config->width_cb != NULL) - icup->tim->DIER |= STM32_TIM_DIER_CC2IE; - } else { - if (icup->config->width_cb != NULL) - icup->tim->DIER |= STM32_TIM_DIER_CC1IE; - if (icup->config->period_cb != NULL) - icup->tim->DIER |= STM32_TIM_DIER_CC2IE; - } - if (icup->config->overflow_cb != NULL) - icup->tim->DIER |= STM32_TIM_DIER_UIE; - icup->tim->CR1 = STM32_TIM_CR1_URS | STM32_TIM_CR1_CEN; -} - -/** - * @brief Disables the input capture. - * - * @param[in] icup pointer to the @p ICUDriver object - * - * @notapi - */ -void icu_lld_disable(ICUDriver *icup) { - - icup->tim->CR1 = 0; /* Initially stopped. */ - icup->tim->SR = 0; /* Clear pending IRQs (if any). */ - - /* All interrupts disabled.*/ - icup->tim->DIER &= ~STM32_TIM_DIER_IRQ_MASK; -} - -#endif /* HAL_USE_ICU */ - -/** @} */ diff --git a/os/hal/platforms/STM32/TIMv1/icu_lld.h b/os/hal/platforms/STM32/TIMv1/icu_lld.h deleted file mode 100644 index f436096c3..000000000 --- a/os/hal/platforms/STM32/TIMv1/icu_lld.h +++ /dev/null @@ -1,412 +0,0 @@ -/* - ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file STM32/icu_lld.h - * @brief STM32 ICU subsystem low level driver header. - * - * @addtogroup ICU - * @{ - */ - -#ifndef _ICU_LLD_H_ -#define _ICU_LLD_H_ - -#if HAL_USE_ICU || defined(__DOXYGEN__) - -#include "stm32_tim.h" - -/*===========================================================================*/ -/* Driver constants. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver pre-compile time settings. */ -/*===========================================================================*/ - -/** - * @name Configuration options - * @{ - */ -/** - * @brief ICUD1 driver enable switch. - * @details If set to @p TRUE the support for ICUD1 is included. - * @note The default is @p TRUE. - */ -#if !defined(STM32_ICU_USE_TIM1) || defined(__DOXYGEN__) -#define STM32_ICU_USE_TIM1 FALSE -#endif - -/** - * @brief ICUD2 driver enable switch. - * @details If set to @p TRUE the support for ICUD2 is included. - * @note The default is @p TRUE. - */ -#if !defined(STM32_ICU_USE_TIM2) || defined(__DOXYGEN__) -#define STM32_ICU_USE_TIM2 FALSE -#endif - -/** - * @brief ICUD3 driver enable switch. - * @details If set to @p TRUE the support for ICUD3 is included. - * @note The default is @p TRUE. - */ -#if !defined(STM32_ICU_USE_TIM3) || defined(__DOXYGEN__) -#define STM32_ICU_USE_TIM3 FALSE -#endif - -/** - * @brief ICUD4 driver enable switch. - * @details If set to @p TRUE the support for ICUD4 is included. - * @note The default is @p TRUE. - */ -#if !defined(STM32_ICU_USE_TIM4) || defined(__DOXYGEN__) -#define STM32_ICU_USE_TIM4 FALSE -#endif - -/** - * @brief ICUD5 driver enable switch. - * @details If set to @p TRUE the support for ICUD5 is included. - * @note The default is @p TRUE. - */ -#if !defined(STM32_ICU_USE_TIM5) || defined(__DOXYGEN__) -#define STM32_ICU_USE_TIM5 FALSE -#endif - -/** - * @brief ICUD8 driver enable switch. - * @details If set to @p TRUE the support for ICUD8 is included. - * @note The default is @p TRUE. - */ -#if !defined(STM32_ICU_USE_TIM8) || defined(__DOXYGEN__) -#define STM32_ICU_USE_TIM8 FALSE -#endif - -/** - * @brief ICUD9 driver enable switch. - * @details If set to @p TRUE the support for ICUD9 is included. - * @note The default is @p TRUE. - */ -#if !defined(STM32_ICU_USE_TIM9) || defined(__DOXYGEN__) -#define STM32_ICU_USE_TIM9 FALSE -#endif - -/** - * @brief ICUD1 interrupt priority level setting. - */ -#if !defined(STM32_ICU_TIM1_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_ICU_TIM1_IRQ_PRIORITY 7 -#endif - -/** - * @brief ICUD2 interrupt priority level setting. - */ -#if !defined(STM32_ICU_TIM2_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_ICU_TIM2_IRQ_PRIORITY 7 -#endif - -/** - * @brief ICUD3 interrupt priority level setting. - */ -#if !defined(STM32_ICU_TIM3_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_ICU_TIM3_IRQ_PRIORITY 7 -#endif - -/** - * @brief ICUD4 interrupt priority level setting. - */ -#if !defined(STM32_ICU_TIM4_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_ICU_TIM4_IRQ_PRIORITY 7 -#endif - -/** - * @brief ICUD5 interrupt priority level setting. - */ -#if !defined(STM32_ICU_TIM5_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_ICU_TIM5_IRQ_PRIORITY 7 -#endif - -/** - * @brief ICUD8 interrupt priority level setting. - */ -#if !defined(STM32_ICU_TIM8_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_ICU_TIM8_IRQ_PRIORITY 7 -#endif - -/** - * @brief ICUD9 interrupt priority level setting. - */ -#if !defined(STM32_ICU_TIM9_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_ICU_TIM9_IRQ_PRIORITY 7 -#endif -/** @} */ - -/*===========================================================================*/ -/* Derived constants and error checks. */ -/*===========================================================================*/ - -#if STM32_ICU_USE_TIM1 && !STM32_HAS_TIM1 -#error "TIM1 not present in the selected device" -#endif - -#if STM32_ICU_USE_TIM2 && !STM32_HAS_TIM2 -#error "TIM2 not present in the selected device" -#endif - -#if STM32_ICU_USE_TIM3 && !STM32_HAS_TIM3 -#error "TIM3 not present in the selected device" -#endif - -#if STM32_ICU_USE_TIM4 && !STM32_HAS_TIM4 -#error "TIM4 not present in the selected device" -#endif - -#if STM32_ICU_USE_TIM5 && !STM32_HAS_TIM5 -#error "TIM5 not present in the selected device" -#endif - -#if STM32_ICU_USE_TIM8 && !STM32_HAS_TIM8 -#error "TIM8 not present in the selected device" -#endif - -#if STM32_ICU_USE_TIM9 && !STM32_HAS_TIM9 -#error "TIM9 not present in the selected device" -#endif - -#if !STM32_ICU_USE_TIM1 && !STM32_ICU_USE_TIM2 && \ - !STM32_ICU_USE_TIM3 && !STM32_ICU_USE_TIM4 && \ - !STM32_ICU_USE_TIM5 && !STM32_ICU_USE_TIM8 && \ - !STM32_ICU_USE_TIM9 -#error "ICU driver activated but no TIM peripheral assigned" -#endif - -#if STM32_ICU_USE_TIM1 && \ - !CORTEX_IS_VALID_KERNEL_PRIORITY(STM32_ICU_TIM1_IRQ_PRIORITY) -#error "Invalid IRQ priority assigned to TIM1" -#endif - -#if STM32_ICU_USE_TIM2 && \ - !CORTEX_IS_VALID_KERNEL_PRIORITY(STM32_ICU_TIM2_IRQ_PRIORITY) -#error "Invalid IRQ priority assigned to TIM2" -#endif - -#if STM32_ICU_USE_TIM3 && \ - !CORTEX_IS_VALID_KERNEL_PRIORITY(STM32_ICU_TIM3_IRQ_PRIORITY) -#error "Invalid IRQ priority assigned to TIM3" -#endif - -#if STM32_ICU_USE_TIM4 && \ - !CORTEX_IS_VALID_KERNEL_PRIORITY(STM32_ICU_TIM4_IRQ_PRIORITY) -#error "Invalid IRQ priority assigned to TIM4" -#endif - -#if STM32_ICU_USE_TIM5 && \ - !CORTEX_IS_VALID_KERNEL_PRIORITY(STM32_ICU_TIM5_IRQ_PRIORITY) -#error "Invalid IRQ priority assigned to TIM5" -#endif - -#if STM32_ICU_USE_TIM8 && \ - !CORTEX_IS_VALID_KERNEL_PRIORITY(STM32_ICU_TIM8_IRQ_PRIORITY) -#error "Invalid IRQ priority assigned to TIM8" -#endif - -#if STM32_ICU_USE_TIM9 && \ - !CORTEX_IS_VALID_KERNEL_PRIORITY(STM32_ICU_TIM9_IRQ_PRIORITY) -#error "Invalid IRQ priority assigned to TIM9" -#endif - -/*===========================================================================*/ -/* Driver data structures and types. */ -/*===========================================================================*/ - -/** - * @brief ICU driver mode. - */ -typedef enum { - ICU_INPUT_ACTIVE_HIGH = 0, /**< Trigger on rising edge. */ - ICU_INPUT_ACTIVE_LOW = 1, /**< Trigger on falling edge. */ -} icumode_t; - -/** - * @brief ICU frequency type. - */ -typedef uint32_t icufreq_t; - -/** - * @brief ICU channel type. - */ -typedef enum { - ICU_CHANNEL_1 = 0, /**< Use TIMxCH1. */ - ICU_CHANNEL_2 = 1, /**< Use TIMxCH2. */ -} icuchannel_t; - -/** - * @brief ICU counter type. - */ -typedef uint16_t icucnt_t; - -/** - * @brief Driver configuration structure. - * @note It could be empty on some architectures. - */ -typedef struct { - /** - * @brief Driver mode. - */ - icumode_t mode; - /** - * @brief Timer clock in Hz. - * @note The low level can use assertions in order to catch invalid - * frequency specifications. - */ - icufreq_t frequency; - /** - * @brief Callback for pulse width measurement. - */ - icucallback_t width_cb; - /** - * @brief Callback for cycle period measurement. - */ - icucallback_t period_cb; - /** - * @brief Callback for timer overflow. - */ - icucallback_t overflow_cb; - /* End of the mandatory fields.*/ - /** - * @brief Timer input channel to be used. - * @note Only inputs TIMx 1 and 2 are supported. - */ - icuchannel_t channel; - /** - * @brief TIM DIER register initialization data. - * @note The value of this field should normally be equal to zero. - * @note Only the DMA-related bits can be specified in this field. - */ - uint32_t dier; -} ICUConfig; - -/** - * @brief Structure representing an ICU driver. - */ -struct ICUDriver { - /** - * @brief Driver state. - */ - icustate_t state; - /** - * @brief Current configuration data. - */ - const ICUConfig *config; -#if defined(ICU_DRIVER_EXT_FIELDS) - ICU_DRIVER_EXT_FIELDS -#endif - /* End of the mandatory fields.*/ - /** - * @brief Timer base clock. - */ - uint32_t clock; - /** - * @brief Pointer to the TIMx registers block. - */ - stm32_tim_t *tim; - /** - * @brief CCR register used for width capture. - */ - volatile uint32_t *wccrp; - /** - * @brief CCR register used for period capture. - */ - volatile uint32_t *pccrp; -}; - -/*===========================================================================*/ -/* Driver macros. */ -/*===========================================================================*/ - -/** - * @brief Returns the width of the latest pulse. - * @details The pulse width is defined as number of ticks between the start - * edge and the stop edge. - * - * @param[in] icup pointer to the @p ICUDriver object - * @return The number of ticks. - * - * @notapi - */ -#define icu_lld_get_width(icup) (*((icup)->wccrp) + 1) - -/** - * @brief Returns the width of the latest cycle. - * @details The cycle width is defined as number of ticks between a start - * edge and the next start edge. - * - * @param[in] icup pointer to the @p ICUDriver object - * @return The number of ticks. - * - * @notapi - */ -#define icu_lld_get_period(icup) (*((icup)->pccrp) + 1) - -/*===========================================================================*/ -/* External declarations. */ -/*===========================================================================*/ - -#if STM32_ICU_USE_TIM1 && !defined(__DOXYGEN__) -extern ICUDriver ICUD1; -#endif - -#if STM32_ICU_USE_TIM2 && !defined(__DOXYGEN__) -extern ICUDriver ICUD2; -#endif - -#if STM32_ICU_USE_TIM3 && !defined(__DOXYGEN__) -extern ICUDriver ICUD3; -#endif - -#if STM32_ICU_USE_TIM4 && !defined(__DOXYGEN__) -extern ICUDriver ICUD4; -#endif - -#if STM32_ICU_USE_TIM5 && !defined(__DOXYGEN__) -extern ICUDriver ICUD5; -#endif - -#if STM32_ICU_USE_TIM8 && !defined(__DOXYGEN__) -extern ICUDriver ICUD8; -#endif - -#if STM32_ICU_USE_TIM9 && !defined(__DOXYGEN__) -extern ICUDriver ICUD9; -#endif - -#ifdef __cplusplus -extern "C" { -#endif - void icu_lld_init(void); - void icu_lld_start(ICUDriver *icup); - void icu_lld_stop(ICUDriver *icup); - void icu_lld_enable(ICUDriver *icup); - void icu_lld_disable(ICUDriver *icup); -#ifdef __cplusplus -} -#endif - -#endif /* HAL_USE_ICU */ - -#endif /* _ICU_LLD_H_ */ - -/** @} */ diff --git a/os/hal/platforms/STM32/TIMv1/pwm_lld.c b/os/hal/platforms/STM32/TIMv1/pwm_lld.c deleted file mode 100644 index 12abc0c44..000000000 --- a/os/hal/platforms/STM32/TIMv1/pwm_lld.c +++ /dev/null @@ -1,695 +0,0 @@ -/* - ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file STM32/pwm_lld.c - * @brief STM32 PWM subsystem low level driver header. - * - * @addtogroup PWM - * @{ - */ - -#include "hal.h" - -#if HAL_USE_PWM || defined(__DOXYGEN__) - -/*===========================================================================*/ -/* Driver local definitions. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver exported variables. */ -/*===========================================================================*/ - -/** - * @brief PWMD1 driver identifier. - * @note The driver PWMD1 allocates the complex timer TIM1 when enabled. - */ -#if STM32_PWM_USE_TIM1 || defined(__DOXYGEN__) -PWMDriver PWMD1; -#endif - -/** - * @brief PWMD2 driver identifier. - * @note The driver PWMD2 allocates the timer TIM2 when enabled. - */ -#if STM32_PWM_USE_TIM2 || defined(__DOXYGEN__) -PWMDriver PWMD2; -#endif - -/** - * @brief PWMD3 driver identifier. - * @note The driver PWMD3 allocates the timer TIM3 when enabled. - */ -#if STM32_PWM_USE_TIM3 || defined(__DOXYGEN__) -PWMDriver PWMD3; -#endif - -/** - * @brief PWMD4 driver identifier. - * @note The driver PWMD4 allocates the timer TIM4 when enabled. - */ -#if STM32_PWM_USE_TIM4 || defined(__DOXYGEN__) -PWMDriver PWMD4; -#endif - -/** - * @brief PWMD5 driver identifier. - * @note The driver PWMD5 allocates the timer TIM5 when enabled. - */ -#if STM32_PWM_USE_TIM5 || defined(__DOXYGEN__) -PWMDriver PWMD5; -#endif - -/** - * @brief PWMD8 driver identifier. - * @note The driver PWMD8 allocates the timer TIM8 when enabled. - */ -#if STM32_PWM_USE_TIM8 || defined(__DOXYGEN__) -PWMDriver PWMD8; -#endif - -/** - * @brief PWMD9 driver identifier. - * @note The driver PWMD9 allocates the timer TIM9 when enabled. - */ -#if STM32_PWM_USE_TIM9 || defined(__DOXYGEN__) -PWMDriver PWMD9; -#endif - -/*===========================================================================*/ -/* Driver local variables and types. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver local functions. */ -/*===========================================================================*/ - -#if STM32_PWM_USE_TIM2 || STM32_PWM_USE_TIM3 || STM32_PWM_USE_TIM4 || \ - STM32_PWM_USE_TIM5 || STM32_PWM_USE_TIM9 || defined(__DOXYGEN__) -/** - * @brief Common TIM2...TIM5,TIM9 IRQ handler. - * @note It is assumed that the various sources are only activated if the - * associated callback pointer is not equal to @p NULL in order to not - * perform an extra check in a potentially critical interrupt handler. - * - * @param[in] pwmp pointer to a @p PWMDriver object - */ -static void pwm_lld_serve_interrupt(PWMDriver *pwmp) { - uint16_t sr; - - sr = pwmp->tim->SR; - sr &= pwmp->tim->DIER & STM32_TIM_DIER_IRQ_MASK; - pwmp->tim->SR = ~sr; - if ((sr & STM32_TIM_SR_CC1IF) != 0) - pwmp->config->channels[0].callback(pwmp); - if ((sr & STM32_TIM_SR_CC2IF) != 0) - pwmp->config->channels[1].callback(pwmp); - if ((sr & STM32_TIM_SR_CC3IF) != 0) - pwmp->config->channels[2].callback(pwmp); - if ((sr & STM32_TIM_SR_CC4IF) != 0) - pwmp->config->channels[3].callback(pwmp); - if ((sr & STM32_TIM_SR_UIF) != 0) - pwmp->config->callback(pwmp); -} -#endif /* STM32_PWM_USE_TIM2 || ... || STM32_PWM_USE_TIM5 */ - -/*===========================================================================*/ -/* Driver interrupt handlers. */ -/*===========================================================================*/ - -#if STM32_PWM_USE_TIM1 -#if !defined(STM32_TIM1_UP_HANDLER) -#error "STM32_TIM1_UP_HANDLER not defined" -#endif -/** - * @brief TIM1 update interrupt handler. - * @note It is assumed that this interrupt is only activated if the callback - * pointer is not equal to @p NULL in order to not perform an extra - * check in a potentially critical interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(STM32_TIM1_UP_HANDLER) { - - OSAL_IRQ_PROLOGUE(); - - STM32_TIM1->SR = ~STM32_TIM_SR_UIF; - PWMD1.config->callback(&PWMD1); - - OSAL_IRQ_EPILOGUE(); -} - -#if !defined(STM32_TIM1_CC_HANDLER) -#error "STM32_TIM1_CC_HANDLER not defined" -#endif -/** - * @brief TIM1 compare interrupt handler. - * @note It is assumed that the various sources are only activated if the - * associated callback pointer is not equal to @p NULL in order to not - * perform an extra check in a potentially critical interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(STM32_TIM1_CC_HANDLER) { - uint16_t sr; - - OSAL_IRQ_PROLOGUE(); - - sr = STM32_TIM1->SR & STM32_TIM1->DIER & STM32_TIM_DIER_IRQ_MASK; - STM32_TIM1->SR = ~sr; - if ((sr & STM32_TIM_SR_CC1IF) != 0) - PWMD1.config->channels[0].callback(&PWMD1); - if ((sr & STM32_TIM_SR_CC2IF) != 0) - PWMD1.config->channels[1].callback(&PWMD1); - if ((sr & STM32_TIM_SR_CC3IF) != 0) - PWMD1.config->channels[2].callback(&PWMD1); - if ((sr & STM32_TIM_SR_CC4IF) != 0) - PWMD1.config->channels[3].callback(&PWMD1); - - OSAL_IRQ_EPILOGUE(); -} -#endif /* STM32_PWM_USE_TIM1 */ - -#if STM32_PWM_USE_TIM2 -#if !defined(STM32_TIM2_HANDLER) -#error "STM32_TIM2_HANDLER not defined" -#endif -/** - * @brief TIM2 interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(STM32_TIM2_HANDLER) { - - OSAL_IRQ_PROLOGUE(); - - pwm_lld_serve_interrupt(&PWMD2); - - OSAL_IRQ_EPILOGUE(); -} -#endif /* STM32_PWM_USE_TIM2 */ - -#if STM32_PWM_USE_TIM3 -#if !defined(STM32_TIM3_HANDLER) -#error "STM32_TIM3_HANDLER not defined" -#endif -/** - * @brief TIM3 interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(STM32_TIM3_HANDLER) { - - OSAL_IRQ_PROLOGUE(); - - pwm_lld_serve_interrupt(&PWMD3); - - OSAL_IRQ_EPILOGUE(); -} -#endif /* STM32_PWM_USE_TIM3 */ - -#if STM32_PWM_USE_TIM4 -#if !defined(STM32_TIM4_HANDLER) -#error "STM32_TIM4_HANDLER not defined" -#endif -/** - * @brief TIM4 interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(STM32_TIM4_HANDLER) { - - OSAL_IRQ_PROLOGUE(); - - pwm_lld_serve_interrupt(&PWMD4); - - OSAL_IRQ_EPILOGUE(); -} -#endif /* STM32_PWM_USE_TIM4 */ - -#if STM32_PWM_USE_TIM5 -#if !defined(STM32_TIM5_HANDLER) -#error "STM32_TIM5_HANDLER not defined" -#endif -/** - * @brief TIM5 interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(STM32_TIM5_HANDLER) { - - OSAL_IRQ_PROLOGUE(); - - pwm_lld_serve_interrupt(&PWMD5); - - OSAL_IRQ_EPILOGUE(); -} -#endif /* STM32_PWM_USE_TIM5 */ - -#if STM32_PWM_USE_TIM8 -#if !defined(STM32_TIM8_UP_HANDLER) -#error "STM32_TIM8_UP_HANDLER not defined" -#endif -/** - * @brief TIM8 update interrupt handler. - * @note It is assumed that this interrupt is only activated if the callback - * pointer is not equal to @p NULL in order to not perform an extra - * check in a potentially critical interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(STM32_TIM8_UP_HANDLER) { - - OSAL_IRQ_PROLOGUE(); - - STM32_TIM8->SR = ~TIM_SR_UIF; - PWMD8.config->callback(&PWMD8); - - OSAL_IRQ_EPILOGUE(); -} - -#if !defined(STM32_TIM8_CC_HANDLER) -#error "STM32_TIM8_CC_HANDLER not defined" -#endif -/** - * @brief TIM8 compare interrupt handler. - * @note It is assumed that the various sources are only activated if the - * associated callback pointer is not equal to @p NULL in order to not - * perform an extra check in a potentially critical interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(STM32_TIM8_CC_HANDLER) { - uint16_t sr; - - OSAL_IRQ_PROLOGUE(); - - sr = STM32_TIM8->SR & STM32_TIM8->DIER & STM32_TIM_DIER_IRQ_MASK; - STM32_TIM8->SR = ~sr; - if ((sr & STM32_TIM_SR_CC1IF) != 0) - PWMD8.config->channels[0].callback(&PWMD8); - if ((sr & STM32_TIM_SR_CC2IF) != 0) - PWMD8.config->channels[1].callback(&PWMD8); - if ((sr & STM32_TIM_SR_CC3IF) != 0) - PWMD8.config->channels[2].callback(&PWMD8); - if ((sr & STM32_TIM_SR_CC4IF) != 0) - PWMD8.config->channels[3].callback(&PWMD8); - - OSAL_IRQ_EPILOGUE(); -} -#endif /* STM32_PWM_USE_TIM8 */ - -#if STM32_PWM_USE_TIM9 -#if !defined(STM32_TIM9_HANDLER) -#error "STM32_TIM9_HANDLER not defined" -#endif -/** - * @brief TIM9 interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(STM32_TIM9_HANDLER) { - - OSAL_IRQ_PROLOGUE(); - - pwm_lld_serve_interrupt(&PWMD9); - - OSAL_IRQ_EPILOGUE(); -} -#endif /* STM32_PWM_USE_TIM9 */ - -/*===========================================================================*/ -/* Driver exported functions. */ -/*===========================================================================*/ - -/** - * @brief Low level PWM driver initialization. - * - * @notapi - */ -void pwm_lld_init(void) { - -#if STM32_PWM_USE_TIM1 - /* Driver initialization.*/ - pwmObjectInit(&PWMD1); - PWMD1.tim = STM32_TIM1; -#endif - -#if STM32_PWM_USE_TIM2 - /* Driver initialization.*/ - pwmObjectInit(&PWMD2); - PWMD2.tim = STM32_TIM2; -#endif - -#if STM32_PWM_USE_TIM3 - /* Driver initialization.*/ - pwmObjectInit(&PWMD3); - PWMD3.tim = STM32_TIM3; -#endif - -#if STM32_PWM_USE_TIM4 - /* Driver initialization.*/ - pwmObjectInit(&PWMD4); - PWMD4.tim = STM32_TIM4; -#endif - -#if STM32_PWM_USE_TIM5 - /* Driver initialization.*/ - pwmObjectInit(&PWMD5); - PWMD5.tim = STM32_TIM5; -#endif - -#if STM32_PWM_USE_TIM8 - /* Driver initialization.*/ - pwmObjectInit(&PWMD8); - PWMD8.tim = STM32_TIM8; -#endif - -#if STM32_PWM_USE_TIM9 - /* Driver initialization.*/ - pwmObjectInit(&PWMD9); - PWMD9.tim = STM32_TIM9; -#endif -} - -/** - * @brief Configures and activates the PWM peripheral. - * @note Starting a driver that is already in the @p PWM_READY state - * disables all the active channels. - * - * @param[in] pwmp pointer to a @p PWMDriver object - * - * @notapi - */ -void pwm_lld_start(PWMDriver *pwmp) { - uint32_t psc; - uint16_t ccer; - - if (pwmp->state == PWM_STOP) { - /* Clock activation and timer reset.*/ -#if STM32_PWM_USE_TIM1 - if (&PWMD1 == pwmp) { - rccEnableTIM1(FALSE); - rccResetTIM1(); - nvicEnableVector(STM32_TIM1_UP_NUMBER, STM32_PWM_TIM1_IRQ_PRIORITY); - nvicEnableVector(STM32_TIM1_CC_NUMBER, STM32_PWM_TIM1_IRQ_PRIORITY); - pwmp->clock = STM32_TIMCLK2; - } -#endif -#if STM32_PWM_USE_TIM2 - if (&PWMD2 == pwmp) { - rccEnableTIM2(FALSE); - rccResetTIM2(); - nvicEnableVector(STM32_TIM2_NUMBER, STM32_PWM_TIM2_IRQ_PRIORITY); - pwmp->clock = STM32_TIMCLK1; - } -#endif -#if STM32_PWM_USE_TIM3 - if (&PWMD3 == pwmp) { - rccEnableTIM3(FALSE); - rccResetTIM3(); - nvicEnableVector(STM32_TIM3_NUMBER, STM32_PWM_TIM3_IRQ_PRIORITY); - pwmp->clock = STM32_TIMCLK1; - } -#endif -#if STM32_PWM_USE_TIM4 - if (&PWMD4 == pwmp) { - rccEnableTIM4(FALSE); - rccResetTIM4(); - nvicEnableVector(STM32_TIM4_NUMBER, STM32_PWM_TIM4_IRQ_PRIORITY); - pwmp->clock = STM32_TIMCLK1; - } -#endif - -#if STM32_PWM_USE_TIM5 - if (&PWMD5 == pwmp) { - rccEnableTIM5(FALSE); - rccResetTIM5(); - nvicEnableVector(STM32_TIM5_NUMBER, STM32_PWM_TIM5_IRQ_PRIORITY); - pwmp->clock = STM32_TIMCLK1; - } -#endif -#if STM32_PWM_USE_TIM8 - if (&PWMD8 == pwmp) { - rccEnableTIM8(FALSE); - rccResetTIM8(); - nvicEnableVector(STM32_TIM8_UP_NUMBER, STM32_PWM_TIM8_IRQ_PRIORITY); - nvicEnableVector(STM32_TIM8_CC_NUMBER, STM32_PWM_TIM8_IRQ_PRIORITY); - pwmp->clock = STM32_TIMCLK2; - } -#endif -#if STM32_PWM_USE_TIM9 - if (&PWMD9 == pwmp) { - rccEnableTIM9(FALSE); - rccResetTIM9(); - nvicEnableVector(STM32_TIM9_NUMBER, STM32_PWM_TIM9_IRQ_PRIORITY); - pwmp->clock = STM32_TIMCLK1; - } -#endif - - /* All channels configured in PWM1 mode with preload enabled and will - stay that way until the driver is stopped.*/ - pwmp->tim->CCMR1 = STM32_TIM_CCMR1_OC1M(6) | STM32_TIM_CCMR1_OC1PE | - STM32_TIM_CCMR1_OC2M(6) | STM32_TIM_CCMR1_OC2PE; - pwmp->tim->CCMR2 = STM32_TIM_CCMR2_OC3M(6) | STM32_TIM_CCMR2_OC3PE | - STM32_TIM_CCMR2_OC4M(6) | STM32_TIM_CCMR2_OC4PE; - } - else { - /* Driver re-configuration scenario, it must be stopped first.*/ - pwmp->tim->CR1 = 0; /* Timer disabled. */ - pwmp->tim->DIER = pwmp->config->dier &/* DMA-related DIER settings. */ - ~STM32_TIM_DIER_IRQ_MASK; - pwmp->tim->SR = 0; /* Clear eventual pending IRQs. */ - pwmp->tim->CCR[0] = 0; /* Comparator 1 disabled. */ - pwmp->tim->CCR[1] = 0; /* Comparator 2 disabled. */ - pwmp->tim->CCR[2] = 0; /* Comparator 3 disabled. */ - pwmp->tim->CCR[3] = 0; /* Comparator 4 disabled. */ - pwmp->tim->CNT = 0; /* Counter reset to zero. */ - } - - /* Timer configuration.*/ - psc = (pwmp->clock / pwmp->config->frequency) - 1; - osalDbgAssert((psc <= 0xFFFF) && - ((psc + 1) * pwmp->config->frequency) == pwmp->clock, - "invalid frequency"); - pwmp->tim->PSC = (uint16_t)psc; - pwmp->tim->ARR = (uint16_t)(pwmp->period - 1); - pwmp->tim->CR2 = pwmp->config->cr2; - - /* Output enables and polarities setup.*/ - ccer = 0; - switch (pwmp->config->channels[0].mode & PWM_OUTPUT_MASK) { - case PWM_OUTPUT_ACTIVE_LOW: - ccer |= STM32_TIM_CCER_CC1P; - case PWM_OUTPUT_ACTIVE_HIGH: - ccer |= STM32_TIM_CCER_CC1E; - default: - ; - } - switch (pwmp->config->channels[1].mode & PWM_OUTPUT_MASK) { - case PWM_OUTPUT_ACTIVE_LOW: - ccer |= STM32_TIM_CCER_CC2P; - case PWM_OUTPUT_ACTIVE_HIGH: - ccer |= STM32_TIM_CCER_CC2E; - default: - ; - } - switch (pwmp->config->channels[2].mode & PWM_OUTPUT_MASK) { - case PWM_OUTPUT_ACTIVE_LOW: - ccer |= STM32_TIM_CCER_CC3P; - case PWM_OUTPUT_ACTIVE_HIGH: - ccer |= STM32_TIM_CCER_CC3E; - default: - ; - } - switch (pwmp->config->channels[3].mode & PWM_OUTPUT_MASK) { - case PWM_OUTPUT_ACTIVE_LOW: - ccer |= STM32_TIM_CCER_CC4P; - case PWM_OUTPUT_ACTIVE_HIGH: - ccer |= STM32_TIM_CCER_CC4E; - default: - ; - } -#if STM32_PWM_USE_ADVANCED -#if STM32_PWM_USE_TIM1 && !STM32_PWM_USE_TIM8 - if (&PWMD1 == pwmp) { -#endif -#if !STM32_PWM_USE_TIM1 && STM32_PWM_USE_TIM8 - if (&PWMD8 == pwmp) { -#endif -#if STM32_PWM_USE_TIM1 && STM32_PWM_USE_TIM8 - if ((&PWMD1 == pwmp) || (&PWMD8 == pwmp)) { -#endif - switch (pwmp->config->channels[0].mode & PWM_COMPLEMENTARY_OUTPUT_MASK) { - case PWM_COMPLEMENTARY_OUTPUT_ACTIVE_LOW: - ccer |= STM32_TIM_CCER_CC1NP; - case PWM_COMPLEMENTARY_OUTPUT_ACTIVE_HIGH: - ccer |= STM32_TIM_CCER_CC1NE; - default: - ; - } - switch (pwmp->config->channels[1].mode & PWM_COMPLEMENTARY_OUTPUT_MASK) { - case PWM_COMPLEMENTARY_OUTPUT_ACTIVE_LOW: - ccer |= STM32_TIM_CCER_CC2NP; - case PWM_COMPLEMENTARY_OUTPUT_ACTIVE_HIGH: - ccer |= STM32_TIM_CCER_CC2NE; - default: - ; - } - switch (pwmp->config->channels[2].mode & PWM_COMPLEMENTARY_OUTPUT_MASK) { - case PWM_COMPLEMENTARY_OUTPUT_ACTIVE_LOW: - ccer |= STM32_TIM_CCER_CC3NP; - case PWM_COMPLEMENTARY_OUTPUT_ACTIVE_HIGH: - ccer |= STM32_TIM_CCER_CC3NE; - default: - ; - } - } -#endif /* STM32_PWM_USE_ADVANCED*/ - - pwmp->tim->CCER = ccer; - pwmp->tim->EGR = STM32_TIM_EGR_UG; /* Update event. */ - pwmp->tim->DIER |= pwmp->config->callback == NULL ? 0 : STM32_TIM_DIER_UIE; - pwmp->tim->SR = 0; /* Clear pending IRQs. */ -#if STM32_PWM_USE_TIM1 || STM32_PWM_USE_TIM8 -#if STM32_PWM_USE_ADVANCED - pwmp->tim->BDTR = pwmp->config->bdtr | STM32_TIM_BDTR_MOE; -#else - pwmp->tim->BDTR = STM32_TIM_BDTR_MOE; -#endif -#endif - /* Timer configured and started.*/ - pwmp->tim->CR1 = STM32_TIM_CR1_ARPE | STM32_TIM_CR1_URS | - STM32_TIM_CR1_CEN; -} - -/** - * @brief Deactivates the PWM peripheral. - * - * @param[in] pwmp pointer to a @p PWMDriver object - * - * @notapi - */ -void pwm_lld_stop(PWMDriver *pwmp) { - - /* If in ready state then disables the PWM clock.*/ - if (pwmp->state == PWM_READY) { - pwmp->tim->CR1 = 0; /* Timer disabled. */ - pwmp->tim->DIER = 0; /* All IRQs disabled. */ - pwmp->tim->SR = 0; /* Clear eventual pending IRQs. */ -#if STM32_PWM_USE_TIM1 || STM32_PWM_USE_TIM8 - pwmp->tim->BDTR = 0; -#endif - -#if STM32_PWM_USE_TIM1 - if (&PWMD1 == pwmp) { - nvicDisableVector(STM32_TIM1_UP_NUMBER); - nvicDisableVector(STM32_TIM1_CC_NUMBER); - rccDisableTIM1(FALSE); - } -#endif -#if STM32_PWM_USE_TIM2 - if (&PWMD2 == pwmp) { - nvicDisableVector(STM32_TIM2_NUMBER); - rccDisableTIM2(FALSE); - } -#endif -#if STM32_PWM_USE_TIM3 - if (&PWMD3 == pwmp) { - nvicDisableVector(STM32_TIM3_NUMBER); - rccDisableTIM3(FALSE); - } -#endif -#if STM32_PWM_USE_TIM4 - if (&PWMD4 == pwmp) { - nvicDisableVector(STM32_TIM4_NUMBER); - rccDisableTIM4(FALSE); - } -#endif -#if STM32_PWM_USE_TIM5 - if (&PWMD5 == pwmp) { - nvicDisableVector(STM32_TIM5_NUMBER); - rccDisableTIM5(FALSE); - } -#endif -#if STM32_PWM_USE_TIM8 - if (&PWMD8 == pwmp) { - nvicDisableVector(STM32_TIM8_UP_NUMBER); - nvicDisableVector(STM32_TIM8_CC_NUMBER); - rccDisableTIM8(FALSE); - } -#endif -#if STM32_PWM_USE_TIM9 - if (&PWMD9 == pwmp) { - nvicDisableVector(STM32_TIM9_NUMBER); - rccDisableTIM9(FALSE); - } -#endif - } -} - -/** - * @brief Enables a PWM channel. - * @pre The PWM unit must have been activated using @p pwmStart(). - * @post The channel is active using the specified configuration. - * @note The function has effect at the next cycle start. - * - * @param[in] pwmp pointer to a @p PWMDriver object - * @param[in] channel PWM channel identifier (0...PWM_CHANNELS-1) - * @param[in] width PWM pulse width as clock pulses number - * - * @notapi - */ -void pwm_lld_enable_channel(PWMDriver *pwmp, - pwmchannel_t channel, - pwmcnt_t width) { - - pwmp->tim->CCR[channel] = width; /* New duty cycle. */ - /* If there is a callback defined for the channel then the associated - interrupt must be enabled.*/ - if (pwmp->config->channels[channel].callback != NULL) { - uint32_t dier = pwmp->tim->DIER; - /* If the IRQ is not already enabled care must be taken to clear it, - it is probably already pending because the timer is running.*/ - if ((dier & (2 << channel)) == 0) { - pwmp->tim->DIER = dier | (2 << channel); - pwmp->tim->SR = ~(2 << channel); - } - } -} - -/** - * @brief Disables a PWM channel. - * @pre The PWM unit must have been activated using @p pwmStart(). - * @post The channel is disabled and its output line returned to the - * idle state. - * @note The function has effect at the next cycle start. - * - * @param[in] pwmp pointer to a @p PWMDriver object - * @param[in] channel PWM channel identifier (0...PWM_CHANNELS-1) - * - * @notapi - */ -void pwm_lld_disable_channel(PWMDriver *pwmp, pwmchannel_t channel) { - - pwmp->tim->CCR[channel] = 0; - pwmp->tim->DIER &= ~(2 << channel); -} - -#endif /* HAL_USE_PWM */ - -/** @} */ diff --git a/os/hal/platforms/STM32/TIMv1/pwm_lld.h b/os/hal/platforms/STM32/TIMv1/pwm_lld.h deleted file mode 100644 index c77acf883..000000000 --- a/os/hal/platforms/STM32/TIMv1/pwm_lld.h +++ /dev/null @@ -1,480 +0,0 @@ -/* - ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file STM32/pwm_lld.h - * @brief STM32 PWM subsystem low level driver header. - * - * @addtogroup PWM - * @{ - */ - -#ifndef _PWM_LLD_H_ -#define _PWM_LLD_H_ - -#if HAL_USE_PWM || defined(__DOXYGEN__) - -#include "stm32_tim.h" - -/*===========================================================================*/ -/* Driver constants. */ -/*===========================================================================*/ - -/** - * @brief Number of PWM channels per PWM driver. - */ -#define PWM_CHANNELS 4 - -/** - * @brief Complementary output modes mask. - * @note This is an STM32-specific setting. - */ -#define PWM_COMPLEMENTARY_OUTPUT_MASK 0xF0 - -/** - * @brief Complementary output not driven. - * @note This is an STM32-specific setting. - */ -#define PWM_COMPLEMENTARY_OUTPUT_DISABLED 0x00 - -/** - * @brief Complementary output, active is logic level one. - * @note This is an STM32-specific setting. - * @note This setting is only available if the configuration option - * @p STM32_PWM_USE_ADVANCED is set to TRUE and only for advanced - * timers TIM1 and TIM8. - */ -#define PWM_COMPLEMENTARY_OUTPUT_ACTIVE_HIGH 0x10 - -/** - * @brief Complementary output, active is logic level zero. - * @note This is an STM32-specific setting. - * @note This setting is only available if the configuration option - * @p STM32_PWM_USE_ADVANCED is set to TRUE and only for advanced - * timers TIM1 and TIM8. - */ -#define PWM_COMPLEMENTARY_OUTPUT_ACTIVE_LOW 0x20 - -/*===========================================================================*/ -/* Driver pre-compile time settings. */ -/*===========================================================================*/ - -/** - * @name Configuration options - * @{ - */ -/** - * @brief If advanced timer features switch. - * @details If set to @p TRUE the advanced features for TIM1 and TIM8 are - * enabled. - * @note The default is @p TRUE. - */ -#if !defined(STM32_PWM_USE_ADVANCED) || defined(__DOXYGEN__) -#define STM32_PWM_USE_ADVANCED FALSE -#endif - -/** - * @brief PWMD1 driver enable switch. - * @details If set to @p TRUE the support for PWMD1 is included. - * @note The default is @p TRUE. - */ -#if !defined(STM32_PWM_USE_TIM1) || defined(__DOXYGEN__) -#define STM32_PWM_USE_TIM1 FALSE -#endif - -/** - * @brief PWMD2 driver enable switch. - * @details If set to @p TRUE the support for PWMD2 is included. - * @note The default is @p TRUE. - */ -#if !defined(STM32_PWM_USE_TIM2) || defined(__DOXYGEN__) -#define STM32_PWM_USE_TIM2 FALSE -#endif - -/** - * @brief PWMD3 driver enable switch. - * @details If set to @p TRUE the support for PWMD3 is included. - * @note The default is @p TRUE. - */ -#if !defined(STM32_PWM_USE_TIM3) || defined(__DOXYGEN__) -#define STM32_PWM_USE_TIM3 FALSE -#endif - -/** - * @brief PWMD4 driver enable switch. - * @details If set to @p TRUE the support for PWMD4 is included. - * @note The default is @p TRUE. - */ -#if !defined(STM32_PWM_USE_TIM4) || defined(__DOXYGEN__) -#define STM32_PWM_USE_TIM4 FALSE -#endif - -/** - * @brief PWMD5 driver enable switch. - * @details If set to @p TRUE the support for PWMD5 is included. - * @note The default is @p TRUE. - */ -#if !defined(STM32_PWM_USE_TIM5) || defined(__DOXYGEN__) -#define STM32_PWM_USE_TIM5 FALSE -#endif - -/** - * @brief PWMD8 driver enable switch. - * @details If set to @p TRUE the support for PWMD8 is included. - * @note The default is @p TRUE. - */ -#if !defined(STM32_PWM_USE_TIM8) || defined(__DOXYGEN__) -#define STM32_PWM_USE_TIM8 FALSE -#endif - -/** - * @brief PWMD9 driver enable switch. - * @details If set to @p TRUE the support for PWMD9 is included. - * @note The default is @p TRUE. - */ -#if !defined(STM32_PWM_USE_TIM9) || defined(__DOXYGEN__) -#define STM32_PWM_USE_TIM9 FALSE -#endif - -/** - * @brief PWMD1 interrupt priority level setting. - */ -#if !defined(STM32_PWM_TIM1_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_PWM_TIM1_IRQ_PRIORITY 7 -#endif - -/** - * @brief PWMD2 interrupt priority level setting. - */ -#if !defined(STM32_PWM_TIM2_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_PWM_TIM2_IRQ_PRIORITY 7 -#endif - -/** - * @brief PWMD3 interrupt priority level setting. - */ -#if !defined(STM32_PWM_TIM3_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_PWM_TIM3_IRQ_PRIORITY 7 -#endif - -/** - * @brief PWMD4 interrupt priority level setting. - */ -#if !defined(STM32_PWM_TIM4_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_PWM_TIM4_IRQ_PRIORITY 7 -#endif - -/** - * @brief PWMD5 interrupt priority level setting. - */ -#if !defined(STM32_PWM_TIM5_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_PWM_TIM5_IRQ_PRIORITY 7 -#endif - -/** - * @brief PWMD8 interrupt priority level setting. - */ -#if !defined(STM32_PWM_TIM8_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_PWM_TIM8_IRQ_PRIORITY 7 -#endif -/** @} */ - -/** - * @brief PWMD9 interrupt priority level setting. - */ -#if !defined(STM32_PWM_TIM9_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_PWM_TIM9_IRQ_PRIORITY 7 -#endif -/** @} */ - -/*===========================================================================*/ -/* Configuration checks. */ -/*===========================================================================*/ - -#if STM32_PWM_USE_TIM1 && !STM32_HAS_TIM1 -#error "TIM1 not present in the selected device" -#endif - -#if STM32_PWM_USE_TIM2 && !STM32_HAS_TIM2 -#error "TIM2 not present in the selected device" -#endif - -#if STM32_PWM_USE_TIM3 && !STM32_HAS_TIM3 -#error "TIM3 not present in the selected device" -#endif - -#if STM32_PWM_USE_TIM4 && !STM32_HAS_TIM4 -#error "TIM4 not present in the selected device" -#endif - -#if STM32_PWM_USE_TIM5 && !STM32_HAS_TIM5 -#error "TIM5 not present in the selected device" -#endif - -#if STM32_PWM_USE_TIM8 && !STM32_HAS_TIM8 -#error "TIM8 not present in the selected device" -#endif - -#if STM32_PWM_USE_TIM9 && !STM32_HAS_TIM9 -#error "TIM9 not present in the selected device" -#endif - -#if !STM32_PWM_USE_TIM1 && !STM32_PWM_USE_TIM2 && \ - !STM32_PWM_USE_TIM3 && !STM32_PWM_USE_TIM4 && \ - !STM32_PWM_USE_TIM5 && !STM32_PWM_USE_TIM8 && \ - !STM32_PWM_USE_TIM9 -#error "PWM driver activated but no TIM peripheral assigned" -#endif - -#if STM32_PWM_USE_ADVANCED && !STM32_PWM_USE_TIM1 && !STM32_PWM_USE_TIM8 -#error "advanced mode selected but no advanced timer assigned" -#endif - -#if STM32_PWM_USE_TIM1 && \ - !CORTEX_IS_VALID_KERNEL_PRIORITY(STM32_PWM_TIM1_IRQ_PRIORITY) -#error "Invalid IRQ priority assigned to TIM1" -#endif - -#if STM32_PWM_USE_TIM2 && \ - !CORTEX_IS_VALID_KERNEL_PRIORITY(STM32_PWM_TIM2_IRQ_PRIORITY) -#error "Invalid IRQ priority assigned to TIM2" -#endif - -#if STM32_PWM_USE_TIM3 && \ - !CORTEX_IS_VALID_KERNEL_PRIORITY(STM32_PWM_TIM3_IRQ_PRIORITY) -#error "Invalid IRQ priority assigned to TIM3" -#endif - -#if STM32_PWM_USE_TIM4 && \ - !CORTEX_IS_VALID_KERNEL_PRIORITY(STM32_PWM_TIM4_IRQ_PRIORITY) -#error "Invalid IRQ priority assigned to TIM4" -#endif - -#if STM32_PWM_USE_TIM5 && \ - !CORTEX_IS_VALID_KERNEL_PRIORITY(STM32_PWM_TIM5_IRQ_PRIORITY) -#error "Invalid IRQ priority assigned to TIM5" -#endif - -#if STM32_PWM_USE_TIM8 && \ - !CORTEX_IS_VALID_KERNEL_PRIORITY(STM32_PWM_TIM8_IRQ_PRIORITY) -#error "Invalid IRQ priority assigned to TIM8" -#endif - -#if STM32_PWM_USE_TIM9 && \ - !CORTEX_IS_VALID_KERNEL_PRIORITY(STM32_PWM_TIM9_IRQ_PRIORITY) -#error "Invalid IRQ priority assigned to TIM9" -#endif - -/*===========================================================================*/ -/* Driver data structures and types. */ -/*===========================================================================*/ - -/** - * @brief PWM mode type. - */ -typedef uint32_t pwmmode_t; - -/** - * @brief PWM channel type. - */ -typedef uint8_t pwmchannel_t; - -/** - * @brief PWM counter type. - */ -typedef uint16_t pwmcnt_t; - -/** - * @brief PWM driver channel configuration structure. - */ -typedef struct { - /** - * @brief Channel active logic level. - */ - pwmmode_t mode; - /** - * @brief Channel callback pointer. - * @note This callback is invoked on the channel compare event. If set to - * @p NULL then the callback is disabled. - */ - pwmcallback_t callback; - /* End of the mandatory fields.*/ -} PWMChannelConfig; - -/** - * @brief PWM driver configuration structure. - */ -typedef struct { - /** - * @brief Timer clock in Hz. - * @note The low level can use assertions in order to catch invalid - * frequency specifications. - */ - uint32_t frequency; - /** - * @brief PWM period in ticks. - * @note The low level can use assertions in order to catch invalid - * period specifications. - */ - pwmcnt_t period; - /** - * @brief Periodic callback pointer. - * @note This callback is invoked on PWM counter reset. If set to - * @p NULL then the callback is disabled. - */ - pwmcallback_t callback; - /** - * @brief Channels configurations. - */ - PWMChannelConfig channels[PWM_CHANNELS]; - /* End of the mandatory fields.*/ - /** - * @brief TIM CR2 register initialization data. - * @note The value of this field should normally be equal to zero. - */ - uint32_t cr2; -#if STM32_PWM_USE_ADVANCED || defined(__DOXYGEN__) - /** - * @brief TIM BDTR (break & dead-time) register initialization data. - * @note The value of this field should normally be equal to zero. - */ \ - uint32_t bdtr; -#endif - /** - * @brief TIM DIER register initialization data. - * @note The value of this field should normally be equal to zero. - * @note Only the DMA-related bits can be specified in this field. - */ - uint32_t dier; -} PWMConfig; - -/** - * @brief Structure representing a PWM driver. - */ -struct PWMDriver { - /** - * @brief Driver state. - */ - pwmstate_t state; - /** - * @brief Current driver configuration data. - */ - const PWMConfig *config; - /** - * @brief Current PWM period in ticks. - */ - pwmcnt_t period; -#if defined(PWM_DRIVER_EXT_FIELDS) - PWM_DRIVER_EXT_FIELDS -#endif - /* End of the mandatory fields.*/ - /** - * @brief Timer base clock. - */ - uint32_t clock; - /** - * @brief Pointer to the TIMx registers block. - */ - stm32_tim_t *tim; -}; - -/*===========================================================================*/ -/* Driver macros. */ -/*===========================================================================*/ - -/** - * @brief Changes the period the PWM peripheral. - * @details This function changes the period of a PWM unit that has already - * been activated using @p pwmStart(). - * @pre The PWM unit must have been activated using @p pwmStart(). - * @post The PWM unit period is changed to the new value. - * @note The function has effect at the next cycle start. - * @note If a period is specified that is shorter than the pulse width - * programmed in one of the channels then the behavior is not - * guaranteed. - * - * @param[in] pwmp pointer to a @p PWMDriver object - * @param[in] period new cycle time in ticks - * - * @notapi - */ -#define pwm_lld_change_period(pwmp, period) \ - ((pwmp)->tim->ARR = (uint16_t)((period) - 1)) - -/** - * @brief Returns a PWM channel status. - * @pre The PWM unit must have been activated using @p pwmStart(). - * - * @param[in] pwmp pointer to a @p PWMDriver object - * @param[in] channel PWM channel identifier (0...PWM_CHANNELS-1) - * - * @notapi - */ -#define pwm_lld_is_channel_enabled(pwmp, channel) \ - (((pwmp)->tim->CCR[channel] != 0) || \ - (((pwmp)->tim->DIER & (2 << channel)) != 0)) - -/*===========================================================================*/ -/* External declarations. */ -/*===========================================================================*/ - -#if STM32_PWM_USE_TIM1 && !defined(__DOXYGEN__) -extern PWMDriver PWMD1; -#endif - -#if STM32_PWM_USE_TIM2 && !defined(__DOXYGEN__) -extern PWMDriver PWMD2; -#endif - -#if STM32_PWM_USE_TIM3 && !defined(__DOXYGEN__) -extern PWMDriver PWMD3; -#endif - -#if STM32_PWM_USE_TIM4 && !defined(__DOXYGEN__) -extern PWMDriver PWMD4; -#endif - -#if STM32_PWM_USE_TIM5 && !defined(__DOXYGEN__) -extern PWMDriver PWMD5; -#endif - -#if STM32_PWM_USE_TIM8 && !defined(__DOXYGEN__) -extern PWMDriver PWMD8; -#endif - -#if STM32_PWM_USE_TIM9 && !defined(__DOXYGEN__) -extern PWMDriver PWMD9; -#endif - -#ifdef __cplusplus -extern "C" { -#endif - void pwm_lld_init(void); - void pwm_lld_start(PWMDriver *pwmp); - void pwm_lld_stop(PWMDriver *pwmp); - void pwm_lld_enable_channel(PWMDriver *pwmp, - pwmchannel_t channel, - pwmcnt_t width); - void pwm_lld_disable_channel(PWMDriver *pwmp, pwmchannel_t channel); -#ifdef __cplusplus -} -#endif - -#endif /* HAL_USE_PWM */ - -#endif /* _PWM_LLD_H_ */ - -/** @} */ diff --git a/os/hal/platforms/STM32/TIMv1/st_lld.c b/os/hal/platforms/STM32/TIMv1/st_lld.c deleted file mode 100644 index 240328ff5..000000000 --- a/os/hal/platforms/STM32/TIMv1/st_lld.c +++ /dev/null @@ -1,161 +0,0 @@ -/* - ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file STM32/st_lld.c - * @brief ST Driver subsystem low level driver code. - * - * @addtogroup ST - * @{ - */ - -#include "hal.h" - -#if (OSAL_ST_MODE != OSAL_ST_MODE_NONE) || defined(__DOXYGEN__) - -/* The following checks and settings are unusually done here because the - file st.h needs to not have external dependencies. In this case there - would be a dependency on osal.h and mcuconf.h.*/ -#if (OSAL_ST_MODE == OSAL_ST_MODE_FREERUNNING) && !STM32_HAS_TIM2 -#error "TIM2 not present in the selected device" -#endif - -#if (OSAL_ST_MODE == OSAL_ST_MODE_FREERUNNING) && !STM32_TIM2_IS_32BITS -#error "TIM2 is not a 32 bits timer" -#endif - -/** - * @name Configuration options - * @{ - */ -/** - * @brief SysTick timer IRQ priority. - */ -#if !defined(STM32_ST_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_ST_IRQ_PRIORITY 8 -#endif -/** @} */ - -/*===========================================================================*/ -/* Driver local definitions. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver exported variables. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver local types. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver local variables and types. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver local functions. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver interrupt handlers. */ -/*===========================================================================*/ - -#if (OSAL_ST_MODE == OSAL_ST_MODE_PERIODIC) || defined(__DOXYGEN__) -/** - * @brief System Timer vector. - * @details This interrupt is used for system tick in periodic mode. - * - * @isr - */ -OSAL_IRQ_HANDLER(SysTick_Handler) { - - OSAL_IRQ_PROLOGUE(); - - osalSysLockFromISR(); - osalOsTimerHandlerI(); - osalSysUnlockFromISR(); - - OSAL_IRQ_EPILOGUE(); -} -#endif - -#if (OSAL_ST_MODE == OSAL_ST_MODE_FREERUNNING) || defined(__DOXYGEN__) -/** - * @brief TIM2 interrupt handler. - * @details This interrupt is used for system tick in free running mode. - * - * @isr - */ -OSAL_IRQ_HANDLER(STM32_TIM2_HANDLER) { - - OSAL_IRQ_PROLOGUE(); - - STM32_TIM2->SR = 0; - - osalSysLockFromISR(); - osalOsTimerHandlerI(); - osalSysUnlockFromISR(); - - OSAL_IRQ_EPILOGUE(); -} -#endif - -/*===========================================================================*/ -/* Driver exported functions. */ -/*===========================================================================*/ - -/** - * @brief Low level ST driver initialization. - * - * @notapi - */ -void st_lld_init(void) { - -#if OSAL_ST_MODE == OSAL_ST_MODE_FREERUNNING - /* Free running counter mode.*/ - rccEnableTIM2(FALSE); - - /* Initializing the counter in free running mode.*/ - STM32_TIM2->PSC = STM32_TIMCLK1 / OSAL_SYSTICK_FREQUENCY - 1; - STM32_TIM2->ARR = 0xFFFFFFFF; - STM32_TIM2->CCMR1 = 0; - STM32_TIM2->CCR[0] = 0; - STM32_TIM2->DIER = 0; - STM32_TIM2->CR2 = 0; - STM32_TIM2->EGR = TIM_EGR_UG; - STM32_TIM2->CR1 = TIM_CR1_CEN; - - /* IRQ enabled.*/ - nvicEnableVector(STM32_TIM2_NUMBER, STM32_ST_IRQ_PRIORITY); -#endif - -#if OSAL_ST_MODE == OSAL_ST_MODE_PERIODIC - /* Periodic systick mode, the Cortex-Mx internal systick timer is used - in this mode.*/ - SysTick->LOAD = STM32_HCLK / OSAL_SYSTICK_FREQUENCY - 1; - SysTick->VAL = 0; - SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk | - SysTick_CTRL_ENABLE_Msk | - SysTick_CTRL_TICKINT_Msk; - - /* IRQ enabled.*/ - nvicSetSystemHandlerPriority(SysTick_IRQn, STM32_ST_IRQ_PRIORITY); -#endif -} - -#endif /* OSAL_ST_MODE != OSAL_ST_MODE_NONE */ - -/** @} */ diff --git a/os/hal/platforms/STM32/TIMv1/st_lld.h b/os/hal/platforms/STM32/TIMv1/st_lld.h deleted file mode 100644 index fb067f202..000000000 --- a/os/hal/platforms/STM32/TIMv1/st_lld.h +++ /dev/null @@ -1,147 +0,0 @@ -/* - ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file STM32/st_lld.h - * @brief ST Driver subsystem low level driver header. - * @details This header is designed to be include-able without having to - * include other files from the HAL. - * - * @addtogroup ST - * @{ - */ - -#ifndef _ST_LLD_H_ -#define _ST_LLD_H_ - -#include "stm32_registry.h" -#include "stm32_tim.h" - -/*===========================================================================*/ -/* Driver constants. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver pre-compile time settings. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Derived constants and error checks. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver data structures and types. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver macros. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* External declarations. */ -/*===========================================================================*/ - -#ifdef __cplusplus -extern "C" { -#endif - void st_lld_init(void); -#ifdef __cplusplus -} -#endif - -/*===========================================================================*/ -/* Driver inline functions. */ -/*===========================================================================*/ - -/** - * @brief Returns the time counter value. - * - * @return The counter value. - * - * @notapi - */ -static inline systime_t st_lld_get_counter(void) { - - return (systime_t)(STM32_TIM2->CNT); -} - -/** - * @brief Starts the alarm. - * @note Makes sure that no spurious alarms are triggered after - * this call. - * - * @param[in] time the time to be set for the first alarm - * - * @notapi - */ -static inline void st_lld_start_alarm(systime_t time) { - - STM32_TIM2->CCR[0] = time; - STM32_TIM2->SR = 0; - STM32_TIM2->DIER = STM32_TIM_DIER_CC1IE; -} - -/** - * @brief Stops the alarm interrupt. - * - * @notapi - */ -static inline void st_lld_stop_alarm(void) { - - STM32_TIM2->DIER = 0; -} - -/** - * @brief Sets the alarm time. - * - * @param[in] time the time to be set for the next alarm - * - * @notapi - */ -static inline void st_lld_set_alarm(systime_t time) { - - STM32_TIM2->CCR[0] = (uint32_t)time; -} - -/** - * @brief Returns the current alarm time. - * - * @return The currently set alarm time. - * - * @notapi - */ -static inline systime_t st_lld_get_alarm(void) { - - return (systime_t)STM32_TIM2->CCR[0]; -} - -/** - * @brief Determines if the alarm is active. - * - * @return The alarm status. - * @retval false if the alarm is not active. - * @retval true is the alarm is active - * - * @notapi - */ -static inline bool st_lld_is_alarm_active(void) { - - return (bool)((STM32_TIM2->DIER & STM32_TIM_DIER_CC1IE) != 0); -} - -#endif /* _ST_LLD_H_ */ - -/** @} */ diff --git a/os/hal/platforms/STM32/TIMv1/stm32_tim.h b/os/hal/platforms/STM32/TIMv1/stm32_tim.h deleted file mode 100644 index ce0274c33..000000000 --- a/os/hal/platforms/STM32/TIMv1/stm32_tim.h +++ /dev/null @@ -1,448 +0,0 @@ -/* - ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file stm32_tim.h - * @brief STM32 TIM registers layout header. - * @note This file requires definitions from the ST STM32 header file. - * - * @addtogroup STM32_TIMv1 - * @{ - */ - -#ifndef _STM32_TIM_H_ -#define _STM32_TIM_H_ - -/*===========================================================================*/ -/* Driver constants. */ -/*===========================================================================*/ - -/** - * @name TIM_CR1 register - * @{ - */ -#define STM32_TIM_CR1_CEN (1U << 0) -#define STM32_TIM_CR1_UDIS (1U << 1) -#define STM32_TIM_CR1_URS (1U << 2) -#define STM32_TIM_CR1_OPM (1U << 3) -#define STM32_TIM_CR1_DIR (1U << 4) - -#define STM32_TIM_CR1_CMS_MASK (3U << 5) -#define STM32_TIM_CR1_CMS(n) ((n) << 5) - -#define STM32_TIM_CR1_ARPE (1U << 7) - -#define STM32_TIM_CR1_CKD_MASK (3U << 8) -#define STM32_TIM_CR1_CKD(n) ((n) << 8) - -#define STM32_TIM_CR1_UIFREMAP (1U << 11) -/** @} */ - -/** - * @name TIM_CR2 register - * @{ - */ -#define STM32_TIM_CR2_CCPC (1U << 0) -#define STM32_TIM_CR2_CCUS (1U << 2) -#define STM32_TIM_CR2_CCDS (1U << 3) - -#define STM32_TIM_CR2_MMS_MASK (7U << 4) -#define STM32_TIM_CR2_MMS(n) ((n) << 4) - -#define STM32_TIM_CR2_TI1S (1U << 7) -#define STM32_TIM_CR2_OIS1 (1U << 8) -#define STM32_TIM_CR2_OIS1N (1U << 9) -#define STM32_TIM_CR2_OIS2 (1U << 10) -#define STM32_TIM_CR2_OIS2N (1U << 11) -#define STM32_TIM_CR2_OIS3 (1U << 12) -#define STM32_TIM_CR2_OIS3N (1U << 13) -#define STM32_TIM_CR2_OIS4 (1U << 14) -#define STM32_TIM_CR2_OIS5 (1U << 16) -#define STM32_TIM_CR2_OIS6 (1U << 18) - -#define STM32_TIM_CR2_MMS2_MASK (15U << 20) -#define STM32_TIM_CR2_MMS2(n) ((n) << 20) -/** @} */ - -/** - * @name TIM_SMCR register - * @{ - */ -#define STM32_TIM_SMCR_SMS_MASK ((7U << 0) | (1U << 16)) -#define STM32_TIM_SMCR_SMS(n) ((((n) & 7) << 0) | \ - (((n) >> 3) << 16)) - -#define STM32_TIM_SMCR_OCCS (1U << 3) - -#define STM32_TIM_SMCR_TS_MASK (7U << 4) -#define STM32_TIM_SMCR_TS(n) ((n) << 4) - -#define STM32_TIM_SMCR_MSM (1U << 7) - -#define STM32_TIM_SMCR_ETF_MASK (15U << 8) -#define STM32_TIM_SMCR_ETF(n) ((n) << 8) - -#define STM32_TIM_SMCR_ETPS_MASK (3U << 12) -#define STM32_TIM_SMCR_ETPS(n) ((n) << 12) - -#define STM32_TIM_SMCR_ECE (1U << 14) -#define STM32_TIM_SMCR_ETP (1U << 15) -/** @} */ - -/** - * @name TIM_DIER register - * @{ - */ -#define STM32_TIM_DIER_UIE (1U << 0) -#define STM32_TIM_DIER_CC1IE (1U << 1) -#define STM32_TIM_DIER_CC2IE (1U << 2) -#define STM32_TIM_DIER_CC3IE (1U << 3) -#define STM32_TIM_DIER_CC4IE (1U << 4) -#define STM32_TIM_DIER_COMIE (1U << 5) -#define STM32_TIM_DIER_TIE (1U << 6) -#define STM32_TIM_DIER_BIE (1U << 7) -#define STM32_TIM_DIER_UDE (1U << 8) -#define STM32_TIM_DIER_CC1DE (1U << 9) -#define STM32_TIM_DIER_CC2DE (1U << 10) -#define STM32_TIM_DIER_CC3DE (1U << 11) -#define STM32_TIM_DIER_CC4DE (1U << 12) -#define STM32_TIM_DIER_COMDE (1U << 13) -#define STM32_TIM_DIER_TDE (1U << 14) - -#define STM32_TIM_DIER_IRQ_MASK (STM32_TIM_DIER_UIE | \ - STM32_TIM_DIER_CC1IE | \ - STM32_TIM_DIER_CC2IE | \ - STM32_TIM_DIER_CC3IE | \ - STM32_TIM_DIER_CC4IE | \ - STM32_TIM_DIER_COMIE | \ - STM32_TIM_DIER_TIE | \ - STM32_TIM_DIER_BIE) - -/** @} */ - -/** - * @name TIM_SR register - * @{ - */ -#define STM32_TIM_SR_UIF (1U << 0) -#define STM32_TIM_SR_CC1IF (1U << 1) -#define STM32_TIM_SR_CC2IF (1U << 2) -#define STM32_TIM_SR_CC3IF (1U << 3) -#define STM32_TIM_SR_CC4IF (1U << 4) -#define STM32_TIM_SR_COMIF (1U << 5) -#define STM32_TIM_SR_TIF (1U << 6) -#define STM32_TIM_SR_BIF (1U << 7) -#define STM32_TIM_SR_B2IF (1U << 8) -#define STM32_TIM_SR_CC1OF (1U << 9) -#define STM32_TIM_SR_CC2OF (1U << 10) -#define STM32_TIM_SR_CC3OF (1U << 11) -#define STM32_TIM_SR_CC4OF (1U << 12) -#define STM32_TIM_SR_CC5IF (1U << 16) -#define STM32_TIM_SR_CC6IF (1U << 17) -/** @} */ - -/** - * @name TIM_EGR register - * @{ - */ -#define STM32_TIM_EGR_UG (1U << 0) -#define STM32_TIM_EGR_CC1G (1U << 1) -#define STM32_TIM_EGR_CC2G (1U << 2) -#define STM32_TIM_EGR_CC3G (1U << 3) -#define STM32_TIM_EGR_CC4G (1U << 4) -#define STM32_TIM_EGR_COMG (1U << 5) -#define STM32_TIM_EGR_TG (1U << 6) -#define STM32_TIM_EGR_BG (1U << 7) -#define STM32_TIM_EGR_B2G (1U << 8) -/** @} */ - -/** - * @name TIM_CCMR1 register (output) - * @{ - */ -#define STM32_TIM_CCMR1_CC1S_MASK (3U << 0) -#define STM32_TIM_CCMR1_CC1S(n) ((n) << 0) - -#define STM32_TIM_CCMR1_OC1FE (1U << 2) -#define STM32_TIM_CCMR1_OC1PE (1U << 3) - -#define STM32_TIM_CCMR1_OC1M_MASK ((7U << 4) | (1U << 16)) -#define STM32_TIM_CCMR1_OC1M(n) ((((n) & 7) << 4) | \ - (((n) >> 2) << 16)) - -#define STM32_TIM_CCMR1_OC1CE (1U << 7) - -#define STM32_TIM_CCMR1_CC2S_MASK (3U << 8) -#define STM32_TIM_CCMR1_CC2S(n) ((n) << 8) - -#define STM32_TIM_CCMR1_OC2FE (1U << 10) -#define STM32_TIM_CCMR1_OC2PE (1U << 11) - -#define STM32_TIM_CCMR1_OC2M_MASK ((7U << 12) | (1U << 24)) -#define STM32_TIM_CCMR1_OC2M(n) ((((n) & 7) << 12) | \ - (((n) >> 2) << 24)) - -#define STM32_TIM_CCMR1_OC2CE (1U << 15) -/** @} */ - -/** - * @name CCMR1 register (input) - * @{ - */ -#define STM32_TIM_CCMR1_IC1PSC_MASK (3U << 2) -#define STM32_TIM_CCMR1_IC1PSC(n) ((n) << 2) - -#define STM32_TIM_CCMR1_IC1F_MASK (15U << 4) -#define STM32_TIM_CCMR1_IC1F(n) ((n) << 4) - -#define STM32_TIM_CCMR1_IC2PSC_MASK (3U << 10) -#define STM32_TIM_CCMR1_IC2PSC(n) ((n) << 10) - -#define STM32_TIM_CCMR1_IC2F_MASK (15U << 12) -#define STM32_TIM_CCMR1_IC2F(n) ((n) << 12) -/** @} */ - -/** - * @name TIM_CCMR2 register (output) - * @{ - */ -#define STM32_TIM_CCMR2_CC3S_MASK (3U << 0) -#define STM32_TIM_CCMR2_CC3S(n) ((n) << 0) - -#define STM32_TIM_CCMR2_OC3FE (1U << 2) -#define STM32_TIM_CCMR2_OC3PE (1U << 3) - -#define STM32_TIM_CCMR2_OC3M_MASK ((7U << 4) | (1U << 16)) -#define STM32_TIM_CCMR2_OC3M(n) ((((n) & 7) << 4) | \ - (((n) >> 2) << 16)) - -#define STM32_TIM_CCMR2_OC3CE (1U << 7) - -#define STM32_TIM_CCMR2_CC4S_MASK (3U << 8) -#define STM32_TIM_CCMR2_CC4S(n) ((n) << 8) - -#define STM32_TIM_CCMR2_OC4FE (1U << 10) -#define STM32_TIM_CCMR2_OC4PE (1U << 11) - -#define STM32_TIM_CCMR2_OC4M_MASK ((7U << 12) | (1U << 24)) -#define STM32_TIM_CCMR2_OC4M(n) ((((n) & 7) << 12) | \ - (((n) >> 2) << 24)) - -#define STM32_TIM_CCMR2_OC4CE (1U << 15) -/** @} */ - -/** - * @name TIM_CCMR2 register (input) - * @{ - */ -#define STM32_TIM_CCMR2_IC3PSC_MASK (3U << 2) -#define STM32_TIM_CCMR2_IC3PSC(n) ((n) << 2) - -#define STM32_TIM_CCMR2_IC3F_MASK (15U << 4) -#define STM32_TIM_CCMR2_IC3F(n) ((n) << 4) - -#define STM32_TIM_CCMR2_IC4PSC_MASK (3U << 10) -#define STM32_TIM_CCMR2_IC4PSC(n) ((n) << 10) - -#define STM32_TIM_CCMR2_IC4F_MASK (15U << 12) -#define STM32_TIM_CCMR2_IC4F(n) ((n) << 12) -/** @} */ - -/** - * @name TIM_CCER register - * @{ - */ -#define STM32_TIM_CCER_CC1E (1U << 0) -#define STM32_TIM_CCER_CC1P (1U << 1) -#define STM32_TIM_CCER_CC1NE (1U << 2) -#define STM32_TIM_CCER_CC1NP (1U << 3) -#define STM32_TIM_CCER_CC2E (1U << 4) -#define STM32_TIM_CCER_CC2P (1U << 5) -#define STM32_TIM_CCER_CC2NE (1U << 6) -#define STM32_TIM_CCER_CC2NP (1U << 7) -#define STM32_TIM_CCER_CC3E (1U << 8) -#define STM32_TIM_CCER_CC3P (1U << 9) -#define STM32_TIM_CCER_CC3NE (1U << 10) -#define STM32_TIM_CCER_CC3NP (1U << 11) -#define STM32_TIM_CCER_CC4E (1U << 12) -#define STM32_TIM_CCER_CC4P (1U << 13) -#define STM32_TIM_CCER_CC4NP (1U << 15) -#define STM32_TIM_CCER_CC5E (1U << 16) -#define STM32_TIM_CCER_CC5P (1U << 17) -#define STM32_TIM_CCER_CC6E (1U << 20) -#define STM32_TIM_CCER_CC6P (1U << 21) -/** @} */ - -/** - * @name TIM_CNT register - * @{ - */ -#define STM32_TIM_CNT_UIFCPY (1U << 31) -/** @} */ - -/** - * @name TIM_BDTR register - * @{ - */ -#define STM32_TIM_BDTR_DTG_MASK (255U << 0) -#define STM32_TIM_BDTR_DTG(n) ((n) << 0) - -#define STM32_TIM_BDTR_LOCK_MASK (3U << 8) -#define STM32_TIM_BDTR_LOCK(n) ((n) << 8) - -#define STM32_TIM_BDTR_OSSI (1U << 10) -#define STM32_TIM_BDTR_OSSR (1U << 11) -#define STM32_TIM_BDTR_BKE (1U << 12) -#define STM32_TIM_BDTR_BKP (1U << 13) -#define STM32_TIM_BDTR_AOE (1U << 14) -#define STM32_TIM_BDTR_MOE (1U << 15) - -#define STM32_TIM_BDTR_BKF_MASK (15U << 16) -#define STM32_TIM_BDTR_BKF(n) ((n) << 16) -#define STM32_TIM_BDTR_BK2F_MASK (15U << 20) -#define STM32_TIM_BDTR_BK2F(n) ((n) << 20) - -#define STM32_TIM_BDTR_BK2E (1U << 24) -#define STM32_TIM_BDTR_BK2P (1U << 25) -/** @} */ - -/** - * @name TIM_DCR register - * @{ - */ -#define STM32_TIM_DCR_DBA_MASK (31U << 0) -#define STM32_TIM_DCR_DBA(n) ((n) << 0) - -#define STM32_TIM_DCR_DBL_MASK (31U << 8) -#define STM32_TIM_DCR_DBL(b) ((n) << 8) -/** @} */ - -/** - * @name TIM16_OR register - * @{ - */ -#define STM32_TIM16_OR_TI1_RMP_MASK (3U << 6) -#define STM32_TIM16_OR_TI1_RMP(n) ((n) << 6) -/** @} */ - -/** - * @name TIM_OR register - * @{ - */ -#define STM32_TIM_OR_ETR_RMP_MASK (15U << 0) -#define STM32_TIM_OR_ETR_RMP(n) ((n) << 0) -/** @} */ - -/** - * @name TIM_CCMR3 register - * @{ - */ -#define STM32_TIM_CCMR3_OC5FE (1U << 2) -#define STM32_TIM_CCMR3_OC5PE (1U << 3) - -#define STM32_TIM_CCMR3_OC5M_MASK ((7U << 4) | (1U << 16)) -#define STM32_TIM_CCMR3_OC5M(n) ((((n) & 7) << 4) | \ - (((n) >> 2) << 16)) - -#define STM32_TIM_CCMR3_OC5CE (1U << 7) - -#define STM32_TIM_CCMR3_OC6FE (1U << 10) -#define STM32_TIM_CCMR3_OC6PE (1U << 11) - -#define STM32_TIM_CCMR3_OC6M_MASK ((7U << 12) | (1U << 24)) -#define STM32_TIM_CCMR3_OC6M(n) ((((n) & 7) << 12) | \ - (((n) >> 2) << 24)) - -#define STM32_TIM_CCMR3_OC6CE (1U << 15) -/** @} */ - -/** - * @name TIM units references - * @{ - */ -#define STM32_TIM1 ((stm32_tim_t *)TIM1_BASE) -#define STM32_TIM2 ((stm32_tim_t *)TIM2_BASE) -#define STM32_TIM3 ((stm32_tim_t *)TIM3_BASE) -#define STM32_TIM4 ((stm32_tim_t *)TIM4_BASE) -#define STM32_TIM5 ((stm32_tim_t *)TIM5_BASE) -#define STM32_TIM6 ((stm32_tim_t *)TIM6_BASE) -#define STM32_TIM7 ((stm32_tim_t *)TIM7_BASE) -#define STM32_TIM8 ((stm32_tim_t *)TIM8_BASE) -#define STM32_TIM9 ((stm32_tim_t *)TIM9_BASE) -#define STM32_TIM10 ((stm32_tim_t *)TIM10_BASE) -#define STM32_TIM11 ((stm32_tim_t *)TIM11_BASE) -#define STM32_TIM12 ((stm32_tim_t *)TIM12_BASE) -#define STM32_TIM13 ((stm32_tim_t *)TIM13_BASE) -#define STM32_TIM14 ((stm32_tim_t *)TIM14_BASE) -#define STM32_TIM15 ((stm32_tim_t *)TIM15_BASE) -#define STM32_TIM16 ((stm32_tim_t *)TIM16_BASE) -#define STM32_TIM17 ((stm32_tim_t *)TIM17_BASE) -#define STM32_TIM18 ((stm32_tim_t *)TIM18_BASE) -#define STM32_TIM19 ((stm32_tim_t *)TIM19_BASE) -/** @} */ - -/*===========================================================================*/ -/* Driver pre-compile time settings. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Derived constants and error checks. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver data structures and types. */ -/*===========================================================================*/ - -/** - * @brief STM32 TIM registers block. - * @note This is the most general known form, not all timers have - * necessarily all registers and bits. - */ -typedef struct { - volatile uint32_t CR1; - volatile uint32_t CR2; - volatile uint32_t SMCR; - volatile uint32_t DIER; - volatile uint32_t SR; - volatile uint32_t EGR; - volatile uint32_t CCMR1; - volatile uint32_t CCMR2; - volatile uint32_t CCER; - volatile uint32_t CNT; - volatile uint32_t PSC; - volatile uint32_t ARR; - volatile uint32_t RCR; - volatile uint32_t CCR[4]; - volatile uint32_t BDTR; - volatile uint32_t DCR; - volatile uint32_t DMAR; - volatile uint32_t OR; - volatile uint32_t CCMR3; - volatile uint32_t CCR5; - volatile uint32_t CCR6; -} stm32_tim_t; - -/*===========================================================================*/ -/* Driver macros. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* External declarations. */ -/*===========================================================================*/ - -#endif /* _STM32_TIM_H_ */ - -/** @} */ diff --git a/os/hal/platforms/STM32/USARTv1/serial_lld.c b/os/hal/platforms/STM32/USARTv1/serial_lld.c deleted file mode 100644 index ae6042a8d..000000000 --- a/os/hal/platforms/STM32/USARTv1/serial_lld.c +++ /dev/null @@ -1,524 +0,0 @@ -/* - ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file STM32/USARTv1/serial_lld.c - * @brief STM32 low level serial driver code. - * - * @addtogroup SERIAL - * @{ - */ - -#include "hal.h" - -#if HAL_USE_SERIAL || defined(__DOXYGEN__) - -/*===========================================================================*/ -/* Driver local definitions. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver exported variables. */ -/*===========================================================================*/ - -/** @brief USART1 serial driver identifier.*/ -#if STM32_SERIAL_USE_USART1 || defined(__DOXYGEN__) -SerialDriver SD1; -#endif - -/** @brief USART2 serial driver identifier.*/ -#if STM32_SERIAL_USE_USART2 || defined(__DOXYGEN__) -SerialDriver SD2; -#endif - -/** @brief USART3 serial driver identifier.*/ -#if STM32_SERIAL_USE_USART3 || defined(__DOXYGEN__) -SerialDriver SD3; -#endif - -/** @brief UART4 serial driver identifier.*/ -#if STM32_SERIAL_USE_UART4 || defined(__DOXYGEN__) -SerialDriver SD4; -#endif - -/** @brief UART5 serial driver identifier.*/ -#if STM32_SERIAL_USE_UART5 || defined(__DOXYGEN__) -SerialDriver SD5; -#endif - -/** @brief USART6 serial driver identifier.*/ -#if STM32_SERIAL_USE_USART6 || defined(__DOXYGEN__) -SerialDriver SD6; -#endif - -/*===========================================================================*/ -/* Driver local variables and types. */ -/*===========================================================================*/ - -/** @brief Driver default configuration.*/ -static const SerialConfig default_config = -{ - SERIAL_DEFAULT_BITRATE, - 0, - USART_CR2_STOP1_BITS | USART_CR2_LINEN, - 0 -}; - -/*===========================================================================*/ -/* Driver local functions. */ -/*===========================================================================*/ - -/** - * @brief USART initialization. - * @details This function must be invoked with interrupts disabled. - * - * @param[in] sdp pointer to a @p SerialDriver object - * @param[in] config the architecture-dependent serial driver configuration - */ -static void usart_init(SerialDriver *sdp, const SerialConfig *config) { - USART_TypeDef *u = sdp->usart; - - /* Baud rate setting.*/ -#if STM32_HAS_USART6 - if ((sdp->usart == USART1) || (sdp->usart == USART6)) -#else - if (sdp->usart == USART1) -#endif - u->BRR = STM32_PCLK2 / config->speed; - else - u->BRR = STM32_PCLK1 / config->speed; - - /* Note that some bits are enforced.*/ - u->CR2 = config->cr2 | USART_CR2_LBDIE; - u->CR3 = config->cr3 | USART_CR3_EIE; - u->CR1 = config->cr1 | USART_CR1_UE | USART_CR1_PEIE | - USART_CR1_RXNEIE | USART_CR1_TE | - USART_CR1_RE; - u->SR = 0; - (void)u->SR; /* SR reset step 1.*/ - (void)u->DR; /* SR reset step 2.*/ -} - -/** - * @brief USART de-initialization. - * @details This function must be invoked with interrupts disabled. - * - * @param[in] u pointer to an USART I/O block - */ -static void usart_deinit(USART_TypeDef *u) { - - u->CR1 = 0; - u->CR2 = 0; - u->CR3 = 0; -} - -/** - * @brief Error handling routine. - * - * @param[in] sdp pointer to a @p SerialDriver object - * @param[in] sr USART SR register value - */ -static void set_error(SerialDriver *sdp, uint16_t sr) { - eventflags_t sts = 0; - - if (sr & USART_SR_ORE) - sts |= SD_OVERRUN_ERROR; - if (sr & USART_SR_PE) - sts |= SD_PARITY_ERROR; - if (sr & USART_SR_FE) - sts |= SD_FRAMING_ERROR; - if (sr & USART_SR_NE) - sts |= SD_NOISE_ERROR; - osalSysLockFromISR(); - chnAddFlagsI(sdp, sts); - osalSysUnlockFromISR(); -} - -/** - * @brief Common IRQ handler. - * - * @param[in] sdp communication channel associated to the USART - */ -static void serve_interrupt(SerialDriver *sdp) { - USART_TypeDef *u = sdp->usart; - uint16_t cr1 = u->CR1; - uint16_t sr = u->SR; /* SR reset step 1.*/ - uint16_t dr = u->DR; /* SR reset step 2.*/ - - /* Error condition detection.*/ - if (sr & (USART_SR_ORE | USART_SR_NE | USART_SR_FE | USART_SR_PE)) - set_error(sdp, sr); - /* Special case, LIN break detection.*/ - if (sr & USART_SR_LBD) { - osalSysLockFromISR(); - chnAddFlagsI(sdp, SD_BREAK_DETECTED); - osalSysUnlockFromISR(); - u->SR &= ~USART_SR_LBD; - } - /* Data available.*/ - if (sr & USART_SR_RXNE) { - osalSysLockFromISR(); - sdIncomingDataI(sdp, (uint8_t)dr); - osalSysUnlockFromISR(); - } - /* Transmission buffer empty.*/ - if ((cr1 & USART_CR1_TXEIE) && (sr & USART_SR_TXE)) { - msg_t b; - osalSysLockFromISR(); - b = oqGetI(&sdp->oqueue); - if (b < Q_OK) { - chnAddFlagsI(sdp, CHN_OUTPUT_EMPTY); - u->CR1 = (cr1 & ~USART_CR1_TXEIE) | USART_CR1_TCIE; - } - else - u->DR = b; - osalSysUnlockFromISR(); - } - /* Physical transmission end.*/ - if (sr & USART_SR_TC) { - osalSysLockFromISR(); - chnAddFlagsI(sdp, CHN_TRANSMISSION_END); - osalSysUnlockFromISR(); - u->CR1 = cr1 & ~USART_CR1_TCIE; - u->SR &= ~USART_SR_TC; - } -} - -#if STM32_SERIAL_USE_USART1 || defined(__DOXYGEN__) -static void notify1(io_queue_t *qp) { - - (void)qp; - USART1->CR1 |= USART_CR1_TXEIE; -} -#endif - -#if STM32_SERIAL_USE_USART2 || defined(__DOXYGEN__) -static void notify2(io_queue_t *qp) { - - (void)qp; - USART2->CR1 |= USART_CR1_TXEIE; -} -#endif - -#if STM32_SERIAL_USE_USART3 || defined(__DOXYGEN__) -static void notify3(io_queue_t *qp) { - - (void)qp; - USART3->CR1 |= USART_CR1_TXEIE; -} -#endif - -#if STM32_SERIAL_USE_UART4 || defined(__DOXYGEN__) -static void notify4(io_queue_t *qp) { - - (void)qp; - UART4->CR1 |= USART_CR1_TXEIE; -} -#endif - -#if STM32_SERIAL_USE_UART5 || defined(__DOXYGEN__) -static void notify5(io_queue_t *qp) { - - (void)qp; - UART5->CR1 |= USART_CR1_TXEIE; -} -#endif - -#if STM32_SERIAL_USE_USART6 || defined(__DOXYGEN__) -static void notify6(io_queue_t *qp) { - - (void)qp; - USART6->CR1 |= USART_CR1_TXEIE; -} -#endif - -/*===========================================================================*/ -/* Driver interrupt handlers. */ -/*===========================================================================*/ - -#if STM32_SERIAL_USE_USART1 || defined(__DOXYGEN__) -#if !defined(STM32_USART1_HANDLER) -#error "STM32_USART1_HANDLER not defined" -#endif -/** - * @brief USART1 interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(STM32_USART1_HANDLER) { - - OSAL_IRQ_PROLOGUE(); - - serve_interrupt(&SD1); - - OSAL_IRQ_EPILOGUE(); -} -#endif - -#if STM32_SERIAL_USE_USART2 || defined(__DOXYGEN__) -#if !defined(STM32_USART2_HANDLER) -#error "STM32_USART2_HANDLER not defined" -#endif -/** - * @brief USART2 interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(STM32_USART2_HANDLER) { - - OSAL_IRQ_PROLOGUE(); - - serve_interrupt(&SD2); - - OSAL_IRQ_EPILOGUE(); -} -#endif - -#if STM32_SERIAL_USE_USART3 || defined(__DOXYGEN__) -#if !defined(STM32_USART3_HANDLER) -#error "STM32_USART3_HANDLER not defined" -#endif -/** - * @brief USART3 interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(STM32_USART3_HANDLER) { - - OSAL_IRQ_PROLOGUE(); - - serve_interrupt(&SD3); - - OSAL_IRQ_EPILOGUE(); -} -#endif - -#if STM32_SERIAL_USE_UART4 || defined(__DOXYGEN__) -#if !defined(STM32_UART4_HANDLER) -#error "STM32_UART4_HANDLER not defined" -#endif -/** - * @brief UART4 interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(STM32_UART4_HANDLER) { - - OSAL_IRQ_PROLOGUE(); - - serve_interrupt(&SD4); - - OSAL_IRQ_EPILOGUE(); -} -#endif - -#if STM32_SERIAL_USE_UART5 || defined(__DOXYGEN__) -#if !defined(STM32_UART5_HANDLER) -#error "STM32_UART5_HANDLER not defined" -#endif -/** - * @brief UART5 interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(STM32_UART5_HANDLER) { - - OSAL_IRQ_PROLOGUE(); - - serve_interrupt(&SD5); - - OSAL_IRQ_EPILOGUE(); -} -#endif - -#if STM32_SERIAL_USE_USART6 || defined(__DOXYGEN__) -#if !defined(STM32_USART6_HANDLER) -#error "STM32_USART6_HANDLER not defined" -#endif -/** - * @brief USART1 interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(STM32_USART6_HANDLER) { - - OSAL_IRQ_PROLOGUE(); - - serve_interrupt(&SD6); - - OSAL_IRQ_EPILOGUE(); -} -#endif - -/*===========================================================================*/ -/* Driver exported functions. */ -/*===========================================================================*/ - -/** - * @brief Low level serial driver initialization. - * - * @notapi - */ -void sd_lld_init(void) { - -#if STM32_SERIAL_USE_USART1 - sdObjectInit(&SD1, NULL, notify1); - SD1.usart = USART1; -#endif - -#if STM32_SERIAL_USE_USART2 - sdObjectInit(&SD2, NULL, notify2); - SD2.usart = USART2; -#endif - -#if STM32_SERIAL_USE_USART3 - sdObjectInit(&SD3, NULL, notify3); - SD3.usart = USART3; -#endif - -#if STM32_SERIAL_USE_UART4 - sdObjectInit(&SD4, NULL, notify4); - SD4.usart = UART4; -#endif - -#if STM32_SERIAL_USE_UART5 - sdObjectInit(&SD5, NULL, notify5); - SD5.usart = UART5; -#endif - -#if STM32_SERIAL_USE_USART6 - sdObjectInit(&SD6, NULL, notify6); - SD6.usart = USART6; -#endif -} - -/** - * @brief Low level serial driver configuration and (re)start. - * - * @param[in] sdp pointer to a @p SerialDriver object - * @param[in] config the architecture-dependent serial driver configuration. - * If this parameter is set to @p NULL then a default - * configuration is used. - * - * @notapi - */ -void sd_lld_start(SerialDriver *sdp, const SerialConfig *config) { - - if (config == NULL) - config = &default_config; - - if (sdp->state == SD_STOP) { -#if STM32_SERIAL_USE_USART1 - if (&SD1 == sdp) { - rccEnableUSART1(FALSE); - nvicEnableVector(STM32_USART1_NUMBER, STM32_SERIAL_USART1_PRIORITY); - } -#endif -#if STM32_SERIAL_USE_USART2 - if (&SD2 == sdp) { - rccEnableUSART2(FALSE); - nvicEnableVector(STM32_USART2_NUMBER, STM32_SERIAL_USART2_PRIORITY); - } -#endif -#if STM32_SERIAL_USE_USART3 - if (&SD3 == sdp) { - rccEnableUSART3(FALSE); - nvicEnableVector(STM32_USART3_NUMBER, STM32_SERIAL_USART3_PRIORITY); - } -#endif -#if STM32_SERIAL_USE_UART4 - if (&SD4 == sdp) { - rccEnableUART4(FALSE); - nvicEnableVector(STM32_UART4_NUMBER, STM32_SERIAL_UART4_PRIORITY); - } -#endif -#if STM32_SERIAL_USE_UART5 - if (&SD5 == sdp) { - rccEnableUART5(FALSE); - nvicEnableVector(STM32_UART5_NUMBER, STM32_SERIAL_UART5_PRIORITY); - } -#endif -#if STM32_SERIAL_USE_USART6 - if (&SD6 == sdp) { - rccEnableUSART6(FALSE); - nvicEnableVector(STM32_USART6_NUMBER, STM32_SERIAL_USART6_PRIORITY); - } -#endif - } - usart_init(sdp, config); -} - -/** - * @brief Low level serial driver stop. - * @details De-initializes the USART, stops the associated clock, resets the - * interrupt vector. - * - * @param[in] sdp pointer to a @p SerialDriver object - * - * @notapi - */ -void sd_lld_stop(SerialDriver *sdp) { - - if (sdp->state == SD_READY) { - usart_deinit(sdp->usart); -#if STM32_SERIAL_USE_USART1 - if (&SD1 == sdp) { - rccDisableUSART1(FALSE); - nvicDisableVector(STM32_USART1_NUMBER); - return; - } -#endif -#if STM32_SERIAL_USE_USART2 - if (&SD2 == sdp) { - rccDisableUSART2(FALSE); - nvicDisableVector(STM32_USART2_NUMBER); - return; - } -#endif -#if STM32_SERIAL_USE_USART3 - if (&SD3 == sdp) { - rccDisableUSART3(FALSE); - nvicDisableVector(STM32_USART3_NUMBER); - return; - } -#endif -#if STM32_SERIAL_USE_UART4 - if (&SD4 == sdp) { - rccDisableUART4(FALSE); - nvicDisableVector(STM32_UART4_NUMBER); - return; - } -#endif -#if STM32_SERIAL_USE_UART5 - if (&SD5 == sdp) { - rccDisableUART5(FALSE); - nvicDisableVector(STM32_UART5_NUMBER); - return; - } -#endif -#if STM32_SERIAL_USE_USART6 - if (&SD6 == sdp) { - rccDisableUSART6(FALSE); - nvicDisableVector(STM32_USART6_NUMBER); - return; - } -#endif - } -} - -#endif /* HAL_USE_SERIAL */ - -/** @} */ diff --git a/os/hal/platforms/STM32/USARTv1/serial_lld.h b/os/hal/platforms/STM32/USARTv1/serial_lld.h deleted file mode 100644 index bdf8e9bdb..000000000 --- a/os/hal/platforms/STM32/USARTv1/serial_lld.h +++ /dev/null @@ -1,303 +0,0 @@ -/* - ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file STM32/USARTv1/serial_lld.h - * @brief STM32 low level serial driver header. - * - * @addtogroup SERIAL - * @{ - */ - -#ifndef _SERIAL_LLD_H_ -#define _SERIAL_LLD_H_ - -#if HAL_USE_SERIAL || defined(__DOXYGEN__) - -/*===========================================================================*/ -/* Driver constants. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver pre-compile time settings. */ -/*===========================================================================*/ - -/** - * @name Configuration options - * @{ - */ -/** - * @brief USART1 driver enable switch. - * @details If set to @p TRUE the support for USART1 is included. - * @note The default is @p TRUE. - */ -#if !defined(STM32_SERIAL_USE_USART1) || defined(__DOXYGEN__) -#define STM32_SERIAL_USE_USART1 FALSE -#endif - -/** - * @brief USART2 driver enable switch. - * @details If set to @p TRUE the support for USART2 is included. - * @note The default is @p TRUE. - */ -#if !defined(STM32_SERIAL_USE_USART2) || defined(__DOXYGEN__) -#define STM32_SERIAL_USE_USART2 FALSE -#endif - -/** - * @brief USART3 driver enable switch. - * @details If set to @p TRUE the support for USART3 is included. - * @note The default is @p TRUE. - */ -#if !defined(STM32_SERIAL_USE_USART3) || defined(__DOXYGEN__) -#define STM32_SERIAL_USE_USART3 FALSE -#endif - -/** - * @brief UART4 driver enable switch. - * @details If set to @p TRUE the support for UART4 is included. - * @note The default is @p TRUE. - */ -#if !defined(STM32_SERIAL_USE_UART4) || defined(__DOXYGEN__) -#define STM32_SERIAL_USE_UART4 FALSE -#endif - -/** - * @brief UART5 driver enable switch. - * @details If set to @p TRUE the support for UART5 is included. - * @note The default is @p TRUE. - */ -#if !defined(STM32_SERIAL_USE_UART5) || defined(__DOXYGEN__) -#define STM32_SERIAL_USE_UART5 FALSE -#endif - -/** - * @brief USART6 driver enable switch. - * @details If set to @p TRUE the support for USART6 is included. - * @note The default is @p TRUE. - */ -#if !defined(STM32_SERIAL_USE_USART6) || defined(__DOXYGEN__) -#define STM32_SERIAL_USE_USART6 FALSE -#endif - -/** - * @brief USART1 interrupt priority level setting. - */ -#if !defined(STM32_SERIAL_USART1_PRIORITY) || defined(__DOXYGEN__) -#define STM32_SERIAL_USART1_PRIORITY 12 -#endif - -/** - * @brief USART2 interrupt priority level setting. - */ -#if !defined(STM32_SERIAL_USART2_PRIORITY) || defined(__DOXYGEN__) -#define STM32_SERIAL_USART2_PRIORITY 12 -#endif - -/** - * @brief USART3 interrupt priority level setting. - */ -#if !defined(STM32_SERIAL_USART3_PRIORITY) || defined(__DOXYGEN__) -#define STM32_SERIAL_USART3_PRIORITY 12 -#endif - -/** - * @brief UART4 interrupt priority level setting. - */ -#if !defined(STM32_SERIAL_UART4_PRIORITY) || defined(__DOXYGEN__) -#define STM32_SERIAL_UART4_PRIORITY 12 -#endif - -/** - * @brief UART5 interrupt priority level setting. - */ -#if !defined(STM32_SERIAL_UART5_PRIORITY) || defined(__DOXYGEN__) -#define STM32_SERIAL_UART5_PRIORITY 12 -#endif - -/** - * @brief USART6 interrupt priority level setting. - */ -#if !defined(STM32_SERIAL_USART6_PRIORITY) || defined(__DOXYGEN__) -#define STM32_SERIAL_USART6_PRIORITY 12 -#endif -/** @} */ - -/*===========================================================================*/ -/* Derived constants and error checks. */ -/*===========================================================================*/ - -#if STM32_SERIAL_USE_USART1 && !STM32_HAS_USART1 -#error "USART1 not present in the selected device" -#endif - -#if STM32_SERIAL_USE_USART2 && !STM32_HAS_USART2 -#error "USART2 not present in the selected device" -#endif - -#if STM32_SERIAL_USE_USART3 && !STM32_HAS_USART3 -#error "USART3 not present in the selected device" -#endif - -#if STM32_SERIAL_USE_UART4 && !STM32_HAS_UART4 -#error "UART4 not present in the selected device" -#endif - -#if STM32_SERIAL_USE_UART5 && !STM32_HAS_UART5 -#error "UART5 not present in the selected device" -#endif - -#if STM32_SERIAL_USE_USART6 && !STM32_HAS_USART6 -#error "USART6 not present in the selected device" -#endif - -#if !STM32_SERIAL_USE_USART1 && !STM32_SERIAL_USE_USART2 && \ - !STM32_SERIAL_USE_USART3 && !STM32_SERIAL_USE_UART4 && \ - !STM32_SERIAL_USE_UART5 && !STM32_SERIAL_USE_USART6 -#error "SERIAL driver activated but no USART/UART peripheral assigned" -#endif - -#if STM32_SERIAL_USE_USART1 && \ - !CORTEX_IS_VALID_KERNEL_PRIORITY(STM32_SERIAL_USART1_PRIORITY) -#error "Invalid IRQ priority assigned to USART1" -#endif - -#if STM32_SERIAL_USE_USART2 && \ - !CORTEX_IS_VALID_KERNEL_PRIORITY(STM32_SERIAL_USART2_PRIORITY) -#error "Invalid IRQ priority assigned to USART2" -#endif - -#if STM32_SERIAL_USE_USART3 && \ - !CORTEX_IS_VALID_KERNEL_PRIORITY(STM32_SERIAL_USART3_PRIORITY) -#error "Invalid IRQ priority assigned to USART3" -#endif - -#if STM32_SERIAL_USE_UART4 && \ - !CORTEX_IS_VALID_KERNEL_PRIORITY(STM32_SERIAL_UART4_PRIORITY) -#error "Invalid IRQ priority assigned to UART4" -#endif - -#if STM32_SERIAL_USE_UART5 && \ - !CORTEX_IS_VALID_KERNEL_PRIORITY(STM32_SERIAL_UART5_PRIORITY) -#error "Invalid IRQ priority assigned to UART5" -#endif - -#if STM32_SERIAL_USE_USART6 && \ - !CORTEX_IS_VALID_KERNEL_PRIORITY(STM32_SERIAL_USART6_PRIORITY) -#error "Invalid IRQ priority assigned to USART6" -#endif - -/*===========================================================================*/ -/* Driver data structures and types. */ -/*===========================================================================*/ - -/** - * @brief STM32 Serial Driver configuration structure. - * @details An instance of this structure must be passed to @p sdStart() - * in order to configure and start a serial driver operations. - * @note This structure content is architecture dependent, each driver - * implementation defines its own version and the custom static - * initializers. - */ -typedef struct { - /** - * @brief Bit rate. - */ - uint32_t speed; - /* End of the mandatory fields.*/ - /** - * @brief Initialization value for the CR1 register. - */ - uint16_t cr1; - /** - * @brief Initialization value for the CR2 register. - */ - uint16_t cr2; - /** - * @brief Initialization value for the CR3 register. - */ - uint16_t cr3; -} SerialConfig; - -/** - * @brief @p SerialDriver specific data. - */ -#define _serial_driver_data \ - _base_asynchronous_channel_data \ - /* Driver state.*/ \ - sdstate_t state; \ - /* Input queue.*/ \ - input_queue_t iqueue; \ - /* Output queue.*/ \ - output_queue_t oqueue; \ - /* Input circular buffer.*/ \ - uint8_t ib[SERIAL_BUFFERS_SIZE]; \ - /* Output circular buffer.*/ \ - uint8_t ob[SERIAL_BUFFERS_SIZE]; \ - /* End of the mandatory fields.*/ \ - /* Pointer to the USART registers block.*/ \ - USART_TypeDef *usart; - -/*===========================================================================*/ -/* Driver macros. */ -/*===========================================================================*/ - -/* - * Extra USARTs definitions here (missing from the ST header file). - */ -#define USART_CR2_STOP1_BITS (0 << 12) /**< @brief CR2 1 stop bit value.*/ -#define USART_CR2_STOP0P5_BITS (1 << 12) /**< @brief CR2 0.5 stop bit value.*/ -#define USART_CR2_STOP2_BITS (2 << 12) /**< @brief CR2 2 stop bit value.*/ -#define USART_CR2_STOP1P5_BITS (3 << 12) /**< @brief CR2 1.5 stop bit value.*/ - -/*===========================================================================*/ -/* External declarations. */ -/*===========================================================================*/ - -#if STM32_SERIAL_USE_USART1 && !defined(__DOXYGEN__) -extern SerialDriver SD1; -#endif -#if STM32_SERIAL_USE_USART2 && !defined(__DOXYGEN__) -extern SerialDriver SD2; -#endif -#if STM32_SERIAL_USE_USART3 && !defined(__DOXYGEN__) -extern SerialDriver SD3; -#endif -#if STM32_SERIAL_USE_UART4 && !defined(__DOXYGEN__) -extern SerialDriver SD4; -#endif -#if STM32_SERIAL_USE_UART5 && !defined(__DOXYGEN__) -extern SerialDriver SD5; -#endif -#if STM32_SERIAL_USE_USART6 && !defined(__DOXYGEN__) -extern SerialDriver SD6; -#endif - -#ifdef __cplusplus -extern "C" { -#endif - void sd_lld_init(void); - void sd_lld_start(SerialDriver *sdp, const SerialConfig *config); - void sd_lld_stop(SerialDriver *sdp); -#ifdef __cplusplus -} -#endif - -#endif /* HAL_USE_SERIAL */ - -#endif /* _SERIAL_LLD_H_ */ - -/** @} */ diff --git a/os/hal/platforms/STM32/USARTv1/uart_lld.c b/os/hal/platforms/STM32/USARTv1/uart_lld.c deleted file mode 100644 index d77d9bd98..000000000 --- a/os/hal/platforms/STM32/USARTv1/uart_lld.c +++ /dev/null @@ -1,794 +0,0 @@ -/* - ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file STM32/USARTv1/uart_lld.c - * @brief STM32 low level UART driver code. - * - * @addtogroup UART - * @{ - */ - -#include "ch.h" -#include "hal.h" - -#if HAL_USE_UART || defined(__DOXYGEN__) - -/*===========================================================================*/ -/* Driver local definitions. */ -/*===========================================================================*/ - -#define USART1_RX_DMA_CHANNEL \ - STM32_DMA_GETCHANNEL(STM32_UART_USART1_RX_DMA_STREAM, \ - STM32_USART1_RX_DMA_CHN) - -#define USART1_TX_DMA_CHANNEL \ - STM32_DMA_GETCHANNEL(STM32_UART_USART1_TX_DMA_STREAM, \ - STM32_USART1_TX_DMA_CHN) - -#define USART2_RX_DMA_CHANNEL \ - STM32_DMA_GETCHANNEL(STM32_UART_USART2_RX_DMA_STREAM, \ - STM32_USART2_RX_DMA_CHN) - -#define USART2_TX_DMA_CHANNEL \ - STM32_DMA_GETCHANNEL(STM32_UART_USART2_TX_DMA_STREAM, \ - STM32_USART2_TX_DMA_CHN) - -#define USART3_RX_DMA_CHANNEL \ - STM32_DMA_GETCHANNEL(STM32_UART_USART3_RX_DMA_STREAM, \ - STM32_USART3_RX_DMA_CHN) - -#define USART3_TX_DMA_CHANNEL \ - STM32_DMA_GETCHANNEL(STM32_UART_USART3_TX_DMA_STREAM, \ - STM32_USART3_TX_DMA_CHN) - -#define UART4_RX_DMA_CHANNEL \ - STM32_DMA_GETCHANNEL(STM32_UART_UART4_RX_DMA_STREAM, \ - STM32_UART4_RX_DMA_CHN) - -#define UART4_TX_DMA_CHANNEL \ - STM32_DMA_GETCHANNEL(STM32_UART_UART4_TX_DMA_STREAM, \ - STM32_UART4_TX_DMA_CHN) - -#define UART5_RX_DMA_CHANNEL \ - STM32_DMA_GETCHANNEL(STM32_UART_UART5_RX_DMA_STREAM, \ - STM32_UART5_RX_DMA_CHN) - -#define UART5_TX_DMA_CHANNEL \ - STM32_DMA_GETCHANNEL(STM32_UART_UART5_TX_DMA_STREAM, \ - STM32_UART5_TX_DMA_CHN) - -#define USART6_RX_DMA_CHANNEL \ - STM32_DMA_GETCHANNEL(STM32_UART_USART6_RX_DMA_STREAM, \ - STM32_USART6_RX_DMA_CHN) - -#define USART6_TX_DMA_CHANNEL \ - STM32_DMA_GETCHANNEL(STM32_UART_USART6_TX_DMA_STREAM, \ - STM32_USART6_TX_DMA_CHN) - -/*===========================================================================*/ -/* Driver exported variables. */ -/*===========================================================================*/ - -/** @brief USART1 UART driver identifier.*/ -#if STM32_UART_USE_USART1 || defined(__DOXYGEN__) -UARTDriver UARTD1; -#endif - -/** @brief USART2 UART driver identifier.*/ -#if STM32_UART_USE_USART2 || defined(__DOXYGEN__) -UARTDriver UARTD2; -#endif - -/** @brief USART3 UART driver identifier.*/ -#if STM32_UART_USE_USART3 || defined(__DOXYGEN__) -UARTDriver UARTD3; -#endif - -/** @brief UART4 UART driver identifier.*/ -#if STM32_UART_USE_UART4 || defined(__DOXYGEN__) -UARTDriver UARTD4; -#endif - -/** @brief UART5 UART driver identifier.*/ -#if STM32_UART_USE_UART5 || defined(__DOXYGEN__) -UARTDriver UARTD5; -#endif - -/** @brief USART6 UART driver identifier.*/ -#if STM32_UART_USE_USART6 || defined(__DOXYGEN__) -UARTDriver UARTD6; -#endif - -/*===========================================================================*/ -/* Driver local variables and types. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver local functions. */ -/*===========================================================================*/ - -/** - * @brief Status bits translation. - * - * @param[in] sr USART SR register value - * - * @return The error flags. - */ -static uartflags_t translate_errors(uint16_t sr) { - uartflags_t sts = 0; - - if (sr & USART_SR_ORE) - sts |= UART_OVERRUN_ERROR; - if (sr & USART_SR_PE) - sts |= UART_PARITY_ERROR; - if (sr & USART_SR_FE) - sts |= UART_FRAMING_ERROR; - if (sr & USART_SR_NE) - sts |= UART_NOISE_ERROR; - if (sr & USART_SR_LBD) - sts |= UART_BREAK_DETECTED; - return sts; -} - -/** - * @brief Puts the receiver in the UART_RX_IDLE state. - * - * @param[in] uartp pointer to the @p UARTDriver object - */ -static void set_rx_idle_loop(UARTDriver *uartp) { - uint32_t mode; - - /* RX DMA channel preparation, if the char callback is defined then the - TCIE interrupt is enabled too.*/ - if (uartp->config->rxchar_cb == NULL) - mode = STM32_DMA_CR_DIR_P2M | STM32_DMA_CR_CIRC; - else - mode = STM32_DMA_CR_DIR_P2M | STM32_DMA_CR_CIRC | STM32_DMA_CR_TCIE; - dmaStreamSetMemory0(uartp->dmarx, &uartp->rxbuf); - dmaStreamSetTransactionSize(uartp->dmarx, 1); - dmaStreamSetMode(uartp->dmarx, uartp->dmamode | mode); - dmaStreamEnable(uartp->dmarx); -} - -/** - * @brief USART de-initialization. - * @details This function must be invoked with interrupts disabled. - * - * @param[in] uartp pointer to the @p UARTDriver object - */ -static void usart_stop(UARTDriver *uartp) { - - /* Stops RX and TX DMA channels.*/ - dmaStreamDisable(uartp->dmarx); - dmaStreamDisable(uartp->dmatx); - - /* Stops USART operations.*/ - uartp->usart->CR1 = 0; - uartp->usart->CR2 = 0; - uartp->usart->CR3 = 0; -} - -/** - * @brief USART initialization. - * @details This function must be invoked with interrupts disabled. - * - * @param[in] uartp pointer to the @p UARTDriver object - */ -static void usart_start(UARTDriver *uartp) { - uint16_t cr1; - USART_TypeDef *u = uartp->usart; - - /* Defensive programming, starting from a clean state.*/ - usart_stop(uartp); - - /* Baud rate setting.*/ -#if STM32_HAS_USART6 - if ((uartp->usart == USART1) || (uartp->usart == USART6)) -#else - if (uartp->usart == USART1) -#endif - u->BRR = STM32_PCLK2 / uartp->config->speed; - else - u->BRR = STM32_PCLK1 / uartp->config->speed; - - /* Resetting eventual pending status flags.*/ - (void)u->SR; /* SR reset step 1.*/ - (void)u->DR; /* SR reset step 2.*/ - u->SR = 0; - - /* Note that some bits are enforced because required for correct driver - operations.*/ - u->CR2 = uartp->config->cr2 | USART_CR2_LBDIE; - u->CR3 = uartp->config->cr3 | USART_CR3_DMAT | USART_CR3_DMAR | - USART_CR3_EIE; - if (uartp->config->txend2_cb == NULL) - cr1 = USART_CR1_UE | USART_CR1_PEIE | USART_CR1_TE | USART_CR1_RE; - else - cr1 = USART_CR1_UE | USART_CR1_PEIE | USART_CR1_TE | USART_CR1_RE | - USART_CR1_TCIE; - u->CR1 = uartp->config->cr1 | cr1; - - /* Starting the receiver idle loop.*/ - set_rx_idle_loop(uartp); -} - -/** - * @brief RX DMA common service routine. - * - * @param[in] uartp pointer to the @p UARTDriver object - * @param[in] flags pre-shifted content of the ISR register - */ -static void uart_lld_serve_rx_end_irq(UARTDriver *uartp, uint32_t flags) { - - /* DMA errors handling.*/ -#if defined(STM32_UART_DMA_ERROR_HOOK) - if ((flags & (STM32_DMA_ISR_TEIF | STM32_DMA_ISR_DMEIF)) != 0) { - STM32_UART_DMA_ERROR_HOOK(uartp); - } -#else - (void)flags; -#endif - - if (uartp->rxstate == UART_RX_IDLE) { - /* Receiver in idle state, a callback is generated, if enabled, for each - received character and then the driver stays in the same state.*/ - if (uartp->config->rxchar_cb != NULL) - uartp->config->rxchar_cb(uartp, uartp->rxbuf); - } - else { - /* Receiver in active state, a callback is generated, if enabled, after - a completed transfer.*/ - dmaStreamDisable(uartp->dmarx); - uartp->rxstate = UART_RX_COMPLETE; - if (uartp->config->rxend_cb != NULL) - uartp->config->rxend_cb(uartp); - - /* If the callback didn't explicitly change state then the receiver - automatically returns to the idle state.*/ - if (uartp->rxstate == UART_RX_COMPLETE) { - uartp->rxstate = UART_RX_IDLE; - set_rx_idle_loop(uartp); - } - } -} - -/** - * @brief TX DMA common service routine. - * - * @param[in] uartp pointer to the @p UARTDriver object - * @param[in] flags pre-shifted content of the ISR register - */ -static void uart_lld_serve_tx_end_irq(UARTDriver *uartp, uint32_t flags) { - - /* DMA errors handling.*/ -#if defined(STM32_UART_DMA_ERROR_HOOK) - if ((flags & (STM32_DMA_ISR_TEIF | STM32_DMA_ISR_DMEIF)) != 0) { - STM32_UART_DMA_ERROR_HOOK(uartp); - } -#else - (void)flags; -#endif - - dmaStreamDisable(uartp->dmatx); - - /* A callback is generated, if enabled, after a completed transfer.*/ - uartp->txstate = UART_TX_COMPLETE; - if (uartp->config->txend1_cb != NULL) - uartp->config->txend1_cb(uartp); - - /* If the callback didn't explicitly change state then the transmitter - automatically returns to the idle state.*/ - if (uartp->txstate == UART_TX_COMPLETE) - uartp->txstate = UART_TX_IDLE; -} - -/** - * @brief USART common service routine. - * - * @param[in] uartp pointer to the @p UARTDriver object - */ -static void serve_usart_irq(UARTDriver *uartp) { - uint16_t sr; - USART_TypeDef *u = uartp->usart; - - sr = u->SR; /* SR reset step 1.*/ - (void)u->DR; /* SR reset step 2.*/ - if (sr & (USART_SR_LBD | USART_SR_ORE | USART_SR_NE | - USART_SR_FE | USART_SR_PE)) { - u->SR = ~USART_SR_LBD; - if (uartp->config->rxerr_cb != NULL) - uartp->config->rxerr_cb(uartp, translate_errors(sr)); - } - if (sr & USART_SR_TC) { - u->SR = ~USART_SR_TC; - - /* End of transmission, a callback is generated.*/ - if (uartp->config->txend2_cb != NULL) - uartp->config->txend2_cb(uartp); - } -} - -/*===========================================================================*/ -/* Driver interrupt handlers. */ -/*===========================================================================*/ - -#if STM32_UART_USE_USART1 || defined(__DOXYGEN__) -#if !defined(STM32_USART1_HANDLER) -#error "STM32_USART1_HANDLER not defined" -#endif -/** - * @brief USART1 IRQ handler. - * - * @isr - */ -CH_IRQ_HANDLER(STM32_USART1_HANDLER) { - - CH_IRQ_PROLOGUE(); - - serve_usart_irq(&UARTD1); - - CH_IRQ_EPILOGUE(); -} -#endif /* STM32_UART_USE_USART1 */ - -#if STM32_UART_USE_USART2 || defined(__DOXYGEN__) -#if !defined(STM32_USART2_HANDLER) -#error "STM32_USART2_HANDLER not defined" -#endif -/** - * @brief USART2 IRQ handler. - * - * @isr - */ -CH_IRQ_HANDLER(STM32_USART2_HANDLER) { - - CH_IRQ_PROLOGUE(); - - serve_usart_irq(&UARTD2); - - CH_IRQ_EPILOGUE(); -} -#endif /* STM32_UART_USE_USART2 */ - -#if STM32_UART_USE_USART3 || defined(__DOXYGEN__) -#if !defined(STM32_USART3_HANDLER) -#error "STM32_USART3_HANDLER not defined" -#endif -/** - * @brief USART3 IRQ handler. - * - * @isr - */ -CH_IRQ_HANDLER(STM32_USART3_HANDLER) { - - CH_IRQ_PROLOGUE(); - - serve_usart_irq(&UARTD3); - - CH_IRQ_EPILOGUE(); -} -#endif /* STM32_UART_USE_USART3 */ - -#if STM32_UART_USE_UART4 || defined(__DOXYGEN__) -#if !defined(STM32_UART4_HANDLER) -#error "STM32_UART4_HANDLER not defined" -#endif -/** - * @brief UART4 IRQ handler. - * - * @isr - */ -CH_IRQ_HANDLER(STM32_UART4_HANDLER) { - - CH_IRQ_PROLOGUE(); - - serve_usart_irq(&UARTD4); - - CH_IRQ_EPILOGUE(); -} -#endif /* STM32_UART_USE_UART4 */ - -#if STM32_UART_USE_UART5 || defined(__DOXYGEN__) -#if !defined(STM32_UART5_HANDLER) -#error "STM32_UART5_HANDLER not defined" -#endif -/** - * @brief UART5 IRQ handler. - * - * @isr - */ -CH_IRQ_HANDLER(STM32_UART5_HANDLER) { - - CH_IRQ_PROLOGUE(); - - serve_usart_irq(&UARTD5); - - CH_IRQ_EPILOGUE(); -} -#endif /* STM32_UART_USE_UART5 */ - -#if STM32_UART_USE_USART6 || defined(__DOXYGEN__) -#if !defined(STM32_USART6_HANDLER) -#error "STM32_USART6_HANDLER not defined" -#endif -/** - * @brief USART6 IRQ handler. - * - * @isr - */ -CH_IRQ_HANDLER(STM32_USART6_HANDLER) { - - CH_IRQ_PROLOGUE(); - - serve_usart_irq(&UARTD6); - - CH_IRQ_EPILOGUE(); -} -#endif /* STM32_UART_USE_USART6 */ - -/*===========================================================================*/ -/* Driver exported functions. */ -/*===========================================================================*/ - -/** - * @brief Low level UART driver initialization. - * - * @notapi - */ -void uart_lld_init(void) { - -#if STM32_UART_USE_USART1 - uartObjectInit(&UARTD1); - UARTD1.usart = USART1; - UARTD1.dmamode = STM32_DMA_CR_DMEIE | STM32_DMA_CR_TEIE; - UARTD1.dmarx = STM32_DMA_STREAM(STM32_UART_USART1_RX_DMA_STREAM); - UARTD1.dmatx = STM32_DMA_STREAM(STM32_UART_USART1_TX_DMA_STREAM); -#endif - -#if STM32_UART_USE_USART2 - uartObjectInit(&UARTD2); - UARTD2.usart = USART2; - UARTD2.dmamode = STM32_DMA_CR_DMEIE | STM32_DMA_CR_TEIE; - UARTD2.dmarx = STM32_DMA_STREAM(STM32_UART_USART2_RX_DMA_STREAM); - UARTD2.dmatx = STM32_DMA_STREAM(STM32_UART_USART2_TX_DMA_STREAM); -#endif - -#if STM32_UART_USE_USART3 - uartObjectInit(&UARTD3); - UARTD3.usart = USART3; - UARTD3.dmamode = STM32_DMA_CR_DMEIE | STM32_DMA_CR_TEIE; - UARTD3.dmarx = STM32_DMA_STREAM(STM32_UART_USART3_RX_DMA_STREAM); - UARTD3.dmatx = STM32_DMA_STREAM(STM32_UART_USART3_TX_DMA_STREAM); -#endif - -#if STM32_UART_USE_UART4 - uartObjectInit(&UARTD4); - UARTD4.usart = UART4; - UARTD4.dmamode = STM32_DMA_CR_DMEIE | STM32_DMA_CR_TEIE; - UARTD4.dmarx = STM32_DMA_STREAM(STM32_UART_UART4_RX_DMA_STREAM); - UARTD4.dmatx = STM32_DMA_STREAM(STM32_UART_UART4_TX_DMA_STREAM); -#endif - -#if STM32_UART_USE_UART5 - uartObjectInit(&UARTD5); - UARTD5.usart = UART5; - UARTD5.dmamode = STM32_DMA_CR_DMEIE | STM32_DMA_CR_TEIE; - UARTD5.dmarx = STM32_DMA_STREAM(STM32_UART_UART5_RX_DMA_STREAM); - UARTD5.dmatx = STM32_DMA_STREAM(STM32_UART_UART5_TX_DMA_STREAM); -#endif - -#if STM32_UART_USE_USART6 - uartObjectInit(&UARTD6); - UARTD6.usart = USART6; - UARTD6.dmarx = STM32_DMA_STREAM(STM32_UART_USART6_RX_DMA_STREAM); - UARTD6.dmatx = STM32_DMA_STREAM(STM32_UART_USART6_TX_DMA_STREAM); -#endif -} - -/** - * @brief Configures and activates the UART peripheral. - * - * @param[in] uartp pointer to the @p UARTDriver object - * - * @notapi - */ -void uart_lld_start(UARTDriver *uartp) { - - if (uartp->state == UART_STOP) { -#if STM32_UART_USE_USART1 - if (&UARTD1 == uartp) { - bool b; - b = dmaStreamAllocate(uartp->dmarx, - STM32_UART_USART1_IRQ_PRIORITY, - (stm32_dmaisr_t)uart_lld_serve_rx_end_irq, - (void *)uartp); - osalDbgAssert(!b, "stream already allocated"); - b = dmaStreamAllocate(uartp->dmatx, - STM32_UART_USART1_IRQ_PRIORITY, - (stm32_dmaisr_t)uart_lld_serve_tx_end_irq, - (void *)uartp); - osalDbgAssert(!b, "stream already allocated"); - rccEnableUSART1(FALSE); - nvicEnableVector(STM32_USART1_NUMBER, STM32_UART_USART1_IRQ_PRIORITY); - uartp->dmamode |= STM32_DMA_CR_CHSEL(USART1_RX_DMA_CHANNEL) | - STM32_DMA_CR_PL(STM32_UART_USART1_DMA_PRIORITY); - } -#endif - -#if STM32_UART_USE_USART2 - if (&UARTD2 == uartp) { - bool b; - b = dmaStreamAllocate(uartp->dmarx, - STM32_UART_USART2_IRQ_PRIORITY, - (stm32_dmaisr_t)uart_lld_serve_rx_end_irq, - (void *)uartp); - osalDbgAssert(!b, "stream already allocated"); - b = dmaStreamAllocate(uartp->dmatx, - STM32_UART_USART2_IRQ_PRIORITY, - (stm32_dmaisr_t)uart_lld_serve_tx_end_irq, - (void *)uartp); - osalDbgAssert(!b, "stream already allocated"); - rccEnableUSART2(FALSE); - nvicEnableVector(STM32_USART2_NUMBER, STM32_UART_USART2_IRQ_PRIORITY); - uartp->dmamode |= STM32_DMA_CR_CHSEL(USART2_RX_DMA_CHANNEL) | - STM32_DMA_CR_PL(STM32_UART_USART2_DMA_PRIORITY); - } -#endif - -#if STM32_UART_USE_USART3 - if (&UARTD3 == uartp) { - bool b; - b = dmaStreamAllocate(uartp->dmarx, - STM32_UART_USART3_IRQ_PRIORITY, - (stm32_dmaisr_t)uart_lld_serve_rx_end_irq, - (void *)uartp); - osalDbgAssert(!b, "stream already allocated"); - b = dmaStreamAllocate(uartp->dmatx, - STM32_UART_USART3_IRQ_PRIORITY, - (stm32_dmaisr_t)uart_lld_serve_tx_end_irq, - (void *)uartp); - osalDbgAssert(!b, "stream already allocated"); - rccEnableUSART3(FALSE); - nvicEnableVector(STM32_USART3_NUMBER, STM32_UART_USART3_IRQ_PRIORITY); - uartp->dmamode |= STM32_DMA_CR_CHSEL(USART3_RX_DMA_CHANNEL) | - STM32_DMA_CR_PL(STM32_UART_USART3_DMA_PRIORITY); - } -#endif - -#if STM32_UART_USE_UART4 - if (&UARTD4 == uartp) { - bool b; - b = dmaStreamAllocate(uartp->dmarx, - STM32_UART_UART4_IRQ_PRIORITY, - (stm32_dmaisr_t)uart_lld_serve_rx_end_irq, - (void *)uartp); - osalDbgAssert(!b, "stream already allocated"); - b = dmaStreamAllocate(uartp->dmatx, - STM32_UART_UART4_IRQ_PRIORITY, - (stm32_dmaisr_t)uart_lld_serve_tx_end_irq, - (void *)uartp); - osalDbgAssert(!b, "stream already allocated"); - rccEnableUART4(FALSE); - nvicEnableVector(STM32_UART4_NUMBER, STM32_UART_UART4_IRQ_PRIORITY); - uartp->dmamode |= STM32_DMA_CR_CHSEL(UART4_RX_DMA_CHANNEL) | - STM32_DMA_CR_PL(STM32_UART_UART4_DMA_PRIORITY); - } -#endif - -#if STM32_UART_USE_UART5 - if (&UARTD5 == uartp) { - bool b; - b = dmaStreamAllocate(uartp->dmarx, - STM32_UART_UART5_IRQ_PRIORITY, - (stm32_dmaisr_t)uart_lld_serve_rx_end_irq, - (void *)uartp); - osalDbgAssert(!b, "stream already allocated"); - b = dmaStreamAllocate(uartp->dmatx, - STM32_UART_UART5_IRQ_PRIORITY, - (stm32_dmaisr_t)uart_lld_serve_tx_end_irq, - (void *)uartp); - osalDbgAssert(!b, "stream already allocated"); - rccEnableUART5(FALSE); - nvicEnableVector(STM32_UART5_NUMBER, STM32_UART_UART5_IRQ_PRIORITY); - uartp->dmamode |= STM32_DMA_CR_CHSEL(UART5_RX_DMA_CHANNEL) | - STM32_DMA_CR_PL(STM32_UART_UART5_DMA_PRIORITY); - } -#endif - -#if STM32_UART_USE_USART6 - if (&UARTD6 == uartp) { - bool b; - b = dmaStreamAllocate(uartp->dmarx, - STM32_UART_USART6_IRQ_PRIORITY, - (stm32_dmaisr_t)uart_lld_serve_rx_end_irq, - (void *)uartp); - osalDbgAssert(!b, "stream already allocated"); - b = dmaStreamAllocate(uartp->dmatx, - STM32_UART_USART6_IRQ_PRIORITY, - (stm32_dmaisr_t)uart_lld_serve_tx_end_irq, - (void *)uartp); - osalDbgAssert(!b, "stream already allocated"); - rccEnableUSART6(FALSE); - nvicEnableVector(STM32_USART6_NUMBER, STM32_UART_USART6_IRQ_PRIORITY); - uartp->dmamode |= STM32_DMA_CR_CHSEL(USART6_RX_DMA_CHANNEL) | - STM32_DMA_CR_PL(STM32_UART_USART6_DMA_PRIORITY); - } -#endif - - /* Static DMA setup, the transfer size depends on the USART settings, - it is 16 bits if M=1 and PCE=0 else it is 8 bits.*/ - if ((uartp->config->cr1 & (USART_CR1_M | USART_CR1_PCE)) == USART_CR1_M) - uartp->dmamode |= STM32_DMA_CR_PSIZE_HWORD | STM32_DMA_CR_MSIZE_HWORD; - dmaStreamSetPeripheral(uartp->dmarx, &uartp->usart->DR); - dmaStreamSetPeripheral(uartp->dmatx, &uartp->usart->DR); - uartp->rxbuf = 0; - } - - uartp->rxstate = UART_RX_IDLE; - uartp->txstate = UART_TX_IDLE; - usart_start(uartp); -} - -/** - * @brief Deactivates the UART peripheral. - * - * @param[in] uartp pointer to the @p UARTDriver object - * - * @notapi - */ -void uart_lld_stop(UARTDriver *uartp) { - - if (uartp->state == UART_READY) { - usart_stop(uartp); - dmaStreamRelease(uartp->dmarx); - dmaStreamRelease(uartp->dmatx); - -#if STM32_UART_USE_USART1 - if (&UARTD1 == uartp) { - nvicDisableVector(STM32_USART1_NUMBER); - rccDisableUSART1(FALSE); - return; - } -#endif - -#if STM32_UART_USE_USART2 - if (&UARTD2 == uartp) { - nvicDisableVector(STM32_USART2_NUMBER); - rccDisableUSART2(FALSE); - return; - } -#endif - -#if STM32_UART_USE_USART3 - if (&UARTD3 == uartp) { - nvicDisableVector(STM32_USART3_NUMBER); - rccDisableUSART3(FALSE); - return; - } -#endif - -#if STM32_UART_USE_UART4 - if (&UARTD4 == uartp) { - nvicDisableVector(STM32_UART4_NUMBER); - rccDisableUART4(FALSE); - return; - } -#endif - -#if STM32_UART_USE_UART5 - if (&UARTD5 == uartp) { - nvicDisableVector(STM32_UART5_NUMBER); - rccDisableUART5(FALSE); - return; - } -#endif - -#if STM32_UART_USE_USART6 - if (&UARTD6 == uartp) { - nvicDisableVector(STM32_USART6_NUMBER); - rccDisableUSART6(FALSE); - return; - } -#endif - } -} - -/** - * @brief Starts a transmission on the UART peripheral. - * @note The buffers are organized as uint8_t arrays for data sizes below - * or equal to 8 bits else it is organized as uint16_t arrays. - * - * @param[in] uartp pointer to the @p UARTDriver object - * @param[in] n number of data frames to send - * @param[in] txbuf the pointer to the transmit buffer - * - * @notapi - */ -void uart_lld_start_send(UARTDriver *uartp, size_t n, const void *txbuf) { - - /* TX DMA channel preparation and start.*/ - dmaStreamSetMemory0(uartp->dmatx, txbuf); - dmaStreamSetTransactionSize(uartp->dmatx, n); - dmaStreamSetMode(uartp->dmatx, uartp->dmamode | STM32_DMA_CR_DIR_M2P | - STM32_DMA_CR_MINC | STM32_DMA_CR_TCIE); - dmaStreamEnable(uartp->dmatx); -} - -/** - * @brief Stops any ongoing transmission. - * @note Stopping a transmission also suppresses the transmission callbacks. - * - * @param[in] uartp pointer to the @p UARTDriver object - * - * @return The number of data frames not transmitted by the - * stopped transmit operation. - * - * @notapi - */ -size_t uart_lld_stop_send(UARTDriver *uartp) { - - dmaStreamDisable(uartp->dmatx); - return dmaStreamGetTransactionSize(uartp->dmatx); -} - -/** - * @brief Starts a receive operation on the UART peripheral. - * @note The buffers are organized as uint8_t arrays for data sizes below - * or equal to 8 bits else it is organized as uint16_t arrays. - * - * @param[in] uartp pointer to the @p UARTDriver object - * @param[in] n number of data frames to send - * @param[out] rxbuf the pointer to the receive buffer - * - * @notapi - */ -void uart_lld_start_receive(UARTDriver *uartp, size_t n, void *rxbuf) { - - /* Stopping previous activity (idle state).*/ - dmaStreamDisable(uartp->dmarx); - - /* RX DMA channel preparation and start.*/ - dmaStreamSetMemory0(uartp->dmarx, rxbuf); - dmaStreamSetTransactionSize(uartp->dmarx, n); - dmaStreamSetMode(uartp->dmarx, uartp->dmamode | STM32_DMA_CR_DIR_P2M | - STM32_DMA_CR_MINC | STM32_DMA_CR_TCIE); - dmaStreamEnable(uartp->dmarx); -} - -/** - * @brief Stops any ongoing receive operation. - * @note Stopping a receive operation also suppresses the receive callbacks. - * - * @param[in] uartp pointer to the @p UARTDriver object - * - * @return The number of data frames not received by the - * stopped receive operation. - * - * @notapi - */ -size_t uart_lld_stop_receive(UARTDriver *uartp) { - size_t n; - - dmaStreamDisable(uartp->dmarx); - n = dmaStreamGetTransactionSize(uartp->dmarx); - set_rx_idle_loop(uartp); - return n; -} - -#endif /* HAL_USE_UART */ - -/** @} */ diff --git a/os/hal/platforms/STM32/USARTv1/uart_lld.h b/os/hal/platforms/STM32/USARTv1/uart_lld.h deleted file mode 100644 index 6c7df15e0..000000000 --- a/os/hal/platforms/STM32/USARTv1/uart_lld.h +++ /dev/null @@ -1,680 +0,0 @@ -/* - ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file STM32/USARTv1/uart_lld.h - * @brief STM32 low level UART driver header. - * - * @addtogroup UART - * @{ - */ - -#ifndef _UART_LLD_H_ -#define _UART_LLD_H_ - -#if HAL_USE_UART || defined(__DOXYGEN__) - -/*===========================================================================*/ -/* Driver constants. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver pre-compile time settings. */ -/*===========================================================================*/ - -/** - * @name Configuration options - * @{ - */ -/** - * @brief UART driver on USART1 enable switch. - * @details If set to @p TRUE the support for USART1 is included. - * @note The default is @p FALSE. - */ -#if !defined(STM32_UART_USE_USART1) || defined(__DOXYGEN__) -#define STM32_UART_USE_USART1 FALSE -#endif - -/** - * @brief UART driver on USART2 enable switch. - * @details If set to @p TRUE the support for USART2 is included. - * @note The default is @p FALSE. - */ -#if !defined(STM32_UART_USE_USART2) || defined(__DOXYGEN__) -#define STM32_UART_USE_USART2 FALSE -#endif - -/** - * @brief UART driver on USART3 enable switch. - * @details If set to @p TRUE the support for USART3 is included. - * @note The default is @p FALSE. - */ -#if !defined(STM32_UART_USE_USART3) || defined(__DOXYGEN__) -#define STM32_UART_USE_USART3 FALSE -#endif - -/** - * @brief UART driver on UART4 enable switch. - * @details If set to @p TRUE the support for UART4 is included. - * @note The default is @p FALSE. - */ -#if !defined(STM32_UART_USE_UART4) || defined(__DOXYGEN__) -#define STM32_UART_USE_UART4 FALSE -#endif - -/** - * @brief UART driver on UART5 enable switch. - * @details If set to @p TRUE the support for UART5 is included. - * @note The default is @p FALSE. - */ -#if !defined(STM32_UART_USE_UART4) || defined(__DOXYGEN__) -#define STM32_UART_USE_UART5 FALSE -#endif - -/** - * @brief UART driver on USART6 enable switch. - * @details If set to @p TRUE the support for USART6 is included. - * @note The default is @p FALSE. - */ -#if !defined(STM32_UART_USE_USART6) || defined(__DOXYGEN__) -#define STM32_UART_USE_USART6 FALSE -#endif - -/** - * @brief USART1 interrupt priority level setting. - */ -#if !defined(STM32_UART_USART1_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_UART_USART1_IRQ_PRIORITY 12 -#endif - -/** - * @brief USART2 interrupt priority level setting. - */ -#if !defined(STM32_UART_USART2_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_UART_USART2_IRQ_PRIORITY 12 -#endif - -/** - * @brief USART3 interrupt priority level setting. - */ -#if !defined(STM32_UART_USART3_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_UART_USART3_IRQ_PRIORITY 12 -#endif - -/** - * @brief UART4 interrupt priority level setting. - */ -#if !defined(STM32_UART_UART4_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_UART_UART4_IRQ_PRIORITY 12 -#endif - -/** - * @brief UART5 interrupt priority level setting. - */ -#if !defined(STM32_UART_UART5_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_UART_UART5_IRQ_PRIORITY 12 -#endif - -/** - * @brief USART6 interrupt priority level setting. - */ -#if !defined(STM32_UART_USART6_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_UART_USART6_IRQ_PRIORITY 12 -#endif - -/** - * @brief USART1 DMA priority (0..3|lowest..highest). - * @note The priority level is used for both the TX and RX DMA channels but - * because of the channels ordering the RX channel has always priority - * over the TX channel. - */ -#if !defined(STM32_UART_USART1_DMA_PRIORITY) || defined(__DOXYGEN__) -#define STM32_UART_USART1_DMA_PRIORITY 0 -#endif - -/** - * @brief USART2 DMA priority (0..3|lowest..highest). - * @note The priority level is used for both the TX and RX DMA channels but - * because of the channels ordering the RX channel has always priority - * over the TX channel. - */ -#if !defined(STM32_UART_USART2_DMA_PRIORITY) || defined(__DOXYGEN__) -#define STM32_UART_USART2_DMA_PRIORITY 0 -#endif - -/** - * @brief USART3 DMA priority (0..3|lowest..highest). - * @note The priority level is used for both the TX and RX DMA channels but - * because of the channels ordering the RX channel has always priority - * over the TX channel. - */ -#if !defined(STM32_UART_USART3_DMA_PRIORITY) || defined(__DOXYGEN__) -#define STM32_UART_USART3_DMA_PRIORITY 0 -#endif - -/** - * @brief UART4 DMA priority (0..3|lowest..highest). - * @note The priority level is used for both the TX and RX DMA channels but - * because of the channels ordering the RX channel has always priority - * over the TX channel. - */ -#if !defined(STM32_UART_UART4_DMA_PRIORITY) || defined(__DOXYGEN__) -#define STM32_UART_UART4_DMA_PRIORITY 0 -#endif - -/** - * @brief UART5 DMA priority (0..3|lowest..highest). - * @note The priority level is used for both the TX and RX DMA channels but - * because of the channels ordering the RX channel has always priority - * over the TX channel. - */ -#if !defined(STM32_UART_UART5_DMA_PRIORITY) || defined(__DOXYGEN__) -#define STM32_UART_UART5_DMA_PRIORITY 0 -#endif - -/** - * @brief USART6 DMA priority (0..3|lowest..highest). - * @note The priority level is used for both the TX and RX DMA channels but - * because of the channels ordering the RX channel has always priority - * over the TX channel. - */ -#if !defined(STM32_UART_USART6_DMA_PRIORITY) || defined(__DOXYGEN__) -#define STM32_UART_USART6_DMA_PRIORITY 0 -#endif - -/** - * @brief USART DMA error hook. - * @note The default action for DMA errors is a system halt because DMA - * error can only happen because programming errors. - */ -#if !defined(STM32_UART_DMA_ERROR_HOOK) || defined(__DOXYGEN__) -#define STM32_UART_DMA_ERROR_HOOK(uartp) chSysHalt() -#endif - -#if STM32_ADVANCED_DMA || defined(__DOXYGEN__) - -/** - * @brief DMA stream used for USART1 RX operations. - * @note This option is only available on platforms with enhanced DMA. - */ -#if !defined(STM32_UART_USART1_RX_DMA_STREAM) || defined(__DOXYGEN__) -#define STM32_UART_USART1_RX_DMA_STREAM STM32_DMA_STREAM_ID(2, 5) -#endif - -/** - * @brief DMA stream used for USART1 TX operations. - * @note This option is only available on platforms with enhanced DMA. - */ -#if !defined(STM32_UART_USART1_TX_DMA_STREAM) || defined(__DOXYGEN__) -#define STM32_UART_USART1_TX_DMA_STREAM STM32_DMA_STREAM_ID(2, 7) -#endif - -/** - * @brief DMA stream used for USART2 RX operations. - * @note This option is only available on platforms with enhanced DMA. - */ -#if !defined(STM32_UART_USART2_RX_DMA_STREAM) || defined(__DOXYGEN__) -#define STM32_UART_USART2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 5) -#endif - -/** - * @brief DMA stream used for USART2 TX operations. - * @note This option is only available on platforms with enhanced DMA. - */ -#if !defined(STM32_UART_USART2_TX_DMA_STREAM) || defined(__DOXYGEN__) -#define STM32_UART_USART2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 6) -#endif - -/** - * @brief DMA stream used for USART3 RX operations. - * @note This option is only available on platforms with enhanced DMA. - */ -#if !defined(STM32_UART_USART3_RX_DMA_STREAM) || defined(__DOXYGEN__) -#define STM32_UART_USART3_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 1) -#endif - -/** - * @brief DMA stream used for USART3 TX operations. - * @note This option is only available on platforms with enhanced DMA. - */ -#if !defined(STM32_UART_USART3_TX_DMA_STREAM) || defined(__DOXYGEN__) -#define STM32_UART_USART3_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 3) -#endif - -/** - * @brief DMA stream used for UART4 RX operations. - * @note This option is only available on platforms with enhanced DMA. - */ -#if !defined(STM32_UART_UART4_RX_DMA_STREAM) || defined(__DOXYGEN__) -#define STM32_UART_UART4_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2) -#endif - -/** - * @brief DMA stream used for UART4 TX operations. - * @note This option is only available on platforms with enhanced DMA. - */ -#if !defined(STM32_UART_UART4_TX_DMA_STREAM) || defined(__DOXYGEN__) -#define STM32_UART_UART4_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) -#endif - -/** - * @brief DMA stream used for UART5 RX operations. - * @note This option is only available on platforms with enhanced DMA. - */ -#if !defined(STM32_UART_UART5_RX_DMA_STREAM) || defined(__DOXYGEN__) -#define STM32_UART_UART5_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 0) -#endif - -/** - * @brief DMA stream used for UART5 TX operations. - * @note This option is only available on platforms with enhanced DMA. - */ -#if !defined(STM32_UART_UART5_TX_DMA_STREAM) || defined(__DOXYGEN__) -#define STM32_UART_UART5_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7) -#endif - -/** - * @brief DMA stream used for USART6 RX operations. - * @note This option is only available on platforms with enhanced DMA. - */ -#if !defined(STM32_UART_USART6_RX_DMA_STREAM) || defined(__DOXYGEN__) -#define STM32_UART_USART6_RX_DMA_STREAM STM32_DMA_STREAM_ID(2, 2) -#endif - -/** - * @brief DMA stream used for USART6 TX operations. - * @note This option is only available on platforms with enhanced DMA. - */ -#if !defined(STM32_UART_USART6_TX_DMA_STREAM) || defined(__DOXYGEN__) -#define STM32_UART_USART6_TX_DMA_STREAM STM32_DMA_STREAM_ID(2, 7) -#endif - -#else /* !STM32_ADVANCED_DMA */ - -/* Fixed streams for platforms using the old DMA peripheral, the values are - valid for both STM32F1xx and STM32L1xx.*/ -#define STM32_UART_USART1_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 5) -#define STM32_UART_USART1_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) -#define STM32_UART_USART2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 6) -#define STM32_UART_USART2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7) -#define STM32_UART_USART3_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 3) -#define STM32_UART_USART3_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2) -#define STM32_UART_UART4_RX_DMA_STREAM STM32_DMA_STREAM_ID(2, 3) -#define STM32_UART_UART4_TX_DMA_STREAM STM32_DMA_STREAM_ID(2, 5) - -#endif /* !STM32_ADVANCED_DMA*/ -/** @} */ - -/*===========================================================================*/ -/* Derived constants and error checks. */ -/*===========================================================================*/ - -#if STM32_UART_USE_USART1 && !STM32_HAS_USART1 -#error "USART1 not present in the selected device" -#endif - -#if STM32_UART_USE_USART2 && !STM32_HAS_USART2 -#error "USART2 not present in the selected device" -#endif - -#if STM32_UART_USE_USART3 && !STM32_HAS_USART3 -#error "USART3 not present in the selected device" -#endif - -#if STM32_UART_USE_UART4 - #if !STM32_HAS_UART4 - #error "UART4 not present in the selected device" - #endif - - #if !defined(STM32F4XX) || !defined(STM32F4XX) - #error "UART4 DMA access not supported in this platform" - #endif -#endif - -#if STM32_UART_USE_UART5 - #if !STM32_HAS_UART5 - #error "UART5 not present in the selected device" - #endif - - #if !defined(STM32F4XX) || !defined(STM32F4XX) - #error "UART5 DMA access not supported in this platform" - #endif -#endif - -#if STM32_UART_USE_USART6 && !STM32_HAS_USART6 -#error "USART6 not present in the selected device" -#endif - -#if !STM32_UART_USE_USART1 && !STM32_UART_USE_USART2 && \ - !STM32_UART_USE_USART3 && !STM32_UART_USE_UART4 && \ - !STM32_UART_USE_UART5 && !STM32_UART_USE_USART6 -#error "UART driver activated but no USART/UART peripheral assigned" -#endif - -#if STM32_UART_USE_USART1 && \ - !CORTEX_IS_VALID_KERNEL_PRIORITY(STM32_UART_USART1_IRQ_PRIORITY) -#error "Invalid IRQ priority assigned to USART1" -#endif - -#if STM32_UART_USE_USART2 && \ - !CORTEX_IS_VALID_KERNEL_PRIORITY(STM32_UART_USART2_IRQ_PRIORITY) -#error "Invalid IRQ priority assigned to USART2" -#endif - -#if STM32_UART_USE_USART3 && \ - !CORTEX_IS_VALID_KERNEL_PRIORITY(STM32_UART_USART3_IRQ_PRIORITY) -#error "Invalid IRQ priority assigned to USART3" -#endif - -#if STM32_UART_USE_UART4 && \ - !CORTEX_IS_VALID_KERNEL_PRIORITY(STM32_UART_UART4_IRQ_PRIORITY) -#error "Invalid IRQ priority assigned to UART4" -#endif - -#if STM32_UART_USE_UART5 && \ - !CORTEX_IS_VALID_KERNEL_PRIORITY(STM32_UART_UART5_IRQ_PRIORITY) -#error "Invalid IRQ priority assigned to UART5" -#endif - -#if STM32_UART_USE_USART6 && \ - !CORTEX_IS_VALID_KERNEL_PRIORITY(STM32_UART_USART6_IRQ_PRIORITY) -#error "Invalid IRQ priority assigned to USART6" -#endif - -#if STM32_UART_USE_USART1 && \ - !STM32_DMA_IS_VALID_PRIORITY(STM32_UART_USART1_DMA_PRIORITY) -#error "Invalid DMA priority assigned to USART1" -#endif - -#if STM32_UART_USE_USART2 && \ - !STM32_DMA_IS_VALID_PRIORITY(STM32_UART_USART2_DMA_PRIORITY) -#error "Invalid DMA priority assigned to USART2" -#endif - -#if STM32_UART_USE_USART3 && \ - !STM32_DMA_IS_VALID_PRIORITY(STM32_UART_USART3_DMA_PRIORITY) -#error "Invalid DMA priority assigned to USART3" -#endif - -#if STM32_UART_USE_UART4 && \ - !STM32_DMA_IS_VALID_PRIORITY(STM32_UART_UART4_DMA_PRIORITY) -#error "Invalid DMA priority assigned to UART4" -#endif - -#if STM32_UART_USE_UART5 && \ - !STM32_DMA_IS_VALID_PRIORITY(STM32_UART_UART5_DMA_PRIORITY) -#error "Invalid DMA priority assigned to UART5" -#endif - -#if STM32_UART_USE_USART6 && \ - !STM32_DMA_IS_VALID_PRIORITY(STM32_UART_USART6_DMA_PRIORITY) -#error "Invalid DMA priority assigned to USART6" -#endif - -#if STM32_UART_USE_USART1 && \ - !STM32_DMA_IS_VALID_ID(STM32_UART_USART1_RX_DMA_STREAM, \ - STM32_USART1_RX_DMA_MSK) -#error "invalid DMA stream associated to USART1 RX" -#endif - -#if STM32_UART_USE_USART1 && \ - !STM32_DMA_IS_VALID_ID(STM32_UART_USART1_TX_DMA_STREAM, \ - STM32_USART1_TX_DMA_MSK) -#error "invalid DMA stream associated to USART1 TX" -#endif - -#if STM32_UART_USE_USART2 && \ - !STM32_DMA_IS_VALID_ID(STM32_UART_USART2_RX_DMA_STREAM, \ - STM32_USART2_RX_DMA_MSK) -#error "invalid DMA stream associated to USART2 RX" -#endif - -#if STM32_UART_USE_USART2 && \ - !STM32_DMA_IS_VALID_ID(STM32_UART_USART2_TX_DMA_STREAM, \ - STM32_USART2_TX_DMA_MSK) -#error "invalid DMA stream associated to USART2 TX" -#endif - -#if STM32_UART_USE_USART3 && \ - !STM32_DMA_IS_VALID_ID(STM32_UART_USART3_RX_DMA_STREAM, \ - STM32_USART3_RX_DMA_MSK) -#error "invalid DMA stream associated to USART3 RX" -#endif - -#if STM32_UART_USE_USART3 && \ - !STM32_DMA_IS_VALID_ID(STM32_UART_USART3_TX_DMA_STREAM, \ - STM32_USART3_TX_DMA_MSK) -#error "invalid DMA stream associated to USART3 TX" -#endif - -#if STM32_UART_USE_UART4 && \ - !STM32_DMA_IS_VALID_ID(STM32_UART_UART4_RX_DMA_STREAM, \ - STM32_UART4_RX_DMA_MSK) -#error "invalid DMA stream associated to UART4 RX" -#endif - -#if STM32_UART_USE_UART4 && \ - !STM32_DMA_IS_VALID_ID(STM32_UART_UART4_TX_DMA_STREAM, \ - STM32_UART4_TX_DMA_MSK) -#error "invalid DMA stream associated to UART4 TX" -#endif - -#if STM32_UART_USE_UART5 && \ - !STM32_DMA_IS_VALID_ID(STM32_UART_UART5_RX_DMA_STREAM, \ - STM32_UART5_RX_DMA_MSK) -#error "invalid DMA stream associated to UART5 RX" -#endif - -#if STM32_UART_USE_UART5 && \ - !STM32_DMA_IS_VALID_ID(STM32_UART_UART5_TX_DMA_STREAM, \ - STM32_UART5_TX_DMA_MSK) -#error "invalid DMA stream associated to UART5 TX" -#endif - -#if STM32_UART_USE_USART6 && \ - !STM32_DMA_IS_VALID_ID(STM32_UART_USART6_RX_DMA_STREAM, \ - STM32_USART6_RX_DMA_MSK) -#error "invalid DMA stream associated to USART6 RX" -#endif - -#if STM32_UART_USE_USART6 && \ - !STM32_DMA_IS_VALID_ID(STM32_UART_USART6_TX_DMA_STREAM, \ - STM32_USART6_TX_DMA_MSK) -#error "invalid DMA stream associated to USART6 TX" -#endif - -#if !defined(STM32_DMA_REQUIRED) -#define STM32_DMA_REQUIRED -#endif - -/*===========================================================================*/ -/* Driver data structures and types. */ -/*===========================================================================*/ - -/** - * @brief UART driver condition flags type. - */ -typedef uint32_t uartflags_t; - -/** - * @brief Structure representing an UART driver. - */ -typedef struct UARTDriver UARTDriver; - -/** - * @brief Generic UART notification callback type. - * - * @param[in] uartp pointer to the @p UARTDriver object - */ -typedef void (*uartcb_t)(UARTDriver *uartp); - -/** - * @brief Character received UART notification callback type. - * - * @param[in] uartp pointer to the @p UARTDriver object - * @param[in] c received character - */ -typedef void (*uartccb_t)(UARTDriver *uartp, uint16_t c); - -/** - * @brief Receive error UART notification callback type. - * - * @param[in] uartp pointer to the @p UARTDriver object - * @param[in] e receive error mask - */ -typedef void (*uartecb_t)(UARTDriver *uartp, uartflags_t e); - -/** - * @brief Driver configuration structure. - * @note It could be empty on some architectures. - */ -typedef struct { - /** - * @brief End of transmission buffer callback. - */ - uartcb_t txend1_cb; - /** - * @brief Physical end of transmission callback. - */ - uartcb_t txend2_cb; - /** - * @brief Receive buffer filled callback. - */ - uartcb_t rxend_cb; - /** - * @brief Character received while out if the @p UART_RECEIVE state. - */ - uartccb_t rxchar_cb; - /** - * @brief Receive error callback. - */ - uartecb_t rxerr_cb; - /* End of the mandatory fields.*/ - /** - * @brief Bit rate. - */ - uint32_t speed; - /** - * @brief Initialization value for the CR1 register. - */ - uint16_t cr1; - /** - * @brief Initialization value for the CR2 register. - */ - uint16_t cr2; - /** - * @brief Initialization value for the CR3 register. - */ - uint16_t cr3; -} UARTConfig; - -/** - * @brief Structure representing an UART driver. - */ -struct UARTDriver { - /** - * @brief Driver state. - */ - uartstate_t state; - /** - * @brief Transmitter state. - */ - uarttxstate_t txstate; - /** - * @brief Receiver state. - */ - uartrxstate_t rxstate; - /** - * @brief Current configuration data. - */ - const UARTConfig *config; -#if defined(UART_DRIVER_EXT_FIELDS) - UART_DRIVER_EXT_FIELDS -#endif - /* End of the mandatory fields.*/ - /** - * @brief Pointer to the USART registers block. - */ - USART_TypeDef *usart; - /** - * @brief DMA mode bit mask. - */ - uint32_t dmamode; - /** - * @brief Receive DMA channel. - */ - const stm32_dma_stream_t *dmarx; - /** - * @brief Transmit DMA channel. - */ - const stm32_dma_stream_t *dmatx; - /** - * @brief Default receive buffer while into @p UART_RX_IDLE state. - */ - volatile uint16_t rxbuf; -}; - -/*===========================================================================*/ -/* Driver macros. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* External declarations. */ -/*===========================================================================*/ - -#if STM32_UART_USE_USART1 && !defined(__DOXYGEN__) -extern UARTDriver UARTD1; -#endif - -#if STM32_UART_USE_USART2 && !defined(__DOXYGEN__) -extern UARTDriver UARTD2; -#endif - -#if STM32_UART_USE_USART3 && !defined(__DOXYGEN__) -extern UARTDriver UARTD3; -#endif - -#if STM32_UART_USE_UART4 && !defined(__DOXYGEN__) -extern UARTDriver UARTD4; -#endif - -#if STM32_UART_USE_UART5 && !defined(__DOXYGEN__) -extern UARTDriver UARTD5; -#endif - -#if STM32_UART_USE_USART6 && !defined(__DOXYGEN__) -extern UARTDriver UARTD6; -#endif - -#ifdef __cplusplus -extern "C" { -#endif - void uart_lld_init(void); - void uart_lld_start(UARTDriver *uartp); - void uart_lld_stop(UARTDriver *uartp); - void uart_lld_start_send(UARTDriver *uartp, size_t n, const void *txbuf); - size_t uart_lld_stop_send(UARTDriver *uartp); - void uart_lld_start_receive(UARTDriver *uartp, size_t n, void *rxbuf); - size_t uart_lld_stop_receive(UARTDriver *uartp); -#ifdef __cplusplus -} -#endif - -#endif /* HAL_USE_UART */ - -#endif /* _UART_LLD_H_ */ - -/** @} */ diff --git a/os/hal/platforms/STM32/USARTv2/serial_lld.c b/os/hal/platforms/STM32/USARTv2/serial_lld.c deleted file mode 100644 index 38042003e..000000000 --- a/os/hal/platforms/STM32/USARTv2/serial_lld.c +++ /dev/null @@ -1,522 +0,0 @@ -/* - ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file STM32/USARTv2/serial_lld.c - * @brief STM32 low level serial driver code. - * - * @addtogroup SERIAL - * @{ - */ - -#include "hal.h" - -#if HAL_USE_SERIAL || defined(__DOXYGEN__) - -/*===========================================================================*/ -/* Driver local definitions. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver exported variables. */ -/*===========================================================================*/ - -/** @brief USART1 serial driver identifier.*/ -#if STM32_SERIAL_USE_USART1 || defined(__DOXYGEN__) -SerialDriver SD1; -#endif - -/** @brief USART2 serial driver identifier.*/ -#if STM32_SERIAL_USE_USART2 || defined(__DOXYGEN__) -SerialDriver SD2; -#endif - -/** @brief USART3 serial driver identifier.*/ -#if STM32_SERIAL_USE_USART3 || defined(__DOXYGEN__) -SerialDriver SD3; -#endif - -/** @brief UART4 serial driver identifier.*/ -#if STM32_SERIAL_USE_UART4 || defined(__DOXYGEN__) -SerialDriver SD4; -#endif - -/** @brief UART5 serial driver identifier.*/ -#if STM32_SERIAL_USE_UART5 || defined(__DOXYGEN__) -SerialDriver SD5; -#endif - -/** @brief USART6 serial driver identifier.*/ -#if STM32_SERIAL_USE_USART6 || defined(__DOXYGEN__) -SerialDriver SD6; -#endif - -/*===========================================================================*/ -/* Driver local variables and types. */ -/*===========================================================================*/ - -/** @brief Driver default configuration.*/ -static const SerialConfig default_config = -{ - SERIAL_DEFAULT_BITRATE, - 0, - USART_CR2_STOP1_BITS | USART_CR2_LINEN, - 0 -}; - -/*===========================================================================*/ -/* Driver local functions. */ -/*===========================================================================*/ - -/** - * @brief USART initialization. - * @details This function must be invoked with interrupts disabled. - * - * @param[in] sdp pointer to a @p SerialDriver object - * @param[in] config the architecture-dependent serial driver configuration - */ -static void usart_init(SerialDriver *sdp, const SerialConfig *config) { - USART_TypeDef *u = sdp->usart; - - /* Baud rate setting.*/ - u->BRR = (uint16_t)(sdp->clock / config->speed); - - /* Note that some bits are enforced.*/ - u->CR2 = config->cr2 | USART_CR2_LBDIE; - u->CR3 = config->cr3 | USART_CR3_EIE; - u->CR1 = config->cr1 | USART_CR1_UE | USART_CR1_PEIE | - USART_CR1_RXNEIE | USART_CR1_TE | - USART_CR1_RE; - u->ICR = 0xFFFFFFFF; -} - -/** - * @brief USART de-initialization. - * @details This function must be invoked with interrupts disabled. - * - * @param[in] u pointer to an USART I/O block - */ -static void usart_deinit(USART_TypeDef *u) { - - u->CR1 = 0; - u->CR2 = 0; - u->CR3 = 0; -} - -/** - * @brief Error handling routine. - * - * @param[in] sdp pointer to a @p SerialDriver object - * @param[in] isr USART ISR register value - */ -static void set_error(SerialDriver *sdp, uint32_t isr) { - eventflags_t sts = 0; - - if (isr & USART_ISR_ORE) - sts |= SD_OVERRUN_ERROR; - if (isr & USART_ISR_PE) - sts |= SD_PARITY_ERROR; - if (isr & USART_ISR_FE) - sts |= SD_FRAMING_ERROR; - if (isr & USART_ISR_NE) - sts |= SD_NOISE_ERROR; - osalSysLockFromISR(); - chnAddFlagsI(sdp, sts); - osalSysUnlockFromISR(); -} - -/** - * @brief Common IRQ handler. - * - * @param[in] sdp communication channel associated to the USART - */ -static void serve_interrupt(SerialDriver *sdp) { - USART_TypeDef *u = sdp->usart; - uint32_t cr1 = u->CR1; - uint32_t isr; - - /* Reading and clearing status.*/ - isr = u->ISR; - u->ICR = isr; - - /* Error condition detection.*/ - if (isr & (USART_ISR_ORE | USART_ISR_NE | USART_ISR_FE | USART_ISR_PE)) - set_error(sdp, isr); - /* Special case, LIN break detection.*/ - if (isr & USART_ISR_LBD) { - osalSysLockFromISR(); - chnAddFlagsI(sdp, SD_BREAK_DETECTED); - osalSysUnlockFromISR(); - } - /* Data available.*/ - if (isr & USART_ISR_RXNE) { - osalSysLockFromISR(); - sdIncomingDataI(sdp, (uint8_t)u->RDR); - osalSysUnlockFromISR(); - } - /* Transmission buffer empty.*/ - if ((cr1 & USART_CR1_TXEIE) && (isr & USART_ISR_TXE)) { - msg_t b; - osalSysLockFromISR(); - b = oqGetI(&sdp->oqueue); - if (b < Q_OK) { - chnAddFlagsI(sdp, CHN_OUTPUT_EMPTY); - u->CR1 = (cr1 & ~USART_CR1_TXEIE) | USART_CR1_TCIE; - } - else - u->TDR = b; - osalSysUnlockFromISR(); - } - /* Physical transmission end.*/ - if (isr & USART_ISR_TC) { - osalSysLockFromISR(); - chnAddFlagsI(sdp, CHN_TRANSMISSION_END); - osalSysUnlockFromISR(); - u->CR1 = cr1 & ~USART_CR1_TCIE; - } -} - -#if STM32_SERIAL_USE_USART1 || defined(__DOXYGEN__) -static void notify1(io_queue_t *qp) { - - (void)qp; - USART1->CR1 |= USART_CR1_TXEIE; -} -#endif - -#if STM32_SERIAL_USE_USART2 || defined(__DOXYGEN__) -static void notify2(io_queue_t *qp) { - - (void)qp; - USART2->CR1 |= USART_CR1_TXEIE; -} -#endif - -#if STM32_SERIAL_USE_USART3 || defined(__DOXYGEN__) -static void notify3(io_queue_t *qp) { - - (void)qp; - USART3->CR1 |= USART_CR1_TXEIE; -} -#endif - -#if STM32_SERIAL_USE_UART4 || defined(__DOXYGEN__) -static void notify4(io_queue_t *qp) { - - (void)qp; - UART4->CR1 |= USART_CR1_TXEIE; -} -#endif - -#if STM32_SERIAL_USE_UART5 || defined(__DOXYGEN__) -static void notify5(io_queue_t *qp) { - - (void)qp; - UART5->CR1 |= USART_CR1_TXEIE; -} -#endif - -#if STM32_SERIAL_USE_USART6 || defined(__DOXYGEN__) -static void notify6(io_queue_t *qp) { - - (void)qp; - USART6->CR1 |= USART_CR1_TXEIE; -} -#endif - -/*===========================================================================*/ -/* Driver interrupt handlers. */ -/*===========================================================================*/ - -#if STM32_SERIAL_USE_USART1 || defined(__DOXYGEN__) -#if !defined(STM32_USART1_HANDLER) -#error "STM32_USART1_HANDLER not defined" -#endif -/** - * @brief USART1 interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(STM32_USART1_HANDLER) { - - OSAL_IRQ_PROLOGUE(); - - serve_interrupt(&SD1); - - OSAL_IRQ_EPILOGUE(); -} -#endif - -#if STM32_SERIAL_USE_USART2 || defined(__DOXYGEN__) -#if !defined(STM32_USART2_HANDLER) -#error "STM32_USART2_HANDLER not defined" -#endif -/** - * @brief USART2 interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(STM32_USART2_HANDLER) { - - OSAL_IRQ_PROLOGUE(); - - serve_interrupt(&SD2); - - OSAL_IRQ_EPILOGUE(); -} -#endif - -#if STM32_SERIAL_USE_USART3 || defined(__DOXYGEN__) -#if !defined(STM32_USART3_HANDLER) -#error "STM32_USART3_HANDLER not defined" -#endif -/** - * @brief USART3 interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(STM32_USART3_HANDLER) { - - OSAL_IRQ_PROLOGUE(); - - serve_interrupt(&SD3); - - OSAL_IRQ_EPILOGUE(); -} -#endif - -#if STM32_SERIAL_USE_UART4 || defined(__DOXYGEN__) -#if !defined(STM32_UART4_HANDLER) -#error "STM32_UART4_HANDLER not defined" -#endif -/** - * @brief UART4 interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(STM32_UART4_HANDLER) { - - OSAL_IRQ_PROLOGUE(); - - serve_interrupt(&SD4); - - OSAL_IRQ_EPILOGUE(); -} -#endif - -#if STM32_SERIAL_USE_UART5 || defined(__DOXYGEN__) -#if !defined(STM32_UART5_HANDLER) -#error "STM32_UART5_HANDLER not defined" -#endif -/** - * @brief UART5 interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(STM32_UART5_HANDLER) { - - OSAL_IRQ_PROLOGUE(); - - serve_interrupt(&SD5); - - OSAL_IRQ_EPILOGUE(); -} -#endif - -#if STM32_SERIAL_USE_USART6 || defined(__DOXYGEN__) -#if !defined(STM32_USART6_HANDLER) -#error "STM32_USART6_HANDLER not defined" -#endif -/** - * @brief USART1 interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(STM32_USART6_HANDLER) { - - OSAL_IRQ_PROLOGUE(); - - serve_interrupt(&SD6); - - OSAL_IRQ_EPILOGUE(); -} -#endif - -/*===========================================================================*/ -/* Driver exported functions. */ -/*===========================================================================*/ - -/** - * @brief Low level serial driver initialization. - * - * @notapi - */ -void sd_lld_init(void) { - -#if STM32_SERIAL_USE_USART1 - sdObjectInit(&SD1, NULL, notify1); - SD1.usart = USART1; - SD1.clock = STM32_USART1CLK; -#endif - -#if STM32_SERIAL_USE_USART2 - sdObjectInit(&SD2, NULL, notify2); - SD2.usart = USART2; - SD2.clock = STM32_USART2CLK; -#endif - -#if STM32_SERIAL_USE_USART3 - sdObjectInit(&SD3, NULL, notify3); - SD3.usart = USART3; - SD3.clock = STM32_USART3CLK; -#endif - -#if STM32_SERIAL_USE_UART4 - sdObjectInit(&SD4, NULL, notify4); - SD4.usart = UART4; - SD4.clock = STM32_UART4CLK; -#endif - -#if STM32_SERIAL_USE_UART5 - sdObjectInit(&SD5, NULL, notify5); - SD5.usart = UART5; - SD5.clock = STM32_UART5CLK; -#endif - -#if STM32_SERIAL_USE_USART6 - sdObjectInit(&SD6, NULL, notify6); - SD6.usart = USART6; - SD6.clock = STM32_USART6CLK; -#endif -} - -/** - * @brief Low level serial driver configuration and (re)start. - * - * @param[in] sdp pointer to a @p SerialDriver object - * @param[in] config the architecture-dependent serial driver configuration. - * If this parameter is set to @p NULL then a default - * configuration is used. - * - * @notapi - */ -void sd_lld_start(SerialDriver *sdp, const SerialConfig *config) { - - if (config == NULL) - config = &default_config; - - if (sdp->state == SD_STOP) { -#if STM32_SERIAL_USE_USART1 - if (&SD1 == sdp) { - rccEnableUSART1(FALSE); - nvicEnableVector(STM32_USART1_NUMBER, STM32_SERIAL_USART1_PRIORITY); - } -#endif -#if STM32_SERIAL_USE_USART2 - if (&SD2 == sdp) { - rccEnableUSART2(FALSE); - nvicEnableVector(STM32_USART2_NUMBER, STM32_SERIAL_USART2_PRIORITY); - } -#endif -#if STM32_SERIAL_USE_USART3 - if (&SD3 == sdp) { - rccEnableUSART3(FALSE); - nvicEnableVector(STM32_USART3_NUMBER, STM32_SERIAL_USART3_PRIORITY); - } -#endif -#if STM32_SERIAL_USE_UART4 - if (&SD4 == sdp) { - rccEnableUART4(FALSE); - nvicEnableVector(STM32_UART4_NUMBER, STM32_SERIAL_UART4_PRIORITY); - } -#endif -#if STM32_SERIAL_USE_UART5 - if (&SD5 == sdp) { - rccEnableUART5(FALSE); - nvicEnableVector(STM32_UART5_NUMBER, STM32_SERIAL_UART5_PRIORITY); - } -#endif -#if STM32_SERIAL_USE_USART6 - if (&SD6 == sdp) { - rccEnableUSART6(FALSE); - nvicEnableVector(STM32_USART6_NUMBER, STM32_SERIAL_USART6_PRIORITY); - } -#endif - } - usart_init(sdp, config); -} - -/** - * @brief Low level serial driver stop. - * @details De-initializes the USART, stops the associated clock, resets the - * interrupt vector. - * - * @param[in] sdp pointer to a @p SerialDriver object - * - * @notapi - */ -void sd_lld_stop(SerialDriver *sdp) { - - if (sdp->state == SD_READY) { - usart_deinit(sdp->usart); -#if STM32_SERIAL_USE_USART1 - if (&SD1 == sdp) { - rccDisableUSART1(FALSE); - nvicDisableVector(STM32_USART1_NUMBER); - return; - } -#endif -#if STM32_SERIAL_USE_USART2 - if (&SD2 == sdp) { - rccDisableUSART2(FALSE); - nvicDisableVector(STM32_USART2_NUMBER); - return; - } -#endif -#if STM32_SERIAL_USE_USART3 - if (&SD3 == sdp) { - rccDisableUSART3(FALSE); - nvicDisableVector(STM32_USART3_NUMBER); - return; - } -#endif -#if STM32_SERIAL_USE_UART4 - if (&SD4 == sdp) { - rccDisableUART4(FALSE); - nvicDisableVector(STM32_UART4_NUMBER); - return; - } -#endif -#if STM32_SERIAL_USE_UART5 - if (&SD5 == sdp) { - rccDisableUART5(FALSE); - nvicDisableVector(STM32_UART5_NUMBER); - return; - } -#endif -#if STM32_SERIAL_USE_USART6 - if (&SD6 == sdp) { - rccDisableUSART6(FALSE); - nvicDisableVector(STM32_USART6_NUMBER); - return; - } -#endif - } -} - -#endif /* HAL_USE_SERIAL */ - -/** @} */ diff --git a/os/hal/platforms/STM32/USARTv2/serial_lld.h b/os/hal/platforms/STM32/USARTv2/serial_lld.h deleted file mode 100644 index ac7415895..000000000 --- a/os/hal/platforms/STM32/USARTv2/serial_lld.h +++ /dev/null @@ -1,305 +0,0 @@ -/* - ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file STM32/USARTv2/serial_lld.h - * @brief STM32 low level serial driver header. - * - * @addtogroup SERIAL - * @{ - */ - -#ifndef _SERIAL_LLD_H_ -#define _SERIAL_LLD_H_ - -#if HAL_USE_SERIAL || defined(__DOXYGEN__) - -/*===========================================================================*/ -/* Driver constants. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver pre-compile time settings. */ -/*===========================================================================*/ - -/** - * @name Configuration options - * @{ - */ -/** - * @brief USART1 driver enable switch. - * @details If set to @p TRUE the support for USART1 is included. - * @note The default is @p TRUE. - */ -#if !defined(STM32_SERIAL_USE_USART1) || defined(__DOXYGEN__) -#define STM32_SERIAL_USE_USART1 FALSE -#endif - -/** - * @brief USART2 driver enable switch. - * @details If set to @p TRUE the support for USART2 is included. - * @note The default is @p TRUE. - */ -#if !defined(STM32_SERIAL_USE_USART2) || defined(__DOXYGEN__) -#define STM32_SERIAL_USE_USART2 FALSE -#endif - -/** - * @brief USART3 driver enable switch. - * @details If set to @p TRUE the support for USART3 is included. - * @note The default is @p TRUE. - */ -#if !defined(STM32_SERIAL_USE_USART3) || defined(__DOXYGEN__) -#define STM32_SERIAL_USE_USART3 FALSE -#endif - -/** - * @brief UART4 driver enable switch. - * @details If set to @p TRUE the support for UART4 is included. - * @note The default is @p TRUE. - */ -#if !defined(STM32_SERIAL_USE_UART4) || defined(__DOXYGEN__) -#define STM32_SERIAL_USE_UART4 FALSE -#endif - -/** - * @brief UART5 driver enable switch. - * @details If set to @p TRUE the support for UART5 is included. - * @note The default is @p TRUE. - */ -#if !defined(STM32_SERIAL_USE_UART5) || defined(__DOXYGEN__) -#define STM32_SERIAL_USE_UART5 FALSE -#endif - -/** - * @brief USART6 driver enable switch. - * @details If set to @p TRUE the support for USART6 is included. - * @note The default is @p TRUE. - */ -#if !defined(STM32_SERIAL_USE_USART6) || defined(__DOXYGEN__) -#define STM32_SERIAL_USE_USART6 FALSE -#endif - -/** - * @brief USART1 interrupt priority level setting. - */ -#if !defined(STM32_SERIAL_USART1_PRIORITY) || defined(__DOXYGEN__) -#define STM32_SERIAL_USART1_PRIORITY 12 -#endif - -/** - * @brief USART2 interrupt priority level setting. - */ -#if !defined(STM32_SERIAL_USART2_PRIORITY) || defined(__DOXYGEN__) -#define STM32_SERIAL_USART2_PRIORITY 12 -#endif - -/** - * @brief USART3 interrupt priority level setting. - */ -#if !defined(STM32_SERIAL_USART3_PRIORITY) || defined(__DOXYGEN__) -#define STM32_SERIAL_USART3_PRIORITY 12 -#endif - -/** - * @brief UART4 interrupt priority level setting. - */ -#if !defined(STM32_SERIAL_UART4_PRIORITY) || defined(__DOXYGEN__) -#define STM32_SERIAL_UART4_PRIORITY 12 -#endif - -/** - * @brief UART5 interrupt priority level setting. - */ -#if !defined(STM32_SERIAL_UART5_PRIORITY) || defined(__DOXYGEN__) -#define STM32_SERIAL_UART5_PRIORITY 12 -#endif - -/** - * @brief USART6 interrupt priority level setting. - */ -#if !defined(STM32_SERIAL_USART6_PRIORITY) || defined(__DOXYGEN__) -#define STM32_SERIAL_USART6_PRIORITY 12 -#endif -/** @} */ - -/*===========================================================================*/ -/* Derived constants and error checks. */ -/*===========================================================================*/ - -#if STM32_SERIAL_USE_USART1 && !STM32_HAS_USART1 -#error "USART1 not present in the selected device" -#endif - -#if STM32_SERIAL_USE_USART2 && !STM32_HAS_USART2 -#error "USART2 not present in the selected device" -#endif - -#if STM32_SERIAL_USE_USART3 && !STM32_HAS_USART3 -#error "USART3 not present in the selected device" -#endif - -#if STM32_SERIAL_USE_UART4 && !STM32_HAS_UART4 -#error "UART4 not present in the selected device" -#endif - -#if STM32_SERIAL_USE_UART5 && !STM32_HAS_UART5 -#error "UART5 not present in the selected device" -#endif - -#if STM32_SERIAL_USE_USART6 && !STM32_HAS_USART6 -#error "USART6 not present in the selected device" -#endif - -#if !STM32_SERIAL_USE_USART1 && !STM32_SERIAL_USE_USART2 && \ - !STM32_SERIAL_USE_USART3 && !STM32_SERIAL_USE_UART4 && \ - !STM32_SERIAL_USE_UART5 && !STM32_SERIAL_USE_USART6 -#error "SERIAL driver activated but no USART/UART peripheral assigned" -#endif - -#if STM32_SERIAL_USE_USART1 && \ - !CORTEX_IS_VALID_KERNEL_PRIORITY(STM32_SERIAL_USART1_PRIORITY) -#error "Invalid IRQ priority assigned to USART1" -#endif - -#if STM32_SERIAL_USE_USART2 && \ - !CORTEX_IS_VALID_KERNEL_PRIORITY(STM32_SERIAL_USART2_PRIORITY) -#error "Invalid IRQ priority assigned to USART2" -#endif - -#if STM32_SERIAL_USE_USART3 && \ - !CORTEX_IS_VALID_KERNEL_PRIORITY(STM32_SERIAL_USART3_PRIORITY) -#error "Invalid IRQ priority assigned to USART3" -#endif - -#if STM32_SERIAL_USE_UART4 && \ - !CORTEX_IS_VALID_KERNEL_PRIORITY(STM32_SERIAL_UART4_PRIORITY) -#error "Invalid IRQ priority assigned to UART4" -#endif - -#if STM32_SERIAL_USE_UART5 && \ - !CORTEX_IS_VALID_KERNEL_PRIORITY(STM32_SERIAL_UART5_PRIORITY) -#error "Invalid IRQ priority assigned to UART5" -#endif - -#if STM32_SERIAL_USE_USART6 && \ - !CORTEX_IS_VALID_KERNEL_PRIORITY(STM32_SERIAL_USART6_PRIORITY) -#error "Invalid IRQ priority assigned to USART6" -#endif - -/*===========================================================================*/ -/* Driver data structures and types. */ -/*===========================================================================*/ - -/** - * @brief STM32 Serial Driver configuration structure. - * @details An instance of this structure must be passed to @p sdStart() - * in order to configure and start a serial driver operations. - * @note This structure content is architecture dependent, each driver - * implementation defines its own version and the custom static - * initializers. - */ -typedef struct { - /** - * @brief Bit rate. - */ - uint32_t speed; - /* End of the mandatory fields.*/ - /** - * @brief Initialization value for the CR1 register. - */ - uint32_t cr1; - /** - * @brief Initialization value for the CR2 register. - */ - uint32_t cr2; - /** - * @brief Initialization value for the CR3 register. - */ - uint32_t cr3; -} SerialConfig; - -/** - * @brief @p SerialDriver specific data. - */ -#define _serial_driver_data \ - _base_asynchronous_channel_data \ - /* Driver state.*/ \ - sdstate_t state; \ - /* Input queue.*/ \ - input_queue_t iqueue; \ - /* Output queue.*/ \ - output_queue_t oqueue; \ - /* Input circular buffer.*/ \ - uint8_t ib[SERIAL_BUFFERS_SIZE]; \ - /* Output circular buffer.*/ \ - uint8_t ob[SERIAL_BUFFERS_SIZE]; \ - /* End of the mandatory fields.*/ \ - /* Pointer to the USART registers block.*/ \ - USART_TypeDef *usart; \ - /* Clock frequency for the associated USART/UART.*/ \ - uint32_t clock; - -/*===========================================================================*/ -/* Driver macros. */ -/*===========================================================================*/ - -/* - * Extra USARTs definitions here (missing from the ST header file). - */ -#define USART_CR2_STOP1_BITS (0 << 12) /**< @brief CR2 1 stop bit value.*/ -#define USART_CR2_STOP0P5_BITS (1 << 12) /**< @brief CR2 0.5 stop bit value.*/ -#define USART_CR2_STOP2_BITS (2 << 12) /**< @brief CR2 2 stop bit value.*/ -#define USART_CR2_STOP1P5_BITS (3 << 12) /**< @brief CR2 1.5 stop bit value.*/ - -/*===========================================================================*/ -/* External declarations. */ -/*===========================================================================*/ - -#if STM32_SERIAL_USE_USART1 && !defined(__DOXYGEN__) -extern SerialDriver SD1; -#endif -#if STM32_SERIAL_USE_USART2 && !defined(__DOXYGEN__) -extern SerialDriver SD2; -#endif -#if STM32_SERIAL_USE_USART3 && !defined(__DOXYGEN__) -extern SerialDriver SD3; -#endif -#if STM32_SERIAL_USE_UART4 && !defined(__DOXYGEN__) -extern SerialDriver SD4; -#endif -#if STM32_SERIAL_USE_UART5 && !defined(__DOXYGEN__) -extern SerialDriver SD5; -#endif -#if STM32_SERIAL_USE_USART6 && !defined(__DOXYGEN__) -extern SerialDriver SD6; -#endif - -#ifdef __cplusplus -extern "C" { -#endif - void sd_lld_init(void); - void sd_lld_start(SerialDriver *sdp, const SerialConfig *config); - void sd_lld_stop(SerialDriver *sdp); -#ifdef __cplusplus -} -#endif - -#endif /* HAL_USE_SERIAL */ - -#endif /* _SERIAL_LLD_H_ */ - -/** @} */ diff --git a/os/hal/platforms/STM32/USARTv2/uart_lld.c b/os/hal/platforms/STM32/USARTv2/uart_lld.c deleted file mode 100644 index 0b85a294c..000000000 --- a/os/hal/platforms/STM32/USARTv2/uart_lld.c +++ /dev/null @@ -1,590 +0,0 @@ -/* - ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file STM32/USARTv2/uart_lld.c - * @brief STM32 low level UART driver code. - * - * @addtogroup UART - * @{ - */ - -#include "hal.h" - -#if HAL_USE_UART || defined(__DOXYGEN__) - -/*===========================================================================*/ -/* Driver local definitions. */ -/*===========================================================================*/ - -#define USART1_RX_DMA_CHANNEL \ - STM32_DMA_GETCHANNEL(STM32_UART_USART1_RX_DMA_STREAM, \ - STM32_USART1_RX_DMA_CHN) - -#define USART1_TX_DMA_CHANNEL \ - STM32_DMA_GETCHANNEL(STM32_UART_USART1_TX_DMA_STREAM, \ - STM32_USART1_TX_DMA_CHN) - -#define USART2_RX_DMA_CHANNEL \ - STM32_DMA_GETCHANNEL(STM32_UART_USART2_RX_DMA_STREAM, \ - STM32_USART2_RX_DMA_CHN) - -#define USART2_TX_DMA_CHANNEL \ - STM32_DMA_GETCHANNEL(STM32_UART_USART2_TX_DMA_STREAM, \ - STM32_USART2_TX_DMA_CHN) - -#define USART3_RX_DMA_CHANNEL \ - STM32_DMA_GETCHANNEL(STM32_UART_USART3_RX_DMA_STREAM, \ - STM32_USART3_RX_DMA_CHN) - -#define USART3_TX_DMA_CHANNEL \ - STM32_DMA_GETCHANNEL(STM32_UART_USART3_TX_DMA_STREAM, \ - STM32_USART3_TX_DMA_CHN) - -/*===========================================================================*/ -/* Driver exported variables. */ -/*===========================================================================*/ - -/** @brief USART1 UART driver identifier.*/ -#if STM32_UART_USE_USART1 || defined(__DOXYGEN__) -UARTDriver UARTD1; -#endif - -/** @brief USART2 UART driver identifier.*/ -#if STM32_UART_USE_USART2 || defined(__DOXYGEN__) -UARTDriver UARTD2; -#endif - -/** @brief USART3 UART driver identifier.*/ -#if STM32_UART_USE_USART3 || defined(__DOXYGEN__) -UARTDriver UARTD3; -#endif - -/*===========================================================================*/ -/* Driver local variables and types. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver local functions. */ -/*===========================================================================*/ - -/** - * @brief Status bits translation. - * - * @param[in] sr USART SR register value - * - * @return The error flags. - */ -static uartflags_t translate_errors(uint32_t isr) { - uartflags_t sts = 0; - - if (isr & USART_ISR_ORE) - sts |= UART_OVERRUN_ERROR; - if (isr & USART_ISR_PE) - sts |= UART_PARITY_ERROR; - if (isr & USART_ISR_FE) - sts |= UART_FRAMING_ERROR; - if (isr & USART_ISR_NE) - sts |= UART_NOISE_ERROR; - if (isr & USART_ISR_LBD) - sts |= UART_BREAK_DETECTED; - return sts; -} - -/** - * @brief Puts the receiver in the UART_RX_IDLE state. - * - * @param[in] uartp pointer to the @p UARTDriver object - */ -static void set_rx_idle_loop(UARTDriver *uartp) { - uint32_t mode; - - /* RX DMA channel preparation, if the char callback is defined then the - TCIE interrupt is enabled too.*/ - if (uartp->config->rxchar_cb == NULL) - mode = STM32_DMA_CR_DIR_P2M | STM32_DMA_CR_CIRC; - else - mode = STM32_DMA_CR_DIR_P2M | STM32_DMA_CR_CIRC | STM32_DMA_CR_TCIE; - dmaStreamSetMemory0(uartp->dmarx, &uartp->rxbuf); - dmaStreamSetTransactionSize(uartp->dmarx, 1); - dmaStreamSetMode(uartp->dmarx, uartp->dmamode | mode); - dmaStreamEnable(uartp->dmarx); -} - -/** - * @brief USART de-initialization. - * @details This function must be invoked with interrupts disabled. - * - * @param[in] uartp pointer to the @p UARTDriver object - */ -static void usart_stop(UARTDriver *uartp) { - - /* Stops RX and TX DMA channels.*/ - dmaStreamDisable(uartp->dmarx); - dmaStreamDisable(uartp->dmatx); - - /* Stops USART operations.*/ - uartp->usart->CR1 = 0; - uartp->usart->CR2 = 0; - uartp->usart->CR3 = 0; -} - -/** - * @brief USART initialization. - * @details This function must be invoked with interrupts disabled. - * - * @param[in] uartp pointer to the @p UARTDriver object - */ -static void usart_start(UARTDriver *uartp) { - uint32_t cr1; - USART_TypeDef *u = uartp->usart; - - /* Defensive programming, starting from a clean state.*/ - usart_stop(uartp); - - /* Baud rate setting.*/ -#if defined(STM32F0XX) - if (uartp->usart == USART1) - u->BRR = STM32_USART1CLK / uartp->config->speed; - else - u->BRR = STM32_PCLK / uartp->config->speed; -#else /* !defined(STM32F0XX) */ - if (uartp->usart == USART1) - u->BRR = STM32_PCLK2 / uartp->config->speed; - else - u->BRR = STM32_PCLK1 / uartp->config->speed; -#endif /* !defined(STM32F0XX) */ - - /* Resetting eventual pending status flags.*/ - u->ICR = 0xFFFFFFFF; - - /* Note that some bits are enforced because required for correct driver - operations.*/ - u->CR2 = uartp->config->cr2 | USART_CR2_LBDIE; - u->CR3 = uartp->config->cr3 | USART_CR3_DMAT | USART_CR3_DMAR | - USART_CR3_EIE; - if (uartp->config->txend2_cb == NULL) - cr1 = USART_CR1_UE | USART_CR1_PEIE | USART_CR1_TE | USART_CR1_RE; - else - cr1 = USART_CR1_UE | USART_CR1_PEIE | USART_CR1_TE | USART_CR1_RE | - USART_CR1_TCIE; - u->CR1 = uartp->config->cr1 | cr1; - - /* Starting the receiver idle loop.*/ - set_rx_idle_loop(uartp); -} - -/** - * @brief RX DMA common service routine. - * - * @param[in] uartp pointer to the @p UARTDriver object - * @param[in] flags pre-shifted content of the ISR register - */ -static void uart_lld_serve_rx_end_irq(UARTDriver *uartp, uint32_t flags) { - - /* DMA errors handling.*/ -#if defined(STM32_UART_DMA_ERROR_HOOK) - if ((flags & (STM32_DMA_ISR_TEIF | STM32_DMA_ISR_DMEIF)) != 0) { - STM32_UART_DMA_ERROR_HOOK(uartp); - } -#else - (void)flags; -#endif - - if (uartp->rxstate == UART_RX_IDLE) { - /* Receiver in idle state, a callback is generated, if enabled, for each - received character and then the driver stays in the same state.*/ - if (uartp->config->rxchar_cb != NULL) - uartp->config->rxchar_cb(uartp, uartp->rxbuf); - } - else { - /* Receiver in active state, a callback is generated, if enabled, after - a completed transfer.*/ - dmaStreamDisable(uartp->dmarx); - uartp->rxstate = UART_RX_COMPLETE; - if (uartp->config->rxend_cb != NULL) - uartp->config->rxend_cb(uartp); - - /* If the callback didn't explicitly change state then the receiver - automatically returns to the idle state.*/ - if (uartp->rxstate == UART_RX_COMPLETE) { - uartp->rxstate = UART_RX_IDLE; - set_rx_idle_loop(uartp); - } - } -} - -/** - * @brief TX DMA common service routine. - * - * @param[in] uartp pointer to the @p UARTDriver object - * @param[in] flags pre-shifted content of the ISR register - */ -static void uart_lld_serve_tx_end_irq(UARTDriver *uartp, uint32_t flags) { - - /* DMA errors handling.*/ -#if defined(STM32_UART_DMA_ERROR_HOOK) - if ((flags & (STM32_DMA_ISR_TEIF | STM32_DMA_ISR_DMEIF)) != 0) { - STM32_UART_DMA_ERROR_HOOK(uartp); - } -#else - (void)flags; -#endif - - dmaStreamDisable(uartp->dmatx); - - /* A callback is generated, if enabled, after a completed transfer.*/ - uartp->txstate = UART_TX_COMPLETE; - if (uartp->config->txend1_cb != NULL) - uartp->config->txend1_cb(uartp); - - /* If the callback didn't explicitly change state then the transmitter - automatically returns to the idle state.*/ - if (uartp->txstate == UART_TX_COMPLETE) - uartp->txstate = UART_TX_IDLE; -} - -/** - * @brief USART common service routine. - * - * @param[in] uartp pointer to the @p UARTDriver object - */ -static void serve_usart_irq(UARTDriver *uartp) { - uint32_t isr; - USART_TypeDef *u = uartp->usart; - - /* Reading and clearing status.*/ - isr = u->ISR; - u->ICR = isr; - - if (isr & (USART_ISR_LBD | USART_ISR_ORE | USART_ISR_NE | - USART_ISR_FE | USART_ISR_PE)) { - if (uartp->config->rxerr_cb != NULL) - uartp->config->rxerr_cb(uartp, translate_errors(isr)); - } - if (isr & USART_ISR_TC) { - /* End of transmission, a callback is generated.*/ - if (uartp->config->txend2_cb != NULL) - uartp->config->txend2_cb(uartp); - } -} - -/*===========================================================================*/ -/* Driver interrupt handlers. */ -/*===========================================================================*/ - -#if STM32_UART_USE_USART1 || defined(__DOXYGEN__) -#if !defined(STM32_USART1_HANDLER) -#error "STM32_USART1_HANDLER not defined" -#endif -/** - * @brief USART1 IRQ handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(STM32_USART1_HANDLER) { - - OSAL_IRQ_PROLOGUE(); - - serve_usart_irq(&UARTD1); - - OSAL_IRQ_EPILOGUE(); -} -#endif /* STM32_UART_USE_USART1 */ - -#if STM32_UART_USE_USART2 || defined(__DOXYGEN__) -#if !defined(STM32_USART2_HANDLER) -#error "STM32_USART2_HANDLER not defined" -#endif -/** - * @brief USART2 IRQ handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(STM32_USART2_HANDLER) { - - OSAL_IRQ_PROLOGUE(); - - serve_usart_irq(&UARTD2); - - OSAL_IRQ_EPILOGUE(); -} -#endif /* STM32_UART_USE_USART2 */ - -#if STM32_UART_USE_USART3 || defined(__DOXYGEN__) -#if !defined(STM32_USART3_HANDLER) -#error "STM32_USART3_HANDLER not defined" -#endif -/** - * @brief USART3 IRQ handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(STM32_USART3_HANDLER) { - - OSAL_IRQ_PROLOGUE(); - - serve_usart_irq(&UARTD3); - - OSAL_IRQ_EPILOGUE(); -} -#endif /* STM32_UART_USE_USART3 */ - -/*===========================================================================*/ -/* Driver exported functions. */ -/*===========================================================================*/ - -/** - * @brief Low level UART driver initialization. - * - * @notapi - */ -void uart_lld_init(void) { - -#if STM32_UART_USE_USART1 - uartObjectInit(&UARTD1); - UARTD1.usart = USART1; - UARTD1.dmamode = STM32_DMA_CR_DMEIE | STM32_DMA_CR_TEIE; - UARTD1.dmarx = STM32_DMA_STREAM(STM32_UART_USART1_RX_DMA_STREAM); - UARTD1.dmatx = STM32_DMA_STREAM(STM32_UART_USART1_TX_DMA_STREAM); -#endif - -#if STM32_UART_USE_USART2 - uartObjectInit(&UARTD2); - UARTD2.usart = USART2; - UARTD2.dmamode = STM32_DMA_CR_DMEIE | STM32_DMA_CR_TEIE; - UARTD2.dmarx = STM32_DMA_STREAM(STM32_UART_USART2_RX_DMA_STREAM); - UARTD2.dmatx = STM32_DMA_STREAM(STM32_UART_USART2_TX_DMA_STREAM); -#endif - -#if STM32_UART_USE_USART3 - uartObjectInit(&UARTD3); - UARTD3.usart = USART3; - UARTD3.dmamode = STM32_DMA_CR_DMEIE | STM32_DMA_CR_TEIE; - UARTD3.dmarx = STM32_DMA_STREAM(STM32_UART_USART3_RX_DMA_STREAM); - UARTD3.dmatx = STM32_DMA_STREAM(STM32_UART_USART3_TX_DMA_STREAM); -#endif -} - -/** - * @brief Configures and activates the UART peripheral. - * - * @param[in] uartp pointer to the @p UARTDriver object - * - * @notapi - */ -void uart_lld_start(UARTDriver *uartp) { - - if (uartp->state == UART_STOP) { -#if STM32_UART_USE_USART1 - if (&UARTD1 == uartp) { - bool_t b; - b = dmaStreamAllocate(uartp->dmarx, - STM32_UART_USART1_IRQ_PRIORITY, - (stm32_dmaisr_t)uart_lld_serve_rx_end_irq, - (void *)uartp); - osalDbgAssert(!b, "stream already allocated"); - b = dmaStreamAllocate(uartp->dmatx, - STM32_UART_USART1_IRQ_PRIORITY, - (stm32_dmaisr_t)uart_lld_serve_tx_end_irq, - (void *)uartp); - osalDbgAssert(!b, "stream already allocated"); - rccEnableUSART1(FALSE); - nvicEnableVector(STM32_USART1_NUMBER, STM32_UART_USART1_IRQ_PRIORITY); - uartp->dmamode |= STM32_DMA_CR_CHSEL(USART1_RX_DMA_CHANNEL) | - STM32_DMA_CR_PL(STM32_UART_USART1_DMA_PRIORITY); - } -#endif - -#if STM32_UART_USE_USART2 - if (&UARTD2 == uartp) { - bool_t b; - b = dmaStreamAllocate(uartp->dmarx, - STM32_UART_USART2_IRQ_PRIORITY, - (stm32_dmaisr_t)uart_lld_serve_rx_end_irq, - (void *)uartp); - osalDbgAssert(!b, "stream already allocated"); - b = dmaStreamAllocate(uartp->dmatx, - STM32_UART_USART2_IRQ_PRIORITY, - (stm32_dmaisr_t)uart_lld_serve_tx_end_irq, - (void *)uartp); - osalDbgAssert(!b, "stream already allocated"); - rccEnableUSART2(FALSE); - nvicEnableVector(STM32_USART2_NUMBER, STM32_UART_USART2_IRQ_PRIORITY); - uartp->dmamode |= STM32_DMA_CR_CHSEL(USART2_RX_DMA_CHANNEL) | - STM32_DMA_CR_PL(STM32_UART_USART2_DMA_PRIORITY); - } -#endif - -#if STM32_UART_USE_USART3 - if (&UARTD3 == uartp) { - bool_t b; - b = dmaStreamAllocate(uartp->dmarx, - STM32_UART_USART3_IRQ_PRIORITY, - (stm32_dmaisr_t)uart_lld_serve_rx_end_irq, - (void *)uartp); - osalDbgAssert(!b, "stream already allocated"); - b = dmaStreamAllocate(uartp->dmatx, - STM32_UART_USART3_IRQ_PRIORITY, - (stm32_dmaisr_t)uart_lld_serve_tx_end_irq, - (void *)uartp); - osalDbgAssert(!b, "stream already allocated"); - rccEnableUSART3(FALSE); - nvicEnableVector(STM32_USART3_NUMBER, STM32_UART_USART3_IRQ_PRIORITY); - uartp->dmamode |= STM32_DMA_CR_CHSEL(USART3_RX_DMA_CHANNEL) | - STM32_DMA_CR_PL(STM32_UART_USART3_DMA_PRIORITY); - } -#endif - - /* Static DMA setup, the transfer size depends on the USART settings, - it is 16 bits if M=1 and PCE=0 else it is 8 bits.*/ - if ((uartp->config->cr1 & (USART_CR1_M | USART_CR1_PCE)) == USART_CR1_M) - uartp->dmamode |= STM32_DMA_CR_PSIZE_HWORD | STM32_DMA_CR_MSIZE_HWORD; - dmaStreamSetPeripheral(uartp->dmarx, &uartp->usart->RDR); - dmaStreamSetPeripheral(uartp->dmatx, &uartp->usart->TDR); - uartp->rxbuf = 0; - } - - uartp->rxstate = UART_RX_IDLE; - uartp->txstate = UART_TX_IDLE; - usart_start(uartp); -} - -/** - * @brief Deactivates the UART peripheral. - * - * @param[in] uartp pointer to the @p UARTDriver object - * - * @notapi - */ -void uart_lld_stop(UARTDriver *uartp) { - - if (uartp->state == UART_READY) { - usart_stop(uartp); - dmaStreamRelease(uartp->dmarx); - dmaStreamRelease(uartp->dmatx); - -#if STM32_UART_USE_USART1 - if (&UARTD1 == uartp) { - nvicDisableVector(STM32_USART1_NUMBER); - rccDisableUSART1(FALSE); - return; - } -#endif - -#if STM32_UART_USE_USART2 - if (&UARTD2 == uartp) { - nvicDisableVector(STM32_USART2_NUMBER); - rccDisableUSART2(FALSE); - return; - } -#endif - -#if STM32_UART_USE_USART3 - if (&UARTD3 == uartp) { - nvicDisableVector(STM32_USART3_NUMBER); - rccDisableUSART3(FALSE); - return; - } -#endif - } -} - -/** - * @brief Starts a transmission on the UART peripheral. - * @note The buffers are organized as uint8_t arrays for data sizes below - * or equal to 8 bits else it is organized as uint16_t arrays. - * - * @param[in] uartp pointer to the @p UARTDriver object - * @param[in] n number of data frames to send - * @param[in] txbuf the pointer to the transmit buffer - * - * @notapi - */ -void uart_lld_start_send(UARTDriver *uartp, size_t n, const void *txbuf) { - - /* TX DMA channel preparation and start.*/ - dmaStreamSetMemory0(uartp->dmatx, txbuf); - dmaStreamSetTransactionSize(uartp->dmatx, n); - dmaStreamSetMode(uartp->dmatx, uartp->dmamode | STM32_DMA_CR_DIR_M2P | - STM32_DMA_CR_MINC | STM32_DMA_CR_TCIE); - dmaStreamEnable(uartp->dmatx); -} - -/** - * @brief Stops any ongoing transmission. - * @note Stopping a transmission also suppresses the transmission callbacks. - * - * @param[in] uartp pointer to the @p UARTDriver object - * - * @return The number of data frames not transmitted by the - * stopped transmit operation. - * - * @notapi - */ -size_t uart_lld_stop_send(UARTDriver *uartp) { - - dmaStreamDisable(uartp->dmatx); - return dmaStreamGetTransactionSize(uartp->dmatx); -} - -/** - * @brief Starts a receive operation on the UART peripheral. - * @note The buffers are organized as uint8_t arrays for data sizes below - * or equal to 8 bits else it is organized as uint16_t arrays. - * - * @param[in] uartp pointer to the @p UARTDriver object - * @param[in] n number of data frames to send - * @param[out] rxbuf the pointer to the receive buffer - * - * @notapi - */ -void uart_lld_start_receive(UARTDriver *uartp, size_t n, void *rxbuf) { - - /* Stopping previous activity (idle state).*/ - dmaStreamDisable(uartp->dmarx); - - /* RX DMA channel preparation and start.*/ - dmaStreamSetMemory0(uartp->dmarx, rxbuf); - dmaStreamSetTransactionSize(uartp->dmarx, n); - dmaStreamSetMode(uartp->dmarx, uartp->dmamode | STM32_DMA_CR_DIR_P2M | - STM32_DMA_CR_MINC | STM32_DMA_CR_TCIE); - dmaStreamEnable(uartp->dmarx); -} - -/** - * @brief Stops any ongoing receive operation. - * @note Stopping a receive operation also suppresses the receive callbacks. - * - * @param[in] uartp pointer to the @p UARTDriver object - * - * @return The number of data frames not received by the - * stopped receive operation. - * - * @notapi - */ -size_t uart_lld_stop_receive(UARTDriver *uartp) { - size_t n; - - dmaStreamDisable(uartp->dmarx); - n = dmaStreamGetTransactionSize(uartp->dmarx); - set_rx_idle_loop(uartp); - return n; -} - -#endif /* HAL_USE_UART */ - -/** @} */ diff --git a/os/hal/platforms/STM32/USARTv2/uart_lld.h b/os/hal/platforms/STM32/USARTv2/uart_lld.h deleted file mode 100644 index 32b1f6e47..000000000 --- a/os/hal/platforms/STM32/USARTv2/uart_lld.h +++ /dev/null @@ -1,417 +0,0 @@ -/* - ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file STM32/USARTv2/uart_lld.h - * @brief STM32 low level UART driver header. - * - * @addtogroup UART - * @{ - */ - -#ifndef _UART_LLD_H_ -#define _UART_LLD_H_ - -#if HAL_USE_UART || defined(__DOXYGEN__) - -/*===========================================================================*/ -/* Driver constants. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver pre-compile time settings. */ -/*===========================================================================*/ - -/** - * @name Configuration options - * @{ - */ -/** - * @brief UART driver on USART1 enable switch. - * @details If set to @p TRUE the support for USART1 is included. - * @note The default is @p FALSE. - */ -#if !defined(STM32_UART_USE_USART1) || defined(__DOXYGEN__) -#define STM32_UART_USE_USART1 FALSE -#endif - -/** - * @brief UART driver on USART2 enable switch. - * @details If set to @p TRUE the support for USART2 is included. - * @note The default is @p FALSE. - */ -#if !defined(STM32_UART_USE_USART2) || defined(__DOXYGEN__) -#define STM32_UART_USE_USART2 FALSE -#endif - -/** - * @brief UART driver on USART3 enable switch. - * @details If set to @p TRUE the support for USART3 is included. - * @note The default is @p FALSE. - */ -#if !defined(STM32_UART_USE_USART3) || defined(__DOXYGEN__) -#define STM32_UART_USE_USART3 FALSE -#endif - -/** - * @brief USART1 interrupt priority level setting. - */ -#if !defined(STM32_UART_USART1_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_UART_USART1_IRQ_PRIORITY 12 -#endif - -/** - * @brief USART2 interrupt priority level setting. - */ -#if !defined(STM32_UART_USART2_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_UART_USART2_IRQ_PRIORITY 12 -#endif - -/** - * @brief USART3 interrupt priority level setting. - */ -#if !defined(STM32_UART_USART3_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_UART_USART3_IRQ_PRIORITY 12 -#endif - -/** - * @brief USART1 DMA priority (0..3|lowest..highest). - * @note The priority level is used for both the TX and RX DMA channels but - * because of the channels ordering the RX channel has always priority - * over the TX channel. - */ -#if !defined(STM32_UART_USART1_DMA_PRIORITY) || defined(__DOXYGEN__) -#define STM32_UART_USART1_DMA_PRIORITY 0 -#endif - -/** - * @brief USART2 DMA priority (0..3|lowest..highest). - * @note The priority level is used for both the TX and RX DMA channels but - * because of the channels ordering the RX channel has always priority - * over the TX channel. - */ -#if !defined(STM32_UART_USART2_DMA_PRIORITY) || defined(__DOXYGEN__) -#define STM32_UART_USART2_DMA_PRIORITY 0 -#endif - -/** - * @brief USART3 DMA priority (0..3|lowest..highest). - * @note The priority level is used for both the TX and RX DMA channels but - * because of the channels ordering the RX channel has always priority - * over the TX channel. - */ -#if !defined(STM32_UART_USART3_DMA_PRIORITY) || defined(__DOXYGEN__) -#define STM32_UART_USART3_DMA_PRIORITY 0 -#endif - -/** - * @brief USART1 DMA error hook. - * @note The default action for DMA errors is a system halt because DMA - * error can only happen because programming errors. - */ -#if !defined(STM32_UART_DMA_ERROR_HOOK) || defined(__DOXYGEN__) -#define STM32_UART_DMA_ERROR_HOOK(uartp) osalSysHalt("DMA failure") -#endif - -#if defined(STM32F37X) -/* Fixed values for STM32F3xx devices.*/ -#define STM32_UART_USART1_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 5) -#define STM32_UART_USART1_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) -#define STM32_UART_USART2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 6) -#define STM32_UART_USART2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7) -#define STM32_UART_USART3_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 3) -#define STM32_UART_USART3_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2) -#endif /* defined(STM32F30X) */ -/** @} */ - -/*===========================================================================*/ -/* Derived constants and error checks. */ -/*===========================================================================*/ - -#if STM32_UART_USE_USART1 && !STM32_HAS_USART1 -#error "USART1 not present in the selected device" -#endif - -#if STM32_UART_USE_USART2 && !STM32_HAS_USART2 -#error "USART2 not present in the selected device" -#endif - -#if STM32_UART_USE_USART3 && !STM32_HAS_USART3 -#error "USART3 not present in the selected device" -#endif - -#if !STM32_UART_USE_USART1 && !STM32_UART_USE_USART2 && \ - !STM32_UART_USE_USART3 -#error "UART driver activated but no USART/UART peripheral assigned" -#endif - -#if STM32_UART_USE_USART1 && \ - !CORTEX_IS_VALID_KERNEL_PRIORITY(STM32_UART_USART1_IRQ_PRIORITY) -#error "Invalid IRQ priority assigned to USART1" -#endif - -#if STM32_UART_USE_USART2 && \ - !CORTEX_IS_VALID_KERNEL_PRIORITY(STM32_UART_USART2_IRQ_PRIORITY) -#error "Invalid IRQ priority assigned to USART2" -#endif - -#if STM32_UART_USE_USART3 && \ - !CORTEX_IS_VALID_KERNEL_PRIORITY(STM32_UART_USART3_IRQ_PRIORITY) -#error "Invalid IRQ priority assigned to USART3" -#endif - -#if STM32_UART_USE_USART1 && \ - !STM32_DMA_IS_VALID_PRIORITY(STM32_UART_USART1_DMA_PRIORITY) -#error "Invalid DMA priority assigned to USART1" -#endif - -#if STM32_UART_USE_USART2 && \ - !STM32_DMA_IS_VALID_PRIORITY(STM32_UART_USART2_DMA_PRIORITY) -#error "Invalid DMA priority assigned to USART2" -#endif - -#if STM32_UART_USE_USART3 && \ - !STM32_DMA_IS_VALID_PRIORITY(STM32_UART_USART3_DMA_PRIORITY) -#error "Invalid DMA priority assigned to USART3" -#endif - -/* The following checks are only required when there is a DMA able to - reassign streams to different channels.*/ -#if STM32_ADVANCED_DMA -/* Check on the presence of the DMA streams settings in mcuconf.h.*/ -#if STM32_UART_USE_USART1 && (!defined(STM32_UART_USART1_RX_DMA_STREAM) || \ - !defined(STM32_UART_USART1_TX_DMA_STREAM)) -#error "USART1 DMA streams not defined" -#endif - -#if STM32_UART_USE_USART2 && (!defined(STM32_UART_USART2_RX_DMA_STREAM) || \ - !defined(STM32_UART_USART2_TX_DMA_STREAM)) -#error "USART2 DMA streams not defined" -#endif - -#if STM32_UART_USE_USART3 && (!defined(STM32_UART_USART3_RX_DMA_STREAM) || \ - !defined(STM32_UART_USART3_TX_DMA_STREAM)) -#error "USART3 DMA streams not defined" -#endif - -/* Check on the validity of the assigned DMA channels.*/ -#if STM32_UART_USE_USART1 && \ - !STM32_DMA_IS_VALID_ID(STM32_UART_USART1_RX_DMA_STREAM, \ - STM32_USART1_RX_DMA_MSK) -#error "invalid DMA stream associated to USART1 RX" -#endif - -#if STM32_UART_USE_USART1 && \ - !STM32_DMA_IS_VALID_ID(STM32_UART_USART1_TX_DMA_STREAM, \ - STM32_USART1_TX_DMA_MSK) -#error "invalid DMA stream associated to USART1 TX" -#endif - -#if STM32_UART_USE_USART2 && \ - !STM32_DMA_IS_VALID_ID(STM32_UART_USART2_RX_DMA_STREAM, \ - STM32_USART2_RX_DMA_MSK) -#error "invalid DMA stream associated to USART2 RX" -#endif - -#if STM32_UART_USE_USART2 && \ - !STM32_DMA_IS_VALID_ID(STM32_UART_USART2_TX_DMA_STREAM, \ - STM32_USART2_TX_DMA_MSK) -#error "invalid DMA stream associated to USART2 TX" -#endif - -#if STM32_UART_USE_USART3 && \ - !STM32_DMA_IS_VALID_ID(STM32_UART_USART3_RX_DMA_STREAM, \ - STM32_USART3_RX_DMA_MSK) -#error "invalid DMA stream associated to USART3 RX" -#endif - -#if STM32_UART_USE_USART3 && \ - !STM32_DMA_IS_VALID_ID(STM32_UART_USART3_TX_DMA_STREAM, \ - STM32_USART3_TX_DMA_MSK) -#error "invalid DMA stream associated to USART3 TX" -#endif -#endif /* STM32_ADVANCED_DMA */ - -#if !defined(STM32_DMA_REQUIRED) -#define STM32_DMA_REQUIRED -#endif - -/*===========================================================================*/ -/* Driver data structures and types. */ -/*===========================================================================*/ - -/** - * @brief UART driver condition flags type. - */ -typedef uint32_t uartflags_t; - -/** - * @brief Structure representing an UART driver. - */ -typedef struct UARTDriver UARTDriver; - -/** - * @brief Generic UART notification callback type. - * - * @param[in] uartp pointer to the @p UARTDriver object - */ -typedef void (*uartcb_t)(UARTDriver *uartp); - -/** - * @brief Character received UART notification callback type. - * - * @param[in] uartp pointer to the @p UARTDriver object - * @param[in] c received character - */ -typedef void (*uartccb_t)(UARTDriver *uartp, uint16_t c); - -/** - * @brief Receive error UART notification callback type. - * - * @param[in] uartp pointer to the @p UARTDriver object - * @param[in] e receive error mask - */ -typedef void (*uartecb_t)(UARTDriver *uartp, uartflags_t e); - -/** - * @brief Driver configuration structure. - * @note It could be empty on some architectures. - */ -typedef struct { - /** - * @brief End of transmission buffer callback. - */ - uartcb_t txend1_cb; - /** - * @brief Physical end of transmission callback. - */ - uartcb_t txend2_cb; - /** - * @brief Receive buffer filled callback. - */ - uartcb_t rxend_cb; - /** - * @brief Character received while out if the @p UART_RECEIVE state. - */ - uartccb_t rxchar_cb; - /** - * @brief Receive error callback. - */ - uartecb_t rxerr_cb; - /* End of the mandatory fields.*/ - /** - * @brief Bit rate. - */ - uint32_t speed; - /** - * @brief Initialization value for the CR1 register. - */ - uint32_t cr1; - /** - * @brief Initialization value for the CR2 register. - */ - uint32_t cr2; - /** - * @brief Initialization value for the CR3 register. - */ - uint32_t cr3; -} UARTConfig; - -/** - * @brief Structure representing an UART driver. - */ -struct UARTDriver { - /** - * @brief Driver state. - */ - uartstate_t state; - /** - * @brief Transmitter state. - */ - uarttxstate_t txstate; - /** - * @brief Receiver state. - */ - uartrxstate_t rxstate; - /** - * @brief Current configuration data. - */ - const UARTConfig *config; -#if defined(UART_DRIVER_EXT_FIELDS) - UART_DRIVER_EXT_FIELDS -#endif - /* End of the mandatory fields.*/ - /** - * @brief Pointer to the USART registers block. - */ - USART_TypeDef *usart; - /** - * @brief DMA mode bit mask. - */ - uint32_t dmamode; - /** - * @brief Receive DMA channel. - */ - const stm32_dma_stream_t *dmarx; - /** - * @brief Transmit DMA channel. - */ - const stm32_dma_stream_t *dmatx; - /** - * @brief Default receive buffer while into @p UART_RX_IDLE state. - */ - volatile uint16_t rxbuf; -}; - -/*===========================================================================*/ -/* Driver macros. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* External declarations. */ -/*===========================================================================*/ - -#if STM32_UART_USE_USART1 && !defined(__DOXYGEN__) -extern UARTDriver UARTD1; -#endif - -#if STM32_UART_USE_USART2 && !defined(__DOXYGEN__) -extern UARTDriver UARTD2; -#endif - -#if STM32_UART_USE_USART3 && !defined(__DOXYGEN__) -extern UARTDriver UARTD3; -#endif - -#ifdef __cplusplus -extern "C" { -#endif - void uart_lld_init(void); - void uart_lld_start(UARTDriver *uartp); - void uart_lld_stop(UARTDriver *uartp); - void uart_lld_start_send(UARTDriver *uartp, size_t n, const void *txbuf); - size_t uart_lld_stop_send(UARTDriver *uartp); - void uart_lld_start_receive(UARTDriver *uartp, size_t n, void *rxbuf); - size_t uart_lld_stop_receive(UARTDriver *uartp); -#ifdef __cplusplus -} -#endif - -#endif /* HAL_USE_UART */ - -#endif /* _UART_LLD_H_ */ - -/** @} */ diff --git a/os/hal/platforms/STM32/USBv1/stm32_usb.h b/os/hal/platforms/STM32/USBv1/stm32_usb.h deleted file mode 100644 index 83f349e42..000000000 --- a/os/hal/platforms/STM32/USBv1/stm32_usb.h +++ /dev/null @@ -1,243 +0,0 @@ -/* - ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file stm32_usb.h - * @brief STM32 USB registers layout header. - * @note This file requires definitions from the ST STM32 header files - * stm32f10x.h or stm32l1xx.h. - * - * @addtogroup USB - * @{ - */ - -#ifndef _STM32_USB_H_ -#define _STM32_USB_H_ - -/** - * @brief Number of the available endpoints. - * @details This value does not include the endpoint 0 which is always present. - */ -#define USB_ENDOPOINTS_NUMBER 7 - -/** - * @brief USB registers block. - */ -typedef struct { - /** - * @brief Endpoint registers. - */ - volatile uint32_t EPR[USB_ENDOPOINTS_NUMBER + 1]; - /* - * @brief Reserved space. - */ - volatile uint32_t _r20[8]; - /* - * @brief Control Register. - */ - volatile uint32_t CNTR; - /* - * @brief Interrupt Status Register. - */ - volatile uint32_t ISTR; - /* - * @brief Frame Number Register. - */ - volatile uint32_t FNR; - /* - * @brief Device Address Register. - */ - volatile uint32_t DADDR; - /* - * @brief Buffer Table Address. - */ - volatile uint32_t BTABLE; -} stm32_usb_t; - -/** - * @brief USB descriptor registers block. - */ -typedef struct { - /** - * @brief TX buffer offset register. - */ - volatile uint32_t TXADDR0; - /** - * @brief TX counter register 0. - */ - volatile uint16_t TXCOUNT0; - /** - * @brief TX counter register 1. - */ - volatile uint16_t TXCOUNT1; - /** - * @brief RX buffer offset register. - */ - volatile uint32_t RXADDR0; - /** - * @brief RX counter register 0. - */ - volatile uint16_t RXCOUNT0; - /** - * @brief RX counter register 1. - */ - volatile uint16_t RXCOUNT1; -} stm32_usb_descriptor_t; - -/** - * @name Register aliases - * @{ - */ -#define RXADDR1 TXADDR0 -#define TXADDR1 RXADDR0 -/** @} */ - -/** - * @brief USB registers block numeric address. - */ -#define STM32_USB_BASE (APB1PERIPH_BASE + 0x5C00) - -/** - * @brief USB RAM numeric address. - */ -#define STM32_USBRAM_BASE (APB1PERIPH_BASE + 0x6000) - -/** - * @brief Pointer to the USB registers block. - */ -#define STM32_USB ((stm32_usb_t *)STM32_USB_BASE) - -/** - * @brief Pointer to the USB RAM. - */ -#define STM32_USBRAM ((uint32_t *)STM32_USBRAM_BASE) - -/** - * @brief Size of the dedicated packet memory. - */ -#define USB_PMA_SIZE 512 - -/** - * @brief Mask of all the toggling bits in the EPR register. - */ -#define EPR_TOGGLE_MASK (EPR_STAT_TX_MASK | EPR_DTOG_TX | \ - EPR_STAT_RX_MASK | EPR_DTOG_RX | \ - EPR_SETUP) - -#define EPR_EA_MASK 0x000F -#define EPR_STAT_TX_MASK 0x0030 -#define EPR_STAT_TX_DIS 0x0000 -#define EPR_STAT_TX_STALL 0x0010 -#define EPR_STAT_TX_NAK 0x0020 -#define EPR_STAT_TX_VALID 0x0030 -#define EPR_DTOG_TX 0x0040 -#define EPR_SWBUF_RX EPR_DTOG_TX -#define EPR_CTR_TX 0x0080 -#define EPR_EP_KIND 0x0100 -#define EPR_EP_DBL_BUF EPR_EP_KIND -#define EPR_EP_STATUS_OUT EPR_EP_KIND -#define EPR_EP_TYPE_MASK 0x0600 -#define EPR_EP_TYPE_BULK 0x0000 -#define EPR_EP_TYPE_CONTROL 0x0200 -#define EPR_EP_TYPE_ISO 0x0400 -#define EPR_EP_TYPE_INTERRUPT 0x0600 -#define EPR_SETUP 0x0800 -#define EPR_STAT_RX_MASK 0x3000 -#define EPR_STAT_RX_DIS 0x0000 -#define EPR_STAT_RX_STALL 0x1000 -#define EPR_STAT_RX_NAK 0x2000 -#define EPR_STAT_RX_VALID 0x3000 -#define EPR_DTOG_RX 0x4000 -#define EPR_SWBUF_TX EPR_DTOG_RX -#define EPR_CTR_RX 0x8000 - -#define CNTR_FRES 0x0001 -#define CNTR_PDWN 0x0002 -#define CNTR_LP_MODE 0x0004 -#define CNTR_FSUSP 0x0008 -#define CNTR_RESUME 0x0010 -#define CNTR_ESOFM 0x0100 -#define CNTR_SOFM 0x0200 -#define CNTR_RESETM 0x0400 -#define CNTR_SUSPM 0x0800 -#define CNTR_WKUPM 0x1000 -#define CNTR_ERRM 0x2000 -#define CNTR_PMAOVRM 0x4000 -#define CNTR_CTRM 0x8000 - -#define ISTR_EP_ID_MASK 0x000F -#define ISTR_DIR 0x0010 -#define ISTR_ESOF 0x0100 -#define ISTR_SOF 0x0200 -#define ISTR_RESET 0x0400 -#define ISTR_SUSP 0x0800 -#define ISTR_WKUP 0x1000 -#define ISTR_ERR 0x2000 -#define ISTR_PMAOVR 0x4000 -#define ISTR_CTR 0x8000 - -#define FNR_FN_MASK 0x07FF -#define FNR_LSOF 0x1800 -#define FNR_LCK 0x2000 -#define FNR_RXDM 0x4000 -#define FNR_RXDP 0x8000 - -#define DADDR_ADD_MASK 0x007F -#define DADDR_EF 0x0080 - -#define RXCOUNT_COUNT_MASK 0x03FF -#define TXCOUNT_COUNT_MASK 0x03FF - -#define EPR_SET(ep, epr) \ - STM32_USB->EPR[ep] = (epr) & ~EPR_TOGGLE_MASK - -#define EPR_TOGGLE(ep, epr) \ - STM32_USB->EPR[ep] = (STM32_USB->EPR[ep] ^ ((epr) & EPR_TOGGLE_MASK)) - -#define EPR_SET_STAT_RX(ep, epr) \ - STM32_USB->EPR[ep] = (STM32_USB->EPR[ep] & \ - ~(EPR_TOGGLE_MASK & ~EPR_STAT_RX_MASK)) ^ \ - (epr) - -#define EPR_SET_STAT_TX(ep, epr) \ - STM32_USB->EPR[ep] = (STM32_USB->EPR[ep] & \ - ~(EPR_TOGGLE_MASK & ~EPR_STAT_TX_MASK)) ^ \ - (epr) - -#define EPR_CLEAR_CTR_RX(ep) \ - STM32_USB->EPR[ep] &= ~EPR_CTR_RX & ~EPR_TOGGLE_MASK - -#define EPR_CLEAR_CTR_TX(ep) \ - STM32_USB->EPR[ep] &= ~EPR_CTR_TX & ~EPR_TOGGLE_MASK - -/** - * @brief Returns an endpoint descriptor pointer. - */ -#define USB_GET_DESCRIPTOR(ep) \ - ((stm32_usb_descriptor_t *)((uint32_t)STM32_USBRAM_BASE + \ - (uint32_t)STM32_USB->BTABLE * 2 + \ - (uint32_t)(ep) * \ - sizeof(stm32_usb_descriptor_t))) - -/** - * @brief Converts from a PMA address to a physical address. - */ -#define USB_ADDR2PTR(addr) \ - ((uint32_t *)((addr) * 2 + STM32_USBRAM_BASE)) - -#endif /* _STM32_USB_H_ */ - -/** @} */ diff --git a/os/hal/platforms/STM32/USBv1/usb_lld.c b/os/hal/platforms/STM32/USBv1/usb_lld.c deleted file mode 100644 index 1a44a678f..000000000 --- a/os/hal/platforms/STM32/USBv1/usb_lld.c +++ /dev/null @@ -1,824 +0,0 @@ -/* - ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file STM32/USBv1/usb_lld.c - * @brief STM32 USB subsystem low level driver source. - * - * @addtogroup USB - * @{ - */ - -#include - -#include "hal.h" - -#if HAL_USE_USB || defined(__DOXYGEN__) - -/*===========================================================================*/ -/* Driver local definitions. */ -/*===========================================================================*/ - -#define BTABLE_ADDR 0x0000 - -/*===========================================================================*/ -/* Driver exported variables. */ -/*===========================================================================*/ - -/** @brief USB1 driver identifier.*/ -#if STM32_USB_USE_USB1 || defined(__DOXYGEN__) -USBDriver USBD1; -#endif - -/*===========================================================================*/ -/* Driver local variables and types. */ -/*===========================================================================*/ - -/** - * @brief EP0 state. - * @note It is an union because IN and OUT endpoints are never used at the - * same time for EP0. - */ -static union { - /** - * @brief IN EP0 state. - */ - USBInEndpointState in; - /** - * @brief OUT EP0 state. - */ - USBOutEndpointState out; -} ep0_state; - -/** - * @brief Buffer for the EP0 setup packets. - */ -static uint8_t ep0setup_buffer[8]; - -/** - * @brief EP0 initialization structure. - */ -static const USBEndpointConfig ep0config = { - USB_EP_MODE_TYPE_CTRL, - _usb_ep0setup, - _usb_ep0in, - _usb_ep0out, - 0x40, - 0x40, - &ep0_state.in, - &ep0_state.out, - 1, - ep0setup_buffer -}; - -/*===========================================================================*/ -/* Driver local functions. */ -/*===========================================================================*/ - -/** - * @brief Resets the packet memory allocator. - * - * @param[in] usbp pointer to the @p USBDriver object - */ -static void usb_pm_reset(USBDriver *usbp) { - - /* The first 64 bytes are reserved for the descriptors table. The effective - available RAM for endpoint buffers is just 448 bytes.*/ - usbp->pmnext = 64; -} - -/** - * @brief Resets the packet memory allocator. - * - * @param[in] usbp pointer to the @p USBDriver object - * @param[in] size size of the packet buffer to allocate - */ -static uint32_t usb_pm_alloc(USBDriver *usbp, size_t size) { - uint32_t next; - - next = usbp->pmnext; - usbp->pmnext += size; - osalDbgAssert(usbp->pmnext <= USB_PMA_SIZE, "PMA overflow"); - return next; -} - -/** - * @brief Reads from a dedicated packet buffer. - * - * @param[in] udp pointer to a @p stm32_usb_descriptor_t - * @param[out] buf buffer where to copy the packet data - * @param[in] n maximum number of bytes to copy. This value must - * not exceed the maximum packet size for this endpoint. - * - * @notapi - */ -static void usb_packet_read_to_buffer(stm32_usb_descriptor_t *udp, - uint8_t *buf, size_t n) { - uint32_t *pmap= USB_ADDR2PTR(udp->RXADDR0); - - n = (n + 1) / 2; - while (n > 0) { - /* Note, this line relies on the Cortex-M3/M4 ability to perform - unaligned word accesses.*/ - *(uint16_t *)buf = (uint16_t)*pmap++; - buf += 2; - n--; - } -} - -/** - * @brief Reads from a dedicated packet buffer. - * - * @param[in] udp pointer to a @p stm32_usb_descriptor_t - * @param[in] iqp pointer to an @p input_queue_t object - * @param[in] n maximum number of bytes to copy. This value must - * not exceed the maximum packet size for this endpoint. - * - * @notapi - */ -static void usb_packet_read_to_queue(stm32_usb_descriptor_t *udp, - input_queue_t *iqp, size_t n) { - size_t nhw; - uint32_t *pmap= USB_ADDR2PTR(udp->RXADDR0); - - nhw = n / 2; - while (nhw > 0) { - uint32_t w; - - w = *pmap++; - *iqp->q_wrptr++ = (uint8_t)w; - if (iqp->q_wrptr >= iqp->q_top) - iqp->q_wrptr = iqp->q_buffer; - *iqp->q_wrptr++ = (uint8_t)(w >> 8); - if (iqp->q_wrptr >= iqp->q_top) - iqp->q_wrptr = iqp->q_buffer; - nhw--; - } - /* Last byte for odd numbers.*/ - if ((n & 1) != 0) { - *iqp->q_wrptr++ = (uint8_t)*pmap; - if (iqp->q_wrptr >= iqp->q_top) - iqp->q_wrptr = iqp->q_buffer; - } - - /* Updating queue.*/ - osalSysLockFromISR(); - - iqp->q_counter += n; - osalQueueWakeupAllI(&iqp->q_waiting, Q_OK); - - osalSysUnlockFromISR(); -} - -/** - * @brief Writes to a dedicated packet buffer. - * - * @param[in] udp pointer to a @p stm32_usb_descriptor_t - * @param[in] buf buffer where to fetch the packet data - * @param[in] n maximum number of bytes to copy. This value must - * not exceed the maximum packet size for this endpoint. - * - * @notapi - */ -static void usb_packet_write_from_buffer(stm32_usb_descriptor_t *udp, - const uint8_t *buf, - size_t n) { - uint32_t *pmap = USB_ADDR2PTR(udp->TXADDR0); - - udp->TXCOUNT0 = (uint16_t)n; - n = (n + 1) / 2; - while (n > 0) { - /* Note, this line relies on the Cortex-M3/M4 ability to perform - unaligned word accesses.*/ - *pmap++ = *(uint16_t *)buf; - buf += 2; - n--; - } -} - -/** - * @brief Writes to a dedicated packet buffer. - * - * @param[in] udp pointer to a @p stm32_usb_descriptor_t - * @param[in] buf buffer where to fetch the packet data - * @param[in] n maximum number of bytes to copy. This value must - * not exceed the maximum packet size for this endpoint. - * - * @notapi - */ -static void usb_packet_write_from_queue(stm32_usb_descriptor_t *udp, - output_queue_t *oqp, size_t n) { - size_t nhw; - syssts_t sts; - uint32_t *pmap = USB_ADDR2PTR(udp->TXADDR0); - - udp->TXCOUNT0 = (uint16_t)n; - nhw = n / 2; - while (nhw > 0) { - uint32_t w; - - w = (uint32_t)*oqp->q_rdptr++; - if (oqp->q_rdptr >= oqp->q_top) - oqp->q_rdptr = oqp->q_buffer; - w |= (uint32_t)*oqp->q_rdptr++ << 8; - if (oqp->q_rdptr >= oqp->q_top) - oqp->q_rdptr = oqp->q_buffer; - *pmap++ = w; - nhw--; - } - - /* Last byte for odd numbers.*/ - if ((n & 1) != 0) { - *pmap = (uint32_t)*oqp->q_rdptr++; - if (oqp->q_rdptr >= oqp->q_top) - oqp->q_rdptr = oqp->q_buffer; - } - - /* Updating queue.*/ - sts = osalSysGetStatusAndLockX(); - - oqp->q_counter += n; - osalQueueWakeupAllI(&oqp->q_waiting, Q_OK); - - osalSysRestoreStatusX(sts); -} - -/*===========================================================================*/ -/* Driver interrupt handlers. */ -/*===========================================================================*/ - -#if STM32_USB_USE_USB1 || defined(__DOXYGEN__) -#if !defined(STM32_USB1_HP_HANDLER) -#error "STM32_USB1_HP_HANDLER not defined" -#endif -/** - * @brief USB high priority interrupt handler. - * - * @isr - */ -CH_IRQ_HANDLER(STM32_USB1_HP_HANDLER) { - - CH_IRQ_PROLOGUE(); - - CH_IRQ_EPILOGUE(); -} - -#if !defined(STM32_USB1_LP_HANDLER) -#error "STM32_USB1_LP_HANDLER not defined" -#endif -/** - * @brief USB low priority interrupt handler. - * - * @isr - */ -CH_IRQ_HANDLER(STM32_USB1_LP_HANDLER) { - uint32_t istr; - USBDriver *usbp = &USBD1; - - CH_IRQ_PROLOGUE(); - - istr = STM32_USB->ISTR; - - /* USB bus reset condition handling.*/ - if (istr & ISTR_RESET) { - _usb_reset(usbp); - _usb_isr_invoke_event_cb(usbp, USB_EVENT_RESET); - STM32_USB->ISTR = ~ISTR_RESET; - } - - /* USB bus SUSPEND condition handling.*/ - if (istr & ISTR_SUSP) { - STM32_USB->CNTR |= CNTR_FSUSP; - _usb_isr_invoke_event_cb(usbp, USB_EVENT_SUSPEND); -#if STM32_USB_LOW_POWER_ON_SUSPEND - STM32_USB->CNTR |= CNTR_LP_MODE; -#endif - STM32_USB->ISTR = ~ISTR_SUSP; - } - - /* USB bus WAKEUP condition handling.*/ - if (istr & ISTR_WKUP) { - uint32_t fnr = STM32_USB->FNR; - if (!(fnr & FNR_RXDP)) { - STM32_USB->CNTR &= ~CNTR_FSUSP; - _usb_isr_invoke_event_cb(usbp, USB_EVENT_WAKEUP); - } -#if STM32_USB_LOW_POWER_ON_SUSPEND - else { - /* Just noise, going back in SUSPEND mode, reference manual 22.4.5, - table 169.*/ - STM32_USB->CNTR |= CNTR_LP_MODE; - } -#endif - STM32_USB->ISTR = ~ISTR_WKUP; - } - - /* SOF handling.*/ - if (istr & ISTR_SOF) { - _usb_isr_invoke_sof_cb(usbp); - STM32_USB->ISTR = ~ISTR_SOF; - } - - /* Endpoint events handling.*/ - while (istr & ISTR_CTR) { - size_t n; - uint32_t ep; - uint32_t epr = STM32_USB->EPR[ep = istr & ISTR_EP_ID_MASK]; - const USBEndpointConfig *epcp = usbp->epc[ep]; - - if (epr & EPR_CTR_TX) { - size_t transmitted; - /* IN endpoint, transmission.*/ - EPR_CLEAR_CTR_TX(ep); - - transmitted = (size_t)USB_GET_DESCRIPTOR(ep)->TXCOUNT0; - epcp->in_state->txcnt += transmitted; - n = epcp->in_state->txsize - epcp->in_state->txcnt; - if (n > 0) { - /* Transfer not completed, there are more packets to send.*/ - if (n > epcp->in_maxsize) - n = epcp->in_maxsize; - - if (epcp->in_state->txqueued) - usb_packet_write_from_queue(USB_GET_DESCRIPTOR(ep), - epcp->in_state->mode.queue.txqueue, - n); - else { - epcp->in_state->mode.linear.txbuf += transmitted; - usb_packet_write_from_buffer(USB_GET_DESCRIPTOR(ep), - epcp->in_state->mode.linear.txbuf, - n); - } - osalSysLockFromISR(); - usb_lld_start_in(usbp, ep); - osalSysUnlockFromISR(); - } - else { - /* Transfer completed, invokes the callback.*/ - _usb_isr_invoke_in_cb(usbp, ep); - } - } - if (epr & EPR_CTR_RX) { - EPR_CLEAR_CTR_RX(ep); - /* OUT endpoint, receive.*/ - if (epr & EPR_SETUP) { - /* Setup packets handling, setup packets are handled using a - specific callback.*/ - _usb_isr_invoke_setup_cb(usbp, ep); - } - else { - stm32_usb_descriptor_t *udp = USB_GET_DESCRIPTOR(ep); - n = (size_t)udp->RXCOUNT0 & RXCOUNT_COUNT_MASK; - - /* Reads the packet into the defined buffer.*/ - if (epcp->out_state->rxqueued) - usb_packet_read_to_queue(udp, - epcp->out_state->mode.queue.rxqueue, - n); - else { - usb_packet_read_to_buffer(udp, - epcp->out_state->mode.linear.rxbuf, - n); - epcp->out_state->mode.linear.rxbuf += n; - } - /* Transaction data updated.*/ - epcp->out_state->rxcnt += n; - epcp->out_state->rxsize -= n; - epcp->out_state->rxpkts -= 1; - - /* The transaction is completed if the specified number of packets - has been received or the current packet is a short packet.*/ - if ((n < epcp->out_maxsize) || (epcp->out_state->rxpkts == 0)) { - /* Transfer complete, invokes the callback.*/ - _usb_isr_invoke_out_cb(usbp, ep); - } - else { - /* Transfer not complete, there are more packets to receive.*/ - EPR_SET_STAT_RX(ep, EPR_STAT_RX_VALID); - } - } - } - istr = STM32_USB->ISTR; - } - - CH_IRQ_EPILOGUE(); -} -#endif - -/*===========================================================================*/ -/* Driver exported functions. */ -/*===========================================================================*/ - -/** - * @brief Low level USB driver initialization. - * - * @notapi - */ -void usb_lld_init(void) { - - /* Driver initialization.*/ - usbObjectInit(&USBD1); -} - -/** - * @brief Configures and activates the USB peripheral. - * - * @param[in] usbp pointer to the @p USBDriver object - * - * @notapi - */ -void usb_lld_start(USBDriver *usbp) { - - if (usbp->state == USB_STOP) { - /* Clock activation.*/ -#if STM32_USB_USE_USB1 - if (&USBD1 == usbp) { - /* USB clock enabled.*/ - rccEnableUSB(FALSE); - /* Powers up the transceiver while holding the USB in reset state.*/ - STM32_USB->CNTR = CNTR_FRES; - /* Enabling the USB IRQ vectors, this also gives enough time to allow - the transceiver power up (1uS).*/ - nvicEnableVector(STM32_USB1_HP_NUMBER, STM32_USB_USB1_HP_IRQ_PRIORITY); - nvicEnableVector(STM32_USB1_LP_NUMBER, STM32_USB_USB1_LP_IRQ_PRIORITY); - /* Releases the USB reset.*/ - STM32_USB->CNTR = 0; - } -#endif - /* Reset procedure enforced on driver start.*/ - _usb_reset(usbp); - } - /* Configuration.*/ -} - -/** - * @brief Deactivates the USB peripheral. - * - * @param[in] usbp pointer to the @p USBDriver object - * - * @notapi - */ -void usb_lld_stop(USBDriver *usbp) { - - /* If in ready state then disables the USB clock.*/ - if (usbp->state == USB_STOP) { -#if STM32_USB_USE_USB1 - if (&USBD1 == usbp) { - nvicDisableVector(STM32_USB1_HP_NUMBER); - nvicDisableVector(STM32_USB1_LP_NUMBER); - STM32_USB->CNTR = CNTR_PDWN | CNTR_FRES; - rccDisableUSB(FALSE); - } -#endif - } -} - -/** - * @brief USB low level reset routine. - * - * @param[in] usbp pointer to the @p USBDriver object - * - * @notapi - */ -void usb_lld_reset(USBDriver *usbp) { - uint32_t cntr; - - /* Post reset initialization.*/ - STM32_USB->BTABLE = 0; - STM32_USB->ISTR = 0; - STM32_USB->DADDR = DADDR_EF; - cntr = /*CNTR_ESOFM | */ CNTR_RESETM | CNTR_SUSPM | - CNTR_WKUPM | /*CNTR_ERRM | CNTR_PMAOVRM |*/ CNTR_CTRM; - /* The SOF interrupt is only enabled if a callback is defined for - this service because it is an high rate source.*/ - if (usbp->config->sof_cb != NULL) - cntr |= CNTR_SOFM; - STM32_USB->CNTR = cntr; - - /* Resets the packet memory allocator.*/ - usb_pm_reset(usbp); - - /* EP0 initialization.*/ - usbp->epc[0] = &ep0config; - usb_lld_init_endpoint(usbp, 0); -} - -/** - * @brief Sets the USB address. - * - * @param[in] usbp pointer to the @p USBDriver object - * - * @notapi - */ -void usb_lld_set_address(USBDriver *usbp) { - - STM32_USB->DADDR = (uint32_t)(usbp->address) | DADDR_EF; -} - -/** - * @brief Enables an endpoint. - * - * @param[in] usbp pointer to the @p USBDriver object - * @param[in] ep endpoint number - * - * @notapi - */ -void usb_lld_init_endpoint(USBDriver *usbp, usbep_t ep) { - uint16_t nblocks, epr; - stm32_usb_descriptor_t *dp; - const USBEndpointConfig *epcp = usbp->epc[ep]; - - /* Setting the endpoint type.*/ - switch (epcp->ep_mode & USB_EP_MODE_TYPE) { - case USB_EP_MODE_TYPE_ISOC: - epr = EPR_EP_TYPE_ISO; - break; - case USB_EP_MODE_TYPE_BULK: - epr = EPR_EP_TYPE_BULK; - break; - case USB_EP_MODE_TYPE_INTR: - epr = EPR_EP_TYPE_INTERRUPT; - break; - default: - epr = EPR_EP_TYPE_CONTROL; - } - - /* IN endpoint initially in NAK mode.*/ - if (epcp->in_cb != NULL) - epr |= EPR_STAT_TX_NAK; - - /* OUT endpoint initially in NAK mode.*/ - if (epcp->out_cb != NULL) - epr |= EPR_STAT_RX_NAK; - - /* EPxR register setup.*/ - EPR_SET(ep, epr | ep); - EPR_TOGGLE(ep, epr); - - /* Endpoint size and address initialization.*/ - if (epcp->out_maxsize > 62) - nblocks = (((((epcp->out_maxsize - 1) | 0x1f) + 1) / 32) << 10) | - 0x8000; - else - nblocks = ((((epcp->out_maxsize - 1) | 1) + 1) / 2) << 10; - dp = USB_GET_DESCRIPTOR(ep); - dp->TXCOUNT0 = 0; - dp->RXCOUNT0 = nblocks; - dp->TXADDR0 = usb_pm_alloc(usbp, epcp->in_maxsize); - dp->RXADDR0 = usb_pm_alloc(usbp, epcp->out_maxsize); -} - -/** - * @brief Disables all the active endpoints except the endpoint zero. - * - * @param[in] usbp pointer to the @p USBDriver object - * - * @notapi - */ -void usb_lld_disable_endpoints(USBDriver *usbp) { - unsigned i; - - /* Resets the packet memory allocator.*/ - usb_pm_reset(usbp); - - /* Disabling all endpoints.*/ - for (i = 1; i <= USB_ENDOPOINTS_NUMBER; i++) { - EPR_TOGGLE(i, 0); - EPR_SET(i, 0); - } -} - -/** - * @brief Returns the status of an OUT endpoint. - * - * @param[in] usbp pointer to the @p USBDriver object - * @param[in] ep endpoint number - * @return The endpoint status. - * @retval EP_STATUS_DISABLED The endpoint is not active. - * @retval EP_STATUS_STALLED The endpoint is stalled. - * @retval EP_STATUS_ACTIVE The endpoint is active. - * - * @notapi - */ -usbepstatus_t usb_lld_get_status_out(USBDriver *usbp, usbep_t ep) { - - (void)usbp; - switch (STM32_USB->EPR[ep] & EPR_STAT_RX_MASK) { - case EPR_STAT_RX_DIS: - return EP_STATUS_DISABLED; - case EPR_STAT_RX_STALL: - return EP_STATUS_STALLED; - default: - return EP_STATUS_ACTIVE; - } -} - -/** - * @brief Returns the status of an IN endpoint. - * - * @param[in] usbp pointer to the @p USBDriver object - * @param[in] ep endpoint number - * @return The endpoint status. - * @retval EP_STATUS_DISABLED The endpoint is not active. - * @retval EP_STATUS_STALLED The endpoint is stalled. - * @retval EP_STATUS_ACTIVE The endpoint is active. - * - * @notapi - */ -usbepstatus_t usb_lld_get_status_in(USBDriver *usbp, usbep_t ep) { - - (void)usbp; - switch (STM32_USB->EPR[ep] & EPR_STAT_TX_MASK) { - case EPR_STAT_TX_DIS: - return EP_STATUS_DISABLED; - case EPR_STAT_TX_STALL: - return EP_STATUS_STALLED; - default: - return EP_STATUS_ACTIVE; - } -} - -/** - * @brief Reads a setup packet from the dedicated packet buffer. - * @details This function must be invoked in the context of the @p setup_cb - * callback in order to read the received setup packet. - * @pre In order to use this function the endpoint must have been - * initialized as a control endpoint. - * @post The endpoint is ready to accept another packet. - * - * @param[in] usbp pointer to the @p USBDriver object - * @param[in] ep endpoint number - * @param[out] buf buffer where to copy the packet data - * - * @notapi - */ -void usb_lld_read_setup(USBDriver *usbp, usbep_t ep, uint8_t *buf) { - uint32_t *pmap; - stm32_usb_descriptor_t *udp; - uint32_t n; - - (void)usbp; - udp = USB_GET_DESCRIPTOR(ep); - pmap = USB_ADDR2PTR(udp->RXADDR0); - for (n = 0; n < 4; n++) { - *(uint16_t *)buf = (uint16_t)*pmap++; - buf += 2; - } -} - -/** - * @brief Prepares for a receive operation. - * - * @param[in] usbp pointer to the @p USBDriver object - * @param[in] ep endpoint number - * - * @notapi - */ -void usb_lld_prepare_receive(USBDriver *usbp, usbep_t ep) { - USBOutEndpointState *osp = usbp->epc[ep]->out_state; - - /* Transfer initialization.*/ - if (osp->rxsize == 0) /* Special case for zero sized packets.*/ - osp->rxpkts = 1; - else - osp->rxpkts = (uint16_t)((osp->rxsize + usbp->epc[ep]->out_maxsize - 1) / - usbp->epc[ep]->out_maxsize); -} - -/** - * @brief Prepares for a transmit operation. - * - * @param[in] usbp pointer to the @p USBDriver object - * @param[in] ep endpoint number - * - * @notapi - */ -void usb_lld_prepare_transmit(USBDriver *usbp, usbep_t ep) { - size_t n; - USBInEndpointState *isp = usbp->epc[ep]->in_state; - - /* Transfer initialization.*/ - n = isp->txsize; - if (n > (size_t)usbp->epc[ep]->in_maxsize) - n = (size_t)usbp->epc[ep]->in_maxsize; - - if (isp->txqueued) - usb_packet_write_from_queue(USB_GET_DESCRIPTOR(ep), - isp->mode.queue.txqueue, n); - else - usb_packet_write_from_buffer(USB_GET_DESCRIPTOR(ep), - isp->mode.linear.txbuf, n); -} - -/** - * @brief Starts a receive operation on an OUT endpoint. - * - * @param[in] usbp pointer to the @p USBDriver object - * @param[in] ep endpoint number - * - * @notapi - */ -void usb_lld_start_out(USBDriver *usbp, usbep_t ep) { - - (void)usbp; - - EPR_SET_STAT_RX(ep, EPR_STAT_RX_VALID); -} - -/** - * @brief Starts a transmit operation on an IN endpoint. - * - * @param[in] usbp pointer to the @p USBDriver object - * @param[in] ep endpoint number - * - * @notapi - */ -void usb_lld_start_in(USBDriver *usbp, usbep_t ep) { - - (void)usbp; - - EPR_SET_STAT_TX(ep, EPR_STAT_TX_VALID); -} - -/** - * @brief Brings an OUT endpoint in the stalled state. - * - * @param[in] usbp pointer to the @p USBDriver object - * @param[in] ep endpoint number - * - * @notapi - */ -void usb_lld_stall_out(USBDriver *usbp, usbep_t ep) { - - (void)usbp; - - EPR_SET_STAT_RX(ep, EPR_STAT_RX_STALL); -} - -/** - * @brief Brings an IN endpoint in the stalled state. - * - * @param[in] usbp pointer to the @p USBDriver object - * @param[in] ep endpoint number - * - * @notapi - */ -void usb_lld_stall_in(USBDriver *usbp, usbep_t ep) { - - (void)usbp; - - EPR_SET_STAT_TX(ep, EPR_STAT_TX_STALL); -} - -/** - * @brief Brings an OUT endpoint in the active state. - * - * @param[in] usbp pointer to the @p USBDriver object - * @param[in] ep endpoint number - * - * @notapi - */ -void usb_lld_clear_out(USBDriver *usbp, usbep_t ep) { - - (void)usbp; - - /* Makes sure to not put to NAK an endpoint that is already - transferring.*/ - if ((STM32_USB->EPR[ep] & EPR_STAT_RX_MASK) != EPR_STAT_RX_VALID) - EPR_SET_STAT_TX(ep, EPR_STAT_RX_NAK); -} - -/** - * @brief Brings an IN endpoint in the active state. - * - * @param[in] usbp pointer to the @p USBDriver object - * @param[in] ep endpoint number - * - * @notapi - */ -void usb_lld_clear_in(USBDriver *usbp, usbep_t ep) { - - (void)usbp; - - /* Makes sure to not put to NAK an endpoint that is already - transferring.*/ - if ((STM32_USB->EPR[ep] & EPR_STAT_TX_MASK) != EPR_STAT_TX_VALID) - EPR_SET_STAT_TX(ep, EPR_STAT_TX_NAK); -} - -#endif /* HAL_USE_USB */ - -/** @} */ diff --git a/os/hal/platforms/STM32/USBv1/usb_lld.h b/os/hal/platforms/STM32/USBv1/usb_lld.h deleted file mode 100644 index 042129758..000000000 --- a/os/hal/platforms/STM32/USBv1/usb_lld.h +++ /dev/null @@ -1,437 +0,0 @@ -/* - ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file STM32/USBv1/usb_lld.h - * @brief STM32 USB subsystem low level driver header. - * - * @addtogroup USB - * @{ - */ - -#ifndef _USB_LLD_H_ -#define _USB_LLD_H_ - -#if HAL_USE_USB || defined(__DOXYGEN__) - -#include "stm32_usb.h" - -/*===========================================================================*/ -/* Driver constants. */ -/*===========================================================================*/ - -/** - * @brief Maximum endpoint address. - */ -#define USB_MAX_ENDPOINTS USB_ENDOPOINTS_NUMBER - -/** - * @brief This device requires the address change after the status packet. - */ -#define USB_SET_ADDRESS_MODE USB_LATE_SET_ADDRESS - -/*===========================================================================*/ -/* Driver pre-compile time settings. */ -/*===========================================================================*/ - -/** - * @brief USB1 driver enable switch. - * @details If set to @p TRUE the support for USB1 is included. - * @note The default is @p TRUE. - */ -#if !defined(STM32_USB_USE_USB1) || defined(__DOXYGEN__) -#define STM32_USB_USE_USB1 FALSE -#endif - -/** - * @brief Enables the USB device low power mode on suspend. - */ -#if !defined(STM32_USB_LOW_POWER_ON_SUSPEND) || defined(__DOXYGEN__) -#define STM32_USB_LOW_POWER_ON_SUSPEND FALSE -#endif - -/** - * @brief USB1 interrupt priority level setting. - */ -#if !defined(STM32_USB_USB1_HP_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_USB_USB1_HP_IRQ_PRIORITY 13 -#endif - -/** - * @brief USB1 interrupt priority level setting. - */ -#if !defined(STM32_USB_USB1_LP_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_USB_USB1_LP_IRQ_PRIORITY 14 -#endif - -/*===========================================================================*/ -/* Derived constants and error checks. */ -/*===========================================================================*/ - -#if STM32_USB_USE_USB1 && !STM32_HAS_USB -#error "USB not present in the selected device" -#endif - -#if !STM32_USB_USE_USB1 -#error "USB driver activated but no USB peripheral assigned" -#endif - -#if STM32_USB_USE_USB1 && \ - !CORTEX_IS_VALID_KERNEL_PRIORITY(STM32_USB_USB1_HP_IRQ_PRIORITY) -#error "Invalid IRQ priority assigned to USB HP" -#endif - -#if STM32_USB_USE_USB1 && \ - !CORTEX_IS_VALID_KERNEL_PRIORITY(STM32_USB_USB1_LP_IRQ_PRIORITY) -#error "Invalid IRQ priority assigned to USB LP" -#endif - -#if STM32_USBCLK != 48000000 -#error "the USB driver requires a 48MHz clock" -#endif - -/*===========================================================================*/ -/* Driver data structures and types. */ -/*===========================================================================*/ - -/** - * @brief Type of an IN endpoint state structure. - */ -typedef struct { - /** - * @brief Buffer mode, queue or linear. - */ - bool txqueued; - /** - * @brief Requested transmit transfer size. - */ - size_t txsize; - /** - * @brief Transmitted bytes so far. - */ - size_t txcnt; - union { - struct { - /** - * @brief Pointer to the transmission linear buffer. - */ - const uint8_t *txbuf; - } linear; - struct { - /** - * @brief Pointer to the output queue. - */ - output_queue_t *txqueue; - } queue; - /* End of the mandatory fields.*/ - } mode; -} USBInEndpointState; - -/** - * @brief Type of an OUT endpoint state structure. - */ -typedef struct { - /** - * @brief Buffer mode, queue or linear. - */ - bool rxqueued; - /** - * @brief Requested receive transfer size. - */ - size_t rxsize; - /** - * @brief Received bytes so far. - */ - size_t rxcnt; - union { - struct { - /** - * @brief Pointer to the receive linear buffer. - */ - uint8_t *rxbuf; - } linear; - struct { - /** - * @brief Pointer to the input queue. - */ - input_queue_t *rxqueue; - } queue; - } mode; - /* End of the mandatory fields.*/ - /** - * @brief Number of packets to receive. - */ - uint16_t rxpkts; -} USBOutEndpointState; - -/** - * @brief Type of an USB endpoint configuration structure. - * @note Platform specific restrictions may apply to endpoints. - */ -typedef struct { - /** - * @brief Type and mode of the endpoint. - */ - uint32_t ep_mode; - /** - * @brief Setup packet notification callback. - * @details This callback is invoked when a setup packet has been - * received. - * @post The application must immediately call @p usbReadPacket() in - * order to access the received packet. - * @note This field is only valid for @p USB_EP_MODE_TYPE_CTRL - * endpoints, it should be set to @p NULL for other endpoint - * types. - */ - usbepcallback_t setup_cb; - /** - * @brief IN endpoint notification callback. - * @details This field must be set to @p NULL if the IN endpoint is not - * used. - */ - usbepcallback_t in_cb; - /** - * @brief OUT endpoint notification callback. - * @details This field must be set to @p NULL if the OUT endpoint is not - * used. - */ - usbepcallback_t out_cb; - /** - * @brief IN endpoint maximum packet size. - * @details This field must be set to zero if the IN endpoint is not - * used. - */ - uint16_t in_maxsize; - /** - * @brief OUT endpoint maximum packet size. - * @details This field must be set to zero if the OUT endpoint is not - * used. - */ - uint16_t out_maxsize; - /** - * @brief @p USBEndpointState associated to the IN endpoint. - * @details This structure maintains the state of the IN endpoint. - */ - USBInEndpointState *in_state; - /** - * @brief @p USBEndpointState associated to the OUT endpoint. - * @details This structure maintains the state of the OUT endpoint. - */ - USBOutEndpointState *out_state; - /* End of the mandatory fields.*/ - /** - * @brief Reserved field, not currently used. - * @note Initialize this field to 1 in order to be forward compatible. - */ - uint16_t ep_buffers; - /** - * @brief Pointer to a buffer for setup packets. - * @details Setup packets require a dedicated 8-bytes buffer, set this - * field to @p NULL for non-control endpoints. - */ - uint8_t *setup_buf; -} USBEndpointConfig; - -/** - * @brief Type of an USB driver configuration structure. - */ -typedef struct { - /** - * @brief USB events callback. - * @details This callback is invoked when an USB driver event is registered. - */ - usbeventcb_t event_cb; - /** - * @brief Device GET_DESCRIPTOR request callback. - * @note This callback is mandatory and cannot be set to @p NULL. - */ - usbgetdescriptor_t get_descriptor_cb; - /** - * @brief Requests hook callback. - * @details This hook allows to be notified of standard requests or to - * handle non standard requests. - */ - usbreqhandler_t requests_hook_cb; - /** - * @brief Start Of Frame callback. - */ - usbcallback_t sof_cb; - /* End of the mandatory fields.*/ -} USBConfig; - -/** - * @brief Structure representing an USB driver. - */ -struct USBDriver { - /** - * @brief Driver state. - */ - usbstate_t state; - /** - * @brief Current configuration data. - */ - const USBConfig *config; - /** - * @brief Bit map of the transmitting IN endpoints. - */ - uint16_t transmitting; - /** - * @brief Bit map of the receiving OUT endpoints. - */ - uint16_t receiving; - /** - * @brief Active endpoints configurations. - */ - const USBEndpointConfig *epc[USB_MAX_ENDPOINTS + 1]; - /** - * @brief Fields available to user, it can be used to associate an - * application-defined handler to an IN endpoint. - * @note The base index is one, the endpoint zero does not have a - * reserved element in this array. - */ - void *in_params[USB_MAX_ENDPOINTS]; - /** - * @brief Fields available to user, it can be used to associate an - * application-defined handler to an OUT endpoint. - * @note The base index is one, the endpoint zero does not have a - * reserved element in this array. - */ - void *out_params[USB_MAX_ENDPOINTS]; - /** - * @brief Endpoint 0 state. - */ - usbep0state_t ep0state; - /** - * @brief Next position in the buffer to be transferred through endpoint 0. - */ - uint8_t *ep0next; - /** - * @brief Number of bytes yet to be transferred through endpoint 0. - */ - size_t ep0n; - /** - * @brief Endpoint 0 end transaction callback. - */ - usbcallback_t ep0endcb; - /** - * @brief Setup packet buffer. - */ - uint8_t setup[8]; - /** - * @brief Current USB device status. - */ - uint16_t status; - /** - * @brief Assigned USB address. - */ - uint8_t address; - /** - * @brief Current USB device configuration. - */ - uint8_t configuration; -#if defined(USB_DRIVER_EXT_FIELDS) - USB_DRIVER_EXT_FIELDS -#endif - /* End of the mandatory fields.*/ - /** - * @brief Pointer to the next address in the packet memory. - */ - uint32_t pmnext; -}; - -/*===========================================================================*/ -/* Driver macros. */ -/*===========================================================================*/ - -/** - * @brief Returns the current frame number. - * - * @param[in] usbp pointer to the @p USBDriver object - * @return The current frame number. - * - * @notapi - */ -#define usb_lld_get_frame_number(usbp) (STM32_USB->FNR & FNR_FN_MASK) - -/** - * @brief Returns the exact size of a receive transaction. - * @details The received size can be different from the size specified in - * @p usbStartReceiveI() because the last packet could have a size - * different from the expected one. - * @pre The OUT endpoint must have been configured in transaction mode - * in order to use this function. - * - * @param[in] usbp pointer to the @p USBDriver object - * @param[in] ep endpoint number - * @return Received data size. - * - * @notapi - */ -#define usb_lld_get_transaction_size(usbp, ep) \ - ((usbp)->epc[ep]->out_state->rxcnt) - -/** - * @brief Returns the exact size of a received packet. - * @pre The OUT endpoint must have been configured in packet mode - * in order to use this function. - * - * @param[in] usbp pointer to the @p USBDriver object - * @param[in] ep endpoint number - * @return Received data size. - * - * @notapi - */ -#define usb_lld_get_packet_size(usbp, ep) \ - ((size_t)USB_GET_DESCRIPTOR(ep)->RXCOUNT & RXCOUNT_COUNT_MASK) - -/*===========================================================================*/ -/* External declarations. */ -/*===========================================================================*/ - -#if STM32_USB_USE_USB1 && !defined(__DOXYGEN__) -extern USBDriver USBD1; -#endif - -#ifdef __cplusplus -extern "C" { -#endif - void usb_lld_init(void); - void usb_lld_start(USBDriver *usbp); - void usb_lld_stop(USBDriver *usbp); - void usb_lld_reset(USBDriver *usbp); - void usb_lld_set_address(USBDriver *usbp); - void usb_lld_init_endpoint(USBDriver *usbp, usbep_t ep); - void usb_lld_disable_endpoints(USBDriver *usbp); - usbepstatus_t usb_lld_get_status_in(USBDriver *usbp, usbep_t ep); - usbepstatus_t usb_lld_get_status_out(USBDriver *usbp, usbep_t ep); - void usb_lld_read_setup(USBDriver *usbp, usbep_t ep, uint8_t *buf); - void usb_lld_prepare_receive(USBDriver *usbp, usbep_t ep); - void usb_lld_prepare_transmit(USBDriver *usbp, usbep_t ep); - void usb_lld_start_out(USBDriver *usbp, usbep_t ep); - void usb_lld_start_in(USBDriver *usbp, usbep_t ep); - void usb_lld_stall_out(USBDriver *usbp, usbep_t ep); - void usb_lld_stall_in(USBDriver *usbp, usbep_t ep); - void usb_lld_clear_out(USBDriver *usbp, usbep_t ep); - void usb_lld_clear_in(USBDriver *usbp, usbep_t ep); -#ifdef __cplusplus -} -#endif - -#endif /* HAL_USE_USB */ - -#endif /* _USB_LLD_H_ */ - -/** @} */ diff --git a/os/hal/platforms/STM32/can_lld.c b/os/hal/platforms/STM32/can_lld.c deleted file mode 100644 index a53a8fe27..000000000 --- a/os/hal/platforms/STM32/can_lld.c +++ /dev/null @@ -1,702 +0,0 @@ -/* - ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file STM32/can_lld.c - * @brief STM32 CAN subsystem low level driver source. - * - * @addtogroup CAN - * @{ - */ - -#include "hal.h" - -#if HAL_USE_CAN || defined(__DOXYGEN__) - -/*===========================================================================*/ -/* Driver local definitions. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver exported variables. */ -/*===========================================================================*/ - -/** @brief CAN1 driver identifier.*/ -#if STM32_CAN_USE_CAN1 || defined(__DOXYGEN__) -CANDriver CAND1; -#endif - -/** @brief CAN2 driver identifier.*/ -#if STM32_CAN_USE_CAN2 || defined(__DOXYGEN__) -CANDriver CAND2; -#endif - -/*===========================================================================*/ -/* Driver local variables and types. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver local functions. */ -/*===========================================================================*/ - -/** - * @brief Programs the filters. - * - * @param[in] can2sb number of the first filter assigned to CAN2 - * @param[in] num number of entries in the filters array, if zero then - * a default filter is programmed - * @param[in] cfp pointer to the filters array, can be @p NULL if - * (num == 0) - * - * @notapi - */ -static void can_lld_set_filters(uint32_t can2sb, - uint32_t num, - const CANFilter *cfp) { - - /* Temporarily enabling CAN1 clock.*/ - rccEnableCAN1(FALSE); - - /* Filters initialization.*/ - CAN1->FMR = (CAN1->FMR & 0xFFFF0000) | (can2sb << 8) | CAN_FMR_FINIT; - if (num > 0) { - uint32_t i, fmask; - - /* All filters cleared.*/ - CAN1->FA1R = 0; - CAN1->FM1R = 0; - CAN1->FS1R = 0; - CAN1->FFA1R = 0; - for (i = 0; i < STM32_CAN_MAX_FILTERS; i++) { - CAN1->sFilterRegister[i].FR1 = 0; - CAN1->sFilterRegister[i].FR2 = 0; - } - - /* Scanning the filters array.*/ - for (i = 0; i < num; i++) { - fmask = 1 << cfp->filter; - if (cfp->mode) - CAN1->FM1R |= fmask; - if (cfp->scale) - CAN1->FS1R |= fmask; - if (cfp->assignment) - CAN1->FFA1R |= fmask; - CAN1->sFilterRegister[cfp->filter].FR1 = cfp->register1; - CAN1->sFilterRegister[cfp->filter].FR2 = cfp->register2; - CAN1->FA1R |= fmask; - cfp++; - } - } - else { - /* Setting up a single default filter that enables everything for both - CANs.*/ - CAN1->sFilterRegister[0].FR1 = 0; - CAN1->sFilterRegister[0].FR2 = 0; - CAN1->sFilterRegister[can2sb].FR1 = 0; - CAN1->sFilterRegister[can2sb].FR2 = 0; - CAN1->FM1R = 0; - CAN1->FFA1R = 0; - CAN1->FS1R = 1 | (1 << can2sb); - CAN1->FA1R = 1 | (1 << can2sb); - } - CAN1->FMR &= ~CAN_FMR_FINIT; - - /* Clock disabled, it will be enabled again in can_lld_start().*/ - rccDisableCAN1(FALSE); -} - -/** - * @brief Common TX ISR handler. - * - * @param[in] canp pointer to the @p CANDriver object - * - * @notapi - */ -static void can_lld_tx_handler(CANDriver *canp) { - - /* No more events until a message is transmitted.*/ - canp->can->TSR = CAN_TSR_RQCP0 | CAN_TSR_RQCP1 | CAN_TSR_RQCP2; - osalSysLockFromISR(); - osalQueueWakeupAllI(&canp->txqueue, MSG_OK); - osalEventBroadcastFlagsI(&canp->txempty_event, CAN_MAILBOX_TO_MASK(1)); - osalSysUnlockFromISR(); -} - -/** - * @brief Common RX0 ISR handler. - * - * @param[in] canp pointer to the @p CANDriver object - * - * @notapi - */ -static void can_lld_rx0_handler(CANDriver *canp) { - uint32_t rf0r; - - rf0r = canp->can->RF0R; - if ((rf0r & CAN_RF0R_FMP0) > 0) { - /* No more receive events until the queue 0 has been emptied.*/ - canp->can->IER &= ~CAN_IER_FMPIE0; - osalSysLockFromISR(); - osalQueueWakeupAllI(&canp->rxqueue, MSG_OK); - osalEventBroadcastFlagsI(&canp->rxfull_event, CAN_MAILBOX_TO_MASK(1)); - osalSysUnlockFromISR(); - } - if ((rf0r & CAN_RF0R_FOVR0) > 0) { - /* Overflow events handling.*/ - canp->can->RF0R = CAN_RF0R_FOVR0; - osalSysLockFromISR(); - osalEventBroadcastFlagsI(&canp->error_event, CAN_OVERFLOW_ERROR); - osalSysUnlockFromISR(); - } -} - -/** - * @brief Common RX1 ISR handler. - * - * @param[in] canp pointer to the @p CANDriver object - * - * @notapi - */ -static void can_lld_rx1_handler(CANDriver *canp) { - uint32_t rf1r; - - rf1r = canp->can->RF1R; - if ((rf1r & CAN_RF1R_FMP1) > 0) { - /* No more receive events until the queue 0 has been emptied.*/ - canp->can->IER &= ~CAN_IER_FMPIE1; - osalSysLockFromISR(); - osalQueueWakeupAllI(&canp->rxqueue, MSG_OK); - osalEventBroadcastFlagsI(&canp->rxfull_event, CAN_MAILBOX_TO_MASK(2)); - osalSysUnlockFromISR(); - } - if ((rf1r & CAN_RF1R_FOVR1) > 0) { - /* Overflow events handling.*/ - canp->can->RF1R = CAN_RF1R_FOVR1; - osalSysLockFromISR(); - osalEventBroadcastFlagsI(&canp->error_event, CAN_OVERFLOW_ERROR); - osalSysUnlockFromISR(); - } -} - -/** - * @brief Common SCE ISR handler. - * - * @param[in] canp pointer to the @p CANDriver object - * - * @notapi - */ -static void can_lld_sce_handler(CANDriver *canp) { - uint32_t msr; - - msr = canp->can->MSR; - canp->can->MSR = CAN_MSR_ERRI | CAN_MSR_WKUI | CAN_MSR_SLAKI; - /* Wakeup event.*/ -#if CAN_USE_SLEEP_MODE - if (msr & CAN_MSR_WKUI) { - canp->state = CAN_READY; - canp->can->MCR &= ~CAN_MCR_SLEEP; - osalSysLockFromISR(); - osalEventBroadcastFlagsI(&canp->wakeup_event, 0); - osalSysUnlockFromISR(); - } -#endif /* CAN_USE_SLEEP_MODE */ - /* Error event.*/ - if (msr & CAN_MSR_ERRI) { - eventflags_t flags; - uint32_t esr = canp->can->ESR; - - canp->can->ESR &= ~CAN_ESR_LEC; - flags = (eventflags_t)(esr & 7); - if ((esr & CAN_ESR_LEC) > 0) - flags |= CAN_FRAMING_ERROR; - - osalSysLockFromISR(); - /* The content of the ESR register is copied unchanged in the upper - half word of the listener flags mask.*/ - osalEventBroadcastFlagsI(&canp->error_event, flags | (eventflags_t)(esr << 16)); - osalSysUnlockFromISR(); - } -} - -/*===========================================================================*/ -/* Driver interrupt handlers. */ -/*===========================================================================*/ - -#if STM32_CAN_USE_CAN1 || defined(__DOXYGEN__) -/** - * @brief CAN1 TX interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(STM32_CAN1_TX_HANDLER) { - - OSAL_IRQ_PROLOGUE(); - - can_lld_tx_handler(&CAND1); - - OSAL_IRQ_EPILOGUE(); -} - -/* - * @brief CAN1 RX0 interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(STM32_CAN1_RX0_HANDLER) { - - OSAL_IRQ_PROLOGUE(); - - can_lld_rx0_handler(&CAND1); - - OSAL_IRQ_EPILOGUE(); -} - -/** - * @brief CAN1 RX1 interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(STM32_CAN1_RX1_HANDLER) { - - OSAL_IRQ_PROLOGUE(); - - can_lld_rx1_handler(&CAND1); - - OSAL_IRQ_EPILOGUE(); -} - -/** - * @brief CAN1 SCE interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(STM32_CAN1_SCE_HANDLER) { - - OSAL_IRQ_PROLOGUE(); - - can_lld_sce_handler(&CAND1); - - OSAL_IRQ_EPILOGUE(); -} -#endif /* STM32_CAN_USE_CAN1 */ - -#if STM32_CAN_USE_CAN2 || defined(__DOXYGEN__) -/** - * @brief CAN2 TX interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(STM32_CAN2_TX_HANDLER) { - - OSAL_IRQ_PROLOGUE(); - - can_lld_tx_handler(&CAND2); - - OSAL_IRQ_EPILOGUE(); -} - -/* - * @brief CAN2 RX0 interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(STM32_CAN2_RX0_HANDLER) { - - OSAL_IRQ_PROLOGUE(); - - can_lld_rx0_handler(&CAND2); - - OSAL_IRQ_EPILOGUE(); -} - -/** - * @brief CAN2 RX1 interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(STM32_CAN2_RX1_HANDLER) { - - OSAL_IRQ_PROLOGUE(); - - can_lld_rx1_handler(&CAND2); - - OSAL_IRQ_EPILOGUE(); -} - -/** - * @brief CAN2 SCE interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(STM32_CAN2_SCE_HANDLER) { - - OSAL_IRQ_PROLOGUE(); - - can_lld_sce_handler(&CAND2); - - OSAL_IRQ_EPILOGUE(); -} -#endif /* STM32_CAN_USE_CAN2 */ - -/*===========================================================================*/ -/* Driver exported functions. */ -/*===========================================================================*/ - -/** - * @brief Low level CAN driver initialization. - * - * @notapi - */ -void can_lld_init(void) { - -#if STM32_CAN_USE_CAN1 - /* Driver initialization.*/ - canObjectInit(&CAND1); - CAND1.can = CAN1; -#endif -#if STM32_CAN_USE_CAN2 - /* Driver initialization.*/ - canObjectInit(&CAND2); - CAND2.can = CAN2; -#endif - - /* Filters initialization.*/ -#if STM32_HAS_CAN2 - can_lld_set_filters(STM32_CAN_MAX_FILTERS / 2, 0, NULL); -#else - can_lld_set_filters(STM32_CAN_MAX_FILTERS, 0, NULL); -#endif - -} - -/** - * @brief Configures and activates the CAN peripheral. - * - * @param[in] canp pointer to the @p CANDriver object - * - * @notapi - */ -void can_lld_start(CANDriver *canp) { - - /* Clock activation.*/ -#if STM32_CAN_USE_CAN1 - if (&CAND1 == canp) { - nvicEnableVector(STM32_CAN1_TX_NUMBER, STM32_CAN_CAN1_IRQ_PRIORITY); - nvicEnableVector(STM32_CAN1_RX0_NUMBER, STM32_CAN_CAN1_IRQ_PRIORITY); - nvicEnableVector(STM32_CAN1_RX1_NUMBER, STM32_CAN_CAN1_IRQ_PRIORITY); - nvicEnableVector(STM32_CAN1_SCE_NUMBER, STM32_CAN_CAN1_IRQ_PRIORITY); - rccEnableCAN1(FALSE); - } -#endif -#if STM32_CAN_USE_CAN2 - if (&CAND2 == canp) { - - osalDbgAssert(CAND1.state != CAN_STOP, "CAN1 must be started"); - - nvicEnableVector(STM32_CAN2_TX_NUMBER, STM32_CAN_CAN2_IRQ_PRIORITY); - nvicEnableVector(STM32_CAN2_RX0_NUMBER, STM32_CAN_CAN2_IRQ_PRIORITY); - nvicEnableVector(STM32_CAN2_RX1_NUMBER, STM32_CAN_CAN2_IRQ_PRIORITY); - nvicEnableVector(STM32_CAN2_SCE_NUMBER, STM32_CAN_CAN2_IRQ_PRIORITY); - rccEnableCAN2(FALSE); - } -#endif - - /* Entering initialization mode. */ - canp->state = CAN_STARTING; - canp->can->MCR = CAN_MCR_INRQ; - while ((canp->can->MSR & CAN_MSR_INAK) == 0) - osalThreadSleepS(1); - /* BTR initialization.*/ - canp->can->BTR = canp->config->btr; - /* MCR initialization.*/ - canp->can->MCR = canp->config->mcr; - - /* Interrupt sources initialization.*/ - canp->can->IER = CAN_IER_TMEIE | CAN_IER_FMPIE0 | CAN_IER_FMPIE1 | - CAN_IER_WKUIE | CAN_IER_ERRIE | CAN_IER_LECIE | - CAN_IER_BOFIE | CAN_IER_EPVIE | CAN_IER_EWGIE | - CAN_IER_FOVIE0 | CAN_IER_FOVIE1; -} - -/** - * @brief Deactivates the CAN peripheral. - * - * @param[in] canp pointer to the @p CANDriver object - * - * @notapi - */ -void can_lld_stop(CANDriver *canp) { - - /* If in ready state then disables the CAN peripheral.*/ - if (canp->state == CAN_READY) { -#if STM32_CAN_USE_CAN1 - if (&CAND1 == canp) { - -#if STM32_CAN_USE_CAN2 - osalDbgAssert(CAND2.state == CAN_STOP, "CAN2 must be stopped"); -#endif - - CAN1->MCR = 0x00010002; /* Register reset value. */ - CAN1->IER = 0x00000000; /* All sources disabled. */ - nvicDisableVector(STM32_CAN1_TX_NUMBER); - nvicDisableVector(STM32_CAN1_RX0_NUMBER); - nvicDisableVector(STM32_CAN1_RX1_NUMBER); - nvicDisableVector(STM32_CAN1_SCE_NUMBER); - rccDisableCAN1(FALSE); - } -#endif -#if STM32_CAN_USE_CAN2 - if (&CAND2 == canp) { - CAN2->MCR = 0x00010002; /* Register reset value. */ - CAN2->IER = 0x00000000; /* All sources disabled. */ - nvicDisableVector(STM32_CAN2_TX_NUMBER); - nvicDisableVector(STM32_CAN2_RX0_NUMBER); - nvicDisableVector(STM32_CAN2_RX1_NUMBER); - nvicDisableVector(STM32_CAN2_SCE_NUMBER); - rccDisableCAN2(FALSE); - } -#endif - } -} - -/** - * @brief Determines whether a frame can be transmitted. - * - * @param[in] canp pointer to the @p CANDriver object - * @param[in] mailbox mailbox number, @p CAN_ANY_MAILBOX for any mailbox - * - * @return The queue space availability. - * @retval FALSE no space in the transmit queue. - * @retval TRUE transmit slot available. - * - * @notapi - */ -bool_t can_lld_is_tx_empty(CANDriver *canp, canmbx_t mailbox) { - - switch (mailbox) { - case CAN_ANY_MAILBOX: - return (canp->can->TSR & CAN_TSR_TME) != 0; - case 1: - return (canp->can->TSR & CAN_TSR_TME0) != 0; - case 2: - return (canp->can->TSR & CAN_TSR_TME1) != 0; - case 3: - return (canp->can->TSR & CAN_TSR_TME2) != 0; - default: - return FALSE; - } -} - -/** - * @brief Inserts a frame into the transmit queue. - * - * @param[in] canp pointer to the @p CANDriver object - * @param[in] ctfp pointer to the CAN frame to be transmitted - * @param[in] mailbox mailbox number, @p CAN_ANY_MAILBOX for any mailbox - * - * @notapi - */ -void can_lld_transmit(CANDriver *canp, - canmbx_t mailbox, - const CANTxFrame *ctfp) { - uint32_t tir; - CAN_TxMailBox_TypeDef *tmbp; - - /* Pointer to a free transmission mailbox.*/ - switch (mailbox) { - case CAN_ANY_MAILBOX: - tmbp = &canp->can->sTxMailBox[(canp->can->TSR & CAN_TSR_CODE) >> 24]; - break; - case 1: - tmbp = &canp->can->sTxMailBox[0]; - break; - case 2: - tmbp = &canp->can->sTxMailBox[1]; - break; - case 3: - tmbp = &canp->can->sTxMailBox[2]; - break; - default: - return; - } - - /* Preparing the message.*/ - if (ctfp->IDE) - tir = ((uint32_t)ctfp->EID << 3) | ((uint32_t)ctfp->RTR << 1) | - CAN_TI0R_IDE; - else - tir = ((uint32_t)ctfp->SID << 21) | ((uint32_t)ctfp->RTR << 1); - tmbp->TDTR = ctfp->DLC; - tmbp->TDLR = ctfp->data32[0]; - tmbp->TDHR = ctfp->data32[1]; - tmbp->TIR = tir | CAN_TI0R_TXRQ; -} - -/** - * @brief Determines whether a frame has been received. - * - * @param[in] canp pointer to the @p CANDriver object - * @param[in] mailbox mailbox number, @p CAN_ANY_MAILBOX for any mailbox - * - * @return The queue space availability. - * @retval FALSE no space in the transmit queue. - * @retval TRUE transmit slot available. - * - * @notapi - */ -bool_t can_lld_is_rx_nonempty(CANDriver *canp, canmbx_t mailbox) { - - switch (mailbox) { - case CAN_ANY_MAILBOX: - return ((canp->can->RF0R & CAN_RF0R_FMP0) != 0 || - (canp->can->RF1R & CAN_RF1R_FMP1) != 0); - case 1: - return (canp->can->RF0R & CAN_RF0R_FMP0) != 0; - case 2: - return (canp->can->RF1R & CAN_RF1R_FMP1) != 0; - default: - return FALSE; - } -} - -/** - * @brief Receives a frame from the input queue. - * - * @param[in] canp pointer to the @p CANDriver object - * @param[in] mailbox mailbox number, @p CAN_ANY_MAILBOX for any mailbox - * @param[out] crfp pointer to the buffer where the CAN frame is copied - * - * @notapi - */ -void can_lld_receive(CANDriver *canp, - canmbx_t mailbox, - CANRxFrame *crfp) { - uint32_t rir, rdtr; - - if (mailbox == CAN_ANY_MAILBOX) { - if ((canp->can->RF0R & CAN_RF0R_FMP0) != 0) - mailbox = 1; - else if ((canp->can->RF1R & CAN_RF1R_FMP1) != 0) - mailbox = 2; - else { - /* Should not happen, do nothing.*/ - return; - } - } - switch (mailbox) { - case 1: - /* Fetches the message.*/ - rir = canp->can->sFIFOMailBox[0].RIR; - rdtr = canp->can->sFIFOMailBox[0].RDTR; - crfp->data32[0] = canp->can->sFIFOMailBox[0].RDLR; - crfp->data32[1] = canp->can->sFIFOMailBox[0].RDHR; - - /* Releases the mailbox.*/ - canp->can->RF0R = CAN_RF0R_RFOM0; - - /* If the queue is empty re-enables the interrupt in order to generate - events again.*/ - if ((canp->can->RF0R & CAN_RF0R_FMP0) == 0) - canp->can->IER |= CAN_IER_FMPIE0; - break; - case 2: - /* Fetches the message.*/ - rir = canp->can->sFIFOMailBox[1].RIR; - rdtr = canp->can->sFIFOMailBox[1].RDTR; - crfp->data32[0] = canp->can->sFIFOMailBox[1].RDLR; - crfp->data32[1] = canp->can->sFIFOMailBox[1].RDHR; - - /* Releases the mailbox.*/ - canp->can->RF1R = CAN_RF1R_RFOM1; - - /* If the queue is empty re-enables the interrupt in order to generate - events again.*/ - if ((canp->can->RF1R & CAN_RF1R_FMP1) == 0) - canp->can->IER |= CAN_IER_FMPIE1; - break; - default: - /* Should not happen, do nothing.*/ - return; - } - - /* Decodes the various fields in the RX frame.*/ - crfp->RTR = (rir & CAN_RI0R_RTR) >> 1; - crfp->IDE = (rir & CAN_RI0R_IDE) >> 2; - if (crfp->IDE) - crfp->EID = rir >> 3; - else - crfp->SID = rir >> 21; - crfp->DLC = rdtr & CAN_RDT0R_DLC; - crfp->FMI = (uint8_t)(rdtr >> 8); - crfp->TIME = (uint16_t)(rdtr >> 16); -} - -#if CAN_USE_SLEEP_MODE || defined(__DOXYGEN__) -/** - * @brief Enters the sleep mode. - * - * @param[in] canp pointer to the @p CANDriver object - * - * @notapi - */ -void can_lld_sleep(CANDriver *canp) { - - canp->can->MCR |= CAN_MCR_SLEEP; -} - -/** - * @brief Enforces leaving the sleep mode. - * - * @param[in] canp pointer to the @p CANDriver object - * - * @notapi - */ -void can_lld_wakeup(CANDriver *canp) { - - canp->can->MCR &= ~CAN_MCR_SLEEP; -} -#endif /* CAN_USE_SLEEP_MODE */ - -/** - * @brief Programs the filters. - * @note This is an STM32-specific API. - * - * @param[in] can2sb number of the first filter assigned to CAN2 - * @param[in] num number of entries in the filters array, if zero then - * a default filter is programmed - * @param[in] cfp pointer to the filters array, can be @p NULL if - * (num == 0) - * - * @api - */ -void canSTM32SetFilters(uint32_t can2sb, uint32_t num, const CANFilter *cfp) { - - osalDbgCheck((can2sb > 1) && (can2sb < STM32_CAN_MAX_FILTERS) && - (num < STM32_CAN_MAX_FILTERS)); - -#if STM32_CAN_USE_CAN1 - osalDbgAssert(CAND1.state == CAN_STOP, "invalid state"); -#endif -#if STM32_CAN_USE_CAN2 - osalDbgAssert(CAND2.state == CAN_STOP, "invalid state"); -#endif - - can_lld_set_filters(can2sb, num, cfp); -} - -#endif /* HAL_USE_CAN */ - -/** @} */ diff --git a/os/hal/platforms/STM32/can_lld.h b/os/hal/platforms/STM32/can_lld.h deleted file mode 100644 index 9f3797029..000000000 --- a/os/hal/platforms/STM32/can_lld.h +++ /dev/null @@ -1,366 +0,0 @@ -/* - ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file STM32/can_lld.h - * @brief STM32 CAN subsystem low level driver header. - * - * @addtogroup CAN - * @{ - */ - -#ifndef _CAN_LLD_H_ -#define _CAN_LLD_H_ - -#if HAL_USE_CAN || defined(__DOXYGEN__) - -/*===========================================================================*/ -/* Driver constants. */ -/*===========================================================================*/ - -/* - * The following macros from the ST header file are replaced with better - * equivalents. - */ -#undef CAN_BTR_BRP -#undef CAN_BTR_TS1 -#undef CAN_BTR_TS2 -#undef CAN_BTR_SJW - -/** - * @brief This switch defines whether the driver implementation supports - * a low power switch mode with automatic an wakeup feature. - */ -#define CAN_SUPPORTS_SLEEP TRUE - -/** - * @brief This implementation supports three transmit mailboxes. - */ -#define CAN_TX_MAILBOXES 3 - -/** - * @brief This implementation supports two receive mailboxes. - */ -#define CAN_RX_MAILBOXES 2 - -/** - * @name CAN registers helper macros - * @{ - */ -#define CAN_BTR_BRP(n) (n) /**< @brief BRP field macro.*/ -#define CAN_BTR_TS1(n) ((n) << 16) /**< @brief TS1 field macro.*/ -#define CAN_BTR_TS2(n) ((n) << 20) /**< @brief TS2 field macro.*/ -#define CAN_BTR_SJW(n) ((n) << 24) /**< @brief SJW field macro.*/ - -#define CAN_IDE_STD 0 /**< @brief Standard id. */ -#define CAN_IDE_EXT 1 /**< @brief Extended id. */ - -#define CAN_RTR_DATA 0 /**< @brief Data frame. */ -#define CAN_RTR_REMOTE 1 /**< @brief Remote frame. */ -/** @} */ - -/*===========================================================================*/ -/* Driver pre-compile time settings. */ -/*===========================================================================*/ - -/** - * @name Configuration options - * @{ - */ -/** - * @brief CAN1 driver enable switch. - * @details If set to @p TRUE the support for CAN1 is included. - */ -#if !defined(STM32_CAN_USE_CAN1) || defined(__DOXYGEN__) -#define STM32_CAN_USE_CAN1 FALSE -#endif - -/** - * @brief CAN2 driver enable switch. - * @details If set to @p TRUE the support for CAN2 is included. - */ -#if !defined(STM32_CAN_USE_CAN2) || defined(__DOXYGEN__) -#define STM32_CAN_USE_CAN2 FALSE -#endif - -/** - * @brief CAN1 interrupt priority level setting. - */ -#if !defined(STM32_CAN_CAN1_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_CAN_CAN1_IRQ_PRIORITY 11 -#endif -/** @} */ - -/** - * @brief CAN2 interrupt priority level setting. - */ -#if !defined(STM32_CAN_CAN2_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_CAN_CAN2_IRQ_PRIORITY 11 -#endif -/** @} */ - -/*===========================================================================*/ -/* Derived constants and error checks. */ -/*===========================================================================*/ - -#if STM32_CAN_USE_CAN1 && !STM32_HAS_CAN1 -#error "CAN1 not present in the selected device" -#endif - -#if STM32_CAN_USE_CAN2 && !STM32_HAS_CAN2 -#error "CAN2 not present in the selected device" -#endif - -#if !STM32_CAN_USE_CAN1 && !STM32_CAN_USE_CAN2 -#error "CAN driver activated but no CAN peripheral assigned" -#endif - -#if !STM32_CAN_USE_CAN1 && STM32_CAN_USE_CAN2 -#error "CAN2 requires CAN1, it cannot operate independently" -#endif - -#if CAN_USE_SLEEP_MODE && !CAN_SUPPORTS_SLEEP -#error "CAN sleep mode not supported in this architecture" -#endif - -/*===========================================================================*/ -/* Driver data structures and types. */ -/*===========================================================================*/ - -/** - * @brief Type of a transmission mailbox index. - */ -typedef uint32_t canmbx_t; - -/** - * @brief CAN transmission frame. - * @note Accessing the frame data as word16 or word32 is not portable because - * machine data endianness, it can be still useful for a quick filling. - */ -typedef struct { - struct { - uint8_t DLC:4; /**< @brief Data length. */ - uint8_t RTR:1; /**< @brief Frame type. */ - uint8_t IDE:1; /**< @brief Identifier type. */ - }; - union { - struct { - uint32_t SID:11; /**< @brief Standard identifier.*/ - }; - struct { - uint32_t EID:29; /**< @brief Extended identifier.*/ - }; - }; - union { - uint8_t data8[8]; /**< @brief Frame data. */ - uint16_t data16[4]; /**< @brief Frame data. */ - uint32_t data32[2]; /**< @brief Frame data. */ - }; -} CANTxFrame; - -/** - * @brief CAN received frame. - * @note Accessing the frame data as word16 or word32 is not portable because - * machine data endianness, it can be still useful for a quick filling. - */ -typedef struct { - struct { - uint8_t FMI; /**< @brief Filter id. */ - uint16_t TIME; /**< @brief Time stamp. */ - }; - struct { - uint8_t DLC:4; /**< @brief Data length. */ - uint8_t RTR:1; /**< @brief Frame type. */ - uint8_t IDE:1; /**< @brief Identifier type. */ - }; - union { - struct { - uint32_t SID:11; /**< @brief Standard identifier.*/ - }; - struct { - uint32_t EID:29; /**< @brief Extended identifier.*/ - }; - }; - union { - uint8_t data8[8]; /**< @brief Frame data. */ - uint16_t data16[4]; /**< @brief Frame data. */ - uint32_t data32[2]; /**< @brief Frame data. */ - }; -} CANRxFrame; - -/** - * @brief CAN filter. - * @note Refer to the STM32 reference manual for info about filters. - */ -typedef struct { - /** - * @brief Number of the filter to be programmed. - */ - uint32_t filter; - /** - * @brief Filter mode. - * @note This bit represent the CAN_FM1R register bit associated to this - * filter (0=mask mode, 1=list mode). - */ - uint32_t mode:1; - /** - * @brief Filter scale. - * @note This bit represent the CAN_FS1R register bit associated to this - * filter (0=16 bits mode, 1=32 bits mode). - */ - uint32_t scale:1; - /** - * @brief Filter mode. - * @note This bit represent the CAN_FFA1R register bit associated to this - * filter, must be set to zero in this version of the driver. - */ - uint32_t assignment:1; - /** - * @brief Filter register 1 (identifier). - */ - uint32_t register1; - /** - * @brief Filter register 2 (mask/identifier depending on mode=0/1). - */ - uint32_t register2; -} CANFilter; - -/** - * @brief Driver configuration structure. - */ -typedef struct { - /** - * @brief CAN MCR register initialization data. - * @note Some bits in this register are enforced by the driver regardless - * their status in this field. - */ - uint32_t mcr; - /** - * @brief CAN BTR register initialization data. - * @note Some bits in this register are enforced by the driver regardless - * their status in this field. - */ - uint32_t btr; -} CANConfig; - -/** - * @brief Structure representing an CAN driver. - */ -typedef struct { - /** - * @brief Driver state. - */ - canstate_t state; - /** - * @brief Current configuration data. - */ - const CANConfig *config; - /** - * @brief Transmission threads queue. - */ - threads_queue_t txqueue; - /** - * @brief Receive threads queue. - */ - threads_queue_t rxqueue; - /** - * @brief One or more frames become available. - * @note After broadcasting this event it will not be broadcasted again - * until the received frames queue has been completely emptied. It - * is not broadcasted for each received frame. It is - * responsibility of the application to empty the queue by - * repeatedly invoking @p chReceive() when listening to this event. - * This behavior minimizes the interrupt served by the system - * because CAN traffic. - * @note The flags associated to the listeners will indicate which - * receive mailboxes become non-empty. - */ - event_source_t rxfull_event; - /** - * @brief One or more transmission mailbox become available. - * @note The flags associated to the listeners will indicate which - * transmit mailboxes become empty. - * - */ - event_source_t txempty_event; - /** - * @brief A CAN bus error happened. - * @note The flags associated to the listeners will indicate the - * error(s) that have occurred. - */ - event_source_t error_event; -#if CAN_USE_SLEEP_MODE || defined (__DOXYGEN__) - /** - * @brief Entering sleep state event. - */ - event_source_t sleep_event; - /** - * @brief Exiting sleep state event. - */ - event_source_t wakeup_event; -#endif /* CAN_USE_SLEEP_MODE */ - /* End of the mandatory fields.*/ - /** - * @brief Pointer to the CAN registers. - */ - CAN_TypeDef *can; -} CANDriver; - -/*===========================================================================*/ -/* Driver macros. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* External declarations. */ -/*===========================================================================*/ - -#if STM32_CAN_USE_CAN1 && !defined(__DOXYGEN__) -extern CANDriver CAND1; -#endif - -#if STM32_CAN_USE_CAN2 && !defined(__DOXYGEN__) -extern CANDriver CAND2; -#endif - -#ifdef __cplusplus -extern "C" { -#endif - void can_lld_init(void); - void can_lld_start(CANDriver *canp); - void can_lld_stop(CANDriver *canp); - bool_t can_lld_is_tx_empty(CANDriver *canp, - canmbx_t mailbox); - void can_lld_transmit(CANDriver *canp, - canmbx_t mailbox, - const CANTxFrame *crfp); - bool_t can_lld_is_rx_nonempty(CANDriver *canp, - canmbx_t mailbox); - void can_lld_receive(CANDriver *canp, - canmbx_t mailbox, - CANRxFrame *ctfp); -#if CAN_USE_SLEEP_MODE - void can_lld_sleep(CANDriver *canp); - void can_lld_wakeup(CANDriver *canp); -#endif /* CAN_USE_SLEEP_MODE */ -#ifdef __cplusplus -} -#endif - -#endif /* HAL_USE_CAN */ - -#endif /* _CAN_LLD_H_ */ - -/** @} */ diff --git a/os/hal/platforms/STM32/ext_lld.c b/os/hal/platforms/STM32/ext_lld.c deleted file mode 100644 index 80b222124..000000000 --- a/os/hal/platforms/STM32/ext_lld.c +++ /dev/null @@ -1,220 +0,0 @@ -/* - ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file STM32/ext_lld.c - * @brief STM32 EXT subsystem low level driver source. - * - * @addtogroup EXT - * @{ - */ - -#include "hal.h" - -#if HAL_USE_EXT || defined(__DOXYGEN__) - -#include "ext_lld_isr.h" - -/*===========================================================================*/ -/* Driver local definitions. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver exported variables. */ -/*===========================================================================*/ - -/** - * @brief EXTD1 driver identifier. - */ -EXTDriver EXTD1; - -/*===========================================================================*/ -/* Driver local variables and types. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver local functions. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver interrupt handlers. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver exported functions. */ -/*===========================================================================*/ - -/** - * @brief Low level EXT driver initialization. - * - * @notapi - */ -void ext_lld_init(void) { - - /* Driver initialization.*/ - extObjectInit(&EXTD1); -} - -/** - * @brief Configures and activates the EXT peripheral. - * - * @param[in] extp pointer to the @p EXTDriver object - * - * @notapi - */ -void ext_lld_start(EXTDriver *extp) { - unsigned i; - - if (extp->state == EXT_STOP) - ext_lld_exti_irq_enable(); - - /* Configuration of automatic channels.*/ - for (i = 0; i < EXT_MAX_CHANNELS; i++) - if (extp->config->channels[i].mode & EXT_CH_MODE_AUTOSTART) - ext_lld_channel_enable(extp, i); - else - ext_lld_channel_disable(extp, i); -} - -/** - * @brief Deactivates the EXT peripheral. - * - * @param[in] extp pointer to the @p EXTDriver object - * - * @notapi - */ -void ext_lld_stop(EXTDriver *extp) { - - if (extp->state == EXT_ACTIVE) - ext_lld_exti_irq_disable(); - - EXTI->EMR = 0; - EXTI->IMR = 0; - EXTI->PR = 0xFFFFFFFF; -#if STM32_EXTI_NUM_CHANNELS > 32 - EXTI->PR2 = 0xFFFFFFFF; -#endif -} - -/** - * @brief Enables an EXT channel. - * - * @param[in] extp pointer to the @p EXTDriver object - * @param[in] channel channel to be enabled - * - * @notapi - */ -void ext_lld_channel_enable(EXTDriver *extp, expchannel_t channel) { - -#if STM32_EXTI_NUM_CHANNELS > 32 - if (channel < 32) { -#endif - /* Programming edge registers.*/ - if (extp->config->channels[channel].mode & EXT_CH_MODE_RISING_EDGE) - EXTI->RTSR |= (1 << channel); - else - EXTI->RTSR &= ~(1 << channel); - if (extp->config->channels[channel].mode & EXT_CH_MODE_FALLING_EDGE) - EXTI->FTSR |= (1 << channel); - else - EXTI->FTSR &= ~(1 << channel); - - /* Programming interrupt and event registers.*/ - if (extp->config->channels[channel].cb != NULL) { - EXTI->IMR |= (1 << channel); - EXTI->EMR &= ~(1 << channel); - } - else { - EXTI->EMR |= (1 << channel); - EXTI->IMR &= ~(1 << channel); - } -#if STM32_EXTI_NUM_CHANNELS > 32 - } - else { - /* Programming edge registers.*/ - if (extp->config->channels[channel].mode & EXT_CH_MODE_RISING_EDGE) - EXTI->RTSR2 |= (1 << (32 - channel)); - else - EXTI->RTSR2 &= ~(1 << (32 - channel)); - if (extp->config->channels[channel].mode & EXT_CH_MODE_FALLING_EDGE) - EXTI->FTSR2 |= (1 << (32 - channel)); - else - EXTI->FTSR2 &= ~(1 << (32 - channel)); - - /* Programming interrupt and event registers.*/ - if (extp->config->channels[channel].cb != NULL) { - EXTI->IMR2 |= (1 << (32 - channel)); - EXTI->EMR2 &= ~(1 << (32 - channel)); - } - else { - EXTI->EMR2 |= (1 << (32 - channel)); - EXTI->IMR2 &= ~(1 << (32 - channel)); - } - } -#endif - - /* Setting the associated GPIO for external channels.*/ - if (channel < 16) { - uint32_t n = channel >> 2; - uint32_t mask = ~(0xF << ((channel & 3) * 4)); - uint32_t port = ((extp->config->channels[channel].mode & - EXT_MODE_GPIO_MASK) >> - EXT_MODE_GPIO_OFF) << ((channel & 3) * 4); - -#if defined(STM32L1XX_MD) || defined(STM32F0XX) || defined(STM32F2XX) || \ - defined(STM32F30X) || defined(STM32F37X) || defined(STM32F4XX) - SYSCFG->EXTICR[n] = (SYSCFG->EXTICR[n] & mask) | port; -#else /* STM32F1XX */ - AFIO->EXTICR[n] = (AFIO->EXTICR[n] & mask) | port; -#endif /* STM32F1XX */ - } -} - -/** - * @brief Disables an EXT channel. - * - * @param[in] extp pointer to the @p EXTDriver object - * @param[in] channel channel to be disabled - * - * @notapi - */ -void ext_lld_channel_disable(EXTDriver *extp, expchannel_t channel) { - - (void)extp; - -#if STM32_EXTI_NUM_CHANNELS > 32 - if (channel < 32) { -#endif - EXTI->IMR &= ~(1 << channel); - EXTI->EMR &= ~(1 << channel); - EXTI->RTSR &= ~(1 << channel); - EXTI->FTSR &= ~(1 << channel); - EXTI->PR = (1 << channel); -#if STM32_EXTI_NUM_CHANNELS > 32 - } - else { - EXTI->IMR2 &= ~(1 << (32 - channel)); - EXTI->EMR2 &= ~(1 << (32 - channel)); - EXTI->RTSR2 &= ~(1 << (32 - channel)); - EXTI->FTSR2 &= ~(1 << (32 - channel)); - EXTI->PR2 = (1 << (32 - channel)); - } -#endif -} - -#endif /* HAL_USE_EXT */ - -/** @} */ diff --git a/os/hal/platforms/STM32/ext_lld.h b/os/hal/platforms/STM32/ext_lld.h deleted file mode 100644 index 7a59fa728..000000000 --- a/os/hal/platforms/STM32/ext_lld.h +++ /dev/null @@ -1,153 +0,0 @@ -/* - ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file STM32/ext_lld.h - * @brief STM32 EXT subsystem low level driver header. - * - * @addtogroup EXT - * @{ - */ - -#ifndef _EXT_LLD_H_ -#define _EXT_LLD_H_ - -#if HAL_USE_EXT || defined(__DOXYGEN__) - -/*===========================================================================*/ -/* Driver constants. */ -/*===========================================================================*/ - -/** - * @brief Available number of EXT channels. - */ -#define EXT_MAX_CHANNELS STM32_EXTI_NUM_CHANNELS - -/** - * @name STM32-specific EXT channel modes - * @{ - */ -#define EXT_MODE_GPIO_MASK 0xF0 /**< @brief Port field mask. */ -#define EXT_MODE_GPIO_OFF 4 /**< @brief Port field offset. */ -#define EXT_MODE_GPIOA 0x00 /**< @brief GPIOA identifier. */ -#define EXT_MODE_GPIOB 0x10 /**< @brief GPIOB identifier. */ -#define EXT_MODE_GPIOC 0x20 /**< @brief GPIOC identifier. */ -#define EXT_MODE_GPIOD 0x30 /**< @brief GPIOD identifier. */ -#define EXT_MODE_GPIOE 0x40 /**< @brief GPIOE identifier. */ -#define EXT_MODE_GPIOF 0x50 /**< @brief GPIOF identifier. */ -#define EXT_MODE_GPIOG 0x60 /**< @brief GPIOG identifier. */ -#define EXT_MODE_GPIOH 0x70 /**< @brief GPIOH identifier. */ -#define EXT_MODE_GPIOI 0x80 /**< @brief GPIOI identifier. */ -/** @} */ - -/*===========================================================================*/ -/* Driver pre-compile time settings. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Derived constants and error checks. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver data structures and types. */ -/*===========================================================================*/ - -/** - * @brief EXT channel identifier. - */ -typedef uint32_t expchannel_t; - -/** - * @brief Type of an EXT generic notification callback. - * - * @param[in] extp pointer to the @p EXPDriver object triggering the - * callback - */ -typedef void (*extcallback_t)(EXTDriver *extp, expchannel_t channel); - -/** - * @brief Channel configuration structure. - */ -typedef struct { - /** - * @brief Channel mode. - */ - uint32_t mode; - /** - * @brief Channel callback. - * @details In the STM32 implementation a @p NULL callback pointer is - * valid and configures the channel as an event sources instead - * of an interrupt source. - */ - extcallback_t cb; -} EXTChannelConfig; - -/** - * @brief Driver configuration structure. - * @note It could be empty on some architectures. - */ -typedef struct { - /** - * @brief Channel configurations. - */ - EXTChannelConfig channels[EXT_MAX_CHANNELS]; - /* End of the mandatory fields.*/ -} EXTConfig; - -/** - * @brief Structure representing an EXT driver. - */ -struct EXTDriver { - /** - * @brief Driver state. - */ - extstate_t state; - /** - * @brief Current configuration data. - */ - const EXTConfig *config; - /* End of the mandatory fields.*/ -}; - -/*===========================================================================*/ -/* Driver macros. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* External declarations. */ -/*===========================================================================*/ - -#if !defined(__DOXYGEN__) -extern EXTDriver EXTD1; -#endif - -#ifdef __cplusplus -extern "C" { -#endif - void ext_lld_init(void); - void ext_lld_start(EXTDriver *extp); - void ext_lld_stop(EXTDriver *extp); - void ext_lld_channel_enable(EXTDriver *extp, expchannel_t channel); - void ext_lld_channel_disable(EXTDriver *extp, expchannel_t channel); -#ifdef __cplusplus -} -#endif - -#endif /* HAL_USE_EXT */ - -#endif /* _EXT_LLD_H_ */ - -/** @} */ diff --git a/os/hal/platforms/STM32/i2s_lld.c b/os/hal/platforms/STM32/i2s_lld.c deleted file mode 100644 index b7eaf4b0c..000000000 --- a/os/hal/platforms/STM32/i2s_lld.c +++ /dev/null @@ -1,161 +0,0 @@ -/* - ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file STM32/i2s_lld.c - * @brief I2S Driver subsystem low level driver source template. - * - * @addtogroup I2S - * @{ - */ - -#include "ch.h" -#include "hal.h" - -#if HAL_USE_I2S || defined(__DOXYGEN__) - -/*===========================================================================*/ -/* Driver local definitions. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver exported variables. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver local variables and types. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver local functions. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver interrupt handlers. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver exported functions. */ -/*===========================================================================*/ - -/** - * @brief Low level I2S driver initialization. - * - * @notapi - */ -void i2s_lld_init(void) { - -#if STM32_I2S_USE_I2S2 - spiObjectInit(&I2SD2); - I2SD2.spi = SPI2; -#endif - -#if STM32_I2S_USE_I2S3 - spiObjectInit(&I2SD3); - I2SD3.spi = SPI3; -#endif -} - -/** - * @brief Configures and activates the I2S peripheral. - * - * @param[in] i2sp pointer to the @p I2SDriver object - * - * @notapi - */ -void i2s_lld_start(I2SDriver *i2sp) { - - /* If in stopped state then enables the SPI and DMA clocks.*/ - if (i2sp->state == I2S_STOP) { -#if STM32_SPI_USE_SPI2 - if (&SPID2 == spip) { - bool_t b; - b = dmaStreamAllocate(spip->dma, - STM32_I2S_I2S2_IRQ_PRIORITY, - (stm32_dmaisr_t)i2s_lld_serve_rx_interrupt, - (void *)spip); - chDbgAssert(!b, "spi_lld_start(), #1", "stream already allocated"); - rccEnableSPI2(FALSE); - } -#endif -#if STM32_SPI_USE_SPI3 - if (&SPID3 == spip) { - bool_t b; - b = dmaStreamAllocate(spip->dma, - STM32_I2S_I2S3_IRQ_PRIORITY, - (stm32_dmaisr_t)i2s_lld_serve_rx_interrupt, - (void *)spip); - chDbgAssert(!b, "spi_lld_start(), #2", "stream already allocated"); - rccEnableSPI3(FALSE); - } -#endif - } - /* Configuration.*/ -} - -/** - * @brief Deactivates the I2S peripheral. - * - * @param[in] i2sp pointer to the @p I2SDriver object - * - * @notapi - */ -void i2s_lld_stop(I2SDriver *i2sp) { - - if (i2sp->state == I2S_READY) { - /* Clock deactivation.*/ - - } -} - -/** - * @brief Starts a I2S data exchange. - * - * @param[in] i2sp pointer to the @p I2SDriver object - * - * @notapi - */ -void i2s_lld_start_exchange(I2SDriver *i2sp) { - -} - -/** - * @brief Starts a I2S data exchange in continuous mode. - * - * @param[in] i2sp pointer to the @p I2SDriver object - * - * @notapi - */ -void i2s_lld_start_exchange_continuous(I2SDriver *i2sp) { - -} - -/** - * @brief Stops the ongoing data exchange. - * @details The ongoing data exchange, if any, is stopped, if the driver - * was not active the function does nothing. - * - * @param[in] i2sp pointer to the @p I2SDriver object - * - * @notapi - */ -void i2s_lld_stop_exchange(I2SDriver *i2sp) { - -} - -#endif /* HAL_USE_I2S */ - -/** @} */ diff --git a/os/hal/platforms/STM32/i2s_lld.h b/os/hal/platforms/STM32/i2s_lld.h deleted file mode 100644 index 3f9c640b3..000000000 --- a/os/hal/platforms/STM32/i2s_lld.h +++ /dev/null @@ -1,317 +0,0 @@ -/* - ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file STM32/i2s_lld.h - * @brief I2S Driver subsystem low level driver header template. - * - * @addtogroup I2S - * @{ - */ - -#ifndef _I2S_LLD_H_ -#define _I2S_LLD_H_ - -#if HAL_USE_I2S || defined(__DOXYGEN__) - -/*===========================================================================*/ -/* Driver constants. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver pre-compile time settings. */ -/*===========================================================================*/ - -/** - * @name Configuration options - * @{ - */ -/** - * @brief I2S2 driver enable switch. - * @details If set to @p TRUE the support for I2S2 is included. - * @note The default is @p TRUE. - */ -#if !defined(STM32_I2S_USE_I2S2) || defined(__DOXYGEN__) -#define STM32_I2S_USE_I2S2 FALSE -#endif - -/** - * @brief I2S3 driver enable switch. - * @details If set to @p TRUE the support for I2S3 is included. - * @note The default is @p TRUE. - */ -#if !defined(STM32_I2S_USE_I2S3) || defined(__DOXYGEN__) -#define STM32_I2S_USE_I2S3 FALSE -#endif - -/** - * @brief I2S2 interrupt priority level setting. - */ -#if !defined(STM32_I2S_I2S2_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_I2S_I2S2_IRQ_PRIORITY 10 -#endif - -/** - * @brief I2S3 interrupt priority level setting. - */ -#if !defined(STM32_I2S_I2S3_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_I2S_I2S3_IRQ_PRIORITY 10 -#endif - -/** - * @brief I2S2 DMA priority (0..3|lowest..highest). - */ -#if !defined(STM32_I2S_I2S2_DMA_PRIORITY) || defined(__DOXYGEN__) -#define STM32_I2S_I2S2_DMA_PRIORITY 1 -#endif - -/** - * @brief I2S3 DMA priority (0..3|lowest..highest). - */ -#if !defined(STM32_I2S_I2S2_DMA_PRIORITY) || defined(__DOXYGEN__) -#define STM32_I2S_I2S2_DMA_PRIORITY 1 -#endif - -/** - * @brief I2S DMA error hook. - */ -#if !defined(STM32_I2S_DMA_ERROR_HOOK) || defined(__DOXYGEN__) -#define STM32_I2S_DMA_ERROR_HOOK(i2sp) chSysHalt() -#endif - -#if STM32_ADVANCED_DMA || defined(__DOXYGEN__) - -/** - * @brief DMA stream used for I2S2 RX operations. - * @note This option is only available on platforms with enhanced DMA. - */ -#if !defined(STM32_I2S_I2S2_RX_DMA_STREAM) || defined(__DOXYGEN__) -#define STM32_I2S_I2S2_RX_DMA_STREAM STM32_DMA_STREAM_ID(2, 0) -#endif - -/** - * @brief DMA stream used for I2S2 TX operations. - * @note This option is only available on platforms with enhanced DMA. - */ -#if !defined(STM32_I2S_I2S2_TX_DMA_STREAM) || defined(__DOXYGEN__) -#define STM32_I2S_I2S2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) -#endif - -/** - * @brief DMA stream used for I2S3 RX operations. - * @note This option is only available on platforms with enhanced DMA. - */ -#if !defined(STM32_I2S_I2S3_RX_DMA_STREAM) || defined(__DOXYGEN__) -#define STM32_I2S_I2S3_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 0) -#endif - -/** - * @brief DMA stream used for I2S3 TX operations. - * @note This option is only available on platforms with enhanced DMA. - */ -#if !defined(STM32_I2S_I2S3_TX_DMA_STREAM) || defined(__DOXYGEN__) -#define STM32_I2S_I2S3_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7) -#endif - -#else /* !STM32_ADVANCED_DMA */ - -/* Fixed streams for platforms using the old DMA peripheral, the values are - valid for both STM32F1xx and STM32L1xx.*/ -#define STM32_I2S_I2S2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) -#define STM32_I2S_I2S2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 5) -#define STM32_I2S_I2S3_RX_DMA_STREAM STM32_DMA_STREAM_ID(2, 1) -#define STM32_I2S_I2S3_TX_DMA_STREAM STM32_DMA_STREAM_ID(2, 2) - -#endif /* !STM32_ADVANCED_DMA */ -/** @} */ - -/*===========================================================================*/ -/* Derived constants and error checks. */ -/*===========================================================================*/ - -#if STM32_I2S_USE_I2S2 && !STM32_HAS_SPI2 -#error "SPI2 not present in the selected device" -#endif - -#if STM32_I2S_USE_I2S3 && !STM32_HAS_SPI3 -#error "SPI3 not present in the selected device" -#endif - -#if !STM32_I2S_USE_I2S2 && !STM32_I2S_USE_I2S3 -#error "I2S driver activated but no I2S peripheral assigned" -#endif - -#if STM32_I2S_USE_I2S2 && \ - !STM32_DMA_IS_VALID_ID(STM32_I2S_I2S2_RX_DMA_STREAM, STM32_SPI2_RX_DMA_MSK) -#error "invalid DMA stream associated to I2S2 RX" -#endif - -#if STM32_I2S_USE_I2S2 && \ - !STM32_DMA_IS_VALID_ID(STM32_I2S_I2S2_TX_DMA_STREAM, STM32_SPI2_TX_DMA_MSK) -#error "invalid DMA stream associated to I2S2 TX" -#endif - -#if STM32_I2S_USE_I2S3 && \ - !STM32_DMA_IS_VALID_ID(STM32_I2S_I2S3_RX_DMA_STREAM, STM32_SPI3_RX_DMA_MSK) -#error "invalid DMA stream associated to I2S3 RX" -#endif - -#if STM32_I2S_USE_I2S3 && \ - !STM32_DMA_IS_VALID_ID(STM32_I2S_I2S3_TX_DMA_STREAM, STM32_SPI3_TX_DMA_MSK) -#error "invalid DMA stream associated to I2S3 TX" -#endif - -#if !defined(STM32_DMA_REQUIRED) -#define STM32_DMA_REQUIRED -#endif - -/*===========================================================================*/ -/* Driver data structures and types. */ -/*===========================================================================*/ - -/** - * @brief I2S mode type. - */ -typedef uint32_t i2smode_t; - -/** - * @brief Type of a structure representing an I2S driver. - */ -typedef struct I2SDriver I2SDriver; - -/** - * @brief I2S notification callback type. - * - * @param[in] i2sp pointer to the @p I2SDriver object - * @param[in] buffer pointer to the buffer - * @param[in] n number of sample positions starting from @p buffer - */ -typedef void (*i2scallback_t)(I2SDriver *i2sp, void *buffer, size_t n); - -/** - * @brief Driver configuration structure. - * @note It could be empty on some architectures. - */ -typedef struct { - /** - * @brief I2S mode selection. - */ - i2smode_t mode; - /** - * @brief Transmission buffer pointer. - */ - const void *tx_buffer; - /** - * @brief Transmission buffer size in number of samples. - */ - size_t tx_size; - /** - * @brief Callback function associated to the transmission or @p NULL. - */ - i2scallback_t tx_cb; - /** - * @brief Receive buffer pointer. - */ - void *rx_buffer; - /** - * @brief Receive buffer size in number of samples. - */ - size_t rx_size; - /** - * @brief Callback function associated to the reception or @p NULL. - */ - i2scallback_t rx_cb;; - /* End of the mandatory fields.*/ - /** - * @brief Configuration of the I2SCFGR register. - * @details See the STM32 reference manual, this register is used for - * the I2S configuration, the following bits must not be - * specified because handled directly by the driver: - * - I2SMOD - * - I2SE - * - I2SCFG - * . - */ - int16_t i2scfgr; - /** - * @brief Configuration of the I2SPR register. - * @details See the STM32 reference manual, this register is used for - * the I2S clock setup. - */ - int16_t i2spr; -} I2SConfig; - -/** - * @brief Structure representing an I2S driver. - */ -struct I2SDriver { - /** - * @brief Driver state. - */ - i2sstate_t state; - /** - * @brief Current configuration data. - */ - const I2SConfig *config; - /* End of the mandatory fields.*/ - /** - * @brief Pointer to the SPIx registers block. - */ - SPI_TypeDef *spi; - /** - * @brief DMA stream. - */ - const stm32_dma_stream_t *dma; - /** - * @brief DMA mode bit mask. - */ - uint32_t dmamode; -}; - -/*===========================================================================*/ -/* Driver macros. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* External declarations. */ -/*===========================================================================*/ - -#if STM32_I2S_USE_I2S2 && !defined(__DOXYGEN__) -extern I2SDriver I2SD2; -#endif - -#if STM32_I2S_USE_I2S3 && !defined(__DOXYGEN__) -extern I2SDriver I2SD3; -#endif - -#ifdef __cplusplus -extern "C" { -#endif - void i2s_lld_init(void); - void i2s_lld_start(I2SDriver *i2sp); - void i2s_lld_stop(I2SDriver *i2sp); - void i2s_lld_start_exchange(I2SDriver *i2sp); - void i2s_lld_start_exchange_continuous(I2SDriver *i2sp); - void i2s_lld_stop_exchange(I2SDriver *i2sp); -#ifdef __cplusplus -} -#endif - -#endif /* HAL_USE_I2S */ - -#endif /* _I2S_LLD_H_ */ - -/** @} */ diff --git a/os/hal/platforms/STM32/mac_lld.c b/os/hal/platforms/STM32/mac_lld.c deleted file mode 100644 index f766698e8..000000000 --- a/os/hal/platforms/STM32/mac_lld.c +++ /dev/null @@ -1,740 +0,0 @@ -/* - ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file STM32/mac_lld.c - * @brief STM32 low level MAC driver code. - * - * @addtogroup MAC - * @{ - */ - -#include - -#include "ch.h" -#include "hal.h" - -#if HAL_USE_MAC || defined(__DOXYGEN__) - -#include "mii.h" - -/*===========================================================================*/ -/* Driver local definitions. */ -/*===========================================================================*/ - -#define BUFFER_SIZE ((((STM32_MAC_BUFFERS_SIZE - 1) | 3) + 1) / 4) - -/* MII divider optimal value.*/ -#if (STM32_HCLK >= 150000000) -#define MACMIIDR_CR ETH_MACMIIAR_CR_Div102 -#elif (STM32_HCLK >= 100000000) -#define MACMIIDR_CR ETH_MACMIIAR_CR_Div62 -#elif (STM32_HCLK >= 60000000) -#define MACMIIDR_CR ETH_MACMIIAR_CR_Div42 -#elif (STM32_HCLK >= 35000000) -#define MACMIIDR_CR ETH_MACMIIAR_CR_Div26 -#elif (STM32_HCLK >= 20000000) -#define MACMIIDR_CR ETH_MACMIIAR_CR_Div16 -#else -#error "STM32_HCLK below minimum frequency for ETH operations (20MHz)" -#endif - -/*===========================================================================*/ -/* Driver exported variables. */ -/*===========================================================================*/ - -/** - * @brief Ethernet driver 1. - */ -MACDriver ETHD1; - -/*===========================================================================*/ -/* Driver local variables and types. */ -/*===========================================================================*/ - -static const uint8_t default_mac_address[] = {0xAA, 0x55, 0x13, - 0x37, 0x01, 0x10}; - -static stm32_eth_rx_descriptor_t rd[STM32_MAC_RECEIVE_BUFFERS]; -static stm32_eth_tx_descriptor_t td[STM32_MAC_TRANSMIT_BUFFERS]; - -static uint32_t rb[STM32_MAC_RECEIVE_BUFFERS][BUFFER_SIZE]; -static uint32_t tb[STM32_MAC_TRANSMIT_BUFFERS][BUFFER_SIZE]; - -/*===========================================================================*/ -/* Driver local functions. */ -/*===========================================================================*/ - -/** - * @brief Writes a PHY register. - * - * @param[in] macp pointer to the @p MACDriver object - * @param[in] reg register number - * @param[in] value new register value - */ -static void mii_write(MACDriver *macp, uint32_t reg, uint32_t value) { - - ETH->MACMIIDR = value; - ETH->MACMIIAR = macp->phyaddr | (reg << 6) | MACMIIDR_CR | - ETH_MACMIIAR_MW | ETH_MACMIIAR_MB; - while ((ETH->MACMIIAR & ETH_MACMIIAR_MB) != 0) - ; -} - -/** - * @brief Reads a PHY register. - * - * @param[in] macp pointer to the @p MACDriver object - * @param[in] reg register number - * - * @return The PHY register content. - */ -static uint32_t mii_read(MACDriver *macp, uint32_t reg) { - - ETH->MACMIIAR = macp->phyaddr | (reg << 6) | MACMIIDR_CR | ETH_MACMIIAR_MB; - while ((ETH->MACMIIAR & ETH_MACMIIAR_MB) != 0) - ; - return ETH->MACMIIDR; -} - -#if !defined(BOARD_PHY_ADDRESS) -/** - * @brief PHY address detection. - * - * @param[in] macp pointer to the @p MACDriver object - */ -static void mii_find_phy(MACDriver *macp) { - uint32_t i; - -#if STM32_MAC_PHY_TIMEOUT > 0 - halrtcnt_t start = halGetCounterValue(); - halrtcnt_t timeout = start + MS2RTT(STM32_MAC_PHY_TIMEOUT); - while (halIsCounterWithin(start, timeout)) { -#endif - for (i = 0; i < 31; i++) { - macp->phyaddr = i << 11; - ETH->MACMIIDR = (i << 6) | MACMIIDR_CR; - if ((mii_read(macp, MII_PHYSID1) == (BOARD_PHY_ID >> 16)) && - ((mii_read(macp, MII_PHYSID2) & 0xFFF0) == (BOARD_PHY_ID & 0xFFF0))) { - return; - } - } -#if STM32_MAC_PHY_TIMEOUT > 0 - } -#endif - /* Wrong or defective board.*/ - chSysHalt(); -} -#endif - -/** - * @brief MAC address setup. - * - * @param[in] p pointer to a six bytes buffer containing the MAC - * address - */ -static void mac_lld_set_address(const uint8_t *p) { - - /* MAC address configuration, only a single address comparator is used, - hash table not used.*/ - ETH->MACA0HR = ((uint32_t)p[5] << 8) | - ((uint32_t)p[4] << 0); - ETH->MACA0LR = ((uint32_t)p[3] << 24) | - ((uint32_t)p[2] << 16) | - ((uint32_t)p[1] << 8) | - ((uint32_t)p[0] << 0); - ETH->MACA1HR = 0x0000FFFF; - ETH->MACA1LR = 0xFFFFFFFF; - ETH->MACA2HR = 0x0000FFFF; - ETH->MACA2LR = 0xFFFFFFFF; - ETH->MACA3HR = 0x0000FFFF; - ETH->MACA3LR = 0xFFFFFFFF; - ETH->MACHTHR = 0; - ETH->MACHTLR = 0; -} - -/*===========================================================================*/ -/* Driver interrupt handlers. */ -/*===========================================================================*/ - -CH_IRQ_HANDLER(ETH_IRQHandler) { - uint32_t dmasr; - - CH_IRQ_PROLOGUE(); - - dmasr = ETH->DMASR; - ETH->DMASR = dmasr; /* Clear status bits.*/ - - if (dmasr & ETH_DMASR_RS) { - /* Data Received.*/ - chSysLockFromIsr(); - chSemResetI(ÐD1.rdsem, 0); -#if MAC_USE_EVENTS - chEvtBroadcastI(ÐD1.rdevent); -#endif - chSysUnlockFromIsr(); - } - - if (dmasr & ETH_DMASR_TS) { - /* Data Transmitted.*/ - chSysLockFromIsr(); - chSemResetI(ÐD1.tdsem, 0); - chSysUnlockFromIsr(); - } - - CH_IRQ_EPILOGUE(); -} - -/*===========================================================================*/ -/* Driver exported functions. */ -/*===========================================================================*/ - -/** - * @brief Low level MAC initialization. - * - * @notapi - */ -void mac_lld_init(void) { - unsigned i; - - macObjectInit(ÐD1); - ETHD1.link_up = FALSE; - - /* Descriptor tables are initialized in chained mode, note that the first - word is not initialized here but in mac_lld_start().*/ - for (i = 0; i < STM32_MAC_RECEIVE_BUFFERS; i++) { - rd[i].rdes1 = STM32_RDES1_RCH | STM32_MAC_BUFFERS_SIZE; - rd[i].rdes2 = (uint32_t)rb[i]; - rd[i].rdes3 = (uint32_t)&rd[(i + 1) % STM32_MAC_RECEIVE_BUFFERS]; - } - for (i = 0; i < STM32_MAC_TRANSMIT_BUFFERS; i++) { - td[i].tdes1 = 0; - td[i].tdes2 = (uint32_t)tb[i]; - td[i].tdes3 = (uint32_t)&td[(i + 1) % STM32_MAC_TRANSMIT_BUFFERS]; - } - - /* Selection of the RMII or MII mode based on info exported by board.h.*/ -#if defined(STM32F10X_CL) -#if defined(BOARD_PHY_RMII) - AFIO->MAPR |= AFIO_MAPR_MII_RMII_SEL; -#else - AFIO->MAPR &= ~AFIO_MAPR_MII_RMII_SEL; -#endif -#elif defined(STM32F2XX) || defined(STM32F4XX) -#if defined(BOARD_PHY_RMII) - SYSCFG->PMC |= SYSCFG_PMC_MII_RMII_SEL; -#else - SYSCFG->PMC &= ~SYSCFG_PMC_MII_RMII_SEL; -#endif -#else -#error "unsupported STM32 platform for MAC driver" -#endif - - /* Reset of the MAC core.*/ - rccResetETH(); - - /* MAC clocks temporary activation.*/ - rccEnableETH(FALSE); - - /* PHY address setup.*/ -#if defined(BOARD_PHY_ADDRESS) - ETHD1.phyaddr = BOARD_PHY_ADDRESS << 11; -#else - mii_find_phy(ÐD1); -#endif - -#if defined(BOARD_PHY_RESET) - /* PHY board-specific reset procedure.*/ - BOARD_PHY_RESET(); -#else - /* PHY soft reset procedure.*/ - mii_write(ÐD1, MII_BMCR, BMCR_RESET); -#if defined(BOARD_PHY_RESET_DELAY) - halPolledDelay(BOARD_PHY_RESET_DELAY); -#endif - while (mii_read(ÐD1, MII_BMCR) & BMCR_RESET) - ; -#endif - -#if STM32_MAC_ETH1_CHANGE_PHY_STATE - /* PHY in power down mode until the driver will be started.*/ - mii_write(ÐD1, MII_BMCR, mii_read(ÐD1, MII_BMCR) | BMCR_PDOWN); -#endif - - /* MAC clocks stopped again.*/ - rccDisableETH(FALSE); -} - -/** - * @brief Configures and activates the MAC peripheral. - * - * @param[in] macp pointer to the @p MACDriver object - * - * @notapi - */ -void mac_lld_start(MACDriver *macp) { - unsigned i; - - /* Resets the state of all descriptors.*/ - for (i = 0; i < STM32_MAC_RECEIVE_BUFFERS; i++) - rd[i].rdes0 = STM32_RDES0_OWN; - macp->rxptr = (stm32_eth_rx_descriptor_t *)rd; - for (i = 0; i < STM32_MAC_TRANSMIT_BUFFERS; i++) - td[i].tdes0 = STM32_TDES0_TCH; - macp->txptr = (stm32_eth_tx_descriptor_t *)td; - - /* MAC clocks activation and commanded reset procedure.*/ - rccEnableETH(FALSE); - ETH->DMABMR |= ETH_DMABMR_SR; - while(ETH->DMABMR & ETH_DMABMR_SR) - ; - - /* ISR vector enabled.*/ - nvicEnableVector(ETH_IRQn, - CORTEX_PRIORITY_MASK(STM32_MAC_ETH1_IRQ_PRIORITY)); - -#if STM32_MAC_ETH1_CHANGE_PHY_STATE - /* PHY in power up mode.*/ - mii_write(macp, MII_BMCR, mii_read(macp, MII_BMCR) & ~BMCR_PDOWN); -#endif - - /* MAC configuration.*/ - ETH->MACFFR = 0; - ETH->MACFCR = 0; - ETH->MACVLANTR = 0; - - /* MAC address setup.*/ - if (macp->config->mac_address == NULL) - mac_lld_set_address(default_mac_address); - else - mac_lld_set_address(macp->config->mac_address); - - /* Transmitter and receiver enabled. - Note that the complete setup of the MAC is performed when the link - status is detected.*/ -#if STM32_MAC_IP_CHECKSUM_OFFLOAD - ETH->MACCR = ETH_MACCR_IPCO | ETH_MACCR_RE | ETH_MACCR_TE; -#else - ETH->MACCR = ETH_MACCR_RE | ETH_MACCR_TE; -#endif - - /* DMA configuration: - Descriptor chains pointers.*/ - ETH->DMARDLAR = (uint32_t)rd; - ETH->DMATDLAR = (uint32_t)td; - - /* Enabling required interrupt sources.*/ - ETH->DMASR = ETH->DMASR; - ETH->DMAIER = ETH_DMAIER_NISE | ETH_DMAIER_RIE | ETH_DMAIER_TIE; - - /* DMA general settings.*/ - ETH->DMABMR = ETH_DMABMR_AAB | ETH_DMABMR_RDP_1Beat | ETH_DMABMR_PBL_1Beat; - - /* Transmit FIFO flush.*/ - ETH->DMAOMR = ETH_DMAOMR_FTF; - while (ETH->DMAOMR & ETH_DMAOMR_FTF) - ; - - /* DMA final configuration and start.*/ - ETH->DMAOMR = ETH_DMAOMR_DTCEFD | ETH_DMAOMR_RSF | ETH_DMAOMR_TSF | - ETH_DMAOMR_ST | ETH_DMAOMR_SR; -} - -/** - * @brief Deactivates the MAC peripheral. - * - * @param[in] macp pointer to the @p MACDriver object - * - * @notapi - */ -void mac_lld_stop(MACDriver *macp) { - - if (macp->state != MAC_STOP) { -#if STM32_MAC_ETH1_CHANGE_PHY_STATE - /* PHY in power down mode until the driver will be restarted.*/ - mii_write(macp, MII_BMCR, mii_read(macp, MII_BMCR) | BMCR_PDOWN); -#endif - - /* MAC and DMA stopped.*/ - ETH->MACCR = 0; - ETH->DMAOMR = 0; - ETH->DMAIER = 0; - ETH->DMASR = ETH->DMASR; - - /* MAC clocks stopped.*/ - rccDisableETH(FALSE); - - /* ISR vector disabled.*/ - nvicDisableVector(ETH_IRQn); - } -} - -/** - * @brief Returns a transmission descriptor. - * @details One of the available transmission descriptors is locked and - * returned. - * - * @param[in] macp pointer to the @p MACDriver object - * @param[out] tdp pointer to a @p MACTransmitDescriptor structure - * @return The operation status. - * @retval RDY_OK the descriptor has been obtained. - * @retval RDY_TIMEOUT descriptor not available. - * - * @notapi - */ -msg_t mac_lld_get_transmit_descriptor(MACDriver *macp, - MACTransmitDescriptor *tdp) { - stm32_eth_tx_descriptor_t *tdes; - - if (!macp->link_up) - return RDY_TIMEOUT; - - chSysLock(); - - /* Get Current TX descriptor.*/ - tdes = macp->txptr; - - /* Ensure that descriptor isn't owned by the Ethernet DMA or locked by - another thread.*/ - if (tdes->tdes0 & (STM32_TDES0_OWN | STM32_TDES0_LOCKED)) { - chSysUnlock(); - return RDY_TIMEOUT; - } - - /* Marks the current descriptor as locked using a reserved bit.*/ - tdes->tdes0 |= STM32_TDES0_LOCKED; - - /* Next TX descriptor to use.*/ - macp->txptr = (stm32_eth_tx_descriptor_t *)tdes->tdes3; - - chSysUnlock(); - - /* Set the buffer size and configuration.*/ - tdp->offset = 0; - tdp->size = STM32_MAC_BUFFERS_SIZE; - tdp->physdesc = tdes; - - return RDY_OK; -} - -/** - * @brief Releases a transmit descriptor and starts the transmission of the - * enqueued data as a single frame. - * - * @param[in] tdp the pointer to the @p MACTransmitDescriptor structure - * - * @notapi - */ -void mac_lld_release_transmit_descriptor(MACTransmitDescriptor *tdp) { - - chDbgAssert(!(tdp->physdesc->tdes0 & STM32_TDES0_OWN), - "mac_lld_release_transmit_descriptor(), #1", - "attempt to release descriptor already owned by DMA"); - - chSysLock(); - - /* Unlocks the descriptor and returns it to the DMA engine.*/ - tdp->physdesc->tdes1 = tdp->offset; - tdp->physdesc->tdes0 = STM32_TDES0_CIC(STM32_MAC_IP_CHECKSUM_OFFLOAD) | - STM32_TDES0_IC | STM32_TDES0_LS | STM32_TDES0_FS | - STM32_TDES0_TCH | STM32_TDES0_OWN; - - /* If the DMA engine is stalled then a restart request is issued.*/ - if ((ETH->DMASR & ETH_DMASR_TPS) == ETH_DMASR_TPS_Suspended) { - ETH->DMASR = ETH_DMASR_TBUS; - ETH->DMATPDR = ETH_DMASR_TBUS; /* Any value is OK.*/ - } - - chSysUnlock(); -} - -/** - * @brief Returns a receive descriptor. - * - * @param[in] macp pointer to the @p MACDriver object - * @param[out] rdp pointer to a @p MACReceiveDescriptor structure - * @return The operation status. - * @retval RDY_OK the descriptor has been obtained. - * @retval RDY_TIMEOUT descriptor not available. - * - * @notapi - */ -msg_t mac_lld_get_receive_descriptor(MACDriver *macp, - MACReceiveDescriptor *rdp) { - stm32_eth_rx_descriptor_t *rdes; - - chSysLock(); - - /* Get Current RX descriptor.*/ - rdes = macp->rxptr; - - /* Iterates through received frames until a valid one is found, invalid - frames are discarded.*/ - while (!(rdes->rdes0 & STM32_RDES0_OWN)) { - if (!(rdes->rdes0 & (STM32_RDES0_AFM | STM32_RDES0_ES)) -#if STM32_MAC_IP_CHECKSUM_OFFLOAD - && (rdes->rdes0 & STM32_RDES0_FT) - && !(rdes->rdes0 & (STM32_RDES0_IPHCE | STM32_RDES0_PCE)) -#endif - && (rdes->rdes0 & STM32_RDES0_FS) && (rdes->rdes0 & STM32_RDES0_LS)) { - /* Found a valid one.*/ - rdp->offset = 0; - rdp->size = ((rdes->rdes0 & STM32_RDES0_FL_MASK) >> 16) - 4; - rdp->physdesc = rdes; - macp->rxptr = (stm32_eth_rx_descriptor_t *)rdes->rdes3; - - chSysUnlock(); - return RDY_OK; - } - /* Invalid frame found, purging.*/ - rdes->rdes0 = STM32_RDES0_OWN; - rdes = (stm32_eth_rx_descriptor_t *)rdes->rdes3; - } - - /* Next descriptor to check.*/ - macp->rxptr = rdes; - - chSysUnlock(); - return RDY_TIMEOUT; -} - -/** - * @brief Releases a receive descriptor. - * @details The descriptor and its buffer are made available for more incoming - * frames. - * - * @param[in] rdp the pointer to the @p MACReceiveDescriptor structure - * - * @notapi - */ -void mac_lld_release_receive_descriptor(MACReceiveDescriptor *rdp) { - - chDbgAssert(!(rdp->physdesc->rdes0 & STM32_RDES0_OWN), - "mac_lld_release_receive_descriptor(), #1", - "attempt to release descriptor already owned by DMA"); - - chSysLock(); - - /* Give buffer back to the Ethernet DMA.*/ - rdp->physdesc->rdes0 = STM32_RDES0_OWN; - - /* If the DMA engine is stalled then a restart request is issued.*/ - if ((ETH->DMASR & ETH_DMASR_RPS) == ETH_DMASR_RPS_Suspended) { - ETH->DMASR = ETH_DMASR_RBUS; - ETH->DMARPDR = ETH_DMASR_RBUS; /* Any value is OK.*/ - } - - chSysUnlock(); -} - -/** - * @brief Updates and returns the link status. - * - * @param[in] macp pointer to the @p MACDriver object - * @return The link status. - * @retval TRUE if the link is active. - * @retval FALSE if the link is down. - * - * @notapi - */ -bool_t mac_lld_poll_link_status(MACDriver *macp) { - uint32_t maccr, bmsr, bmcr; - - maccr = ETH->MACCR; - - /* PHY CR and SR registers read.*/ - (void)mii_read(macp, MII_BMSR); - bmsr = mii_read(macp, MII_BMSR); - bmcr = mii_read(macp, MII_BMCR); - - /* Check on auto-negotiation mode.*/ - if (bmcr & BMCR_ANENABLE) { - uint32_t lpa; - - /* Auto-negotiation must be finished without faults and link established.*/ - if ((bmsr & (BMSR_LSTATUS | BMSR_RFAULT | BMSR_ANEGCOMPLETE)) != - (BMSR_LSTATUS | BMSR_ANEGCOMPLETE)) - return macp->link_up = FALSE; - - /* Auto-negotiation enabled, checks the LPA register.*/ - lpa = mii_read(macp, MII_LPA); - - /* Check on link speed.*/ - if (lpa & (LPA_100HALF | LPA_100FULL | LPA_100BASE4)) - maccr |= ETH_MACCR_FES; - else - maccr &= ~ETH_MACCR_FES; - - /* Check on link mode.*/ - if (lpa & (LPA_10FULL | LPA_100FULL)) - maccr |= ETH_MACCR_DM; - else - maccr &= ~ETH_MACCR_DM; - } - else { - /* Link must be established.*/ - if (!(bmsr & BMSR_LSTATUS)) - return macp->link_up = FALSE; - - /* Check on link speed.*/ - if (bmcr & BMCR_SPEED100) - maccr |= ETH_MACCR_FES; - else - maccr &= ~ETH_MACCR_FES; - - /* Check on link mode.*/ - if (bmcr & BMCR_FULLDPLX) - maccr |= ETH_MACCR_DM; - else - maccr &= ~ETH_MACCR_DM; - } - - /* Changes the mode in the MAC.*/ - ETH->MACCR = maccr; - - /* Returns the link status.*/ - return macp->link_up = TRUE; -} - -/** - * @brief Writes to a transmit descriptor's stream. - * - * @param[in] tdp pointer to a @p MACTransmitDescriptor structure - * @param[in] buf pointer to the buffer containing the data to be - * written - * @param[in] size number of bytes to be written - * @return The number of bytes written into the descriptor's - * stream, this value can be less than the amount - * specified in the parameter @p size if the maximum - * frame size is reached. - * - * @notapi - */ -size_t mac_lld_write_transmit_descriptor(MACTransmitDescriptor *tdp, - uint8_t *buf, - size_t size) { - - chDbgAssert(!(tdp->physdesc->tdes0 & STM32_TDES0_OWN), - "mac_lld_write_transmit_descriptor(), #1", - "attempt to write descriptor already owned by DMA"); - - if (size > tdp->size - tdp->offset) - size = tdp->size - tdp->offset; - - if (size > 0) { - memcpy((uint8_t *)(tdp->physdesc->tdes2) + tdp->offset, buf, size); - tdp->offset += size; - } - return size; -} - -/** - * @brief Reads from a receive descriptor's stream. - * - * @param[in] rdp pointer to a @p MACReceiveDescriptor structure - * @param[in] buf pointer to the buffer that will receive the read data - * @param[in] size number of bytes to be read - * @return The number of bytes read from the descriptor's - * stream, this value can be less than the amount - * specified in the parameter @p size if there are - * no more bytes to read. - * - * @notapi - */ -size_t mac_lld_read_receive_descriptor(MACReceiveDescriptor *rdp, - uint8_t *buf, - size_t size) { - - chDbgAssert(!(rdp->physdesc->rdes0 & STM32_RDES0_OWN), - "mac_lld_read_receive_descriptor(), #1", - "attempt to read descriptor already owned by DMA"); - - if (size > rdp->size - rdp->offset) - size = rdp->size - rdp->offset; - - if (size > 0) { - memcpy(buf, (uint8_t *)(rdp->physdesc->rdes2) + rdp->offset, size); - rdp->offset += size; - } - return size; -} - -#if MAC_USE_ZERO_COPY || defined(__DOXYGEN__) -/** - * @brief Returns a pointer to the next transmit buffer in the descriptor - * chain. - * @note The API guarantees that enough buffers can be requested to fill - * a whole frame. - * - * @param[in] tdp pointer to a @p MACTransmitDescriptor structure - * @param[in] size size of the requested buffer. Specify the frame size - * on the first call then scale the value down subtracting - * the amount of data already copied into the previous - * buffers. - * @param[out] sizep pointer to variable receiving the buffer size, it is - * zero when the last buffer has already been returned. - * Note that a returned size lower than the amount - * requested means that more buffers must be requested - * in order to fill the frame data entirely. - * @return Pointer to the returned buffer. - * @retval NULL if the buffer chain has been entirely scanned. - * - * @notapi - */ -uint8_t *mac_lld_get_next_transmit_buffer(MACTransmitDescriptor *tdp, - size_t size, - size_t *sizep) { - - if (tdp->offset == 0) { - *sizep = tdp->size; - tdp->offset = size; - return (uint8_t *)tdp->physdesc->tdes2; - } - *sizep = 0; - return NULL; -} - -/** - * @brief Returns a pointer to the next receive buffer in the descriptor - * chain. - * @note The API guarantees that the descriptor chain contains a whole - * frame. - * - * @param[in] rdp pointer to a @p MACReceiveDescriptor structure - * @param[out] sizep pointer to variable receiving the buffer size, it is - * zero when the last buffer has already been returned. - * @return Pointer to the returned buffer. - * @retval NULL if the buffer chain has been entirely scanned. - * - * @notapi - */ -const uint8_t *mac_lld_get_next_receive_buffer(MACReceiveDescriptor *rdp, - size_t *sizep) { - - if (rdp->size > 0) { - *sizep = rdp->size; - rdp->offset = rdp->size; - rdp->size = 0; - return (uint8_t *)rdp->physdesc->rdes2; - } - *sizep = 0; - return NULL; -} -#endif /* MAC_USE_ZERO_COPY */ - -#endif /* HAL_USE_MAC */ - -/** @} */ diff --git a/os/hal/platforms/STM32/mac_lld.h b/os/hal/platforms/STM32/mac_lld.h deleted file mode 100644 index bde7e0345..000000000 --- a/os/hal/platforms/STM32/mac_lld.h +++ /dev/null @@ -1,362 +0,0 @@ -/* - ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file STM32/mac_lld.h - * @brief STM32 low level MAC driver header. - * - * @addtogroup MAC - * @{ - */ - -#ifndef _MAC_LLD_H_ -#define _MAC_LLD_H_ - -#if HAL_USE_MAC || defined(__DOXYGEN__) - -/*===========================================================================*/ -/* Driver constants. */ -/*===========================================================================*/ - -/** - * @brief This implementation supports the zero-copy mode API. - */ -#define MAC_SUPPORTS_ZERO_COPY TRUE - -/** - * @name RDES0 constants - * @{ - */ -#define STM32_RDES0_OWN 0x80000000 -#define STM32_RDES0_AFM 0x40000000 -#define STM32_RDES0_FL_MASK 0x3FFF0000 -#define STM32_RDES0_ES 0x00008000 -#define STM32_RDES0_DESERR 0x00004000 -#define STM32_RDES0_SAF 0x00002000 -#define STM32_RDES0_LE 0x00001000 -#define STM32_RDES0_OE 0x00000800 -#define STM32_RDES0_VLAN 0x00000400 -#define STM32_RDES0_FS 0x00000200 -#define STM32_RDES0_LS 0x00000100 -#define STM32_RDES0_IPHCE 0x00000080 -#define STM32_RDES0_LCO 0x00000040 -#define STM32_RDES0_FT 0x00000020 -#define STM32_RDES0_RWT 0x00000010 -#define STM32_RDES0_RE 0x00000008 -#define STM32_RDES0_DE 0x00000004 -#define STM32_RDES0_CE 0x00000002 -#define STM32_RDES0_PCE 0x00000001 -/** @} */ - -/** - * @name RDES1 constants - * @{ - */ -#define STM32_RDES1_DIC 0x80000000 -#define STM32_RDES1_RBS2_MASK 0x1FFF0000 -#define STM32_RDES1_RER 0x00008000 -#define STM32_RDES1_RCH 0x00004000 -#define STM32_RDES1_RBS1_MASK 0x00001FFF -/** @} */ - -/** - * @name TDES0 constants - * @{ - */ -#define STM32_TDES0_OWN 0x80000000 -#define STM32_TDES0_IC 0x40000000 -#define STM32_TDES0_LS 0x20000000 -#define STM32_TDES0_FS 0x10000000 -#define STM32_TDES0_DC 0x08000000 -#define STM32_TDES0_DP 0x04000000 -#define STM32_TDES0_TTSE 0x02000000 -#define STM32_TDES0_LOCKED 0x01000000 /* NOTE: Pseudo flag. */ -#define STM32_TDES0_CIC_MASK 0x00C00000 -#define STM32_TDES0_CIC(n) ((n) << 22) -#define STM32_TDES0_TER 0x00200000 -#define STM32_TDES0_TCH 0x00100000 -#define STM32_TDES0_TTSS 0x00020000 -#define STM32_TDES0_IHE 0x00010000 -#define STM32_TDES0_ES 0x00008000 -#define STM32_TDES0_JT 0x00004000 -#define STM32_TDES0_FF 0x00002000 -#define STM32_TDES0_IPE 0x00001000 -#define STM32_TDES0_LCA 0x00000800 -#define STM32_TDES0_NC 0x00000400 -#define STM32_TDES0_LCO 0x00000200 -#define STM32_TDES0_EC 0x00000100 -#define STM32_TDES0_VF 0x00000080 -#define STM32_TDES0_CC_MASK 0x00000078 -#define STM32_TDES0_ED 0x00000004 -#define STM32_TDES0_UF 0x00000002 -#define STM32_TDES0_DB 0x00000001 -/** @} */ - -/** - * @name TDES1 constants - * @{ - */ -#define STM32_TDES1_TBS2_MASK 0x1FFF0000 -#define STM32_TDES1_TBS1_MASK 0x00001FFF -/** @} */ - -/*===========================================================================*/ -/* Driver pre-compile time settings. */ -/*===========================================================================*/ - -/** - * @name Configuration options - * @{ - */ -/** - * @brief Number of available transmit buffers. - */ -#if !defined(STM32_MAC_TRANSMIT_BUFFERS) || defined(__DOXYGEN__) -#define STM32_MAC_TRANSMIT_BUFFERS 2 -#endif - -/** - * @brief Number of available receive buffers. - */ -#if !defined(STM32_MAC_RECEIVE_BUFFERS) || defined(__DOXYGEN__) -#define STM32_MAC_RECEIVE_BUFFERS 4 -#endif - -/** - * @brief Maximum supported frame size. - */ -#if !defined(STM32_MAC_BUFFERS_SIZE) || defined(__DOXYGEN__) -#define STM32_MAC_BUFFERS_SIZE 1522 -#endif - -/** - * @brief PHY detection timeout. - * @details Timeout, in milliseconds, for PHY address detection, if a PHY - * is not detected within the timeout then the driver halts during - * initialization. This setting applies only if the PHY address is - * not explicitly set in the board header file using - * @p BOARD_PHY_ADDRESS. A zero value disables the timeout and a - * single search path is performed. - */ -#if !defined(STM32_MAC_PHY_TIMEOUT) || defined(__DOXYGEN__) -#define STM32_MAC_PHY_TIMEOUT 100 -#endif - -/** - * @brief Change the PHY power state inside the driver. - */ -#if !defined(STM32_MAC_ETH1_CHANGE_PHY_STATE) || defined(__DOXYGEN__) -#define STM32_MAC_ETH1_CHANGE_PHY_STATE TRUE -#endif - -/** - * @brief ETHD1 interrupt priority level setting. - */ -#if !defined(STM32_MAC_ETH1_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_MAC_ETH1_IRQ_PRIORITY 13 -#endif - -/** - * @brief IP checksum offload. - * @details The following modes are available: - * - 0 Function disabled. - * - 1 Only IP header checksum calculation and insertion are enabled. - * - 2 IP header checksum and payload checksum calculation and - * insertion are enabled, but pseudo-header checksum is not - * calculated in hardware. - * - 3 IP Header checksum and payload checksum calculation and - * insertion are enabled, and pseudo-header checksum is - * calculated in hardware. - * . - */ -#if !defined(STM32_MAC_IP_CHECKSUM_OFFLOAD) || defined(__DOXYGEN__) -#define STM32_MAC_IP_CHECKSUM_OFFLOAD 0 -#endif -/** @} */ - -/*===========================================================================*/ -/* Derived constants and error checks. */ -/*===========================================================================*/ - -#if (STM32_MAC_PHY_TIMEOUT > 0) && !HAL_IMPLEMENTS_COUNTERS -#error "STM32_MAC_PHY_TIMEOUT requires the realtime counter service" -#endif - -/*===========================================================================*/ -/* Driver data structures and types. */ -/*===========================================================================*/ - -/** - * @brief Type of an STM32 Ethernet receive descriptor. - */ -typedef struct { - volatile uint32_t rdes0; - volatile uint32_t rdes1; - volatile uint32_t rdes2; - volatile uint32_t rdes3; -} stm32_eth_rx_descriptor_t; - -/** - * @brief Type of an STM32 Ethernet transmit descriptor. - */ -typedef struct { - volatile uint32_t tdes0; - volatile uint32_t tdes1; - volatile uint32_t tdes2; - volatile uint32_t tdes3; -} stm32_eth_tx_descriptor_t; - -/** - * @brief Driver configuration structure. - */ -typedef struct { - /** - * @brief MAC address. - */ - uint8_t *mac_address; - /* End of the mandatory fields.*/ -} MACConfig; - -/** - * @brief Structure representing a MAC driver. - */ -struct MACDriver { - /** - * @brief Driver state. - */ - macstate_t state; - /** - * @brief Current configuration data. - */ - const MACConfig *config; - /** - * @brief Transmit semaphore. - */ - Semaphore tdsem; - /** - * @brief Receive semaphore. - */ - Semaphore rdsem; -#if MAC_USE_EVENTS || defined(__DOXYGEN__) - /** - * @brief Receive event. - */ - EventSource rdevent; -#endif - /* End of the mandatory fields.*/ - /** - * @brief Link status flag. - */ - bool_t link_up; - /** - * @brief PHY address (pre shifted). - */ - uint32_t phyaddr; - /** - * @brief Receive next frame pointer. - */ - stm32_eth_rx_descriptor_t *rxptr; - /** - * @brief Transmit next frame pointer. - */ - stm32_eth_tx_descriptor_t *txptr; -}; - -/** - * @brief Structure representing a transmit descriptor. - */ -typedef struct { - /** - * @brief Current write offset. - */ - size_t offset; - /** - * @brief Available space size. - */ - size_t size; - /* End of the mandatory fields.*/ - /** - * @brief Pointer to the physical descriptor. - */ - stm32_eth_tx_descriptor_t *physdesc; -} MACTransmitDescriptor; - -/** - * @brief Structure representing a receive descriptor. - */ -typedef struct { - /** - * @brief Current read offset. - */ - size_t offset; - /** - * @brief Available data size. - */ - size_t size; - /* End of the mandatory fields.*/ - /** - * @brief Pointer to the physical descriptor. - */ - stm32_eth_rx_descriptor_t *physdesc; -} MACReceiveDescriptor; - -/*===========================================================================*/ -/* Driver macros. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* External declarations. */ -/*===========================================================================*/ - -#if !defined(__DOXYGEN__) -extern MACDriver ETHD1; -#endif - -#ifdef __cplusplus -extern "C" { -#endif - void mac_lld_init(void); - void mac_lld_start(MACDriver *macp); - void mac_lld_stop(MACDriver *macp); - msg_t mac_lld_get_transmit_descriptor(MACDriver *macp, - MACTransmitDescriptor *tdp); - void mac_lld_release_transmit_descriptor(MACTransmitDescriptor *tdp); - msg_t mac_lld_get_receive_descriptor(MACDriver *macp, - MACReceiveDescriptor *rdp); - void mac_lld_release_receive_descriptor(MACReceiveDescriptor *rdp); - bool_t mac_lld_poll_link_status(MACDriver *macp); - size_t mac_lld_write_transmit_descriptor(MACTransmitDescriptor *tdp, - uint8_t *buf, - size_t size); - size_t mac_lld_read_receive_descriptor(MACReceiveDescriptor *rdp, - uint8_t *buf, - size_t size); -#if MAC_USE_ZERO_COPY - uint8_t *mac_lld_get_next_transmit_buffer(MACTransmitDescriptor *tdp, - size_t size, - size_t *sizep); - const uint8_t *mac_lld_get_next_receive_buffer(MACReceiveDescriptor *rdp, - size_t *sizep); -#endif /* MAC_USE_ZERO_COPY */ -#ifdef __cplusplus -} -#endif - -#endif /* HAL_USE_MAC */ - -#endif /* _MAC_LLD_H_ */ - -/** @} */ diff --git a/os/hal/platforms/STM32/sdc_lld.c b/os/hal/platforms/STM32/sdc_lld.c deleted file mode 100644 index 69873d5f0..000000000 --- a/os/hal/platforms/STM32/sdc_lld.c +++ /dev/null @@ -1,788 +0,0 @@ -/* - ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file STM32/sdc_lld.c - * @brief STM32 SDC subsystem low level driver source. - * - * @addtogroup SDC - * @{ - */ - -/* - TODO: Try preerase blocks before writing (ACMD23). - */ - -#include - -#include "ch.h" -#include "hal.h" - -#if HAL_USE_SDC || defined(__DOXYGEN__) - -/*===========================================================================*/ -/* Driver local definitions. */ -/*===========================================================================*/ - -#define DMA_CHANNEL \ - STM32_DMA_GETCHANNEL(STM32_SDC_SDIO_DMA_STREAM, \ - STM32_SDC_SDIO_DMA_CHN) - -/*===========================================================================*/ -/* Driver exported variables. */ -/*===========================================================================*/ - -/** @brief SDCD1 driver identifier.*/ -SDCDriver SDCD1; - -/*===========================================================================*/ -/* Driver local variables and types. */ -/*===========================================================================*/ - -#if STM32_SDC_SDIO_UNALIGNED_SUPPORT -/** - * @brief Buffer for temporary storage during unaligned transfers. - */ -static union { - uint32_t alignment; - uint8_t buf[MMCSD_BLOCK_SIZE]; -} u; -#endif /* STM32_SDC_SDIO_UNALIGNED_SUPPORT */ - -/*===========================================================================*/ -/* Driver local functions. */ -/*===========================================================================*/ - -/** - * @brief Prepares card to handle read transaction. - * - * @param[in] sdcp pointer to the @p SDCDriver object - * @param[in] startblk first block to read - * @param[in] n number of blocks to read - * @param[in] resp pointer to the response buffer - * - * @return The operation status. - * @retval CH_SUCCESS operation succeeded. - * @retval CH_FAILED operation failed. - * - * @notapi - */ -static bool_t sdc_lld_prepare_read(SDCDriver *sdcp, uint32_t startblk, - uint32_t n, uint32_t *resp) { - - /* Driver handles data in 512 bytes blocks (just like HC cards). But if we - have not HC card than we must convert address from blocks to bytes.*/ - if (!(sdcp->cardmode & SDC_MODE_HIGH_CAPACITY)) - startblk *= MMCSD_BLOCK_SIZE; - - if (n > 1) { - /* Send read multiple blocks command to card.*/ - if (sdc_lld_send_cmd_short_crc(sdcp, MMCSD_CMD_READ_MULTIPLE_BLOCK, - startblk, resp) || MMCSD_R1_ERROR(resp[0])) - return CH_FAILED; - } - else{ - /* Send read single block command.*/ - if (sdc_lld_send_cmd_short_crc(sdcp, MMCSD_CMD_READ_SINGLE_BLOCK, - startblk, resp) || MMCSD_R1_ERROR(resp[0])) - return CH_FAILED; - } - - return CH_SUCCESS; -} - -/** - * @brief Prepares card to handle write transaction. - * - * @param[in] sdcp pointer to the @p SDCDriver object - * @param[in] startblk first block to read - * @param[in] n number of blocks to write - * @param[in] resp pointer to the response buffer - * - * @return The operation status. - * @retval CH_SUCCESS operation succeeded. - * @retval CH_FAILED operation failed. - * - * @notapi - */ -static bool_t sdc_lld_prepare_write(SDCDriver *sdcp, uint32_t startblk, - uint32_t n, uint32_t *resp) { - - /* Driver handles data in 512 bytes blocks (just like HC cards). But if we - have not HC card than we must convert address from blocks to bytes.*/ - if (!(sdcp->cardmode & SDC_MODE_HIGH_CAPACITY)) - startblk *= MMCSD_BLOCK_SIZE; - - if (n > 1) { - /* Write multiple blocks command.*/ - if (sdc_lld_send_cmd_short_crc(sdcp, MMCSD_CMD_WRITE_MULTIPLE_BLOCK, - startblk, resp) || MMCSD_R1_ERROR(resp[0])) - return CH_FAILED; - } - else{ - /* Write single block command.*/ - if (sdc_lld_send_cmd_short_crc(sdcp, MMCSD_CMD_WRITE_BLOCK, - startblk, resp) || MMCSD_R1_ERROR(resp[0])) - return CH_FAILED; - } - - return CH_SUCCESS; -} - -/** - * @brief Wait end of data transaction and performs finalizations. - * - * @param[in] sdcp pointer to the @p SDCDriver object - * @param[in] n number of blocks in transaction - * @param[in] resp pointer to the response buffer - * - * @return The operation status. - * @retval CH_SUCCESS operation succeeded. - * @retval CH_FAILED operation failed. - */ -static bool_t sdc_lld_wait_transaction_end(SDCDriver *sdcp, uint32_t n, - uint32_t *resp) { - - /* Note the mask is checked before going to sleep because the interrupt - may have occurred before reaching the critical zone.*/ - chSysLock(); - if (SDIO->MASK != 0) { - chDbgAssert(sdcp->thread == NULL, - "sdc_lld_start_data_transaction(), #1", "not NULL"); - sdcp->thread = chThdSelf(); - chSchGoSleepS(THD_STATE_SUSPENDED); - chDbgAssert(sdcp->thread == NULL, - "sdc_lld_start_data_transaction(), #2", "not NULL"); - } - if ((SDIO->STA & SDIO_STA_DATAEND) == 0) { - chSysUnlock(); - return CH_FAILED; - } - -#if (defined(STM32F4XX) || defined(STM32F2XX)) - /* Wait until DMA channel enabled to be sure that all data transferred.*/ - while (sdcp->dma->stream->CR & STM32_DMA_CR_EN) - ; - - /* DMA event flags must be manually cleared.*/ - dmaStreamClearInterrupt(sdcp->dma); - - SDIO->ICR = STM32_SDIO_ICR_ALL_FLAGS; - SDIO->DCTRL = 0; - chSysUnlock(); - - /* Wait until interrupt flags to be cleared.*/ - /*while (((DMA2->LISR) >> (sdcp->dma->ishift)) & STM32_DMA_ISR_TCIF) - dmaStreamClearInterrupt(sdcp->dma);*/ -#else - /* Waits for transfer completion at DMA level, the the stream is - disabled and cleared.*/ - dmaWaitCompletion(sdcp->dma); - - SDIO->ICR = STM32_SDIO_ICR_ALL_FLAGS; - SDIO->DCTRL = 0; - chSysUnlock(); -#endif - - /* Finalize transaction.*/ - if (n > 1) - return sdc_lld_send_cmd_short_crc(sdcp, MMCSD_CMD_STOP_TRANSMISSION, 0, resp); - - return CH_SUCCESS; -} - -/** - * @brief Gets SDC errors. - * - * @param[in] sdcp pointer to the @p SDCDriver object - * @param[in] sta value of the STA register - * - * @notapi - */ -static void sdc_lld_collect_errors(SDCDriver *sdcp, uint32_t sta) { - uint32_t errors = SDC_NO_ERROR; - - if (sta & SDIO_STA_CCRCFAIL) - errors |= SDC_CMD_CRC_ERROR; - if (sta & SDIO_STA_DCRCFAIL) - errors |= SDC_DATA_CRC_ERROR; - if (sta & SDIO_STA_CTIMEOUT) - errors |= SDC_COMMAND_TIMEOUT; - if (sta & SDIO_STA_DTIMEOUT) - errors |= SDC_DATA_TIMEOUT; - if (sta & SDIO_STA_TXUNDERR) - errors |= SDC_TX_UNDERRUN; - if (sta & SDIO_STA_RXOVERR) - errors |= SDC_RX_OVERRUN; - if (sta & SDIO_STA_STBITERR) - errors |= SDC_STARTBIT_ERROR; - - sdcp->errors |= errors; -} - -/** - * @brief Performs clean transaction stopping in case of errors. - * - * @param[in] sdcp pointer to the @p SDCDriver object - * @param[in] n number of blocks in transaction - * @param[in] resp pointer to the response buffer - * - * @notapi - */ -static void sdc_lld_error_cleanup(SDCDriver *sdcp, - uint32_t n, - uint32_t *resp) { - uint32_t sta = SDIO->STA; - - dmaStreamClearInterrupt(sdcp->dma); - dmaStreamDisable(sdcp->dma); - SDIO->ICR = STM32_SDIO_ICR_ALL_FLAGS; - SDIO->MASK = 0; - SDIO->DCTRL = 0; - sdc_lld_collect_errors(sdcp, sta); - if (n > 1) - sdc_lld_send_cmd_short_crc(sdcp, MMCSD_CMD_STOP_TRANSMISSION, 0, resp); -} - -/*===========================================================================*/ -/* Driver interrupt handlers. */ -/*===========================================================================*/ - -#if !defined(STM32_SDIO_HANDLER) -#error "STM32_SDIO_HANDLER not defined" -#endif -/** - * @brief SDIO IRQ handler. - * @details It just wakes transaction thread. All error handling performs in - * that thread. - * - * @isr - */ -CH_IRQ_HANDLER(STM32_SDIO_HANDLER) { - - CH_IRQ_PROLOGUE(); - - chSysLockFromIsr() - - /* Disables the source but the status flags are not reset because the - read/write functions needs to check them.*/ - SDIO->MASK = 0; - - if (SDCD1.thread != NULL) { - chSchReadyI(SDCD1.thread); - SDCD1.thread = NULL; - } - - chSysUnlockFromIsr(); - - CH_IRQ_EPILOGUE(); -} - -/*===========================================================================*/ -/* Driver exported functions. */ -/*===========================================================================*/ - -/** - * @brief Low level SDC driver initialization. - * - * @notapi - */ -void sdc_lld_init(void) { - - sdcObjectInit(&SDCD1); - SDCD1.thread = NULL; - SDCD1.dma = STM32_DMA_STREAM(STM32_SDC_SDIO_DMA_STREAM); -#if CH_DBG_ENABLE_ASSERTS - SDCD1.sdio = SDIO; -#endif -} - -/** - * @brief Configures and activates the SDC peripheral. - * - * @param[in] sdcp pointer to the @p SDCDriver object - * - * @notapi - */ -void sdc_lld_start(SDCDriver *sdcp) { - - sdcp->dmamode = STM32_DMA_CR_CHSEL(DMA_CHANNEL) | - STM32_DMA_CR_PL(STM32_SDC_SDIO_DMA_PRIORITY) | - STM32_DMA_CR_PSIZE_WORD | - STM32_DMA_CR_MSIZE_WORD | - STM32_DMA_CR_MINC; - -#if (defined(STM32F4XX) || defined(STM32F2XX)) - sdcp->dmamode |= STM32_DMA_CR_PFCTRL | - STM32_DMA_CR_PBURST_INCR4 | - STM32_DMA_CR_MBURST_INCR4; -#endif - - if (sdcp->state == BLK_STOP) { - /* Note, the DMA must be enabled before the IRQs.*/ - bool_t b; - b = dmaStreamAllocate(sdcp->dma, STM32_SDC_SDIO_IRQ_PRIORITY, NULL, NULL); - chDbgAssert(!b, "sdc_lld_start(), #1", "stream already allocated"); - dmaStreamSetPeripheral(sdcp->dma, &SDIO->FIFO); -#if (defined(STM32F4XX) || defined(STM32F2XX)) - dmaStreamSetFIFO(sdcp->dma, STM32_DMA_FCR_DMDIS | STM32_DMA_FCR_FTH_FULL); -#endif - nvicEnableVector(STM32_SDIO_NUMBER, - CORTEX_PRIORITY_MASK(STM32_SDC_SDIO_IRQ_PRIORITY)); - rccEnableSDIO(FALSE); - } - - /* Configuration, card clock is initially stopped.*/ - SDIO->POWER = 0; - SDIO->CLKCR = 0; - SDIO->DCTRL = 0; - SDIO->DTIMER = 0; -} - -/** - * @brief Deactivates the SDC peripheral. - * - * @param[in] sdcp pointer to the @p SDCDriver object - * - * @notapi - */ -void sdc_lld_stop(SDCDriver *sdcp) { - - if (sdcp->state != BLK_STOP) { - - /* SDIO deactivation.*/ - SDIO->POWER = 0; - SDIO->CLKCR = 0; - SDIO->DCTRL = 0; - SDIO->DTIMER = 0; - - /* Clock deactivation.*/ - nvicDisableVector(STM32_SDIO_NUMBER); - dmaStreamRelease(sdcp->dma); - rccDisableSDIO(FALSE); - } -} - -/** - * @brief Starts the SDIO clock and sets it to init mode (400kHz or less). - * - * @param[in] sdcp pointer to the @p SDCDriver object - * - * @notapi - */ -void sdc_lld_start_clk(SDCDriver *sdcp) { - - (void)sdcp; - - /* Initial clock setting: 400kHz, 1bit mode.*/ - SDIO->CLKCR = STM32_SDIO_DIV_LS; - SDIO->POWER |= SDIO_POWER_PWRCTRL_0 | SDIO_POWER_PWRCTRL_1; - SDIO->CLKCR |= SDIO_CLKCR_CLKEN; -} - -/** - * @brief Sets the SDIO clock to data mode (25MHz or less). - * - * @param[in] sdcp pointer to the @p SDCDriver object - * - * @notapi - */ -void sdc_lld_set_data_clk(SDCDriver *sdcp) { - - (void)sdcp; - - SDIO->CLKCR = (SDIO->CLKCR & 0xFFFFFF00) | STM32_SDIO_DIV_HS; -} - -/** - * @brief Stops the SDIO clock. - * - * @param[in] sdcp pointer to the @p SDCDriver object - * - * @notapi - */ -void sdc_lld_stop_clk(SDCDriver *sdcp) { - - (void)sdcp; - - SDIO->CLKCR = 0; - SDIO->POWER = 0; -} - -/** - * @brief Switches the bus to 4 bits mode. - * - * @param[in] sdcp pointer to the @p SDCDriver object - * @param[in] mode bus mode - * - * @notapi - */ -void sdc_lld_set_bus_mode(SDCDriver *sdcp, sdcbusmode_t mode) { - uint32_t clk = SDIO->CLKCR & ~SDIO_CLKCR_WIDBUS; - - (void)sdcp; - - switch (mode) { - case SDC_MODE_1BIT: - SDIO->CLKCR = clk; - break; - case SDC_MODE_4BIT: - SDIO->CLKCR = clk | SDIO_CLKCR_WIDBUS_0; - break; - case SDC_MODE_8BIT: - SDIO->CLKCR = clk | SDIO_CLKCR_WIDBUS_1; - break; - } -} - -/** - * @brief Sends an SDIO command with no response expected. - * - * @param[in] sdcp pointer to the @p SDCDriver object - * @param[in] cmd card command - * @param[in] arg command argument - * - * @notapi - */ -void sdc_lld_send_cmd_none(SDCDriver *sdcp, uint8_t cmd, uint32_t arg) { - - (void)sdcp; - - SDIO->ARG = arg; - SDIO->CMD = (uint32_t)cmd | SDIO_CMD_CPSMEN; - while ((SDIO->STA & SDIO_STA_CMDSENT) == 0) - ; - SDIO->ICR = SDIO_ICR_CMDSENTC; -} - -/** - * @brief Sends an SDIO command with a short response expected. - * @note The CRC is not verified. - * - * @param[in] sdcp pointer to the @p SDCDriver object - * @param[in] cmd card command - * @param[in] arg command argument - * @param[out] resp pointer to the response buffer (one word) - * - * @return The operation status. - * @retval CH_SUCCESS operation succeeded. - * @retval CH_FAILED operation failed. - * - * @notapi - */ -bool_t sdc_lld_send_cmd_short(SDCDriver *sdcp, uint8_t cmd, uint32_t arg, - uint32_t *resp) { - uint32_t sta; - - (void)sdcp; - - SDIO->ARG = arg; - SDIO->CMD = (uint32_t)cmd | SDIO_CMD_WAITRESP_0 | SDIO_CMD_CPSMEN; - while (((sta = SDIO->STA) & (SDIO_STA_CMDREND | SDIO_STA_CTIMEOUT | - SDIO_STA_CCRCFAIL)) == 0) - ; - SDIO->ICR = sta; - if ((sta & (SDIO_STA_CTIMEOUT)) != 0) { - sdc_lld_collect_errors(sdcp, sta); - return CH_FAILED; - } - *resp = SDIO->RESP1; - return CH_SUCCESS; -} - -/** - * @brief Sends an SDIO command with a short response expected and CRC. - * - * @param[in] sdcp pointer to the @p SDCDriver object - * @param[in] cmd card command - * @param[in] arg command argument - * @param[out] resp pointer to the response buffer (one word) - * - * @return The operation status. - * @retval CH_SUCCESS operation succeeded. - * @retval CH_FAILED operation failed. - * - * @notapi - */ -bool_t sdc_lld_send_cmd_short_crc(SDCDriver *sdcp, uint8_t cmd, uint32_t arg, - uint32_t *resp) { - uint32_t sta; - - (void)sdcp; - - SDIO->ARG = arg; - SDIO->CMD = (uint32_t)cmd | SDIO_CMD_WAITRESP_0 | SDIO_CMD_CPSMEN; - while (((sta = SDIO->STA) & (SDIO_STA_CMDREND | SDIO_STA_CTIMEOUT | - SDIO_STA_CCRCFAIL)) == 0) - ; - SDIO->ICR = sta; - if ((sta & (SDIO_STA_CTIMEOUT | SDIO_STA_CCRCFAIL)) != 0) { - sdc_lld_collect_errors(sdcp, sta); - return CH_FAILED; - } - *resp = SDIO->RESP1; - return CH_SUCCESS; -} - -/** - * @brief Sends an SDIO command with a long response expected and CRC. - * - * @param[in] sdcp pointer to the @p SDCDriver object - * @param[in] cmd card command - * @param[in] arg command argument - * @param[out] resp pointer to the response buffer (four words) - * - * @return The operation status. - * @retval CH_SUCCESS operation succeeded. - * @retval CH_FAILED operation failed. - * - * @notapi - */ -bool_t sdc_lld_send_cmd_long_crc(SDCDriver *sdcp, uint8_t cmd, uint32_t arg, - uint32_t *resp) { - uint32_t sta; - - (void)sdcp; - - SDIO->ARG = arg; - SDIO->CMD = (uint32_t)cmd | SDIO_CMD_WAITRESP_0 | SDIO_CMD_WAITRESP_1 | - SDIO_CMD_CPSMEN; - while (((sta = SDIO->STA) & (SDIO_STA_CMDREND | SDIO_STA_CTIMEOUT | - SDIO_STA_CCRCFAIL)) == 0) - ; - SDIO->ICR = sta; - if ((sta & (STM32_SDIO_STA_ERROR_MASK)) != 0) { - sdc_lld_collect_errors(sdcp, sta); - return CH_FAILED; - } - /* Save bytes in reverse order because MSB in response comes first.*/ - *resp++ = SDIO->RESP4; - *resp++ = SDIO->RESP3; - *resp++ = SDIO->RESP2; - *resp = SDIO->RESP1; - return CH_SUCCESS; -} - -/** - * @brief Reads one or more blocks. - * - * @param[in] sdcp pointer to the @p SDCDriver object - * @param[in] startblk first block to read - * @param[out] buf pointer to the read buffer - * @param[in] n number of blocks to read - * - * @return The operation status. - * @retval CH_SUCCESS operation succeeded. - * @retval CH_FAILED operation failed. - * - * @notapi - */ -bool_t sdc_lld_read_aligned(SDCDriver *sdcp, uint32_t startblk, - uint8_t *buf, uint32_t n) { - uint32_t resp[1]; - - chDbgCheck((n < (0x1000000 / MMCSD_BLOCK_SIZE)), "max transaction size"); - - SDIO->DTIMER = STM32_SDC_READ_TIMEOUT; - - /* Checks for errors and waits for the card to be ready for reading.*/ - if (_sdc_wait_for_transfer_state(sdcp)) - return CH_FAILED; - - /* Prepares the DMA channel for writing.*/ - dmaStreamSetMemory0(sdcp->dma, buf); - dmaStreamSetTransactionSize(sdcp->dma, - (n * MMCSD_BLOCK_SIZE) / sizeof (uint32_t)); - dmaStreamSetMode(sdcp->dma, sdcp->dmamode | STM32_DMA_CR_DIR_P2M); - dmaStreamEnable(sdcp->dma); - - /* Setting up data transfer.*/ - SDIO->ICR = STM32_SDIO_ICR_ALL_FLAGS; - SDIO->MASK = SDIO_MASK_DCRCFAILIE | - SDIO_MASK_DTIMEOUTIE | - SDIO_MASK_STBITERRIE | - SDIO_MASK_RXOVERRIE | - SDIO_MASK_DATAENDIE; - SDIO->DLEN = n * MMCSD_BLOCK_SIZE; - - /* Talk to card what we want from it.*/ - if (sdc_lld_prepare_read(sdcp, startblk, n, resp) == TRUE) - goto error; - - /* Transaction starts just after DTEN bit setting.*/ - SDIO->DCTRL = SDIO_DCTRL_DTDIR | - SDIO_DCTRL_DBLOCKSIZE_3 | - SDIO_DCTRL_DBLOCKSIZE_0 | - SDIO_DCTRL_DMAEN | - SDIO_DCTRL_DTEN; - if (sdc_lld_wait_transaction_end(sdcp, n, resp) == TRUE) - goto error; - - return CH_SUCCESS; - -error: - sdc_lld_error_cleanup(sdcp, n, resp); - return CH_FAILED; -} - -/** - * @brief Writes one or more blocks. - * - * @param[in] sdcp pointer to the @p SDCDriver object - * @param[in] startblk first block to write - * @param[out] buf pointer to the write buffer - * @param[in] n number of blocks to write - * - * @return The operation status. - * @retval CH_SUCCESS operation succeeded. - * @retval CH_FAILED operation failed. - * - * @notapi - */ -bool_t sdc_lld_write_aligned(SDCDriver *sdcp, uint32_t startblk, - const uint8_t *buf, uint32_t n) { - uint32_t resp[1]; - - chDbgCheck((n < (0x1000000 / MMCSD_BLOCK_SIZE)), "max transaction size"); - - SDIO->DTIMER = STM32_SDC_WRITE_TIMEOUT; - - /* Checks for errors and waits for the card to be ready for writing.*/ - if (_sdc_wait_for_transfer_state(sdcp)) - return CH_FAILED; - - /* Prepares the DMA channel for writing.*/ - dmaStreamSetMemory0(sdcp->dma, buf); - dmaStreamSetTransactionSize(sdcp->dma, - (n * MMCSD_BLOCK_SIZE) / sizeof (uint32_t)); - dmaStreamSetMode(sdcp->dma, sdcp->dmamode | STM32_DMA_CR_DIR_M2P); - dmaStreamEnable(sdcp->dma); - - /* Setting up data transfer.*/ - SDIO->ICR = STM32_SDIO_ICR_ALL_FLAGS; - SDIO->MASK = SDIO_MASK_DCRCFAILIE | - SDIO_MASK_DTIMEOUTIE | - SDIO_MASK_STBITERRIE | - SDIO_MASK_TXUNDERRIE | - SDIO_MASK_DATAENDIE; - SDIO->DLEN = n * MMCSD_BLOCK_SIZE; - - /* Talk to card what we want from it.*/ - if (sdc_lld_prepare_write(sdcp, startblk, n, resp) == TRUE) - goto error; - - /* Transaction starts just after DTEN bit setting.*/ - SDIO->DCTRL = SDIO_DCTRL_DBLOCKSIZE_3 | - SDIO_DCTRL_DBLOCKSIZE_0 | - SDIO_DCTRL_DMAEN | - SDIO_DCTRL_DTEN; - if (sdc_lld_wait_transaction_end(sdcp, n, resp) == TRUE) - goto error; - - return CH_SUCCESS; - -error: - sdc_lld_error_cleanup(sdcp, n, resp); - return CH_FAILED; -} - -/** - * @brief Reads one or more blocks. - * - * @param[in] sdcp pointer to the @p SDCDriver object - * @param[in] startblk first block to read - * @param[out] buf pointer to the read buffer - * @param[in] n number of blocks to read - * - * @return The operation status. - * @retval CH_SUCCESS operation succeeded. - * @retval CH_FAILED operation failed. - * - * @notapi - */ -bool_t sdc_lld_read(SDCDriver *sdcp, uint32_t startblk, - uint8_t *buf, uint32_t n) { - -#if STM32_SDC_SDIO_UNALIGNED_SUPPORT - if (((unsigned)buf & 3) != 0) { - uint32_t i; - for (i = 0; i < n; i++) { - if (sdc_lld_read_aligned(sdcp, startblk, u.buf, 1)) - return CH_FAILED; - memcpy(buf, u.buf, MMCSD_BLOCK_SIZE); - buf += MMCSD_BLOCK_SIZE; - startblk++; - } - return CH_SUCCESS; - } -#endif /* STM32_SDC_SDIO_UNALIGNED_SUPPORT */ - return sdc_lld_read_aligned(sdcp, startblk, buf, n); -} - -/** - * @brief Writes one or more blocks. - * - * @param[in] sdcp pointer to the @p SDCDriver object - * @param[in] startblk first block to write - * @param[out] buf pointer to the write buffer - * @param[in] n number of blocks to write - * - * @return The operation status. - * @retval CH_SUCCESS operation succeeded. - * @retval CH_FAILED operation failed. - * - * @notapi - */ -bool_t sdc_lld_write(SDCDriver *sdcp, uint32_t startblk, - const uint8_t *buf, uint32_t n) { - -#if STM32_SDC_SDIO_UNALIGNED_SUPPORT - if (((unsigned)buf & 3) != 0) { - uint32_t i; - for (i = 0; i < n; i++) { - memcpy(u.buf, buf, MMCSD_BLOCK_SIZE); - buf += MMCSD_BLOCK_SIZE; - if (sdc_lld_write_aligned(sdcp, startblk, u.buf, 1)) - return CH_FAILED; - startblk++; - } - return CH_SUCCESS; - } -#endif /* STM32_SDC_SDIO_UNALIGNED_SUPPORT */ - return sdc_lld_write_aligned(sdcp, startblk, buf, n); -} - -/** - * @brief Waits for card idle condition. - * - * @param[in] sdcp pointer to the @p SDCDriver object - * - * @return The operation status. - * @retval CH_SUCCESS the operation succeeded. - * @retval CH_FAILED the operation failed. - * - * @api - */ -bool_t sdc_lld_sync(SDCDriver *sdcp) { - - /* TODO: Implement.*/ - (void)sdcp; - return CH_SUCCESS; -} - -#endif /* HAL_USE_SDC */ - -/** @} */ diff --git a/os/hal/platforms/STM32/sdc_lld.h b/os/hal/platforms/STM32/sdc_lld.h deleted file mode 100644 index 8b01ba915..000000000 --- a/os/hal/platforms/STM32/sdc_lld.h +++ /dev/null @@ -1,310 +0,0 @@ -/* - ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file STM32/sdc_lld.h - * @brief STM32 SDC subsystem low level driver header. - * - * @addtogroup SDC - * @{ - */ - -#ifndef _SDC_LLD_H_ -#define _SDC_LLD_H_ - -#if HAL_USE_SDC || defined(__DOXYGEN__) - -/*===========================================================================*/ -/* Driver constants. */ -/*===========================================================================*/ - -/** - * @brief Value to clear all interrupts flag at once. - */ -#define STM32_SDIO_ICR_ALL_FLAGS (SDIO_ICR_CCRCFAILC | SDIO_ICR_DCRCFAILC | \ - SDIO_ICR_CTIMEOUTC | SDIO_ICR_DTIMEOUTC | \ - SDIO_ICR_TXUNDERRC | SDIO_ICR_RXOVERRC | \ - SDIO_ICR_CMDRENDC | SDIO_ICR_CMDSENTC | \ - SDIO_ICR_DATAENDC | SDIO_ICR_STBITERRC | \ - SDIO_ICR_DBCKENDC | SDIO_ICR_SDIOITC | \ - SDIO_ICR_CEATAENDC) - -/** - * @brief Mask of error flags in STA register. - */ -#define STM32_SDIO_STA_ERROR_MASK (SDIO_STA_CCRCFAIL | SDIO_STA_DCRCFAIL | \ - SDIO_STA_CTIMEOUT | SDIO_STA_DTIMEOUT | \ - SDIO_STA_TXUNDERR | SDIO_STA_RXOVERR) - -/*===========================================================================*/ -/* Driver pre-compile time settings. */ -/*===========================================================================*/ - -/** - * @name Configuration options - * @{ - */ -/** - * @brief SDIO DMA priority (0..3|lowest..highest). - */ -#if !defined(STM32_SDC_SDIO_DMA_PRIORITY) || defined(__DOXYGEN__) -#define STM32_SDC_SDIO_DMA_PRIORITY 3 -#endif - -/** - * @brief SDIO interrupt priority level setting. - */ -#if !defined(STM32_SDC_SDIO_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_SDC_SDIO_IRQ_PRIORITY 9 -#endif - -/** - * @brief Write timeout in milliseconds. - */ -#if !defined(SDC_WRITE_TIMEOUT_MS) || defined(__DOXYGEN__) -#define SDC_WRITE_TIMEOUT_MS 250 -#endif - -/** - * @brief Read timeout in milliseconds. - */ -#if !defined(SDC_READ_TIMEOUT_MS) || defined(__DOXYGEN__) -#define SDC_READ_TIMEOUT_MS 5 -#endif - -/** - * @brief Support for unaligned transfers. - * @note Unaligned transfers are much slower. - */ -#if !defined(STM32_SDC_SDIO_UNALIGNED_SUPPORT) || defined(__DOXYGEN__) -#define STM32_SDC_SDIO_UNALIGNED_SUPPORT TRUE -#endif - -#if STM32_ADVANCED_DMA || defined(__DOXYGEN__) - -/** - * @brief DMA stream used for SDC operations. - * @note This option is only available on platforms with enhanced DMA. - */ -#if !defined(STM32_SDC_SDIO_DMA_STREAM) || defined(__DOXYGEN__) -#define STM32_SDC_SDIO_DMA_STREAM STM32_DMA_STREAM_ID(2, 3) -#endif - -#else /* !STM32_ADVANCED_DMA*/ -#define STM32_SDC_SDIO_DMA_STREAM STM32_DMA_STREAM_ID(2, 4) - -#endif /* !STM32_ADVANCED_DMA*/ -/** @} */ - -/*===========================================================================*/ -/* Derived constants and error checks. */ -/*===========================================================================*/ - -#if !STM32_HAS_SDIO -#error "SDIO not present in the selected device" -#endif - -#if !CORTEX_IS_VALID_KERNEL_PRIORITY(STM32_SDC_SDIO_IRQ_PRIORITY) -#error "Invalid IRQ priority assigned to SDIO" -#endif - -#if !STM32_DMA_IS_VALID_PRIORITY(STM32_SDC_SDIO_DMA_PRIORITY) -#error "Invalid DMA priority assigned to SDIO" -#endif - -#if !defined(STM32_DMA_REQUIRED) -#define STM32_DMA_REQUIRED -#endif - -/* - * SDIO clock divider. - */ -#if (defined(STM32F4XX) || defined(STM32F2XX)) -#define STM32_SDIO_DIV_HS 0 -#define STM32_SDIO_DIV_LS 120 - -#elif STM32_HCLK > 48000000 -#define STM32_SDIO_DIV_HS 1 -#define STM32_SDIO_DIV_LS 178 -#else - -#define STM32_SDIO_DIV_HS 0 -#define STM32_SDIO_DIV_LS 118 -#endif - -/** - * @brief SDIO data timeouts in SDIO clock cycles. - */ -#if (defined(STM32F4XX) || defined(STM32F2XX)) -#if !STM32_CLOCK48_REQUIRED -#error "SDIO requires STM32_CLOCK48_REQUIRED to be enabled" -#endif - -#define STM32_SDC_WRITE_TIMEOUT \ - (((STM32_PLL48CLK / (STM32_SDIO_DIV_HS + 2)) / 1000) * SDC_WRITE_TIMEOUT_MS) -#define STM32_SDC_READ_TIMEOUT \ - (((STM32_PLL48CLK / (STM32_SDIO_DIV_HS + 2)) / 1000) * SDC_READ_TIMEOUT_MS) - -#else -#define STM32_SDC_WRITE_TIMEOUT \ - (((STM32_HCLK / (STM32_SDIO_DIV_HS + 2)) / 1000) * SDC_WRITE_TIMEOUT_MS) -#define STM32_SDC_READ_TIMEOUT \ - (((STM32_HCLK / (STM32_SDIO_DIV_HS + 2)) / 1000) * SDC_READ_TIMEOUT_MS) -#endif - -/*===========================================================================*/ -/* Driver data structures and types. */ -/*===========================================================================*/ - -/** - * @brief Type of SDIO bus mode. - */ -typedef enum { - SDC_MODE_1BIT = 0, - SDC_MODE_4BIT, - SDC_MODE_8BIT -} sdcbusmode_t; - -/** - * @brief Type of card flags. - */ -typedef uint32_t sdcmode_t; - -/** - * @brief SDC Driver condition flags type. - */ -typedef uint32_t sdcflags_t; - -/** - * @brief Type of a structure representing an SDC driver. - */ -typedef struct SDCDriver SDCDriver; - -/** - * @brief Driver configuration structure. - * @note It could be empty on some architectures. - */ -typedef struct { - uint32_t dummy; -} SDCConfig; - -/** - * @brief @p SDCDriver specific methods. - */ -#define _sdc_driver_methods \ - _mmcsd_block_device_methods - -/** - * @extends MMCSDBlockDeviceVMT - * - * @brief @p SDCDriver virtual methods table. - */ -struct SDCDriverVMT { - _sdc_driver_methods -}; - -/** - * @brief Structure representing an SDC driver. - */ -struct SDCDriver { - /** - * @brief Virtual Methods Table. - */ - const struct SDCDriverVMT *vmt; - _mmcsd_block_device_data - /** - * @brief Current configuration data. - */ - const SDCConfig *config; - /** - * @brief Various flags regarding the mounted card. - */ - sdcmode_t cardmode; - /** - * @brief Errors flags. - */ - sdcflags_t errors; - /** - * @brief Card RCA. - */ - uint32_t rca; - /* End of the mandatory fields.*/ - /** - * @brief Thread waiting for I/O completion IRQ. - */ - Thread *thread; - /** - * @brief DMA mode bit mask. - */ - uint32_t dmamode; - /** - * @brief Transmit DMA channel. - */ - const stm32_dma_stream_t *dma; - /** - * @brief Pointer to the SDIO registers block. - * @note Used only for dubugging purpose. - */ -#if CH_DBG_ENABLE_ASSERTS - SDIO_TypeDef *sdio; -#endif -}; - -/*===========================================================================*/ -/* Driver macros. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* External declarations. */ -/*===========================================================================*/ - -#if !defined(__DOXYGEN__) -extern SDCDriver SDCD1; -#endif - -#ifdef __cplusplus -extern "C" { -#endif - void sdc_lld_init(void); - void sdc_lld_start(SDCDriver *sdcp); - void sdc_lld_stop(SDCDriver *sdcp); - void sdc_lld_start_clk(SDCDriver *sdcp); - void sdc_lld_set_data_clk(SDCDriver *sdcp); - void sdc_lld_stop_clk(SDCDriver *sdcp); - void sdc_lld_set_bus_mode(SDCDriver *sdcp, sdcbusmode_t mode); - void sdc_lld_send_cmd_none(SDCDriver *sdcp, uint8_t cmd, uint32_t arg); - bool_t sdc_lld_send_cmd_short(SDCDriver *sdcp, uint8_t cmd, uint32_t arg, - uint32_t *resp); - bool_t sdc_lld_send_cmd_short_crc(SDCDriver *sdcp, uint8_t cmd, uint32_t arg, - uint32_t *resp); - bool_t sdc_lld_send_cmd_long_crc(SDCDriver *sdcp, uint8_t cmd, uint32_t arg, - uint32_t *resp); - bool_t sdc_lld_read(SDCDriver *sdcp, uint32_t startblk, - uint8_t *buf, uint32_t n); - bool_t sdc_lld_write(SDCDriver *sdcp, uint32_t startblk, - const uint8_t *buf, uint32_t n); - bool_t sdc_lld_sync(SDCDriver *sdcp); - bool_t sdc_lld_is_card_inserted(SDCDriver *sdcp); - bool_t sdc_lld_is_write_protected(SDCDriver *sdcp); -#ifdef __cplusplus -} -#endif - -#endif /* HAL_USE_SDC */ - -#endif /* _SDC_LLD_H_ */ - -/** @} */ diff --git a/os/hal/platforms/STM32/stm32.h b/os/hal/platforms/STM32/stm32.h deleted file mode 100644 index eb8ea8140..000000000 --- a/os/hal/platforms/STM32/stm32.h +++ /dev/null @@ -1,120 +0,0 @@ -/* - ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file STM32/stm32.h - * @brief STM32 common header. - * @pre One of the following macros must be defined before including - * this header, the macro selects the inclusion of the appropriate - * vendor header: - * - STM32F0XX for Entry Level devices. - * - STM32F10X_LD_VL for Value Line Low Density devices. - * - STM32F10X_MD_VL for Value Line Medium Density devices. - * - STM32F10X_LD for Performance Low Density devices. - * - STM32F10X_MD for Performance Medium Density devices. - * - STM32F10X_HD for Performance High Density devices. - * - STM32F10X_XL for Performance eXtra Density devices. - * - STM32F10X_CL for Connectivity Line devices. - * - STM32F2XX for High-performance STM32 F-2 devices. - * - STM32F30X for Analog & DSP devices. - * - STM32F37X for Analog & DSP devices. - * - STM32F4XX for High-performance STM32 F-4 devices. - * - STM32L1XX_MD for Ultra Low Power Medium-density devices. - * . - * - * @addtogroup HAL - * @{ - */ - -#ifndef _STM32_H_ -#define _STM32_H_ - - -#if defined(STM32F10X_LD_VL) || defined(STM32F10X_MD_VL) || \ - defined(STM32F10X_HD_VL) || defined(STM32F10X_LD) || \ - defined(STM32F10X_MD) || defined(STM32F10X_HD) || \ - defined(STM32F10X_XL) || defined(STM32F10X_CL) || \ - defined(__DOXYGEN__) -#include "stm32f10x.h" - -#else /* !STM32F1XX_XX */ - -#if defined(STM32F0XX) -#include "stm32f0xx.h" - -#elif defined(STM32F2XX) -#include "stm32f2xx.h" - -#elif defined(STM32F30X) -#include "stm32f30x.h" - -#elif defined(STM32F37X) -#include "stm32f37x.h" - -#elif defined(STM32F4XX) -#include "stm32f4xx.h" - -#elif defined(STM32L1XX_MD) -#include "stm32l1xx.h" - -#else -#error "STM32 device not specified" -#endif - -/* Discarded definitions from the ST headers, the PAL driver uses its own - definitions in order to have an unified handling for all devices. - Unfortunately the ST headers have no uniform definitions for the same - objects across the various sub-families.*/ -#undef GPIOA -#undef GPIOB -#undef GPIOC -#undef GPIOD -#undef GPIOE -#undef GPIOF -#undef GPIOG -#undef GPIOH -#undef GPIOI - -#endif /* !STM32F1XX_XX */ - - -/*===========================================================================*/ -/* Driver constants. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver pre-compile time settings. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Derived constants and error checks. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver data structures and types. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver macros. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* External declarations. */ -/*===========================================================================*/ - -#endif /* _STM32_H_ */ - -/** @} */ diff --git a/os/hal/platforms/STM32F0xx/adc_lld.c b/os/hal/platforms/STM32F0xx/adc_lld.c deleted file mode 100644 index 1c4ffce7f..000000000 --- a/os/hal/platforms/STM32F0xx/adc_lld.c +++ /dev/null @@ -1,296 +0,0 @@ -/* - ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file STM32F0xx/adc_lld.c - * @brief STM32F0xx ADC subsystem low level driver source. - * - * @addtogroup ADC - * @{ - */ - -#include "hal.h" - -#if HAL_USE_ADC || defined(__DOXYGEN__) - -/*===========================================================================*/ -/* Driver local definitions. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver exported variables. */ -/*===========================================================================*/ - -/** @brief ADC1 driver identifier.*/ -#if STM32_ADC_USE_ADC1 || defined(__DOXYGEN__) -ADCDriver ADCD1; -#endif - -/*===========================================================================*/ -/* Driver local variables and types. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver local functions. */ -/*===========================================================================*/ - -/** - * @brief Stops an ongoing conversion, if any. - * - * @param[in] adc pointer to the ADC registers block - */ -static void adc_lld_stop_adc(ADC_TypeDef *adc) { - - if (adc->CR & ADC_CR_ADSTART) { - adc->CR |= ADC_CR_ADSTP; - while (adc->CR & ADC_CR_ADSTP) - ; - } -} - -/** - * @brief ADC DMA ISR service routine. - * - * @param[in] adcp pointer to the @p ADCDriver object - * @param[in] flags pre-shifted content of the ISR register - */ -static void adc_lld_serve_rx_interrupt(ADCDriver *adcp, uint32_t flags) { - - /* DMA errors handling.*/ - if ((flags & (STM32_DMA_ISR_TEIF | STM32_DMA_ISR_DMEIF)) != 0) { - /* DMA, this could help only if the DMA tries to access an unmapped - address space or violates alignment rules.*/ - _adc_isr_error_code(adcp, ADC_ERR_DMAFAILURE); - } - else { - /* It is possible that the conversion group has already be reset by the - ADC error handler, in this case this interrupt is spurious.*/ - if (adcp->grpp != NULL) { - if ((flags & STM32_DMA_ISR_HTIF) != 0) { - /* Half transfer processing.*/ - _adc_isr_half_code(adcp); - } - if ((flags & STM32_DMA_ISR_TCIF) != 0) { - /* Transfer complete processing.*/ - _adc_isr_full_code(adcp); - } - } - } -} - -/*===========================================================================*/ -/* Driver interrupt handlers. */ -/*===========================================================================*/ - -#if STM32_ADC_USE_ADC1 || defined(__DOXYGEN__) -/** - * @brief ADC interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(Vector70) { - uint32_t isr; - - OSAL_IRQ_PROLOGUE(); - - isr = ADC1->ISR; - ADC1->ISR = isr; - - /* It could be a spurious interrupt caused by overflows after DMA disabling, - just ignore it in this case.*/ - if (ADCD1.grpp != NULL) { - /* Note, an overflow may occur after the conversion ended before the driver - is able to stop the ADC, this is why the DMA channel is checked too.*/ - if ((isr & ADC_ISR_OVR) && - (dmaStreamGetTransactionSize(ADCD1.dmastp) > 0)) { - /* ADC overflow condition, this could happen only if the DMA is unable - to read data fast enough.*/ - _adc_isr_error_code(&ADCD1, ADC_ERR_OVERFLOW); - } - if (isr & ADC_ISR_AWD) { - /* Analog watchdog error.*/ - _adc_isr_error_code(&ADCD1, ADC_ERR_AWD); - } - } - - OSAL_IRQ_EPILOGUE(); -} -#endif - -/*===========================================================================*/ -/* Driver exported functions. */ -/*===========================================================================*/ - -/** - * @brief Low level ADC driver initialization. - * - * @notapi - */ -void adc_lld_init(void) { - -#if STM32_ADC_USE_ADC1 - /* Driver initialization.*/ - adcObjectInit(&ADCD1); - ADCD1.adc = ADC1; - ADCD1.dmastp = STM32_DMA1_STREAM1; - ADCD1.dmamode = STM32_DMA_CR_PL(STM32_ADC_ADC1_DMA_PRIORITY) | - STM32_DMA_CR_DIR_P2M | - STM32_DMA_CR_MSIZE_HWORD | STM32_DMA_CR_PSIZE_HWORD | - STM32_DMA_CR_MINC | STM32_DMA_CR_TCIE | - STM32_DMA_CR_DMEIE | STM32_DMA_CR_TEIE; -#endif - - /* The shared vector is initialized on driver initialization and never - disabled.*/ - nvicEnableVector(ADC1_COMP_IRQn, STM32_ADC_IRQ_PRIORITY); - - /* Calibration procedure.*/ - rccEnableADC1(FALSE); - osalDbgAssert(ADC1->CR == 0, "invalid register state"); - ADC1->CR |= ADC_CR_ADCAL; - while (ADC1->CR & ADC_CR_ADCAL) - ; - rccDisableADC1(FALSE); -} - -/** - * @brief Configures and activates the ADC peripheral. - * - * @param[in] adcp pointer to the @p ADCDriver object - * - * @notapi - */ -void adc_lld_start(ADCDriver *adcp) { - - /* If in stopped state then enables the ADC and DMA clocks.*/ - if (adcp->state == ADC_STOP) { -#if STM32_ADC_USE_ADC1 - if (&ADCD1 == adcp) { - bool_t b; - b = dmaStreamAllocate(adcp->dmastp, - STM32_ADC_ADC1_DMA_IRQ_PRIORITY, - (stm32_dmaisr_t)adc_lld_serve_rx_interrupt, - (void *)adcp); - osalDbgAssert(!b, "stream already allocated"); - dmaStreamSetPeripheral(adcp->dmastp, &ADC1->DR); - rccEnableADC1(FALSE); -#if STM32_ADCSW == STM32_ADCSW_HSI14 - /* Clock from HSI14, no need for jitter removal.*/ - ADC1->CFGR2 = 0x00001000; -#else -#if STM32_ADCPRE == STM32_ADCPRE_DIV2 - ADC1->CFGR2 = 0x00001000 | ADC_CFGR2_JITOFFDIV2; -#else - ADC1->CFGR2 = 0x00001000 | ADC_CFGR2_JITOFFDIV4; -#endif -#endif - } -#endif /* STM32_ADC_USE_ADC1 */ - - /* ADC initial setup, starting the analog part here in order to reduce - the latency when starting a conversion.*/ - adcp->adc->CR = ADC_CR_ADEN; - while (!(adcp->adc->ISR & ADC_ISR_ADRDY)) - ; - } -} - -/** - * @brief Deactivates the ADC peripheral. - * - * @param[in] adcp pointer to the @p ADCDriver object - * - * @notapi - */ -void adc_lld_stop(ADCDriver *adcp) { - - /* If in ready state then disables the ADC clock and analog part.*/ - if (adcp->state == ADC_READY) { - - dmaStreamRelease(adcp->dmastp); - - /* Disabling ADC.*/ - if (adcp->adc->CR & ADC_CR_ADEN) { - adc_lld_stop_adc(adcp->adc); - adcp->adc->CR |= ADC_CR_ADDIS; - while (adcp->adc->CR & ADC_CR_ADDIS) - ; - } - -#if STM32_ADC_USE_ADC1 - if (&ADCD1 == adcp) - rccDisableADC1(FALSE); -#endif - } -} - -/** - * @brief Starts an ADC conversion. - * - * @param[in] adcp pointer to the @p ADCDriver object - * - * @notapi - */ -void adc_lld_start_conversion(ADCDriver *adcp) { - uint32_t mode; - const ADCConversionGroup *grpp = adcp->grpp; - - /* DMA setup.*/ - mode = adcp->dmamode; - if (grpp->circular) { - mode |= STM32_DMA_CR_CIRC; - } - if (adcp->depth > 1) { - /* If the buffer depth is greater than one then the half transfer interrupt - interrupt is enabled in order to allows streaming processing.*/ - mode |= STM32_DMA_CR_HTIE; - } - dmaStreamSetMemory0(adcp->dmastp, adcp->samples); - dmaStreamSetTransactionSize(adcp->dmastp, (uint32_t)grpp->num_channels * - (uint32_t)adcp->depth); - dmaStreamSetMode(adcp->dmastp, mode); - dmaStreamEnable(adcp->dmastp); - - /* ADC setup, if it is defined a callback for the analog watch dog then it - is enabled.*/ - adcp->adc->ISR = adcp->adc->ISR; - adcp->adc->IER = ADC_IER_OVRIE | ADC_IER_AWDIE; - adcp->adc->TR = grpp->tr; - adcp->adc->SMPR = grpp->smpr; - adcp->adc->CHSELR = grpp->chselr; - - /* ADC configuration and start.*/ - adcp->adc->CFGR1 = grpp->cfgr1 | ADC_CFGR1_CONT | ADC_CFGR1_DMACFG | - ADC_CFGR1_DMAEN; - adcp->adc->CR |= ADC_CR_ADSTART; -} - -/** - * @brief Stops an ongoing conversion. - * - * @param[in] adcp pointer to the @p ADCDriver object - * - * @notapi - */ -void adc_lld_stop_conversion(ADCDriver *adcp) { - - dmaStreamDisable(adcp->dmastp); - adc_lld_stop_adc(adcp->adc); -} - -#endif /* HAL_USE_ADC */ - -/** @} */ diff --git a/os/hal/platforms/STM32F0xx/adc_lld.h b/os/hal/platforms/STM32F0xx/adc_lld.h deleted file mode 100644 index 635dcefaa..000000000 --- a/os/hal/platforms/STM32F0xx/adc_lld.h +++ /dev/null @@ -1,329 +0,0 @@ -/* - ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file STM32F0xx/adc_lld.h - * @brief STM32F0xx ADC subsystem low level driver header. - * - * @addtogroup ADC - * @{ - */ - -#ifndef _ADC_LLD_H_ -#define _ADC_LLD_H_ - -#if HAL_USE_ADC || defined(__DOXYGEN__) - -/*===========================================================================*/ -/* Driver constants. */ -/*===========================================================================*/ - -/** - * @name Sampling rates - * @{ - */ -#define ADC_SMPR_SMP_1P5 0 /**< @brief 14 cycles conversion time */ -#define ADC_SMPR_SMP_7P5 1 /**< @brief 21 cycles conversion time. */ -#define ADC_SMPR_SMP_13P5 2 /**< @brief 28 cycles conversion time. */ -#define ADC_SMPR_SMP_28P5 3 /**< @brief 41 cycles conversion time. */ -#define ADC_SMPR_SMP_41P5 4 /**< @brief 54 cycles conversion time. */ -#define ADC_SMPR_SMP_55P5 5 /**< @brief 68 cycles conversion time. */ -#define ADC_SMPR_SMP_71P5 6 /**< @brief 84 cycles conversion time. */ -#define ADC_SMPR_SMP_239P5 7 /**< @brief 252 cycles conversion time. */ -/** @} */ - -/** - * @name Resolution - * @{ - */ -#define ADC_CFGR1_RES_12BIT (0 << 3) -#define ADC_CFGR1_RES_10BIT (1 << 3) -#define ADC_CFGR1_RES_8BIT (2 << 3) -#define ADC_CFGR1_RES_6BIT (3 << 3) -/** @} */ - -/** - * @name Threashold register initializer - * @{ - */ -#define ADC_TR(low, high) (((uint32_t)(high) << 16) | (uint32_t)(low)) -/** @} */ - -/*===========================================================================*/ -/* Driver pre-compile time settings. */ -/*===========================================================================*/ - -/** - * @name Configuration options - * @{ - */ -/** - * @brief ADC1 driver enable switch. - * @details If set to @p TRUE the support for ADC1 is included. - * @note The default is @p FALSE. - */ -#if !defined(STM32_ADC_USE_ADC1) || defined(__DOXYGEN__) -#define STM32_ADC_USE_ADC1 FALSE -#endif - -/** - * @brief ADC1 DMA priority (0..3|lowest..highest). - */ -#if !defined(STM32_ADC_ADC1_DMA_PRIORITY) || defined(__DOXYGEN__) -#define STM32_ADC_ADC1_DMA_PRIORITY 2 -#endif - -/** - * @brief ADC interrupt priority level setting. - */ -#if !defined(STM32_ADC_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_ADC_IRQ_PRIORITY 2 -#endif - -/** - * @brief ADC1 DMA interrupt priority level setting. - */ -#if !defined(STM32_ADC_ADC1_DMA_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_ADC_ADC1_DMA_IRQ_PRIORITY 2 -#endif - -/** @} */ - -/*===========================================================================*/ -/* Derived constants and error checks. */ -/*===========================================================================*/ - -#if STM32_ADC_USE_ADC1 && !STM32_HAS_ADC1 -#error "ADC1 not present in the selected device" -#endif - -#if !STM32_ADC_USE_ADC1 -#error "ADC driver activated but no ADC peripheral assigned" -#endif - -#if STM32_ADC_USE_ADC1 && \ - !CORTEX_IS_VALID_KERNEL_PRIORITY(STM32_ADC_IRQ_PRIORITY) -#error "Invalid IRQ priority assigned to ADC1" -#endif - -#if STM32_ADC_USE_ADC1 && \ - !CORTEX_IS_VALID_KERNEL_PRIORITY(STM32_ADC_ADC1_DMA_IRQ_PRIORITY) -#error "Invalid IRQ priority assigned to ADC1 DMA" -#endif - -#if STM32_ADC_USE_ADC1 && \ - !STM32_DMA_IS_VALID_PRIORITY(STM32_ADC_ADC1_DMA_PRIORITY) -#error "Invalid DMA priority assigned to ADC1" -#endif - -#if !defined(STM32_DMA_REQUIRED) -#define STM32_DMA_REQUIRED -#endif - -/*===========================================================================*/ -/* Driver data structures and types. */ -/*===========================================================================*/ - -/** - * @brief ADC sample data type. - */ -typedef uint16_t adcsample_t; - -/** - * @brief Channels number in a conversion group. - */ -typedef uint16_t adc_channels_num_t; - -/** - * @brief Possible ADC failure causes. - * @note Error codes are architecture dependent and should not relied - * upon. - */ -typedef enum { - ADC_ERR_DMAFAILURE = 0, /**< DMA operations failure. */ - ADC_ERR_OVERFLOW = 1, /**< ADC overflow condition. */ - ADC_ERR_AWD = 2 /**< Analog watchdog triggered. */ -} adcerror_t; - -/** - * @brief Type of a structure representing an ADC driver. - */ -typedef struct ADCDriver ADCDriver; - -/** - * @brief ADC notification callback type. - * - * @param[in] adcp pointer to the @p ADCDriver object triggering the - * callback - * @param[in] buffer pointer to the most recent samples data - * @param[in] n number of buffer rows available starting from @p buffer - */ -typedef void (*adccallback_t)(ADCDriver *adcp, adcsample_t *buffer, size_t n); - -/** - * @brief ADC error callback type. - * - * @param[in] adcp pointer to the @p ADCDriver object triggering the - * callback - * @param[in] err ADC error code - */ -typedef void (*adcerrorcallback_t)(ADCDriver *adcp, adcerror_t err); - -/** - * @brief Conversion group configuration structure. - * @details This implementation-dependent structure describes a conversion - * operation. - * @note The use of this configuration structure requires knowledge of - * STM32 ADC cell registers interface, please refer to the STM32 - * reference manual for details. - */ -typedef struct { - /** - * @brief Enables the circular buffer mode for the group. - */ - bool_t circular; - /** - * @brief Number of the analog channels belonging to the conversion group. - */ - adc_channels_num_t num_channels; - /** - * @brief Callback function associated to the group or @p NULL. - */ - adccallback_t end_cb; - /** - * @brief Error callback or @p NULL. - */ - adcerrorcallback_t error_cb; - /* End of the mandatory fields.*/ - /** - * @brief ADC CFGR1 register initialization data. - */ - uint32_t cfgr1; - /** - * @brief ADC TR register initialization data. - */ - uint32_t tr; - /** - * @brief ADC SMPR register initialization data. - */ - uint32_t smpr; - /** - * @brief ADC CHSELR register initialization data. - * @details The number of bits at logic level one in this register must - * be equal to the number in the @p num_channels field. - */ - uint32_t chselr; -} ADCConversionGroup; - -/** - * @brief Driver configuration structure. - * @note It could be empty on some architectures. - */ -typedef struct { - uint32_t dummy; -} ADCConfig; - -/** - * @brief Structure representing an ADC driver. - */ -struct ADCDriver { - /** - * @brief Driver state. - */ - adcstate_t state; - /** - * @brief Current configuration data. - */ - const ADCConfig *config; - /** - * @brief Current samples buffer pointer or @p NULL. - */ - adcsample_t *samples; - /** - * @brief Current samples buffer depth or @p 0. - */ - size_t depth; - /** - * @brief Current conversion group pointer or @p NULL. - */ - const ADCConversionGroup *grpp; -#if ADC_USE_WAIT || defined(__DOXYGEN__) - /** - * @brief Waiting thread. - */ - thread_reference_t thread; -#endif -#if ADC_USE_MUTUAL_EXCLUSION || defined(__DOXYGEN__) - /** - * @brief Mutex protecting the peripheral. - */ - mutex_t mutex; -#endif /* ADC_USE_MUTUAL_EXCLUSION */ -#if defined(ADC_DRIVER_EXT_FIELDS) - ADC_DRIVER_EXT_FIELDS -#endif - /* End of the mandatory fields.*/ - /** - * @brief Pointer to the ADCx registers block. - */ - ADC_TypeDef *adc; - /** - * @brief Pointer to associated DMA channel. - */ - const stm32_dma_stream_t *dmastp; - /** - * @brief DMA mode bit mask. - */ - uint32_t dmamode; -}; - -/*===========================================================================*/ -/* Driver macros. */ -/*===========================================================================*/ - -/** - * @brief Changes the value of the ADC CCR register. - * @details Use this function in order to enable or disable the internal - * analog sources. See the documentation in the STM32F0xx Reference - * Manual. - */ -#define adcSTM32SetCCR(ccr) (ADC->CCR = (ccr)) - -/*===========================================================================*/ -/* External declarations. */ -/*===========================================================================*/ - -#if STM32_ADC_USE_ADC1 && !defined(__DOXYGEN__) -extern ADCDriver ADCD1; -#endif - -#ifdef __cplusplus -extern "C" { -#endif - void adc_lld_init(void); - void adc_lld_start(ADCDriver *adcp); - void adc_lld_stop(ADCDriver *adcp); - void adc_lld_start_conversion(ADCDriver *adcp); - void adc_lld_stop_conversion(ADCDriver *adcp); -#ifdef __cplusplus -} -#endif - -#endif /* HAL_USE_ADC */ - -#endif /* _ADC_LLD_H_ */ - -/** @} */ diff --git a/os/hal/platforms/STM32F0xx/ext_lld_isr.c b/os/hal/platforms/STM32F0xx/ext_lld_isr.c deleted file mode 100644 index fb5100e8c..000000000 --- a/os/hal/platforms/STM32F0xx/ext_lld_isr.c +++ /dev/null @@ -1,197 +0,0 @@ -/* - ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file STM32F0xx/ext_lld_isr.c - * @brief STM32F0xx EXT subsystem low level driver ISR code. - * - * @addtogroup EXT - * @{ - */ - -#include "hal.h" - -#if HAL_USE_EXT || defined(__DOXYGEN__) - -#include "ext_lld_isr.h" - -/*===========================================================================*/ -/* Driver local definitions. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver exported variables. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver local variables. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver local functions. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver interrupt handlers. */ -/*===========================================================================*/ - -/** - * @brief EXTI[0]...EXTI[1] interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(Vector54) { - uint32_t pr; - - OSAL_IRQ_PROLOGUE(); - - pr = EXTI->PR & ((1 << 0) | (1 << 1)); - EXTI->PR = pr; - if (pr & (1 << 0)) - EXTD1.config->channels[0].cb(&EXTD1, 0); - if (pr & (1 << 1)) - EXTD1.config->channels[1].cb(&EXTD1, 1); - - OSAL_IRQ_EPILOGUE(); -} - -/** - * @brief EXTI[2]...EXTI[3] interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(Vector58) { - uint32_t pr; - - OSAL_IRQ_PROLOGUE(); - - pr = EXTI->PR & ((1 << 2) | (1 << 3)); - EXTI->PR = pr; - if (pr & (1 << 2)) - EXTD1.config->channels[2].cb(&EXTD1, 2); - if (pr & (1 << 3)) - EXTD1.config->channels[3].cb(&EXTD1, 3); - - OSAL_IRQ_EPILOGUE(); -} - -/** - * @brief EXTI[4]...EXTI[15] interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(Vector5C) { - uint32_t pr; - - OSAL_IRQ_PROLOGUE(); - - pr = EXTI->PR & ((1 << 4) | (1 << 5) | (1 << 6) | (1 << 7) | (1 << 8) | - (1 << 9) | (1 << 10) | (1 << 11) | (1 << 12) | (1 << 13) | - (1 << 14) | (1 << 15)); - EXTI->PR = pr; - if (pr & (1 << 4)) - EXTD1.config->channels[4].cb(&EXTD1, 4); - if (pr & (1 << 5)) - EXTD1.config->channels[5].cb(&EXTD1, 5); - if (pr & (1 << 6)) - EXTD1.config->channels[6].cb(&EXTD1, 6); - if (pr & (1 << 7)) - EXTD1.config->channels[7].cb(&EXTD1, 7); - if (pr & (1 << 8)) - EXTD1.config->channels[8].cb(&EXTD1, 8); - if (pr & (1 << 9)) - EXTD1.config->channels[9].cb(&EXTD1, 9); - if (pr & (1 << 10)) - EXTD1.config->channels[10].cb(&EXTD1, 10); - if (pr & (1 << 11)) - EXTD1.config->channels[11].cb(&EXTD1, 11); - if (pr & (1 << 12)) - EXTD1.config->channels[12].cb(&EXTD1, 12); - if (pr & (1 << 13)) - EXTD1.config->channels[13].cb(&EXTD1, 13); - if (pr & (1 << 14)) - EXTD1.config->channels[14].cb(&EXTD1, 14); - if (pr & (1 << 15)) - EXTD1.config->channels[15].cb(&EXTD1, 15); - - OSAL_IRQ_EPILOGUE(); -} - -/** - * @brief EXTI[16] interrupt handler (PVD). - * - * @isr - */ -OSAL_IRQ_HANDLER(Vector44) { - - OSAL_IRQ_PROLOGUE(); - - EXTI->PR = (1 << 16); - EXTD1.config->channels[16].cb(&EXTD1, 16); - - OSAL_IRQ_EPILOGUE(); -} - -/** - * @brief EXTI[17] interrupt handler (RTC). - * - * @isr - */ -OSAL_IRQ_HANDLER(Vector48) { - - OSAL_IRQ_PROLOGUE(); - - EXTI->PR = (1 << 17); - EXTD1.config->channels[17].cb(&EXTD1, 17); - - OSAL_IRQ_EPILOGUE(); -} - -/*===========================================================================*/ -/* Driver exported functions. */ -/*===========================================================================*/ - -/** - * @brief Enables EXTI IRQ sources. - * - * @notapi - */ -void ext_lld_exti_irq_enable(void) { - - nvicEnableVector(EXTI0_1_IRQn, STM32_EXT_EXTI0_1_IRQ_PRIORITY); - nvicEnableVector(EXTI2_3_IRQn, STM32_EXT_EXTI2_3_IRQ_PRIORITY); - nvicEnableVector(EXTI4_15_IRQn, STM32_EXT_EXTI4_15_IRQ_PRIORITY); - nvicEnableVector(PVD_IRQn, STM32_EXT_EXTI16_IRQ_PRIORITY); - nvicEnableVector(RTC_IRQn, STM32_EXT_EXTI17_IRQ_PRIORITY); -} - -/** - * @brief Disables EXTI IRQ sources. - * - * @notapi - */ -void ext_lld_exti_irq_disable(void) { - - nvicDisableVector(EXTI0_1_IRQn); - nvicDisableVector(EXTI2_3_IRQn); - nvicDisableVector(EXTI4_15_IRQn); - nvicDisableVector(PVD_IRQn); - nvicDisableVector(RTC_IRQn); -} - -#endif /* HAL_USE_EXT */ - -/** @} */ diff --git a/os/hal/platforms/STM32F0xx/ext_lld_isr.h b/os/hal/platforms/STM32F0xx/ext_lld_isr.h deleted file mode 100644 index 9885fbc65..000000000 --- a/os/hal/platforms/STM32F0xx/ext_lld_isr.h +++ /dev/null @@ -1,107 +0,0 @@ -/* - ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file STM32F0xx/ext_lld_isr.h - * @brief STM32F0xx EXT subsystem low level driver ISR header. - * - * @addtogroup EXT - * @{ - */ - -#ifndef _EXT_LLD_ISR_H_ -#define _EXT_LLD_ISR_H_ - -#if HAL_USE_EXT || defined(__DOXYGEN__) - -/*===========================================================================*/ -/* Driver constants. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver pre-compile time settings. */ -/*===========================================================================*/ - -/** - * @name Configuration options - * @{ - */ -/** - * @brief EXTI0..1 interrupt priority level setting. - */ -#if !defined(STM32_EXT_EXTI0_1_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_EXT_EXTI0_1_IRQ_PRIORITY 3 -#endif - -/** - * @brief EXTI2..3 interrupt priority level setting. - */ -#if !defined(STM32_EXT_EXTI2_3_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_EXT_EXTI2_3_IRQ_PRIORITY 3 -#endif - -/** - * @brief EXTI4..15 interrupt priority level setting. - */ -#if !defined(STM32_EXT_EXTI4_15_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_EXT_EXTI4_15_IRQ_PRIORITY 3 -#endif - -/** - * @brief EXTI16 interrupt priority level setting. - */ -#if !defined(STM32_EXT_EXTI16_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_EXT_EXTI16_IRQ_PRIORITY 3 -#endif - -/** - * @brief EXTI17 interrupt priority level setting. - */ -#if !defined(STM32_EXT_EXTI17_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_EXT_EXTI17_IRQ_PRIORITY 3 -#endif -/** @} */ - -/*===========================================================================*/ -/* Derived constants and error checks. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver data structures and types. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver macros. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* External declarations. */ -/*===========================================================================*/ - -#ifdef __cplusplus -extern "C" { -#endif - void ext_lld_exti_irq_enable(void); - void ext_lld_exti_irq_disable(void); -#ifdef __cplusplus -} -#endif - -#endif /* HAL_USE_EXT */ - -#endif /* _EXT_LLD_ISR_H_ */ - -/** @} */ diff --git a/os/hal/platforms/STM32F0xx/hal_lld.c b/os/hal/platforms/STM32F0xx/hal_lld.c deleted file mode 100644 index 09ab62923..000000000 --- a/os/hal/platforms/STM32F0xx/hal_lld.c +++ /dev/null @@ -1,199 +0,0 @@ -/* - ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file STM32F0xx/hal_lld.c - * @brief STM32F0xx HAL subsystem low level driver source. - * - * @addtogroup HAL - * @{ - */ - -#include "hal.h" - -/*===========================================================================*/ -/* Driver local definitions. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver exported variables. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver local variables and types. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver local functions. */ -/*===========================================================================*/ - -/** - * @brief Initializes the backup domain. - * @note WARNING! Changing clock source impossible without resetting - * of the whole BKP domain. - */ -static void hal_lld_backup_domain_init(void) { - - /* Backup domain access enabled and left open.*/ - PWR->CR |= PWR_CR_DBP; - - /* Reset BKP domain if different clock source selected.*/ - if ((RCC->BDCR & STM32_RTCSEL_MASK) != STM32_RTCSEL){ - /* Backup domain reset.*/ - RCC->BDCR = RCC_BDCR_BDRST; - RCC->BDCR = 0; - } - - /* If enabled then the LSE is started.*/ -#if STM32_LSE_ENABLED -#if defined(STM32_LSE_BYPASS) - /* LSE Bypass.*/ - RCC->BDCR = STM32_LSEDRV | RCC_BDCR_LSEON | RCC_BDCR_LSEBYP; -#else - /* No LSE Bypass.*/ - RCC->BDCR = STM32_LSEDRV | RCC_BDCR_LSEON; -#endif - while ((RCC->BDCR & RCC_BDCR_LSERDY) == 0) - ; /* Waits until LSE is stable. */ -#endif - -#if STM32_RTCSEL != STM32_RTCSEL_NOCLOCK - /* If the backup domain hasn't been initialized yet then proceed with - initialization.*/ - if ((RCC->BDCR & RCC_BDCR_RTCEN) == 0) { - /* Selects clock source.*/ - RCC->BDCR |= STM32_RTCSEL; - - /* RTC clock enabled.*/ - RCC->BDCR |= RCC_BDCR_RTCEN; - } -#endif /* STM32_RTCSEL != STM32_RTCSEL_NOCLOCK */ -} - -/*===========================================================================*/ -/* Driver interrupt handlers. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver exported functions. */ -/*===========================================================================*/ - -/** - * @brief Low level HAL driver initialization. - * - * @notapi - */ -void hal_lld_init(void) { - - /* Reset of all peripherals.*/ - rccResetAPB1(0xFFFFFFFF); - rccResetAPB2(~RCC_APB2RSTR_DBGMCURST); - - /* PWR clock enabled.*/ - rccEnablePWRInterface(FALSE); - - /* Initializes the backup domain.*/ - hal_lld_backup_domain_init(); - -#if defined(STM32_DMA_REQUIRED) - dmaInit(); -#endif - - /* Programmable voltage detector enable.*/ -#if STM32_PVD_ENABLE - PWR->CR |= PWR_CR_PVDE | (STM32_PLS & STM32_PLS_MASK); -#endif /* STM32_PVD_ENABLE */ -} - -/** - * @brief STM32 clocks and PLL initialization. - * @note All the involved constants come from the file @p board.h. - * @note This function should be invoked just after the system reset. - * - * @special - */ -void stm32_clock_init(void) { - -#if !STM32_NO_INIT - /* HSI setup, it enforces the reset situation in order to handle possible - problems with JTAG probes and re-initializations.*/ - RCC->CR |= RCC_CR_HSION; /* Make sure HSI is ON. */ - while (!(RCC->CR & RCC_CR_HSIRDY)) - ; /* Wait until HSI is stable. */ - RCC->CR &= RCC_CR_HSITRIM | RCC_CR_HSION; /* CR Reset value. */ - RCC->CFGR = 0; /* CFGR reset value. */ - while ((RCC->CFGR & RCC_CFGR_SWS) != RCC_CFGR_SWS_HSI) - ; /* Waits until HSI is selected. */ - -#if STM32_HSE_ENABLED - /* HSE activation.*/ -#if defined(STM32_HSE_BYPASS) - /* HSE Bypass.*/ - RCC->CR |= RCC_CR_HSEON | RCC_CR_HSEBYP; -#else - /* No HSE Bypass.*/ - RCC->CR |= RCC_CR_HSEON; -#endif - while (!(RCC->CR & RCC_CR_HSERDY)) - ; /* Waits until HSE is stable. */ -#endif - -#if STM32_HSE14_ENABLED - /* HSI14 activation.*/ - RCC->CR2 |= RCC_CR2_HSI14ON; - while (!(RCC->CR2 & RCC_CR2_HSI14RDY)) - ; /* Waits until HSI14 is stable. */ -#endif - -#if STM32_LSI_ENABLED - /* LSI activation.*/ - RCC->CSR |= RCC_CSR_LSION; - while ((RCC->CSR & RCC_CSR_LSIRDY) == 0) - ; /* Waits until LSI is stable. */ -#endif - - /* Clock settings.*/ - RCC->CFGR = STM32_MCOSEL | STM32_PLLMUL | STM32_PLLSRC | - STM32_ADCPRE | STM32_PPRE | STM32_HPRE; - RCC->CFGR2 = STM32_PREDIV; - RCC->CFGR3 = STM32_ADCSW | STM32_CECSW | STM32_I2C1SW | - STM32_USART1SW; - -#if STM32_ACTIVATE_PLL - /* PLL activation.*/ - RCC->CR |= RCC_CR_PLLON; - while (!(RCC->CR & RCC_CR_PLLRDY)) - ; /* Waits until PLL is stable. */ -#endif - - /* Flash setup and final clock selection. */ - FLASH->ACR = STM32_FLASHBITS; - - /* Switching to the configured clock source if it is different from HSI.*/ -#if (STM32_SW != STM32_SW_HSI) - /* Switches clock source.*/ - RCC->CFGR |= STM32_SW; - while ((RCC->CFGR & RCC_CFGR_SWS) != (STM32_SW << 2)) - ; /* Waits selection complete. */ -#endif - - /* SYSCFG clock enabled here because it is a multi-functional unit shared - among multiple drivers.*/ - rccEnableAPB2(RCC_APB2ENR_SYSCFGEN, TRUE); -#endif /* !STM32_NO_INIT */ -} - -/** @} */ diff --git a/os/hal/platforms/STM32F0xx/hal_lld.h b/os/hal/platforms/STM32F0xx/hal_lld.h deleted file mode 100644 index c7238de56..000000000 --- a/os/hal/platforms/STM32F0xx/hal_lld.h +++ /dev/null @@ -1,781 +0,0 @@ -/* - ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file STM32F0xx/hal_lld.h - * @brief STM32F0xx HAL subsystem low level driver header. - * @pre This module requires the following macros to be defined in the - * @p board.h file: - * - STM32_LSECLK. - * - STM32_LSEDRV. - * - STM32_LSE_BYPASS (optionally). - * - STM32_HSECLK. - * - STM32_HSE_BYPASS (optionally). - * . - * One of the following macros must also be defined: - * - STM32F0XX for Entry Level devices. - * . - * - * @addtogroup HAL - * @{ - */ - -#ifndef _HAL_LLD_H_ -#define _HAL_LLD_H_ - -#include "stm32.h" -#include "stm32_registry.h" - -/*===========================================================================*/ -/* Driver constants. */ -/*===========================================================================*/ - -/** - * @brief Defines the support for realtime counters in the HAL. - */ -#define HAL_IMPLEMENTS_COUNTERS FALSE - -/** - * @name Platform identification - * @{ - */ -#define PLATFORM_NAME "STM32F05x Entry Level" -/** @} */ - -/** - * @name Absolute Maximum Ratings - * @{ - */ -/** - * @brief Maximum system clock frequency. - */ -#define STM32_SYSCLK_MAX 48000000 - -/** - * @brief Maximum HSE clock frequency. - */ -#define STM32_HSECLK_MAX 32000000 - -/** - * @brief Minimum HSE clock frequency. - */ -#define STM32_HSECLK_MIN 1000000 - -/** - * @brief Maximum LSE clock frequency. - */ -#define STM32_LSECLK_MAX 1000000 - -/** - * @brief Minimum LSE clock frequency. - */ -#define STM32_LSECLK_MIN 32768 - -/** - * @brief Maximum PLLs input clock frequency. - */ -#define STM32_PLLIN_MAX 25000000 - -/** - * @brief Minimum PLLs input clock frequency. - */ -#define STM32_PLLIN_MIN 1000000 - -/** - * @brief Maximum PLL output clock frequency. - */ -#define STM32_PLLOUT_MAX 48000000 - -/** - * @brief Minimum PLL output clock frequency. - */ -#define STM32_PLLOUT_MIN 16000000 - -/** - * @brief Maximum APB clock frequency. - */ -#define STM32_PCLK_MAX 48000000 - -/** - * @brief Maximum ADC clock frequency. - */ -#define STM32_ADCCLK_MAX 14000000 -/** @} */ - -/** - * @name Internal clock sources - * @{ - */ -#define STM32_HSICLK 8000000 /**< High speed internal clock. */ -#define STM32_HSI14CLK 14000000 /**< 14MHz speed internal clock.*/ -#define STM32_LSICLK 40000 /**< Low speed internal clock. */ -/** @} */ - -/** - * @name PWR_CR register bits definitions - * @{ - */ -#define STM32_PLS_MASK (7 << 5) /**< PLS bits mask. */ -#define STM32_PLS_LEV0 (0 << 5) /**< PVD level 0. */ -#define STM32_PLS_LEV1 (1 << 5) /**< PVD level 1. */ -#define STM32_PLS_LEV2 (2 << 5) /**< PVD level 2. */ -#define STM32_PLS_LEV3 (3 << 5) /**< PVD level 3. */ -#define STM32_PLS_LEV4 (4 << 5) /**< PVD level 4. */ -#define STM32_PLS_LEV5 (5 << 5) /**< PVD level 5. */ -#define STM32_PLS_LEV6 (6 << 5) /**< PVD level 6. */ -#define STM32_PLS_LEV7 (7 << 5) /**< PVD level 7. */ -/** @} */ - -/** - * @name RCC_CFGR register bits definitions - * @{ - */ -#define STM32_SW_HSI (0 << 0) /**< SYSCLK source is HSI. */ -#define STM32_SW_HSE (1 << 0) /**< SYSCLK source is HSE. */ -#define STM32_SW_PLL (2 << 0) /**< SYSCLK source is PLL. */ - -#define STM32_HPRE_DIV1 (0 << 4) /**< SYSCLK divided by 1. */ -#define STM32_HPRE_DIV2 (8 << 4) /**< SYSCLK divided by 2. */ -#define STM32_HPRE_DIV4 (9 << 4) /**< SYSCLK divided by 4. */ -#define STM32_HPRE_DIV8 (10 << 4) /**< SYSCLK divided by 8. */ -#define STM32_HPRE_DIV16 (11 << 4) /**< SYSCLK divided by 16. */ -#define STM32_HPRE_DIV64 (12 << 4) /**< SYSCLK divided by 64. */ -#define STM32_HPRE_DIV128 (13 << 4) /**< SYSCLK divided by 128. */ -#define STM32_HPRE_DIV256 (14 << 4) /**< SYSCLK divided by 256. */ -#define STM32_HPRE_DIV512 (15 << 4) /**< SYSCLK divided by 512. */ - -#define STM32_PPRE_DIV1 (0 << 8) /**< HCLK divided by 1. */ -#define STM32_PPRE_DIV2 (4 << 8) /**< HCLK divided by 2. */ -#define STM32_PPRE_DIV4 (5 << 8) /**< HCLK divided by 4. */ -#define STM32_PPRE_DIV8 (6 << 8) /**< HCLK divided by 8. */ -#define STM32_PPRE_DIV16 (7 << 8) /**< HCLK divided by 16. */ - -#define STM32_ADCPRE_DIV2 (0 << 14) /**< PCLK divided by 2. */ -#define STM32_ADCPRE_DIV4 (1 << 14) /**< PCLK divided by 4. */ - -#define STM32_PLLSRC_HSI (0 << 16) /**< PLL clock source is HSI. */ -#define STM32_PLLSRC_HSE (1 << 16) /**< PLL clock source is HSE. */ - -#define STM32_MCOSEL_NOCLOCK (0 << 24) /**< No clock on MCO pin. */ -#define STM32_MCOSEL_HSI14 (3 << 24) /**< HSI14 clock on MCO pin. */ -#define STM32_MCOSEL_SYSCLK (4 << 24) /**< SYSCLK on MCO pin. */ -#define STM32_MCOSEL_HSI (5 << 24) /**< HSI clock on MCO pin. */ -#define STM32_MCOSEL_HSE (6 << 24) /**< HSE clock on MCO pin. */ -#define STM32_MCOSEL_PLLDIV2 (7 << 24) /**< PLL/2 clock on MCO pin. */ -/** @} */ - -/** - * @name RCC_BDCR register bits definitions - * @{ - */ -#define STM32_RTCSEL_MASK (3 << 8) /**< RTC clock source mask. */ -#define STM32_RTCSEL_NOCLOCK (0 << 8) /**< No clock. */ -#define STM32_RTCSEL_LSE (1 << 8) /**< LSE used as RTC clock. */ -#define STM32_RTCSEL_LSI (2 << 8) /**< LSI used as RTC clock. */ -#define STM32_RTCSEL_HSEDIV (3 << 8) /**< HSE divided by 32 used as - RTC clock. */ -/** @} */ - -/** - * @name RCC_CFGR3 register bits definitions - * @{ - */ -#define STM32_USART1SW_MASK (3 << 0) /**< USART1 clock source mask. */ -#define STM32_USART1SW_PCLK (0 << 0) /**< USART1 clock is PCLK. */ -#define STM32_USART1SW_SYSCLK (1 << 0) /**< USART1 clock is SYSCLK. */ -#define STM32_USART1SW_LSE (2 << 0) /**< USART1 clock is LSE. */ -#define STM32_USART1SW_HSI (3 << 0) /**< USART1 clock is HSI. */ -#define STM32_I2C1SW_MASK (1 << 4) /**< I2C clock source mask. */ -#define STM32_I2C1SW_HSI (0 << 4) /**< I2C clock is HSI. */ -#define STM32_I2C1SW_SYSCLK (1 << 4) /**< I2C clock is SYSCLK. */ -#define STM32_CECSW_MASK (1 << 6) /**< CEC clock source mask. */ -#define STM32_CECSW_HSI (0 << 6) /**< CEC clock is HSI/244. */ -#define STM32_CECSW_LSE (1 << 6) /**< CEC clock is LSE. */ -#define STM32_ADCSW_MASK (1 << 8) /**< ADC clock source mask. */ -#define STM32_ADCSW_HSI14 (0 << 8) /**< ADC clock is HSI14. */ -#define STM32_ADCSW_PCLK (1 << 8) /**< ADC clock is PCLK/2|4. */ -/** @} */ - -/*===========================================================================*/ -/* Driver pre-compile time settings. */ -/*===========================================================================*/ - -/** - * @name Configuration options - * @{ - */ -/** - * @brief Disables the PWR/RCC initialization in the HAL. - */ -#if !defined(STM32_NO_INIT) || defined(__DOXYGEN__) -#define STM32_NO_INIT FALSE -#endif - -/** - * @brief Enables or disables the programmable voltage detector. - */ -#if !defined(STM32_PVD_ENABLE) || defined(__DOXYGEN__) -#define STM32_PVD_ENABLE FALSE -#endif - -/** - * @brief Sets voltage level for programmable voltage detector. - */ -#if !defined(STM32_PLS) || defined(__DOXYGEN__) -#define STM32_PLS STM32_PLS_LEV0 -#endif - -/** - * @brief Enables or disables the HSI clock source. - */ -#if !defined(STM32_HSI_ENABLED) || defined(__DOXYGEN__) -#define STM32_HSI_ENABLED TRUE -#endif - -/** - * @brief Enables or disables the HSI14 clock source. - */ -#if !defined(STM32_HSI14_ENABLED) || defined(__DOXYGEN__) -#define STM32_HSI14_ENABLED TRUE -#endif - -/** - * @brief Enables or disables the LSI clock source. - */ -#if !defined(STM32_LSI_ENABLED) || defined(__DOXYGEN__) -#define STM32_LSI_ENABLED FALSE -#endif - -/** - * @brief Enables or disables the HSE clock source. - */ -#if !defined(STM32_HSE_ENABLED) || defined(__DOXYGEN__) -#define STM32_HSE_ENABLED TRUE -#endif - -/** - * @brief Enables or disables the LSE clock source. - */ -#if !defined(STM32_LSE_ENABLED) || defined(__DOXYGEN__) -#define STM32_LSE_ENABLED FALSE -#endif - -/** - * @brief Main clock source selection. - * @note If the selected clock source is not the PLL then the PLL is not - * initialized and started. - * @note The default value is calculated for a 48MHz system clock from - * a 8MHz crystal using the PLL. - */ -#if !defined(STM32_SW) || defined(__DOXYGEN__) -#define STM32_SW STM32_SW_PLL -#endif - -/** - * @brief Clock source for the PLL. - * @note This setting has only effect if the PLL is selected as the - * system clock source. - * @note The default value is calculated for a 48MHz system clock from - * a 8MHz crystal using the PLL. - */ -#if !defined(STM32_PLLSRC) || defined(__DOXYGEN__) -#define STM32_PLLSRC STM32_PLLSRC_HSE -#endif - -/** - * @brief Crystal PLL pre-divider. - * @note This setting has only effect if the PLL is selected as the - * system clock source. - * @note The default value is calculated for a 72MHz system clock from - * a 8MHz crystal using the PLL. - */ -#if !defined(STM32_PREDIV_VALUE) || defined(__DOXYGEN__) -#define STM32_PREDIV_VALUE 1 -#endif - -/** - * @brief PLL multiplier value. - * @note The allowed range is 2...16. - * @note The default value is calculated for a 48MHz system clock from - * a 8MHz crystal using the PLL. - */ -#if !defined(STM32_PLLMUL_VALUE) || defined(__DOXYGEN__) -#define STM32_PLLMUL_VALUE 6 -#endif - -/** - * @brief AHB prescaler value. - * @note The default value is calculated for a 48MHz system clock from - * a 8MHz crystal using the PLL. - */ -#if !defined(STM32_HPRE) || defined(__DOXYGEN__) -#define STM32_HPRE STM32_HPRE_DIV1 -#endif - -/** - * @brief APB1 prescaler value. - */ -#if !defined(STM32_PPRE) || defined(__DOXYGEN__) -#define STM32_PPRE STM32_PPRE_DIV1 -#endif - -/** - * @brief MCO pin setting. - */ -#if !defined(STM32_MCOSEL) || defined(__DOXYGEN__) -#define STM32_MCOSEL STM32_MCOSEL_NOCLOCK -#endif - -/** - * @brief ADC prescaler value. - */ -#if !defined(STM32_ADCPRE) || defined(__DOXYGEN__) -#define STM32_ADCPRE STM32_ADCPRE_DIV4 -#endif - -/** - * @brief ADC clock source. - */ -#if !defined(STM32_ADCSW) || defined(__DOXYGEN__) -#define STM32_ADCSW STM32_ADCSW_HSI14 -#endif - -/** - * @brief CEC clock source. - */ -#if !defined(STM32_CECSW) || defined(__DOXYGEN__) -#define STM32_CECSW STM32_CECSW_HSI -#endif - -/** - * @brief I2C1 clock source. - */ -#if !defined(STM32_I2C1SW) || defined(__DOXYGEN__) -#define STM32_I2C1SW STM32_I2C1SW_HSI -#endif - -/** - * @brief USART1 clock source. - */ -#if !defined(STM32_USART1SW) || defined(__DOXYGEN__) -#define STM32_USART1SW STM32_USART1SW_PCLK -#endif - -/** - * @brief RTC clock source. - */ -#if !defined(STM32_RTCSEL) || defined(__DOXYGEN__) -#define STM32_RTCSEL STM32_RTCSEL_LSI -#endif -/** @} */ - -/*===========================================================================*/ -/* Derived constants and error checks. */ -/*===========================================================================*/ - -/* - * Configuration-related checks. - */ -#if !defined(STM32F0xx_MCUCONF) -#error "Using a wrong mcuconf.h file, STM32F0xx_MCUCONF not defined" -#endif - -/* - * HSI related checks. - */ -#if STM32_HSI_ENABLED -#else /* !STM32_HSI_ENABLED */ - -#if STM32_SW == STM32_SW_HSI -#error "HSI not enabled, required by STM32_SW" -#endif - -#if STM32_CECSW == STM32_CECSW_HSI -#error "HSI not enabled, required by STM32_CECSW" -#endif - -#if STM32_I2C1SW == STM32_I2C1SW_HSI -#error "HSI not enabled, required by STM32_I2C1SW" -#endif - -#if STM32_USART1SW == STM32_USART1SW_HSI -#error "HSI not enabled, required by STM32_USART1SW" -#endif - -#if (STM32_SW == STM32_SW_PLL) && (STM32_PLLSRC == STM32_PLLSRC_HSI) -#error "HSI not enabled, required by STM32_SW and STM32_PLLSRC" -#endif - -#if (STM32_MCOSEL == STM32_MCOSEL_HSI) || \ - ((STM32_MCOSEL == STM32_MCOSEL_PLLDIV2) && \ - (STM32_PLLSRC == STM32_PLLSRC_HSI)) -#error "HSI not enabled, required by STM32_MCOSEL" -#endif - -#endif /* !STM32_HSI_ENABLED */ - -/* - * HSI14 related checks. - */ -#if STM32_HSI14_ENABLED -#else /* !STM32_HSI14_ENABLED */ - -#if STM32_MCOSEL == STM32_MCOSEL_HSI14 -#error "HSI14 not enabled, required by STM32_MCOSEL" -#endif - -#if STM32_ADCSW == STM32_ADCSW_HSI14 -#error "HSI14 not enabled, required by STM32_ADCSW" -#endif - -#endif /* !STM32_HSI14_ENABLED */ - -/* - * HSE related checks. - */ -#if STM32_HSE_ENABLED - -#if STM32_HSECLK == 0 -#error "HSE frequency not defined" -#elif (STM32_HSECLK < STM32_HSECLK_MIN) || (STM32_HSECLK > STM32_HSECLK_MAX) -#error "STM32_HSECLK outside acceptable range (STM32_HSECLK_MIN...STM32_HSECLK_MAX)" -#endif - -#else /* !STM32_HSE_ENABLED */ - -#if STM32_SW == STM32_SW_HSE -#error "HSE not enabled, required by STM32_SW" -#endif - -#if (STM32_SW == STM32_SW_PLL) && (STM32_PLLSRC == STM32_PLLSRC_HSE) -#error "HSE not enabled, required by STM32_SW and STM32_PLLSRC" -#endif - -#if (STM32_MCOSEL == STM32_MCOSEL_HSE) || \ - ((STM32_MCOSEL == STM32_MCOSEL_PLLDIV2) && \ - (STM32_PLLSRC == STM32_PLLSRC_HSE)) -#error "HSE not enabled, required by STM32_MCOSEL" -#endif - -#if STM32_RTCSEL == STM32_RTCSEL_HSEDIV -#error "HSE not enabled, required by STM32_RTCSEL" -#endif - -#endif /* !STM32_HSE_ENABLED */ - -/* - * LSI related checks. - */ -#if STM32_LSI_ENABLED -#else /* !STM32_LSI_ENABLED */ - -#if STM32_RTCSEL == STM32_RTCSEL_LSI -#error "LSI not enabled, required by STM32_RTCSEL" -#endif - -#endif /* !STM32_LSI_ENABLED */ - -/* - * LSE related checks. - */ -#if STM32_LSE_ENABLED - -#if (STM32_LSECLK == 0) -#error "LSE frequency not defined" -#endif - -#if (STM32_LSECLK < STM32_LSECLK_MIN) || (STM32_LSECLK > STM32_LSECLK_MAX) -#error "STM32_LSECLK outside acceptable range (STM32_LSECLK_MIN...STM32_LSECLK_MAX)" -#endif - -#if !defined(STM32_LSEDRV) -#error "STM32_LSEDRV not defined" -#endif - -#if (STM32_LSEDRV >> 3) > 3 -#error "STM32_LSEDRV outside acceptable range ((0<<3)...(3<<3))" -#endif - -#if STM32_CECSW == STM32_CECSW_LSE -#error "LSE not enabled, required by STM32_CECSW" -#endif - -#if STM32_USART1SW == STM32_USART1SW_LSE -#error "LSE not enabled, required by STM32_USART1SW" -#endif - -#else /* !STM32_LSE_ENABLED */ - -#if STM32_RTCSEL == STM32_RTCSEL_LSE -#error "LSE not enabled, required by STM32_RTCSEL" -#endif - -#endif /* !STM32_LSE_ENABLED */ - -/* PLL activation conditions.*/ -#if (STM32_SW == STM32_SW_PLL) || \ - (STM32_MCOSEL == STM32_MCOSEL_PLLDIV2) || \ - defined(__DOXYGEN__) -/** - * @brief PLL activation flag. - */ -#define STM32_ACTIVATE_PLL TRUE -#else -#define STM32_ACTIVATE_PLL FALSE -#endif - -/* HSE prescaler setting check.*/ -#if ((STM32_PREDIV_VALUE >= 1) || (STM32_PREDIV_VALUE <= 16)) -#define STM32_PREDIV ((STM32_PREDIV_VALUE - 1) << 0) -#else -#error "invalid STM32_PREDIV value specified" -#endif - -/** - * @brief PLLMUL field. - */ -#if ((STM32_PLLMUL_VALUE >= 2) && (STM32_PLLMUL_VALUE <= 16)) || \ - defined(__DOXYGEN__) -#define STM32_PLLMUL ((STM32_PLLMUL_VALUE - 2) << 18) -#else -#error "invalid STM32_PLLMUL_VALUE value specified" -#endif - -/** - * @brief PLL input clock frequency. - */ -#if (STM32_PLLSRC == STM32_PLLSRC_HSE) || defined(__DOXYGEN__) -#define STM32_PLLCLKIN (STM32_HSECLK / STM32_PREDIV_VALUE) -#elif STM32_PLLSRC == STM32_PLLSRC_HSI -#define STM32_PLLCLKIN (STM32_HSICLK / 2) -#else -#error "invalid STM32_PLLSRC value specified" -#endif - -/* PLL input frequency range check.*/ -#if (STM32_PLLCLKIN < STM32_PLLIN_MIN) || (STM32_PLLCLKIN > STM32_PLLIN_MAX) -#error "STM32_PLLCLKIN outside acceptable range (STM32_PLLIN_MIN...STM32_PLLIN_MAX)" -#endif - -/** - * @brief PLL output clock frequency. - */ -#define STM32_PLLCLKOUT (STM32_PLLCLKIN * STM32_PLLMUL_VALUE) - -/* PLL output frequency range check.*/ -#if (STM32_PLLCLKOUT < STM32_PLLOUT_MIN) || (STM32_PLLCLKOUT > STM32_PLLOUT_MAX) -#error "STM32_PLLCLKOUT outside acceptable range (STM32_PLLOUT_MIN...STM32_PLLOUT_MAX)" -#endif - -/** - * @brief System clock source. - */ -#if (STM32_SW == STM32_SW_PLL) || defined(__DOXYGEN__) -#define STM32_SYSCLK STM32_PLLCLKOUT -#elif (STM32_SW == STM32_SW_HSI) -#define STM32_SYSCLK STM32_HSICLK -#elif (STM32_SW == STM32_SW_HSE) -#define STM32_SYSCLK STM32_HSECLK -#else -#error "invalid STM32_SW value specified" -#endif - -/* Check on the system clock.*/ -#if STM32_SYSCLK > STM32_SYSCLK_MAX -#error "STM32_SYSCLK above maximum rated frequency (STM32_SYSCLK_MAX)" -#endif - -/** - * @brief AHB frequency. - */ -#if (STM32_HPRE == STM32_HPRE_DIV1) || defined(__DOXYGEN__) -#define STM32_HCLK (STM32_SYSCLK / 1) -#elif STM32_HPRE == STM32_HPRE_DIV2 -#define STM32_HCLK (STM32_SYSCLK / 2) -#elif STM32_HPRE == STM32_HPRE_DIV4 -#define STM32_HCLK (STM32_SYSCLK / 4) -#elif STM32_HPRE == STM32_HPRE_DIV8 -#define STM32_HCLK (STM32_SYSCLK / 8) -#elif STM32_HPRE == STM32_HPRE_DIV16 -#define STM32_HCLK (STM32_SYSCLK / 16) -#elif STM32_HPRE == STM32_HPRE_DIV64 -#define STM32_HCLK (STM32_SYSCLK / 64) -#elif STM32_HPRE == STM32_HPRE_DIV128 -#define STM32_HCLK (STM32_SYSCLK / 128) -#elif STM32_HPRE == STM32_HPRE_DIV256 -#define STM32_HCLK (STM32_SYSCLK / 256) -#elif STM32_HPRE == STM32_HPRE_DIV512 -#define STM32_HCLK (STM32_SYSCLK / 512) -#else -#error "invalid STM32_HPRE value specified" -#endif - -/* AHB frequency check.*/ -#if STM32_HCLK > STM32_SYSCLK_MAX -#error "STM32_HCLK exceeding maximum frequency (STM32_SYSCLK_MAX)" -#endif - -/** - * @brief APB frequency. - */ -#if (STM32_PPRE == STM32_PPRE_DIV1) || defined(__DOXYGEN__) -#define STM32_PCLK (STM32_HCLK / 1) -#elif STM32_PPRE == STM32_PPRE_DIV2 -#define STM32_PCLK (STM32_HCLK / 2) -#elif STM32_PPRE == STM32_PPRE_DIV4 -#define STM32_PCLK (STM32_HCLK / 4) -#elif STM32_PPRE == STM32_PPRE_DIV8 -#define STM32_PCLK (STM32_HCLK / 8) -#elif STM32_PPRE == STM32_PPRE_DIV16 -#define STM32_PCLK (STM32_HCLK / 16) -#else -#error "invalid STM32_PPRE value specified" -#endif - -/* APB frequency check.*/ -#if STM32_PCLK > STM32_PCLK_MAX -#error "STM32_PCLK exceeding maximum frequency (STM32_PCLK_MAX)" -#endif - -/** - * @brief RTC clock. - */ -#if (STM32_RTCSEL == STM32_RTCSEL_LSE) || defined(__DOXYGEN__) -#define STM32_RTCCLK STM32_LSECLK -#elif STM32_RTCSEL == STM32_RTCSEL_LSI -#define STM32_RTCCLK STM32_LSICLK -#elif STM32_RTCSEL == STM32_RTCSEL_HSEDIV -#define STM32_RTCCLK (STM32_HSECLK / 32) -#elif STM32_RTCSEL == STM32_RTCSEL_NOCLOCK -#define STM32_RTCCLK 0 -#else -#error "invalid source selected for RTC clock" -#endif - -/** - * @brief ADC frequency. - */ -#if STM32_ADCSW == STM32_ADCSW_HSI14 -#define STM32_ADCCLK STM32_HSI14CLK -#elif STM32_ADCSW == STM32_ADCSW_PCLK -#if (STM32_ADCPRE == STM32_ADCPRE_DIV2) || defined(__DOXYGEN__) -#define STM32_ADCCLK (STM32_PCLK / 2) -#elif STM32_ADCPRE == STM32_ADCPRE_DIV4 -#define STM32_ADCCLK (STM32_PCLK / 4) -#else -#error "invalid STM32_ADCPRE value specified" -#endif -#else -#error "invalid source selected for ADC clock" -#endif - -/* ADC frequency check.*/ -#if STM32_ADCCLK > STM32_ADCCLK_MAX -#error "STM32_ADCCLK exceeding maximum frequency (STM32_ADCCLK_MAX)" -#endif - -/** - * @brief CEC frequency. - */ -#if STM32_CECSW == STM32_CECSW_HSI -#define STM32_CECCLK STM32_HSICLK -#elif STM32_CECSW == STM32_CECSW_LSE -#define STM32_CECCLK STM32_LSECLK -#else -#error "invalid source selected for CEC clock" -#endif - -/** - * @brief I2C1 frequency. - */ -#if STM32_I2CSW == STM32_I2C1SW_HSI -#define STM32_I2C1CLK STM32_HSICLK -#elif STM32_I2CSW == STM32_I2C1SW_SYSCLK -#define STM32_I2C1CLK STM32_SYSCLK -#else -#error "invalid source selected for I2C1 clock" -#endif - -/** - * @brief USART1 frequency. - */ -#if STM32_USART1SW == STM32_USART1SW_PCLK -#define STM32_USART1CLK STM32_PCLK -#elif STM32_USART1SW == STM32_USART1SW_SYSCLK -#define STM32_USART1CLK STM32_SYSCLK -#elif STM32_USART1SW == STM32_USART1SW_LSECLK -#define STM32_USART1CLK STM32_LSECLK -#elif STM32_USART1SW == STM32_USART1SW_HSICLK -#define STM32_USART1CLK STM32_HSICLK -#else -#error "invalid source selected for USART1 clock" -#endif - -/** - * @brief USART2 frequency. - */ -#define STM32_USART2CLK STM32_PCLK - -/** - * @brief Timers clock. - */ -#if (STM32_PPRE == STM32_PPRE_DIV1) || defined(__DOXYGEN__) -#define STM32_TIMCLK1 (STM32_PCLK * 1) -#define STM32_TIMCLK2 (STM32_PCLK * 1) -#else -#define STM32_TIMCLK1 (STM32_PCLK * 2) -#define STM32_TIMCLK2 (STM32_PCLK * 2) -#endif - -/** - * @brief Flash settings. - */ -#if (STM32_HCLK <= 24000000) || defined(__DOXYGEN__) -#define STM32_FLASHBITS 0x00000010 -#else -#define STM32_FLASHBITS 0x00000011 -#endif - -/*===========================================================================*/ -/* Driver data structures and types. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver macros. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* External declarations. */ -/*===========================================================================*/ - -/* Various helpers.*/ -#include "nvic.h" -#include "stm32_isr.h" -#include "stm32_dma.h" -#include "stm32_rcc.h" - -#ifdef __cplusplus -extern "C" { -#endif - void hal_lld_init(void); - void stm32_clock_init(void); -#ifdef __cplusplus -} -#endif - -#endif /* _HAL_LLD_H_ */ - -/** @} */ diff --git a/os/hal/platforms/STM32F0xx/platform.mk b/os/hal/platforms/STM32F0xx/platform.mk deleted file mode 100644 index 0a5c73362..000000000 --- a/os/hal/platforms/STM32F0xx/platform.mk +++ /dev/null @@ -1,28 +0,0 @@ -# List of all the STM32F0xx platform files. -PLATFORMSRC = ${CHIBIOS}/os/hal/platforms/common/ARMCMx/nvic.c \ - ${CHIBIOS}/os/hal/platforms/STM32F0xx/stm32_dma.c \ - ${CHIBIOS}/os/hal/platforms/STM32F0xx/hal_lld.c \ - ${CHIBIOS}/os/hal/platforms/STM32F0xx/adc_lld.c \ - ${CHIBIOS}/os/hal/platforms/STM32F0xx/ext_lld_isr.c \ - ${CHIBIOS}/os/hal/platforms/STM32/ext_lld.c \ - ${CHIBIOS}/os/hal/platforms/STM32/GPIOv2/pal_lld.c \ - ${CHIBIOS}/os/hal/platforms/STM32/I2Cv2/i2c_lld.c \ - ${CHIBIOS}/os/hal/platforms/STM32/SPIv2/spi_lld.c \ - ${CHIBIOS}/os/hal/platforms/STM32/TIMv1/gpt_lld.c \ - ${CHIBIOS}/os/hal/platforms/STM32/TIMv1/icu_lld.c \ - ${CHIBIOS}/os/hal/platforms/STM32/TIMv1/pwm_lld.c \ - ${CHIBIOS}/os/hal/platforms/STM32/TIMv1/st_lld.c \ - ${CHIBIOS}/os/hal/platforms/STM32/USARTv2/serial_lld.c \ - ${CHIBIOS}/os/hal/platforms/STM32/USARTv2/uart_lld.c \ - ${CHIBIOS}/os/hal/platforms/STM32/USBv1/usb_lld.c - -# Required include directories -PLATFORMINC = ${CHIBIOS}/os/hal/platforms/common/ARMCMx \ - ${CHIBIOS}/os/hal/platforms/STM32F0xx \ - ${CHIBIOS}/os/hal/platforms/STM32 \ - ${CHIBIOS}/os/hal/platforms/STM32/GPIOv2 \ - ${CHIBIOS}/os/hal/platforms/STM32/I2Cv2 \ - ${CHIBIOS}/os/hal/platforms/STM32/SPIv2 \ - ${CHIBIOS}/os/hal/platforms/STM32/TIMv1 \ - ${CHIBIOS}/os/hal/platforms/STM32/USARTv2 \ - ${CHIBIOS}/os/hal/platforms/STM32/USBv1 diff --git a/os/hal/platforms/STM32F0xx/stm32_dma.c b/os/hal/platforms/STM32F0xx/stm32_dma.c deleted file mode 100644 index 623c9d11b..000000000 --- a/os/hal/platforms/STM32F0xx/stm32_dma.c +++ /dev/null @@ -1,291 +0,0 @@ -/* - ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file STM32F0xx/stm32_dma.c - * @brief DMA helper driver code. - * - * @addtogroup STM32F0xx_DMA - * @details DMA sharing helper driver. In the STM32 the DMA streams are a - * shared resource, this driver allows to allocate and free DMA - * streams at runtime in order to allow all the other device - * drivers to coordinate the access to the resource. - * @note The DMA ISR handlers are all declared into this module because - * sharing, the various device drivers can associate a callback to - * ISRs when allocating streams. - * @{ - */ - -#include "hal.h" - -/* The following macro is only defined if some driver requiring DMA services - has been enabled.*/ -#if defined(STM32_DMA_REQUIRED) || defined(__DOXYGEN__) - -/*===========================================================================*/ -/* Driver local definitions. */ -/*===========================================================================*/ - -/** - * @brief Mask of the DMA1 streams in @p dma_streams_mask. - */ -#define STM32_DMA1_STREAMS_MASK 0x0000007F - -/** - * @brief Mask of the DMA2 streams in @p dma_streams_mask. - */ -#define STM32_DMA2_STREAMS_MASK 0x00000F80 - -/** - * @brief Post-reset value of the stream CCR register. - */ -#define STM32_DMA_CCR_RESET_VALUE 0x00000000 - -/*===========================================================================*/ -/* Driver exported variables. */ -/*===========================================================================*/ - -/** - * @brief DMA streams descriptors. - * @details This table keeps the association between an unique stream - * identifier and the involved physical registers. - * @note Don't use this array directly, use the appropriate wrapper macros - * instead: @p STM32_DMA1_STREAM1, @p STM32_DMA1_STREAM2 etc. - */ -const stm32_dma_stream_t _stm32_dma_streams[STM32_DMA_STREAMS] = { - {DMA1_Channel1, &DMA1->IFCR, 0, 0, DMA1_Channel1_IRQn}, - {DMA1_Channel2, &DMA1->IFCR, 4, 1, DMA1_Channel2_3_IRQn}, - {DMA1_Channel3, &DMA1->IFCR, 8, 2, DMA1_Channel2_3_IRQn}, - {DMA1_Channel4, &DMA1->IFCR, 12, 3, DMA1_Channel4_5_IRQn}, - {DMA1_Channel5, &DMA1->IFCR, 16, 4, DMA1_Channel4_5_IRQn} -}; - -/*===========================================================================*/ -/* Driver local variables and types. */ -/*===========================================================================*/ - -/** - * @brief DMA ISR redirector type. - */ -typedef struct { - stm32_dmaisr_t dma_func; /**< @brief DMA callback function. */ - void *dma_param; /**< @brief DMA callback parameter. */ -} dma_isr_redir_t; - -/** - * @brief Mask of the allocated streams. - */ -static uint32_t dma_streams_mask; - -/** - * @brief DMA IRQ redirectors. - */ -static dma_isr_redir_t dma_isr_redir[STM32_DMA_STREAMS]; - -/*===========================================================================*/ -/* Driver local functions. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver interrupt handlers. */ -/*===========================================================================*/ - -/** - * @brief DMA1 stream 1 shared interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(Vector64) { - uint32_t flags; - - OSAL_IRQ_PROLOGUE(); - - flags = (DMA1->ISR >> 0) & STM32_DMA_ISR_MASK; - DMA1->IFCR = STM32_DMA_ISR_MASK << 0; - if (dma_isr_redir[0].dma_func) - dma_isr_redir[0].dma_func(dma_isr_redir[0].dma_param, flags); - - OSAL_IRQ_EPILOGUE(); -} - -/** - * @brief DMA1 streams 2 and 3 shared interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(Vector68) { - uint32_t flags; - - OSAL_IRQ_PROLOGUE(); - - /* Check on channel 2.*/ - flags = (DMA1->ISR >> 4) & STM32_DMA_ISR_MASK; - if (flags & STM32_DMA_ISR_MASK) { - DMA1->IFCR = STM32_DMA_ISR_MASK << 4; - if (dma_isr_redir[1].dma_func) - dma_isr_redir[1].dma_func(dma_isr_redir[1].dma_param, flags); - } - - /* Check on channel 3.*/ - flags = (DMA1->ISR >> 8) & STM32_DMA_ISR_MASK; - if (flags & STM32_DMA_ISR_MASK) { - DMA1->IFCR = STM32_DMA_ISR_MASK << 8; - if (dma_isr_redir[2].dma_func) - dma_isr_redir[2].dma_func(dma_isr_redir[2].dma_param, flags); - } - - OSAL_IRQ_EPILOGUE(); -} - -/** - * @brief DMA1 streams 4 and 5 shared interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(Vector6C) { - uint32_t flags; - - OSAL_IRQ_PROLOGUE(); - - /* Check on channel 4.*/ - flags = (DMA1->ISR >> 12) & STM32_DMA_ISR_MASK; - if (flags & STM32_DMA_ISR_MASK) { - DMA1->IFCR = STM32_DMA_ISR_MASK << 12; - if (dma_isr_redir[3].dma_func) - dma_isr_redir[3].dma_func(dma_isr_redir[3].dma_param, flags); - } - - /* Check on channel 5.*/ - flags = (DMA1->ISR >> 16) & STM32_DMA_ISR_MASK; - if (flags & STM32_DMA_ISR_MASK) { - DMA1->IFCR = STM32_DMA_ISR_MASK << 16; - if (dma_isr_redir[4].dma_func) - dma_isr_redir[4].dma_func(dma_isr_redir[4].dma_param, flags); - } - - OSAL_IRQ_EPILOGUE(); -} - -/*===========================================================================*/ -/* Driver exported functions. */ -/*===========================================================================*/ - -/** - * @brief STM32 DMA helper initialization. - * - * @init - */ -void dmaInit(void) { - int i; - - dma_streams_mask = 0; - for (i = 0; i < STM32_DMA_STREAMS; i++) { - _stm32_dma_streams[i].channel->CCR = 0; - dma_isr_redir[i].dma_func = NULL; - } - DMA1->IFCR = 0xFFFFFFFF; -} - -/** - * @brief Allocates a DMA stream. - * @details The stream is allocated and, if required, the DMA clock enabled. - * The function also enables the IRQ vector associated to the stream - * and initializes its priority. - * @pre The stream must not be already in use or an error is returned. - * @post The stream is allocated and the default ISR handler redirected - * to the specified function. - * @post The stream ISR vector is enabled and its priority configured. - * @post The stream must be freed using @p dmaStreamRelease() before it can - * be reused with another peripheral. - * @post The stream is in its post-reset state. - * @note This function can be invoked in both ISR or thread context. - * - * @param[in] dmastp pointer to a stm32_dma_stream_t structure - * @param[in] priority IRQ priority mask for the DMA stream - * @param[in] func handling function pointer, can be @p NULL - * @param[in] param a parameter to be passed to the handling function - * @return The operation status. - * @retval FALSE no error, stream taken. - * @retval TRUE error, stream already taken. - * - * @special - */ -bool_t dmaStreamAllocate(const stm32_dma_stream_t *dmastp, - uint32_t priority, - stm32_dmaisr_t func, - void *param) { - - osalDbgCheck(dmastp != NULL); - - /* Checks if the stream is already taken.*/ - if ((dma_streams_mask & (1 << dmastp->selfindex)) != 0) - return TRUE; - - /* Marks the stream as allocated.*/ - dma_isr_redir[dmastp->selfindex].dma_func = func; - dma_isr_redir[dmastp->selfindex].dma_param = param; - dma_streams_mask |= (1 << dmastp->selfindex); - - /* Enabling DMA clocks required by the current streams set.*/ - if ((dma_streams_mask & STM32_DMA1_STREAMS_MASK) != 0) - rccEnableDMA1(FALSE); - - /* Putting the stream in a safe state.*/ - dmaStreamDisable(dmastp); - dmastp->channel->CCR = STM32_DMA_CCR_RESET_VALUE; - - /* Enables the associated IRQ vector if a callback is defined.*/ - if (func != NULL) - nvicEnableVector(dmastp->vector, priority); - - return FALSE; -} - -/** - * @brief Releases a DMA stream. - * @details The stream is freed and, if required, the DMA clock disabled. - * Trying to release a unallocated stream is an illegal operation - * and is trapped if assertions are enabled. - * @pre The stream must have been allocated using @p dmaStreamAllocate(). - * @post The stream is again available. - * @note This function can be invoked in both ISR or thread context. - * - * @param[in] dmastp pointer to a stm32_dma_stream_t structure - * - * @special - */ -void dmaStreamRelease(const stm32_dma_stream_t *dmastp) { - - osalDbgCheck(dmastp != NULL); - - /* Check if the streams is not taken.*/ - osalDbgAssert((dma_streams_mask & (1 << dmastp->selfindex)) != 0, - "not allocated"); - - /* Disables the associated IRQ vector.*/ - nvicDisableVector(dmastp->vector); - - /* Marks the stream as not allocated.*/ - dma_streams_mask &= ~(1 << dmastp->selfindex); - - /* Shutting down clocks that are no more required, if any.*/ - if ((dma_streams_mask & STM32_DMA1_STREAMS_MASK) == 0) - rccDisableDMA1(FALSE); -} - -#endif /* STM32_DMA_REQUIRED */ - -/** @} */ diff --git a/os/hal/platforms/STM32F0xx/stm32_dma.h b/os/hal/platforms/STM32F0xx/stm32_dma.h deleted file mode 100644 index 277ebf4d4..000000000 --- a/os/hal/platforms/STM32F0xx/stm32_dma.h +++ /dev/null @@ -1,394 +0,0 @@ -/* - ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file STM32F0xx/stm32_dma.h - * @brief DMA helper driver header. - * @note This file requires definitions from the ST header file stm32f0xx.h. - * @note This driver uses the new naming convention used for the STM32F2xx - * so the "DMA channels" are referred as "DMA streams". - * - * @addtogroup STM32F0xx_DMA - * @{ - */ - -#ifndef _STM32_DMA_H_ -#define _STM32_DMA_H_ - -/*===========================================================================*/ -/* Driver constants. */ -/*===========================================================================*/ - -/** - * @brief Total number of DMA streams. - * @note This is the total number of streams among all the DMA units. - */ -#define STM32_DMA_STREAMS 5 - -/** - * @brief Mask of the ISR bits passed to the DMA callback functions. - */ -#define STM32_DMA_ISR_MASK 0x0F - -/** - * @brief Returns the channel associated to the specified stream. - * - * @param[in] n the stream number (0...STM32_DMA_STREAMS-1) - * @param[in] c a stream/channel association word, one channel per - * nibble, not associated channels must be set to 0xF - * @return Always zero, in this platform there is no dynamic - * association between streams and channels. - */ -#define STM32_DMA_GETCHANNEL(n, c) 0 - -/** - * @brief Checks if a DMA priority is within the valid range. - * @param[in] prio DMA priority - * - * @retval The check result. - * @retval FALSE invalid DMA priority. - * @retval TRUE correct DMA priority. - */ -#define STM32_DMA_IS_VALID_PRIORITY(prio) (((prio) >= 0) && ((prio) <= 3)) - -/** - * @brief Returns an unique numeric identifier for a DMA stream. - * - * @param[in] dma the DMA unit number - * @param[in] stream the stream number - * @return An unique numeric stream identifier. - */ -#define STM32_DMA_STREAM_ID(dma, stream) ((stream) - 1) - -/** - * @brief Returns a DMA stream identifier mask. - * - * - * @param[in] dma the DMA unit number - * @param[in] stream the stream number - * @return A DMA stream identifier mask. - */ -#define STM32_DMA_STREAM_ID_MSK(dma, stream) \ - (1 << STM32_DMA_STREAM_ID(dma, stream)) - -/** - * @brief Checks if a DMA stream unique identifier belongs to a mask. - * @param[in] id the stream numeric identifier - * @param[in] mask the stream numeric identifiers mask - * - * @retval The check result. - * @retval FALSE id does not belong to the mask. - * @retval TRUE id belongs to the mask. - */ -#define STM32_DMA_IS_VALID_ID(id, mask) (((1 << (id)) & (mask))) - -/** - * @name DMA streams identifiers - * @{ - */ -/** - * @brief Returns a pointer to a stm32_dma_stream_t structure. - * - * @param[in] id the stream numeric identifier - * @return A pointer to the stm32_dma_stream_t constant structure - * associated to the DMA stream. - */ -#define STM32_DMA_STREAM(id) (&_stm32_dma_streams[id]) - -#define STM32_DMA1_STREAM1 STM32_DMA_STREAM(0) -#define STM32_DMA1_STREAM2 STM32_DMA_STREAM(1) -#define STM32_DMA1_STREAM3 STM32_DMA_STREAM(2) -#define STM32_DMA1_STREAM4 STM32_DMA_STREAM(3) -#define STM32_DMA1_STREAM5 STM32_DMA_STREAM(4) -/** @} */ - -/** - * @name CR register constants common to all DMA types - * @{ - */ -#define STM32_DMA_CR_EN DMA_CCR_EN -#define STM32_DMA_CR_TEIE DMA_CCR_TEIE -#define STM32_DMA_CR_HTIE DMA_CCR_HTIE -#define STM32_DMA_CR_TCIE DMA_CCR_TCIE -#define STM32_DMA_CR_DIR_MASK (DMA_CCR_DIR | DMA_CCR_MEM2MEM) -#define STM32_DMA_CR_DIR_P2M 0 -#define STM32_DMA_CR_DIR_M2P DMA_CCR_DIR -#define STM32_DMA_CR_DIR_M2M DMA_CCR_MEM2MEM -#define STM32_DMA_CR_CIRC DMA_CCR_CIRC -#define STM32_DMA_CR_PINC DMA_CCR_PINC -#define STM32_DMA_CR_MINC DMA_CCR_MINC -#define STM32_DMA_CR_PSIZE_MASK DMA_CCR_PSIZE -#define STM32_DMA_CR_PSIZE_BYTE 0 -#define STM32_DMA_CR_PSIZE_HWORD DMA_CCR_PSIZE_0 -#define STM32_DMA_CR_PSIZE_WORD DMA_CCR_PSIZE_1 -#define STM32_DMA_CR_MSIZE_MASK DMA_CCR_MSIZE -#define STM32_DMA_CR_MSIZE_BYTE 0 -#define STM32_DMA_CR_MSIZE_HWORD DMA_CCR_MSIZE_0 -#define STM32_DMA_CR_MSIZE_WORD DMA_CCR_MSIZE_1 -#define STM32_DMA_CR_SIZE_MASK (STM32_DMA_CR_PSIZE_MASK | \ - STM32_DMA_CR_MSIZE_MASK) -#define STM32_DMA_CR_PL_MASK DMA_CCR_PL -#define STM32_DMA_CR_PL(n) ((n) << 12) -/** @} */ - -/** - * @name CR register constants only found in enhanced DMA - * @{ - */ -#define STM32_DMA_CR_DMEIE 0 /**< @brief Ignored by normal DMA. */ -#define STM32_DMA_CR_CHSEL_MASK 0 /**< @brief Ignored by normal DMA. */ -#define STM32_DMA_CR_CHSEL(n) 0 /**< @brief Ignored by normal DMA. */ -/** @} */ - -/** - * @name Status flags passed to the ISR callbacks - * @{ - */ -#define STM32_DMA_ISR_FEIF 0 -#define STM32_DMA_ISR_DMEIF 0 -#define STM32_DMA_ISR_TEIF DMA_ISR_TEIF1 -#define STM32_DMA_ISR_HTIF DMA_ISR_HTIF1 -#define STM32_DMA_ISR_TCIF DMA_ISR_TCIF1 -/** @} */ - -/*===========================================================================*/ -/* Driver pre-compile time settings. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Derived constants and error checks. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver data structures and types. */ -/*===========================================================================*/ - -/** - * @brief STM32 DMA stream descriptor structure. - */ -typedef struct { - DMA_Channel_TypeDef *channel; /**< @brief Associated DMA channel. */ - volatile uint32_t *ifcr; /**< @brief Associated IFCR reg. */ - uint8_t ishift; /**< @brief Bits offset in xIFCR - register. */ - uint8_t selfindex; /**< @brief Index to self in array. */ - uint8_t vector; /**< @brief Associated IRQ vector. */ -} stm32_dma_stream_t; - -/** - * @brief STM32 DMA ISR function type. - * - * @param[in] p parameter for the registered function - * @param[in] flags pre-shifted content of the ISR register, the bits - * are aligned to bit zero - */ -typedef void (*stm32_dmaisr_t)(void *p, uint32_t flags); - -/*===========================================================================*/ -/* Driver macros. */ -/*===========================================================================*/ - -/** - * @name Macro Functions - * @{ - */ -/** - * @brief Associates a peripheral data register to a DMA stream. - * @note This function can be invoked in both ISR or thread context. - * @pre The stream must have been allocated using @p dmaStreamAllocate(). - * @post After use the stream can be released using @p dmaStreamRelease(). - * - * @param[in] dmastp pointer to a stm32_dma_stream_t structure - * @param[in] addr value to be written in the CPAR register - * - * @special - */ -#define dmaStreamSetPeripheral(dmastp, addr) { \ - (dmastp)->channel->CPAR = (uint32_t)(addr); \ -} - -/** - * @brief Associates a memory destination to a DMA stream. - * @note This function can be invoked in both ISR or thread context. - * @pre The stream must have been allocated using @p dmaStreamAllocate(). - * @post After use the stream can be released using @p dmaStreamRelease(). - * - * @param[in] dmastp pointer to a stm32_dma_stream_t structure - * @param[in] addr value to be written in the CMAR register - * - * @special - */ -#define dmaStreamSetMemory0(dmastp, addr) { \ - (dmastp)->channel->CMAR = (uint32_t)(addr); \ -} - -/** - * @brief Sets the number of transfers to be performed. - * @note This function can be invoked in both ISR or thread context. - * @pre The stream must have been allocated using @p dmaStreamAllocate(). - * @post After use the stream can be released using @p dmaStreamRelease(). - * - * @param[in] dmastp pointer to a stm32_dma_stream_t structure - * @param[in] size value to be written in the CNDTR register - * - * @special - */ -#define dmaStreamSetTransactionSize(dmastp, size) { \ - (dmastp)->channel->CNDTR = (uint32_t)(size); \ -} - -/** - * @brief Returns the number of transfers to be performed. - * @note This function can be invoked in both ISR or thread context. - * @pre The stream must have been allocated using @p dmaStreamAllocate(). - * @post After use the stream can be released using @p dmaStreamRelease(). - * - * @param[in] dmastp pointer to a stm32_dma_stream_t structure - * @return The number of transfers to be performed. - * - * @special - */ -#define dmaStreamGetTransactionSize(dmastp) ((size_t)((dmastp)->channel->CNDTR)) - -/** - * @brief Programs the stream mode settings. - * @note This function can be invoked in both ISR or thread context. - * @pre The stream must have been allocated using @p dmaStreamAllocate(). - * @post After use the stream can be released using @p dmaStreamRelease(). - * - * @param[in] dmastp pointer to a stm32_dma_stream_t structure - * @param[in] mode value to be written in the CCR register - * - * @special - */ -#define dmaStreamSetMode(dmastp, mode) { \ - (dmastp)->channel->CCR = (uint32_t)(mode); \ -} - -/** - * @brief DMA stream enable. - * @note This function can be invoked in both ISR or thread context. - * @pre The stream must have been allocated using @p dmaStreamAllocate(). - * @post After use the stream can be released using @p dmaStreamRelease(). - * - * @param[in] dmastp pointer to a stm32_dma_stream_t structure - * - * @special - */ -#define dmaStreamEnable(dmastp) { \ - (dmastp)->channel->CCR |= STM32_DMA_CR_EN; \ -} - -/** - * @brief DMA stream disable. - * @details The function disables the specified stream and then clears any - * pending interrupt. - * @note This function can be invoked in both ISR or thread context. - * @note Interrupts enabling flags are set to zero after this call, see - * bug 3607518. - * @pre The stream must have been allocated using @p dmaStreamAllocate(). - * @post After use the stream can be released using @p dmaStreamRelease(). - * - * @param[in] dmastp pointer to a stm32_dma_stream_t structure - * - * @special - */ -#define dmaStreamDisable(dmastp) { \ - (dmastp)->channel->CCR &= ~(STM32_DMA_CR_TCIE | STM32_DMA_CR_HTIE | \ - STM32_DMA_CR_TEIE | STM32_DMA_CR_EN); \ - dmaStreamClearInterrupt(dmastp); \ -} - -/** - * @brief DMA stream interrupt sources clear. - * @note This function can be invoked in both ISR or thread context. - * @pre The stream must have been allocated using @p dmaStreamAllocate(). - * @post After use the stream can be released using @p dmaStreamRelease(). - * - * @param[in] dmastp pointer to a stm32_dma_stream_t structure - * - * @special - */ -#define dmaStreamClearInterrupt(dmastp) { \ - *(dmastp)->ifcr = STM32_DMA_ISR_MASK << (dmastp)->ishift; \ -} - -/** - * @brief Starts a memory to memory operation using the specified stream. - * @note The default transfer data mode is "byte to byte" but it can be - * changed by specifying extra options in the @p mode parameter. - * @pre The stream must have been allocated using @p dmaStreamAllocate(). - * @post After use the stream can be released using @p dmaStreamRelease(). - * - * @param[in] dmastp pointer to a stm32_dma_stream_t structure - * @param[in] mode value to be written in the CCR register, this value - * is implicitly ORed with: - * - @p STM32_DMA_CR_MINC - * - @p STM32_DMA_CR_PINC - * - @p STM32_DMA_CR_DIR_M2M - * - @p STM32_DMA_CR_EN - * . - * @param[in] src source address - * @param[in] dst destination address - * @param[in] n number of data units to copy - */ -#define dmaStartMemCopy(dmastp, mode, src, dst, n) { \ - dmaStreamSetPeripheral(dmastp, src); \ - dmaStreamSetMemory0(dmastp, dst); \ - dmaStreamSetTransactionSize(dmastp, n); \ - dmaStreamSetMode(dmastp, (mode) | \ - STM32_DMA_CR_MINC | STM32_DMA_CR_PINC | \ - STM32_DMA_CR_DIR_M2M | STM32_DMA_CR_EN); \ -} - -/** - * @brief Polled wait for DMA transfer end. - * @pre The stream must have been allocated using @p dmaStreamAllocate(). - * @post After use the stream can be released using @p dmaStreamRelease(). - * - * @param[in] dmastp pointer to a stm32_dma_stream_t structure - */ -#define dmaWaitCompletion(dmastp) { \ - while ((dmastp)->channel->CNDTR > 0) \ - ; \ - dmaStreamDisable(dmastp); \ -} -/** @} */ - -/*===========================================================================*/ -/* External declarations. */ -/*===========================================================================*/ - -#if !defined(__DOXYGEN__) -extern const stm32_dma_stream_t _stm32_dma_streams[STM32_DMA_STREAMS]; -#endif - -#ifdef __cplusplus -extern "C" { -#endif - void dmaInit(void); - bool_t dmaStreamAllocate(const stm32_dma_stream_t *dmastp, - uint32_t priority, - stm32_dmaisr_t func, - void *param); - void dmaStreamRelease(const stm32_dma_stream_t *dmastp); -#ifdef __cplusplus -} -#endif - -#endif /* _STM32_DMA_H_ */ - -/** @} */ diff --git a/os/hal/platforms/STM32F0xx/stm32_isr.h b/os/hal/platforms/STM32F0xx/stm32_isr.h deleted file mode 100644 index 52421a4d5..000000000 --- a/os/hal/platforms/STM32F0xx/stm32_isr.h +++ /dev/null @@ -1,91 +0,0 @@ -/* - ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file STM32F0xx/stm32_isr.h - * @brief ISR remapper driver header. - * - * @addtogroup STM32F0xx_ISR - * @{ - */ - -#ifndef _STM32_ISR_H_ -#define _STM32_ISR_H_ - -/*===========================================================================*/ -/* Driver constants. */ -/*===========================================================================*/ - -/** - * @name ISR names and numbers remapping - * @{ - */ - -/* - * I2C units. - */ -#define STM32_I2C1_GLOBAL_HANDLER Vector9C -#define STM32_I2C1_GLOBAL_NUMBER 23 - -#define STM32_I2C2_GLOBAL_HANDLER VectorA0 -#define STM32_I2C2_GLOBAL_NUMBER 24 - -/* - * TIM units. - */ -#define STM32_TIM1_UP_HANDLER Vector74 -#define STM32_TIM1_CC_HANDLER Vector78 -#define STM32_TIM2_HANDLER Vector7C -#define STM32_TIM3_HANDLER Vector80 - -#define STM32_TIM1_UP_NUMBER 13 -#define STM32_TIM1_CC_NUMBER 14 -#define STM32_TIM2_NUMBER 15 -#define STM32_TIM3_NUMBER 16 - -/* - * USART units. - */ -#define STM32_USART1_HANDLER VectorAC -#define STM32_USART2_HANDLER VectorB0 - -#define STM32_USART1_NUMBER 27 -#define STM32_USART2_NUMBER 28 -/** @} */ - -/*===========================================================================*/ -/* Driver pre-compile time settings. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Derived constants and error checks. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver data structures and types. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver macros. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* External declarations. */ -/*===========================================================================*/ - -#endif /* _STM32_ISR_H_ */ - -/** @} */ diff --git a/os/hal/platforms/STM32F0xx/stm32_rcc.h b/os/hal/platforms/STM32F0xx/stm32_rcc.h deleted file mode 100644 index 88e47f2c0..000000000 --- a/os/hal/platforms/STM32F0xx/stm32_rcc.h +++ /dev/null @@ -1,596 +0,0 @@ -/* - ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file STM32F0xx/stm32_rcc.h - * @brief RCC helper driver header. - * @note This file requires definitions from the ST header file - * @p stm32f0xx.h. - * - * @addtogroup STM32F0xx_RCC - * @{ - */ - -#ifndef _STM32_RCC_ -#define _STM32_RCC_ - -/*===========================================================================*/ -/* Driver constants. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver pre-compile time settings. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Derived constants and error checks. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver data structures and types. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver macros. */ -/*===========================================================================*/ - -/** - * @name Generic RCC operations - * @{ - */ -/** - * @brief Enables the clock of one or more peripheral on the APB1 bus. - * @note The @p lp parameter is ignored in this family. - * - * @param[in] mask APB1 peripherals mask - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableAPB1(mask, lp) { \ - RCC->APB1ENR |= (mask); \ -} - -/** - * @brief Disables the clock of one or more peripheral on the APB1 bus. - * @note The @p lp parameter is ignored in this family. - * - * @param[in] mask APB1 peripherals mask - * @param[in] lp low power enable flag - * - * @api - */ -#define rccDisableAPB1(mask, lp) { \ - RCC->APB1ENR &= ~(mask); \ -} - -/** - * @brief Resets one or more peripheral on the APB1 bus. - * - * @param[in] mask APB1 peripherals mask - * - * @api - */ -#define rccResetAPB1(mask) { \ - RCC->APB1RSTR |= (mask); \ - RCC->APB1RSTR = 0; \ -} - -/** - * @brief Enables the clock of one or more peripheral on the APB2 bus. - * @note The @p lp parameter is ignored in this family. - * - * @param[in] mask APB2 peripherals mask - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableAPB2(mask, lp) { \ - RCC->APB2ENR |= (mask); \ -} - -/** - * @brief Disables the clock of one or more peripheral on the APB2 bus. - * @note The @p lp parameter is ignored in this family. - * - * @param[in] mask APB2 peripherals mask - * @param[in] lp low power enable flag - * - * @api - */ -#define rccDisableAPB2(mask, lp) { \ - RCC->APB2ENR &= ~(mask); \ -} - -/** - * @brief Resets one or more peripheral on the APB2 bus. - * - * @param[in] mask APB2 peripherals mask - * - * @api - */ -#define rccResetAPB2(mask) { \ - RCC->APB2RSTR |= (mask); \ - RCC->APB2RSTR = 0; \ -} - -/** - * @brief Enables the clock of one or more peripheral on the AHB bus. - * @note The @p lp parameter is ignored in this family. - * - * @param[in] mask AHB peripherals mask - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableAHB(mask, lp) { \ - RCC->AHBENR |= (mask); \ -} - -/** - * @brief Disables the clock of one or more peripheral on the AHB bus. - * @note The @p lp parameter is ignored in this family. - * - * @param[in] mask AHB peripherals mask - * @param[in] lp low power enable flag - * - * @api - */ -#define rccDisableAHB(mask, lp) { \ - RCC->AHBENR &= ~(mask); \ -} - -/** - * @brief Resets one or more peripheral on the AHB bus. - * - * @param[in] mask AHB peripherals mask - * - * @api - */ -#define rccResetAHB(mask) { \ - RCC->AHBRSTR |= (mask); \ - RCC->AHBRSTR = 0; \ -} -/** @} */ - -/** - * @name ADC peripherals specific RCC operations - * @{ - */ -/** - * @brief Enables the ADC1 peripheral clock. - * @note The @p lp parameter is ignored in this family. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableADC1(lp) rccEnableAPB2(RCC_APB2ENR_ADC1EN, lp) - -/** - * @brief Disables the ADC1 peripheral clock. - * @note The @p lp parameter is ignored in this family. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccDisableADC1(lp) rccDisableAPB2(RCC_APB2ENR_ADC1EN, lp) - -/** - * @brief Resets the ADC1 peripheral. - * - * @api - */ -#define rccResetADC1() rccResetAPB2(RCC_APB2RSTR_ADC1RST) -/** @} */ - -/** - * @name PWR interface specific RCC operations - * @{ - */ -/** - * @brief Enables the PWR interface clock. - * @note The @p lp parameter is ignored in this family. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnablePWRInterface(lp) rccEnableAPB1(RCC_APB1ENR_PWREN, lp) - -/** - * @brief Disables PWR interface clock. - * @note The @p lp parameter is ignored in this family. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccDisablePWRInterface(lp) rccDisableAPB1(RCC_APB1ENR_PWREN, lp) - -/** - * @brief Resets the PWR interface. - * - * @api - */ -#define rccResetPWRInterface() rccResetAPB1(RCC_APB1RSTR_PWRRST) -/** @} */ - -/** - * @name DMA peripherals specific RCC operations - * @{ - */ -/** - * @brief Enables the DMA1 peripheral clock. - * @note The @p lp parameter is ignored in this family. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableDMA1(lp) rccEnableAHB(RCC_AHBENR_DMA1EN, lp) - -/** - * @brief Disables the DMA1 peripheral clock. - * @note The @p lp parameter is ignored in this family. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccDisableDMA1(lp) rccDisableAHB(RCC_AHBENR_DMA1EN, lp) - -/** - * @brief Resets the DMA1 peripheral. - * @note Not supported in this family, does nothing. - * - * @api - */ -#define rccResetDMA1() -/** @} */ - -/** - * @name I2C peripherals specific RCC operations - * @{ - */ -/** - * @brief Enables the I2C1 peripheral clock. - * @note The @p lp parameter is ignored in this family. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableI2C1(lp) rccEnableAPB1(RCC_APB1ENR_I2C1EN, lp) - -/** - * @brief Disables the I2C1 peripheral clock. - * @note The @p lp parameter is ignored in this family. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccDisableI2C1(lp) rccDisableAPB1(RCC_APB1ENR_I2C1EN, lp) - -/** - * @brief Resets the I2C1 peripheral. - * - * @api - */ -#define rccResetI2C1() rccResetAPB1(RCC_APB1RSTR_I2C1RST) - -/** - * @brief Enables the I2C2 peripheral clock. - * @note The @p lp parameter is ignored in this family. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableI2C2(lp) rccEnableAPB1(RCC_APB1ENR_I2C2EN, lp) - -/** - * @brief Disables the I2C2 peripheral clock. - * @note The @p lp parameter is ignored in this family. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccDisableI2C2(lp) rccDisableAPB1(RCC_APB1ENR_I2C2EN, lp) - -/** - * @brief Resets the I2C2 peripheral. - * - * @api - */ -#define rccResetI2C2() rccResetAPB1(RCC_APB1RSTR_I2C2RST) -/** @} */ - -/** - * @name SPI peripherals specific RCC operations - * @{ - */ -/** - * @brief Enables the SPI1 peripheral clock. - * @note The @p lp parameter is ignored in this family. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableSPI1(lp) rccEnableAPB2(RCC_APB2ENR_SPI1EN, lp) - -/** - * @brief Disables the SPI1 peripheral clock. - * @note The @p lp parameter is ignored in this family. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccDisableSPI1(lp) rccDisableAPB2(RCC_APB2ENR_SPI1EN, lp) - -/** - * @brief Resets the SPI1 peripheral. - * - * @api - */ -#define rccResetSPI1() rccResetAPB2(RCC_APB2RSTR_SPI1RST) - -/** - * @brief Enables the SPI2 peripheral clock. - * @note The @p lp parameter is ignored in this family. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableSPI2(lp) rccEnableAPB1(RCC_APB1ENR_SPI2EN, lp) - -/** - * @brief Disables the SPI2 peripheral clock. - * @note The @p lp parameter is ignored in this family. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccDisableSPI2(lp) rccDisableAPB1(RCC_APB1ENR_SPI2EN, lp) - -/** - * @brief Resets the SPI2 peripheral. - * - * @api - */ -#define rccResetSPI2() rccResetAPB1(RCC_APB1RSTR_SPI2RST) -/** @} */ - -/** - * @name TIM peripherals specific RCC operations - * @{ - */ -/** - * @brief Enables the TIM1 peripheral clock. - * @note The @p lp parameter is ignored in this family. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableTIM1(lp) rccEnableAPB2(RCC_APB2ENR_TIM1EN, lp) - -/** - * @brief Disables the TIM1 peripheral clock. - * @note The @p lp parameter is ignored in this family. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccDisableTIM1(lp) rccDisableAPB2(RCC_APB2ENR_TIM1EN, lp) - -/** - * @brief Resets the TIM1 peripheral. - * - * @api - */ -#define rccResetTIM1() rccResetAPB2(RCC_APB2RSTR_TIM1RST) - -/** - * @brief Enables the TIM2 peripheral clock. - * @note The @p lp parameter is ignored in this family. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableTIM2(lp) rccEnableAPB1(RCC_APB1ENR_TIM2EN, lp) - -/** - * @brief Disables the TIM2 peripheral clock. - * @note The @p lp parameter is ignored in this family. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccDisableTIM2(lp) rccDisableAPB1(RCC_APB1ENR_TIM2EN, lp) - -/** - * @brief Resets the TIM2 peripheral. - * - * @api - */ -#define rccResetTIM2() rccResetAPB1(RCC_APB1RSTR_TIM2RST) - -/** - * @brief Enables the TIM3 peripheral clock. - * @note The @p lp parameter is ignored in this family. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableTIM3(lp) rccEnableAPB1(RCC_APB1ENR_TIM3EN, lp) - -/** - * @brief Disables the TIM3 peripheral clock. - * @note The @p lp parameter is ignored in this family. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccDisableTIM3(lp) rccDisableAPB1(RCC_APB1ENR_TIM3EN, lp) - -/** - * @brief Resets the TIM3 peripheral. - * - * @api - */ -#define rccResetTIM3() rccResetAPB1(RCC_APB1RSTR_TIM3RST) -/** @} */ - -/** - * @name USART/UART peripherals specific RCC operations - * @{ - */ -/** - * @brief Enables the USART1 peripheral clock. - * @note The @p lp parameter is ignored in this family. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableUSART1(lp) rccEnableAPB2(RCC_APB2ENR_USART1EN, lp) - -/** - * @brief Disables the USART1 peripheral clock. - * @note The @p lp parameter is ignored in this family. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccDisableUSART1(lp) rccDisableAPB2(RCC_APB2ENR_USART1EN, lp) - -/** - * @brief Resets the USART1 peripheral. - * - * @api - */ -#define rccResetUSART1() rccResetAPB2(RCC_APB2RSTR_USART1RST) - -/** - * @brief Enables the USART2 peripheral clock. - * @note The @p lp parameter is ignored in this family. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableUSART2(lp) rccEnableAPB1(RCC_APB1ENR_USART2EN, lp) - -/** - * @brief Disables the USART2 peripheral clock. - * @note The @p lp parameter is ignored in this family. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccDisableUSART2(lp) rccDisableAPB1(RCC_APB1ENR_USART2EN, lp) - -/** - * @brief Resets the USART2 peripheral. - * - * @api - */ -#define rccResetUSART2() rccResetAPB1(RCC_APB1RSTR_USART2RST) - -/** - * @brief Enables the CRC peripheral clock. - * @note The @p lp parameter is ignored in this family. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableCRC(lp) rccEnableAHB(RCC_AHBENR_CRCEN, lp) - -/** - * @brief Disables the CRC peripheral clock. - * @note The @p lp parameter is ignored in this family. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccDisableCRC(lp) rccDisableAHB(RCC_AHBENR_CRCEN, lp) - -/** - * @brief Resets the CRC peripheral. - * - * @api - */ -#define rccResetCRC() rccResetAHB(RCC_AHBRSTR_CRCRST) - -/** - * @brief Enables the WWDG peripheral clock. - * @note The @p lp parameter is ignored in this family. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableWWDG(lp) rccEnableAPB1(RCC_APB1ENR_WWDGEN, lp) - -/** - * @brief Disables the WWDG peripheral clock. - * @note The @p lp parameter is ignored in this family. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccDisableWWDG(lp) rccDisableAPB1(RCC_APB1ENR_WWDGEN, lp) - -/** - * @brief Resets the WWDG peripheral. - * - * @api - */ -#define rccResetWWDG() rccResetAPB1(RCC_APB1RSTR_WWDGRST) -/** @} */ - -/*===========================================================================*/ -/* External declarations. */ -/*===========================================================================*/ - -#ifdef __cplusplus -extern "C" { -#endif -#ifdef __cplusplus -} -#endif - -#endif /* _STM32_RCC_ */ - -/** @} */ diff --git a/os/hal/platforms/STM32F0xx/stm32_registry.h b/os/hal/platforms/STM32F0xx/stm32_registry.h deleted file mode 100644 index 0b12f7bb0..000000000 --- a/os/hal/platforms/STM32F0xx/stm32_registry.h +++ /dev/null @@ -1,168 +0,0 @@ -/* - ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file STM32F0xx/stm32_registry.h - * @brief STM32F0xx capabilities registry. - * - * @addtogroup HAL - * @{ - */ - -#ifndef _STM32_REGISTRY_H_ -#define _STM32_REGISTRY_H_ - -/*===========================================================================*/ -/* Platform capabilities. */ -/*===========================================================================*/ - -/** - * @name STM32F0xx capabilities - * @{ - */ -/* ADC attributes.*/ -#define STM32_HAS_ADC1 TRUE -#define STM32_HAS_ADC2 FALSE -#define STM32_HAS_ADC3 FALSE -#define STM32_HAS_ADC4 FALSE - -/* CAN attributes.*/ -#define STM32_HAS_CAN1 FALSE -#define STM32_HAS_CAN2 FALSE - -/* DAC attributes.*/ -#define STM32_HAS_DAC TRUE - -/* DMA attributes.*/ -#define STM32_ADVANCED_DMA FALSE -#define STM32_HAS_DMA1 TRUE -#define STM32_HAS_DMA2 FALSE - -/* ETH attributes.*/ -#define STM32_HAS_ETH FALSE - -/* EXTI attributes.*/ -#define STM32_EXTI_NUM_CHANNELS 28 - -/* GPIO attributes.*/ -#define STM32_HAS_GPIOA TRUE -#define STM32_HAS_GPIOB TRUE -#define STM32_HAS_GPIOC TRUE -#define STM32_HAS_GPIOD TRUE -#define STM32_HAS_GPIOE FALSE -#define STM32_HAS_GPIOF TRUE -#define STM32_HAS_GPIOG FALSE -#define STM32_HAS_GPIOH FALSE -#define STM32_HAS_GPIOI FALSE - -/* I2C attributes.*/ -#define STM32_HAS_I2C1 TRUE -#define STM32_I2C_I2C1_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 3) -#define STM32_I2C_I2C1_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2) - -#define STM32_HAS_I2C2 TRUE -#define STM32_I2C_I2C2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 5) -#define STM32_I2C_I2C2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) - -#define STM32_HAS_I2C3 FALSE - -/* RTC attributes.*/ -#define STM32_HAS_RTC TRUE -#define STM32_RTC_HAS_SUBSECONDS FALSE -#define STM32_RTC_IS_CALENDAR TRUE - -/* SDIO attributes.*/ -#define STM32_HAS_SDIO FALSE - -/* SPI attributes.*/ -#define STM32_HAS_SPI1 TRUE -#define STM32_SPI_SPI1_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2) -#define STM32_SPI_SPI1_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 3) - -#define STM32_HAS_SPI2 TRUE -#define STM32_SPI_SPI2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) -#define STM32_SPI_SPI2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 5) - -#define STM32_HAS_SPI3 FALSE - -/* TIM attributes.*/ -#define STM32_HAS_TIM1 TRUE -#define STM32_TIM1_IS_32BITS FALSE -#define STM32_TIM1_CHANNELS 4 - -#define STM32_HAS_TIM2 TRUE -#define STM32_TIM2_IS_32BITS TRUE -#define STM32_TIM2_CHANNELS 4 - -#define STM32_HAS_TIM3 TRUE -#define STM32_TIM3_IS_32BITS FALSE -#define STM32_TIM3_CHANNELS 4 - -#define STM32_HAS_TIM6 TRUE -#define STM32_TIM6_IS_32BITS FALSE -#define STM32_TIM6_CHANNELS 0 - -#define STM32_HAS_TIM14 TRUE -#define STM32_TIM14_IS_32BITS FALSE -#define STM32_TIM14_CHANNELS 1 - -#define STM32_HAS_TIM15 TRUE -#define STM32_TIM15_IS_32BITS FALSE -#define STM32_TIM15_CHANNELS 2 - -#define STM32_HAS_TIM16 TRUE -#define STM32_TIM16_IS_32BITS FALSE -#define STM32_TIM16_CHANNELS 2 - -#define STM32_HAS_TIM17 TRUE -#define STM32_TIM17_IS_32BITS FALSE -#define STM32_TIM17_CHANNELS 2 - -#define STM32_HAS_TIM4 FALSE -#define STM32_HAS_TIM5 FALSE -#define STM32_HAS_TIM7 FALSE -#define STM32_HAS_TIM8 FALSE -#define STM32_HAS_TIM9 FALSE -#define STM32_HAS_TIM10 FALSE -#define STM32_HAS_TIM11 FALSE -#define STM32_HAS_TIM12 FALSE -#define STM32_HAS_TIM13 FALSE -#define STM32_HAS_TIM18 FALSE -#define STM32_HAS_TIM19 FALSE - -/* USART attributes.*/ -#define STM32_HAS_USART1 TRUE -#define STM32_UART_USART1_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 3) -#define STM32_UART_USART1_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2) - -#define STM32_HAS_USART2 TRUE -#define STM32_UART_USART2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 5) -#define STM32_UART_USART2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) - -#define STM32_HAS_USART3 FALSE -#define STM32_HAS_UART4 FALSE -#define STM32_HAS_UART5 FALSE -#define STM32_HAS_USART6 FALSE - -/* USB attributes.*/ -#define STM32_HAS_USB TRUE -#define STM32_HAS_OTG1 FALSE -#define STM32_HAS_OTG2 FALSE -/** @} */ - -#endif /* _STM32_REGISTRY_H_ */ - -/** @} */ diff --git a/os/hal/platforms/STM32F30x/adc_lld.c b/os/hal/platforms/STM32F30x/adc_lld.c deleted file mode 100644 index d516cf21b..000000000 --- a/os/hal/platforms/STM32F30x/adc_lld.c +++ /dev/null @@ -1,548 +0,0 @@ -/* - ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file STM32F30x/adc_lld.c - * @brief STM32F30x ADC subsystem low level driver source. - * - * @addtogroup ADC - * @{ - */ - -#include "hal.h" - -#if HAL_USE_ADC || defined(__DOXYGEN__) - -/*===========================================================================*/ -/* Driver local definitions. */ -/*===========================================================================*/ - -#if STM32_ADC_DUAL_MODE -#if STM32_ADC_COMPACT_SAMPLES -/* Compact type dual mode.*/ -#define ADC_DMA_SIZE (STM32_DMA_CR_MSIZE_HWORD | STM32_DMA_CR_PSIZE_HWORD) -#define ADC_DMA_MDMA ADC_CCR_MDMA_HWORD - -#else /* !STM32_ADC_COMPACT_SAMPLES */ -/* Large type dual mode.*/ -#define ADC_DMA_SIZE (STM32_DMA_CR_MSIZE_WORD | STM32_DMA_CR_PSIZE_WORD) -#define ADC_DMA_MDMA ADC_CCR_MDMA_WORD -#endif /* !STM32_ADC_COMPACT_SAMPLES */ - -#else /* !STM32_ADC_DUAL_MODE */ -#if STM32_ADC_COMPACT_SAMPLES -/* Compact type single mode.*/ -#define ADC_DMA_SIZE (STM32_DMA_CR_MSIZE_BYTE | STM32_DMA_CR_PSIZE_BYTE) -#define ADC_DMA_MDMA ADC_CCR_MDMA_DISABLED - -#else /* !STM32_ADC_COMPACT_SAMPLES */ -/* Large type single mode.*/ -#define ADC_DMA_SIZE (STM32_DMA_CR_MSIZE_HWORD | STM32_DMA_CR_PSIZE_HWORD) -#define ADC_DMA_MDMA ADC_CCR_MDMA_DISABLED -#endif /* !STM32_ADC_COMPACT_SAMPLES */ -#endif /* !STM32_ADC_DUAL_MODE */ - -/*===========================================================================*/ -/* Driver exported variables. */ -/*===========================================================================*/ - -/** @brief ADC1 driver identifier.*/ -#if STM32_ADC_USE_ADC1 || defined(__DOXYGEN__) -ADCDriver ADCD1; -#endif - -/** @brief ADC1 driver identifier.*/ -#if STM32_ADC_USE_ADC3 || defined(__DOXYGEN__) -ADCDriver ADCD3; -#endif - -/*===========================================================================*/ -/* Driver local variables and types. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver local functions. */ -/*===========================================================================*/ - -/** - * @brief Enables the ADC voltage regulator. - * - * @param[in] adcp pointer to the @p ADCDriver object - */ -static void adc_lld_vreg_on(ADCDriver *adcp) { - - adcp->adcm->CR = 0; /* RM 12.4.3.*/ - adcp->adcm->CR = ADC_CR_ADVREGEN_0; -#if STM32_ADC_DUAL_MODE - adcp->adcs->CR = ADC_CR_ADVREGEN_0; -#endif - osalSysPolledDelayX(US2RTC(10)); -} - -/** - * @brief Disables the ADC voltage regulator. - * - * @param[in] adcp pointer to the @p ADCDriver object - */ -static void adc_lld_vreg_off(ADCDriver *adcp) { - - adcp->adcm->CR = 0; /* RM 12.4.3.*/ - adcp->adcm->CR = ADC_CR_ADVREGEN_1; -#if STM32_ADC_DUAL_MODE - adcp->adcs->CR = ADC_CR_ADVREGEN_1; -#endif -} - -/** - * @brief Enables the ADC analog circuit. - * - * @param[in] adcp pointer to the @p ADCDriver object - */ -static void adc_lld_analog_on(ADCDriver *adcp) { - - adcp->adcm->CR |= ADC_CR_ADEN; - while ((adcp->adcm->ISR & ADC_ISR_ADRDY) == 0) - ; -#if STM32_ADC_DUAL_MODE - adcp->adcs->CR |= ADC_CR_ADEN; - while ((adcp->adcs->ISR & ADC_ISR_ADRDY) == 0) - ; -#endif -} - -/** - * @brief Disables the ADC analog circuit. - * - * @param[in] adcp pointer to the @p ADCDriver object - */ -static void adc_lld_analog_off(ADCDriver *adcp) { - - adcp->adcm->CR |= ADC_CR_ADDIS; - while ((adcp->adcm->CR & ADC_CR_ADDIS) != 0) - ; -#if STM32_ADC_DUAL_MODE - adcp->adcs->CR |= ADC_CR_ADDIS; - while ((adcp->adcs->CR & ADC_CR_ADDIS) != 0) - ; -#endif -} - -/** - * @brief Calibrates and ADC unit. - * - * @param[in] adcp pointer to the @p ADCDriver object - */ -static void adc_lld_calibrate(ADCDriver *adcp) { - - osalDbgAssert(adcp->adcm->CR == ADC_CR_ADVREGEN_0, "invalid register state"); - adcp->adcm->CR |= ADC_CR_ADCAL; - while ((adcp->adcm->CR & ADC_CR_ADCAL) != 0) - ; -#if STM32_ADC_DUAL_MODE - osalDbgAssert(adcp->adcs->CR == ADC_CR_ADVREGEN_0, "invalid register state"); - adcp->adcs->CR |= ADC_CR_ADCAL; - while ((adcp->adcs->CR & ADC_CR_ADCAL) != 0) - ; -#endif -} - -/** - * @brief Stops an ongoing conversion, if any. - * - * @param[in] adcp pointer to the @p ADCDriver object - */ -static void adc_lld_stop_adc(ADCDriver *adcp) { - - if (adcp->adcm->CR & ADC_CR_ADSTART) { - adcp->adcm->CR |= ADC_CR_ADSTP; - while (adcp->adcm->CR & ADC_CR_ADSTP) - ; - } -} - -/** - * @brief ADC DMA ISR service routine. - * - * @param[in] adcp pointer to the @p ADCDriver object - * @param[in] flags pre-shifted content of the ISR register - */ -static void adc_lld_serve_dma_interrupt(ADCDriver *adcp, uint32_t flags) { - - /* DMA errors handling.*/ - if ((flags & (STM32_DMA_ISR_TEIF | STM32_DMA_ISR_DMEIF)) != 0) { - /* DMA, this could help only if the DMA tries to access an unmapped - address space or violates alignment rules.*/ - _adc_isr_error_code(adcp, ADC_ERR_DMAFAILURE); - } - else { - /* It is possible that the conversion group has already be reset by the - ADC error handler, in this case this interrupt is spurious.*/ - if (adcp->grpp != NULL) { - if ((flags & STM32_DMA_ISR_HTIF) != 0) { - /* Half transfer processing.*/ - _adc_isr_half_code(adcp); - } - if ((flags & STM32_DMA_ISR_TCIF) != 0) { - /* Transfer complete processing.*/ - _adc_isr_full_code(adcp); - } - } - } -} - -/** - * @brief ADC ISR service routine. - * - * @param[in] adcp pointer to the @p ADCDriver object - * @param[in] isr content of the ISR register - */ -static void adc_lld_serve_interrupt(ADCDriver *adcp, uint32_t isr) { - - /* It could be a spurious interrupt caused by overflows after DMA disabling, - just ignore it in this case.*/ - if (adcp->grpp != NULL) { - /* Note, an overflow may occur after the conversion ended before the driver - is able to stop the ADC, this is why the DMA channel is checked too.*/ - if ((isr & ADC_ISR_OVR) && - (dmaStreamGetTransactionSize(adcp->dmastp) > 0)) { - /* ADC overflow condition, this could happen only if the DMA is unable - to read data fast enough.*/ - _adc_isr_error_code(adcp, ADC_ERR_OVERFLOW); - } - if (isr & ADC_ISR_AWD1) { - /* Analog watchdog error.*/ - _adc_isr_error_code(adcp, ADC_ERR_AWD1); - } - if (isr & ADC_ISR_AWD2) { - /* Analog watchdog error.*/ - _adc_isr_error_code(adcp, ADC_ERR_AWD2); - } - if (isr & ADC_ISR_AWD3) { - /* Analog watchdog error.*/ - _adc_isr_error_code(adcp, ADC_ERR_AWD3); - } - } -} - -/*===========================================================================*/ -/* Driver interrupt handlers. */ -/*===========================================================================*/ - -#if STM32_ADC_USE_ADC1 || defined(__DOXYGEN__) -/** - * @brief ADC1/ADC2 interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(Vector88) { - uint32_t isr; - - OSAL_IRQ_PROLOGUE(); - -#if STM32_ADC_DUAL_MODE - isr = ADC1->ISR; - isr |= ADC2->ISR; - ADC1->ISR = isr; - ADC2->ISR = isr; -#else /* !STM32_ADC_DUAL_MODE */ - isr = ADC1->ISR; - ADC1->ISR = isr; -#endif /* !STM32_ADC_DUAL_MODE */ - - adc_lld_serve_interrupt(&ADCD1, isr); - - OSAL_IRQ_EPILOGUE(); -} -#endif /* STM32_ADC_USE_ADC1 */ - -#if STM32_ADC_USE_ADC3 || defined(__DOXYGEN__) -/** - * @brief ADC3 interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(VectorFC) { - uint32_t isr; - - OSAL_IRQ_PROLOGUE(); - - isr = ADC3->ISR; - ADC3->ISR = isr; - - adc_lld_serve_interrupt(&ADCD3, isr); - - OSAL_IRQ_EPILOGUE(); -} - -#if STM32_ADC_DUAL_MODE -/** - * @brief ADC4 interrupt handler (as ADC3 slave). - * - * @isr - */ -OSAL_IRQ_HANDLER(Vector134) { - uint32_t isr; - - OSAL_IRQ_PROLOGUE(); - - isr = ADC4->ISR; - ADC4->ISR = isr; - - adc_lld_serve_interrupt(&ADCD3, isr); - - OSAL_IRQ_EPILOGUE(); -} -#endif /* STM32_ADC_DUAL_MODE */ -#endif /* STM32_ADC_USE_ADC3 */ - -/*===========================================================================*/ -/* Driver exported functions. */ -/*===========================================================================*/ - -/** - * @brief Low level ADC driver initialization. - * - * @notapi - */ -void adc_lld_init(void) { - -#if STM32_ADC_USE_ADC1 - /* Driver initialization.*/ - adcObjectInit(&ADCD1); - ADCD1.adcc = ADC1_2; - ADCD1.adcm = ADC1; -#if STM32_ADC_DUAL_MODE - ADCD1.adcs = ADC2; -#endif - ADCD1.dmastp = STM32_DMA1_STREAM1; - ADCD1.dmamode = ADC_DMA_SIZE | - STM32_DMA_CR_PL(STM32_ADC_ADC12_DMA_PRIORITY) | - STM32_DMA_CR_DIR_P2M | - STM32_DMA_CR_MINC | STM32_DMA_CR_TCIE | - STM32_DMA_CR_DMEIE | STM32_DMA_CR_TEIE; - nvicEnableVector(ADC1_2_IRQn, STM32_ADC_ADC12_IRQ_PRIORITY); -#endif /* STM32_ADC_USE_ADC1 */ - -#if STM32_ADC_USE_ADC3 - /* Driver initialization.*/ - adcObjectInit(&ADCD3); - ADCD3.adcc = ADC3_4; - ADCD3.adcm = ADC3; -#if STM32_ADC_DUAL_MODE - ADCD3.adcs = ADC4; -#endif - ADCD3.dmastp = STM32_DMA2_STREAM5; - ADCD3.dmamode = ADC_DMA_SIZE | - STM32_DMA_CR_PL(STM32_ADC_ADC12_DMA_PRIORITY) | - STM32_DMA_CR_DIR_P2M | - STM32_DMA_CR_MINC | STM32_DMA_CR_TCIE | - STM32_DMA_CR_DMEIE | STM32_DMA_CR_TEIE; - nvicEnableVector(ADC3_IRQn, STM32_ADC_ADC34_IRQ_PRIORITY); -#if STM32_ADC_DUAL_MODE - nvicEnableVector(ADC4_IRQn, STM32_ADC_ADC34_IRQ_PRIORITY); -#endif -#endif /* STM32_ADC_USE_ADC3 */ -} - -/** - * @brief Configures and activates the ADC peripheral. - * - * @param[in] adcp pointer to the @p ADCDriver object - * - * @notapi - */ -void adc_lld_start(ADCDriver *adcp) { - - /* If in stopped state then enables the ADC and DMA clocks.*/ - if (adcp->state == ADC_STOP) { -#if STM32_ADC_USE_ADC1 - if (&ADCD1 == adcp) { - bool_t b; - b = dmaStreamAllocate(adcp->dmastp, - STM32_ADC_ADC12_DMA_IRQ_PRIORITY, - (stm32_dmaisr_t)adc_lld_serve_dma_interrupt, - (void *)adcp); - osalDbgAssert(!b, "stream already allocated"); - rccEnableADC12(FALSE); - } -#endif /* STM32_ADC_USE_ADC1 */ - -#if STM32_ADC_USE_ADC3 - if (&ADCD3 == adcp) { - bool_t b; - b = dmaStreamAllocate(adcp->dmastp, - STM32_ADC_ADC34_DMA_IRQ_PRIORITY, - (stm32_dmaisr_t)adc_lld_serve_dma_interrupt, - (void *)adcp); - osalDbgAssert(!b, "stream already allocated"); - rccEnableADC34(FALSE); - } -#endif /* STM32_ADC_USE_ADC2 */ - - /* Setting DMA peripheral-side pointer.*/ -#if STM32_ADC_DUAL_MODE - dmaStreamSetPeripheral(adcp->dmastp, &adcp->adcc->CDR); -#else - dmaStreamSetPeripheral(adcp->dmastp, &adcp->adcm->DR); -#endif - - /* Clock source setting.*/ - adcp->adcc->CCR = STM32_ADC_ADC12_CLOCK_MODE | ADC_DMA_MDMA; - - /* Master ADC calibration.*/ - adc_lld_vreg_on(adcp); - adc_lld_calibrate(adcp); - - /* Master ADC enabled here in order to reduce conversions latencies.*/ - adc_lld_analog_on(adcp); - } -} - -/** - * @brief Deactivates the ADC peripheral. - * - * @param[in] adcp pointer to the @p ADCDriver object - * - * @notapi - */ -void adc_lld_stop(ADCDriver *adcp) { - - /* If in ready state then disables the ADC clock and analog part.*/ - if (adcp->state == ADC_READY) { - - /* Releasing the associated DMA channel.*/ - dmaStreamRelease(adcp->dmastp); - - /* Stopping the ongoing conversion, if any.*/ - adc_lld_stop_adc(adcp); - - /* Disabling ADC analog circuit and regulator.*/ - adc_lld_analog_off(adcp); - adc_lld_vreg_off(adcp); - -#if STM32_ADC_USE_ADC1 - if (&ADCD1 == adcp) - rccDisableADC12(FALSE); -#endif - -#if STM32_ADC_USE_ADC3 - if (&ADCD1 == adcp) - rccDisableADC34(FALSE); -#endif - } -} - -/** - * @brief Starts an ADC conversion. - * - * @param[in] adcp pointer to the @p ADCDriver object - * - * @notapi - */ -void adc_lld_start_conversion(ADCDriver *adcp) { - uint32_t dmamode, ccr, cfgr; - const ADCConversionGroup *grpp = adcp->grpp; - - osalDbgAssert(!STM32_ADC_DUAL_MODE || ((grpp->num_channels & 1) == 0), - "odd number of channels in dual mode"); - - /* Calculating control registers values.*/ - dmamode = adcp->dmamode; - ccr = grpp->ccr | (adcp->adcc->CCR & (ADC_CCR_CKMODE_MASK | - ADC_CCR_MDMA_MASK)); - cfgr = grpp->cfgr | ADC_CFGR_CONT | ADC_CFGR_DMAEN; - if (grpp->circular) { - dmamode |= STM32_DMA_CR_CIRC; -#if STM32_ADC_DUAL_MODE - ccr |= ADC_CCR_DMACFG_CIRCULAR; -#else - cfgr |= ADC_CFGR_DMACFG_CIRCULAR; -#endif - } - - /* DMA setup.*/ - if (adcp->depth > 1) { - /* If the buffer depth is greater than one then the half transfer interrupt - interrupt is enabled in order to allows streaming processing.*/ - dmamode |= STM32_DMA_CR_HTIE; - } - dmaStreamSetMemory0(adcp->dmastp, adcp->samples); -#if STM32_ADC_DUAL_MODE - dmaStreamSetTransactionSize(adcp->dmastp, ((uint32_t)grpp->num_channels/2) * - (uint32_t)adcp->depth); -#else - dmaStreamSetTransactionSize(adcp->dmastp, (uint32_t)grpp->num_channels * - (uint32_t)adcp->depth); -#endif - dmaStreamSetMode(adcp->dmastp, dmamode); - dmaStreamEnable(adcp->dmastp); - - /* Configuring the CCR register with the static settings ORed with - the user-specified settings in the conversion group configuration - structure.*/ - adcp->adcc->CCR = ccr; - - /* ADC setup, if it is defined a callback for the analog watch dog then it - is enabled.*/ - adcp->adcm->ISR = adcp->adcm->ISR; - adcp->adcm->IER = ADC_IER_OVR | ADC_IER_AWD1; - adcp->adcm->TR1 = grpp->tr1; -#if STM32_ADC_DUAL_MODE - adcp->adcm->SMPR1 = grpp->smpr[0]; - adcp->adcm->SMPR2 = grpp->smpr[1]; - adcp->adcm->SQR1 = grpp->sqr[0] | ADC_SQR1_NUM_CH(grpp->num_channels / 2); - adcp->adcm->SQR2 = grpp->sqr[1]; - adcp->adcm->SQR3 = grpp->sqr[2]; - adcp->adcm->SQR4 = grpp->sqr[3]; - adcp->adcs->SMPR1 = grpp->ssmpr[0]; - adcp->adcs->SMPR2 = grpp->ssmpr[1]; - adcp->adcs->SQR1 = grpp->ssqr[0] | ADC_SQR1_NUM_CH(grpp->num_channels / 2); - adcp->adcs->SQR2 = grpp->ssqr[1]; - adcp->adcs->SQR3 = grpp->ssqr[2]; - adcp->adcs->SQR4 = grpp->ssqr[3]; - -#else /* !STM32_ADC_DUAL_MODE */ - adcp->adcm->SMPR1 = grpp->smpr[0]; - adcp->adcm->SMPR2 = grpp->smpr[1]; - adcp->adcm->SQR1 = grpp->sqr[0] | ADC_SQR1_NUM_CH(grpp->num_channels); - adcp->adcm->SQR2 = grpp->sqr[1]; - adcp->adcm->SQR3 = grpp->sqr[2]; - adcp->adcm->SQR4 = grpp->sqr[3]; -#endif /* !STM32_ADC_DUAL_MODE */ - - /* ADC configuration.*/ - adcp->adcm->CFGR = cfgr; - - /* Starting conversion.*/ - adcp->adcm->CR |= ADC_CR_ADSTART; -} - -/** - * @brief Stops an ongoing conversion. - * - * @param[in] adcp pointer to the @p ADCDriver object - * - * @notapi - */ -void adc_lld_stop_conversion(ADCDriver *adcp) { - - dmaStreamDisable(adcp->dmastp); - adc_lld_stop_adc(adcp); -} - -#endif /* HAL_USE_ADC */ - -/** @} */ diff --git a/os/hal/platforms/STM32F30x/adc_lld.h b/os/hal/platforms/STM32F30x/adc_lld.h deleted file mode 100644 index 66c725cdd..000000000 --- a/os/hal/platforms/STM32F30x/adc_lld.h +++ /dev/null @@ -1,608 +0,0 @@ -/* - ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file STM32F30x/adc_lld.h - * @brief STM32F30x ADC subsystem low level driver header. - * - * @addtogroup ADC - * @{ - */ - -#ifndef _ADC_LLD_H_ -#define _ADC_LLD_H_ - -#if HAL_USE_ADC || defined(__DOXYGEN__) - -/*===========================================================================*/ -/* Driver constants. */ -/*===========================================================================*/ - -/** - * @name Available analog channels - * @{ - */ -#define ADC_CHANNEL_IN1 1 /**< @brief External analog input 1. */ -#define ADC_CHANNEL_IN2 2 /**< @brief External analog input 2. */ -#define ADC_CHANNEL_IN3 3 /**< @brief External analog input 3. */ -#define ADC_CHANNEL_IN4 4 /**< @brief External analog input 4. */ -#define ADC_CHANNEL_IN5 5 /**< @brief External analog input 5. */ -#define ADC_CHANNEL_IN6 6 /**< @brief External analog input 6. */ -#define ADC_CHANNEL_IN7 7 /**< @brief External analog input 7. */ -#define ADC_CHANNEL_IN8 8 /**< @brief External analog input 8. */ -#define ADC_CHANNEL_IN9 9 /**< @brief External analog input 9. */ -#define ADC_CHANNEL_IN10 10 /**< @brief External analog input 10. */ -#define ADC_CHANNEL_IN11 11 /**< @brief External analog input 11. */ -#define ADC_CHANNEL_IN12 12 /**< @brief External analog input 12. */ -#define ADC_CHANNEL_IN13 13 /**< @brief External analog input 13. */ -#define ADC_CHANNEL_IN14 14 /**< @brief External analog input 14. */ -#define ADC_CHANNEL_IN15 15 /**< @brief External analog input 15. */ -#define ADC_CHANNEL_IN16 16 /**< @brief External analog input 16. */ -#define ADC_CHANNEL_IN17 17 /**< @brief External analog input 17. */ -#define ADC_CHANNEL_IN18 18 /**< @brief External analog input 18. */ -/** @} */ - -/** - * @name Sampling rates - * @{ - */ -#define ADC_SMPR_SMP_1P5 0 /**< @brief 14 cycles conversion time */ -#define ADC_SMPR_SMP_2P5 1 /**< @brief 15 cycles conversion time. */ -#define ADC_SMPR_SMP_4P5 2 /**< @brief 17 cycles conversion time. */ -#define ADC_SMPR_SMP_7P5 3 /**< @brief 20 cycles conversion time. */ -#define ADC_SMPR_SMP_19P5 4 /**< @brief 32 cycles conversion time. */ -#define ADC_SMPR_SMP_61P5 5 /**< @brief 74 cycles conversion time. */ -#define ADC_SMPR_SMP_181P5 6 /**< @brief 194 cycles conversion time. */ -#define ADC_SMPR_SMP_601P5 7 /**< @brief 614 cycles conversion time. */ -/** @} */ - -/** - * @name Resolution - * @{ - */ -#define ADC_CFGR1_RES_12BIT (0 << 3) -#define ADC_CFGR1_RES_10BIT (1 << 3) -#define ADC_CFGR1_RES_8BIT (2 << 3) -#define ADC_CFGR1_RES_6BIT (3 << 3) -/** @} */ - -/** - * @name CFGR register configuration helpers - * @{ - */ -#define ADC_CFGR_DMACFG_MASK (1 << 1) -#define ADC_CFGR_DMACFG_ONESHOT (0 << 1) -#define ADC_CFGR_DMACFG_CIRCULAR (1 << 1) - -#define ADC_CFGR_RES_MASK (3 << 3) -#define ADC_CFGR_RES_12BITS (0 << 3) -#define ADC_CFGR_RES_10BITS (1 << 3) -#define ADC_CFGR_RES_8BITS (2 << 3) -#define ADC_CFGR_RES_6BITS (3 << 3) - -#define ADC_CFGR_ALIGN_MASK (1 << 5) -#define ADC_CFGR_ALIGN_RIGHT (0 << 5) -#define ADC_CFGR_ALIGN_LEFT (1 << 5) - -#define ADC_CFGR_EXTSEL_MASK (15 << 6) -#define ADC_CFGR_EXTSEL_SRC(n) ((n) << 6) - -#define ADC_CFGR_EXTEN_MASK (3 << 10) -#define ADC_CFGR_EXTEN_DISABLED (0 << 10) -#define ADC_CFGR_EXTEN_RISING (1 << 10) -#define ADC_CFGR_EXTEN_FALLING (2 << 10) -#define ADC_CFGR_EXTEN_BOTH (3 << 10) - -#define ADC_CFGR_DISCEN_MASK (1 << 16) -#define ADC_CFGR_DISCEN_DISABLED (0 << 16) -#define ADC_CFGR_DISCEN_ENABLED (1 << 16) - -#define ADC_CFGR_DISCNUM_MASK (7 << 17) -#define ADC_CFGR_DISCNUM_VAL(n) ((n) << 17) - -#define ADC_CFGR_AWD1_DISABLED 0 -#define ADC_CFGR_AWD1_ALL (1 << 23) -#define ADC_CFGR_AWD1_SINGLE(n) (((n) << 26) | (1 << 23) | (1 << 22)) -/** @} */ - -/** - * @name CCR register configuration helpers - * @{ - */ -#define ADC_CCR_DUAL_MASK (31 << 0) -#define ADC_CCR_DUAL(n) ((n) << 0) -#define ADC_CCR_DELAY_MASK (15 << 8) -#define ADC_CCR_DELAY(n) ((n) << 8) -#define ADC_CCR_DMACFG_MASK (1 << 13) -#define ADC_CCR_DMACFG_ONESHOT (0 << 13) -#define ADC_CCR_DMACFG_CIRCULAR (1 << 13) -#define ADC_CCR_MDMA_MASK (3 << 14) -#define ADC_CCR_MDMA_DISABLED (0 << 14) -#define ADC_CCR_MDMA_WORD (2 << 14) -#define ADC_CCR_MDMA_HWORD (3 << 14) -#define ADC_CCR_CKMODE_MASK (3 << 16) -#define ADC_CCR_CKMODE_ADCCK (0 << 16) -#define ADC_CCR_CKMODE_AHB_DIV1 (1 << 16) -#define ADC_CCR_CKMODE_AHB_DIV2 (2 << 16) -#define ADC_CCR_CKMODE_AHB_DIV4 (3 << 16) -#define ADC_CCR_VREFEN (1 << 22) -#define ADC_CCR_TSEN (1 << 23) -#define ADC_CCR_VBATEN (1 << 24) -/** @} */ - -/*===========================================================================*/ -/* Driver pre-compile time settings. */ -/*===========================================================================*/ - -/** - * @name Configuration options - * @{ - */ -/** - * @brief ADC1 driver enable switch. - * @details If set to @p TRUE the support for ADC1 is included. - * @note The default is @p FALSE. - */ -#if !defined(STM32_ADC_USE_ADC1) || defined(__DOXYGEN__) -#define STM32_ADC_USE_ADC1 FALSE -#endif - -/** - * @brief ADC3 driver enable switch. - * @details If set to @p TRUE the support for ADC3 is included. - * @note The default is @p FALSE. - */ -#if !defined(STM32_ADC_USE_ADC3) || defined(__DOXYGEN__) -#define STM32_ADC_USE_ADC3 FALSE -#endif - -/** - * @brief ADC1/ADC2 DMA priority (0..3|lowest..highest). - */ -#if !defined(STM32_ADC_ADC12_DMA_PRIORITY) || defined(__DOXYGEN__) -#define STM32_ADC_ADC12_DMA_PRIORITY 2 -#endif - -/** - * @brief ADC3/ADC4 DMA priority (0..3|lowest..highest). - */ -#if !defined(STM32_ADC_ADC34_DMA_PRIORITY) || defined(__DOXYGEN__) -#define STM32_ADC_ADC34_DMA_PRIORITY 2 -#endif - -/** - * @brief ADC1/ADC2 interrupt priority level setting. - */ -#if !defined(STM32_ADC_ADC12_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_ADC_ADC12_IRQ_PRIORITY 5 -#endif - -/** - * @brief ADC3/ADC4 interrupt priority level setting. - */ -#if !defined(STM32_ADC34_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_ADC_ADC34_IRQ_PRIORITY 5 -#endif - -/** - * @brief ADC1/ADC2 DMA interrupt priority level setting. - */ -#if !defined(STM32_ADC_ADC12_DMA_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_ADC_ADC12_DMA_IRQ_PRIORITY 5 -#endif - -/** - * @brief ADC3/ADC4 DMA interrupt priority level setting. - */ -#if !defined(STM32_ADC_ADC34_DMA_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_ADC_ADC34_DMA_IRQ_PRIORITY 5 -#endif - -/** - * @brief ADC1/ADC2 clock source and mode. - */ -#if !defined(STM32_ADC_ADC12_CLOCK_MODE) || defined(__DOXYGEN__) -#define STM32_ADC_ADC12_CLOCK_MODE ADC_CCR_CKMODE_AHB_DIV1 -#endif - -/** - * @brief ADC3/ADC4 clock source and mode. - */ -#if !defined(STM32_ADC_ADC34_CLOCK_MODE) || defined(__DOXYGEN__) -#define STM32_ADC_ADC34_CLOCK_MODE ADC_CCR_CKMODE_AHB_DIV1 -#endif - -/** - * @brief Enables the ADC master/slave mode. - */ -#if !defined(STM32_ADC_DUAL_MODE) || defined(__DOXYGEN__) -#define STM32_ADC_DUAL_MODE FALSE -#endif - -/** - * @brief Makes the ADC samples type an 8bits one. - */ -#if !defined(STM32_ADC_COMPACT_SAMPLES) || defined(__DOXYGEN__) -#define STM32_ADC_COMPACT_SAMPLES FALSE -#endif -/** @} */ - -/*===========================================================================*/ -/* Derived constants and error checks. */ -/*===========================================================================*/ - -#if STM32_ADC_USE_ADC1 && !STM32_HAS_ADC1 -#error "ADC1 not present in the selected device" -#endif - -#if STM32_ADC_USE_ADC3 && !STM32_HAS_ADC3 -#error "ADC3 not present in the selected device" -#endif - -#if !STM32_ADC_USE_ADC1 && !STM32_ADC_USE_ADC3 -#error "ADC driver activated but no ADC peripheral assigned" -#endif - -#if STM32_ADC_USE_ADC1 && \ - !CORTEX_IS_VALID_KERNEL_PRIORITY(STM32_ADC_ADC12_IRQ_PRIORITY) -#error "Invalid IRQ priority assigned to ADC1" -#endif - -#if STM32_ADC_USE_ADC1 && \ - !CORTEX_IS_VALID_KERNEL_PRIORITY(STM32_ADC_ADC12_DMA_IRQ_PRIORITY) -#error "Invalid IRQ priority assigned to ADC1 DMA" -#endif - -#if STM32_ADC_USE_ADC1 && \ - !STM32_DMA_IS_VALID_PRIORITY(STM32_ADC_ADC12_DMA_PRIORITY) -#error "Invalid DMA priority assigned to ADC1" -#endif - -#if STM32_ADC_USE_ADC3 && \ - !CORTEX_IS_VALID_KERNEL_PRIORITY(STM32_ADC_ADC34_IRQ_PRIORITY) -#error "Invalid IRQ priority assigned to ADC3" -#endif - -#if STM32_ADC_USE_ADC3 && \ - !CORTEX_IS_VALID_KERNEL_PRIORITY(STM32_ADC_ADC34_DMA_IRQ_PRIORITY) -#error "Invalid IRQ priority assigned to ADC3 DMA" -#endif - -#if STM32_ADC_USE_ADC3 && \ - !STM32_DMA_IS_VALID_PRIORITY(STM32_ADC_ADC34_DMA_PRIORITY) -#error "Invalid DMA priority assigned to ADC3" -#endif - -#if STM32_ADC_ADC12_CLOCK_MODE == ADC_CCR_CKMODE_ADCCK -#define STM32_ADC12_CLOCK STM32_ADC12CLK -#elif STM32_ADC_ADC12_CLOCK_MODE == ADC_CCR_CKMODE_AHB_DIV1 -#define STM32_ADC12_CLOCK (STM32_HCLK / 1) -#elif STM32_ADC_ADC12_CLOCK_MODE == ADC_CCR_CKMODE_AHB_DIV2 -#define STM32_ADC12_CLOCK (STM32_HCLK / 2) -#elif STM32_ADC_ADC12_CLOCK_MODE == ADC_CCR_CKMODE_AHB_DIV4 -#define STM32_ADC12_CLOCK (STM32_HCLK / 4) -#else -#error "invalid clock mode selected for STM32_ADC_ADC12_CLOCK_MODE" -#endif - -#if STM32_ADC_ADC34_CLOCK_MODE == ADC_CCR_CKMODE_ADCCK -#define STM32_ADC34_CLOCK STM32_ADC34CLK -#elif STM32_ADC_ADC34_CLOCK_MODE == ADC_CCR_CKMODE_AHB_DIV1 -#define STM32_ADC34_CLOCK (STM32_HCLK / 1) -#elif STM32_ADC_ADC34_CLOCK_MODE == ADC_CCR_CKMODE_AHB_DIV2 -#define STM32_ADC34_CLOCK (STM32_HCLK / 2) -#elif STM32_ADC_ADC34_CLOCK_MODE == ADC_CCR_CKMODE_AHB_DIV4 -#define STM32_ADC34_CLOCK (STM32_HCLK / 4) -#else -#error "invalid clock mode selected for STM32_ADC_ADC12_CLOCK_MODE" -#endif - -#if STM32_ADC12_CLOCK > 72000000 -#error "STM32_ADC12_CLOCK exceeding maximum frequency (72000000)" -#endif - -#if STM32_ADC34_CLOCK > 72000000 -#error "STM32_ADC34_CLOCK exceeding maximum frequency (72000000)" -#endif - -#if !defined(STM32_DMA_REQUIRED) -#define STM32_DMA_REQUIRED -#endif - -/*===========================================================================*/ -/* Driver data structures and types. */ -/*===========================================================================*/ - -/** - * @brief ADC sample data type. - */ -#if !STM32_ADC_COMPACT_SAMPLES || defined(__DOXYGEN__) -typedef uint16_t adcsample_t; -#else -typedef uint8_t adcsample_t; -#endif - -/** - * @brief Channels number in a conversion group. - */ -typedef uint16_t adc_channels_num_t; - -/** - * @brief Possible ADC failure causes. - * @note Error codes are architecture dependent and should not relied - * upon. - */ -typedef enum { - ADC_ERR_DMAFAILURE = 0, /**< DMA operations failure. */ - ADC_ERR_OVERFLOW = 1, /**< ADC overflow condition. */ - ADC_ERR_AWD1 = 2, /**< Watchdog 1 triggered. */ - ADC_ERR_AWD2 = 3, /**< Watchdog 2 triggered. */ - ADC_ERR_AWD3 = 4 /**< Watchdog 3 triggered. */ -} adcerror_t; - -/** - * @brief Type of a structure representing an ADC driver. - */ -typedef struct ADCDriver ADCDriver; - -/** - * @brief ADC notification callback type. - * - * @param[in] adcp pointer to the @p ADCDriver object triggering the - * callback - * @param[in] buffer pointer to the most recent samples data - * @param[in] n number of buffer rows available starting from @p buffer - */ -typedef void (*adccallback_t)(ADCDriver *adcp, adcsample_t *buffer, size_t n); - -/** - * @brief ADC error callback type. - * - * @param[in] adcp pointer to the @p ADCDriver object triggering the - * callback - * @param[in] err ADC error code - */ -typedef void (*adcerrorcallback_t)(ADCDriver *adcp, adcerror_t err); - -/** - * @brief Conversion group configuration structure. - * @details This implementation-dependent structure describes a conversion - * operation. - * @note The use of this configuration structure requires knowledge of - * STM32 ADC cell registers interface, please refer to the STM32 - * reference manual for details. - */ -typedef struct { - /** - * @brief Enables the circular buffer mode for the group. - */ - bool_t circular; - /** - * @brief Number of the analog channels belonging to the conversion group. - */ - adc_channels_num_t num_channels; - /** - * @brief Callback function associated to the group or @p NULL. - */ - adccallback_t end_cb; - /** - * @brief Error callback or @p NULL. - */ - adcerrorcallback_t error_cb; - /* End of the mandatory fields.*/ - /** - * @brief ADC CFGR register initialization data. - * @note The bits DMAEN, DMACFG, OVRMOD, CONT are enforced internally - * to the driver, keep them to zero. - */ - uint32_t cfgr; - /** - * @brief ADC TR1 register initialization data. - */ - uint32_t tr1; - /** - * @brief ADC CCR register initialization data. - * @note The bits CKMODE, MDMA, DMACFG are enforced internally to the - * driver, keep them to zero. - */ - uint32_t ccr; - /** - * @brief ADC SMPRx registers initialization data. - */ - uint32_t smpr[2]; - /** - * @brief ADC SQRx register initialization data. - */ - uint32_t sqr[4]; -#if STM32_ADC_DUAL_MODE || defined(__DOXYGEN__) - /** - * @brief Slave ADC SMPRx registers initialization data. - */ - uint32_t ssmpr[2]; - /** - * @brief Slave ADC SQRx register initialization data. - */ - uint32_t ssqr[4]; -#endif /* STM32_ADC_DUAL_MODE */ -} ADCConversionGroup; - -/** - * @brief Driver configuration structure. - * @note It could be empty on some architectures. - */ -typedef struct { - uint32_t dummy; -} ADCConfig; - -/** - * @brief Structure representing an ADC driver. - */ -struct ADCDriver { - /** - * @brief Driver state. - */ - adcstate_t state; - /** - * @brief Current configuration data. - */ - const ADCConfig *config; - /** - * @brief Current samples buffer pointer or @p NULL. - */ - adcsample_t *samples; - /** - * @brief Current samples buffer depth or @p 0. - */ - size_t depth; - /** - * @brief Current conversion group pointer or @p NULL. - */ - const ADCConversionGroup *grpp; -#if ADC_USE_WAIT || defined(__DOXYGEN__) - /** - * @brief Waiting thread. - */ - thread_reference_t thread; -#endif -#if ADC_USE_MUTUAL_EXCLUSION || defined(__DOXYGEN__) - /** - * @brief Mutex protecting the peripheral. - */ - mutex_t mutex; -#endif /* ADC_USE_MUTUAL_EXCLUSION */ -#if defined(ADC_DRIVER_EXT_FIELDS) - ADC_DRIVER_EXT_FIELDS -#endif - /* End of the mandatory fields.*/ - /** - * @brief Pointer to the common ADCx_y registers block. - */ - ADC_Common_TypeDef *adcc; - /** - * @brief Pointer to the master ADCx registers block. - */ - ADC_TypeDef *adcm; -#if STM32_ADC_DUAL_MODE || defined(__DOXYGEN__) - /** - * @brief Pointer to the slave ADCx registers block. - */ - ADC_TypeDef *adcs; -#endif /* STM32_ADC_DUAL_MODE */ - /** - * @brief Pointer to associated DMA channel. - */ - const stm32_dma_stream_t *dmastp; - /** - * @brief DMA mode bit mask. - */ - uint32_t dmamode; -}; - -/*===========================================================================*/ -/* Driver macros. */ -/*===========================================================================*/ - -/** - * @name Threashold register initializer - * @{ - */ -#define ADC_TR(low, high) (((uint32_t)(high) << 16) | (uint32_t)(low)) -/** @} */ - -/** - * @name Sequences building helper macros - * @{ - */ -/** - * @brief Number of channels in a conversion sequence. - */ -#define ADC_SQR1_NUM_CH(n) (((n) - 1) << 0) - -#define ADC_SQR1_SQ1_N(n) ((n) << 6) /**< @brief 1st channel in seq. */ -#define ADC_SQR1_SQ2_N(n) ((n) << 12) /**< @brief 2nd channel in seq. */ -#define ADC_SQR1_SQ3_N(n) ((n) << 18) /**< @brief 3rd channel in seq. */ -#define ADC_SQR1_SQ4_N(n) ((n) << 24) /**< @brief 4th channel in seq. */ - -#define ADC_SQR2_SQ5_N(n) ((n) << 0) /**< @brief 5th channel in seq. */ -#define ADC_SQR2_SQ6_N(n) ((n) << 6) /**< @brief 6th channel in seq. */ -#define ADC_SQR2_SQ7_N(n) ((n) << 12) /**< @brief 7th channel in seq. */ -#define ADC_SQR2_SQ8_N(n) ((n) << 18) /**< @brief 8th channel in seq. */ -#define ADC_SQR2_SQ9_N(n) ((n) << 24) /**< @brief 9th channel in seq. */ - -#define ADC_SQR3_SQ10_N(n) ((n) << 0) /**< @brief 10th channel in seq.*/ -#define ADC_SQR3_SQ11_N(n) ((n) << 6) /**< @brief 11th channel in seq.*/ -#define ADC_SQR3_SQ12_N(n) ((n) << 12) /**< @brief 12th channel in seq.*/ -#define ADC_SQR3_SQ13_N(n) ((n) << 18) /**< @brief 13th channel in seq.*/ -#define ADC_SQR3_SQ14_N(n) ((n) << 24) /**< @brief 14th channel in seq.*/ - -#define ADC_SQR4_SQ15_N(n) ((n) << 0) /**< @brief 15th channel in seq.*/ -#define ADC_SQR4_SQ16_N(n) ((n) << 6) /**< @brief 16th channel in seq.*/ -/** @} */ - -/** - * @name Sampling rate settings helper macros - * @{ - */ -#define ADC_SMPR1_SMP_AN1(n) ((n) << 3) /**< @brief AN1 sampling time. */ -#define ADC_SMPR1_SMP_AN2(n) ((n) << 6) /**< @brief AN2 sampling time. */ -#define ADC_SMPR1_SMP_AN3(n) ((n) << 9) /**< @brief AN3 sampling time. */ -#define ADC_SMPR1_SMP_AN4(n) ((n) << 12) /**< @brief AN4 sampling time. */ -#define ADC_SMPR1_SMP_AN5(n) ((n) << 15) /**< @brief AN5 sampling time. */ -#define ADC_SMPR1_SMP_AN6(n) ((n) << 18) /**< @brief AN6 sampling time. */ -#define ADC_SMPR1_SMP_AN7(n) ((n) << 21) /**< @brief AN7 sampling time. */ -#define ADC_SMPR1_SMP_AN8(n) ((n) << 24) /**< @brief AN8 sampling time. */ -#define ADC_SMPR1_SMP_AN9(n) ((n) << 27) /**< @brief AN9 sampling time. */ - -#define ADC_SMPR2_SMP_AN10(n) ((n) << 0) /**< @brief AN10 sampling time. */ -#define ADC_SMPR2_SMP_AN11(n) ((n) << 3) /**< @brief AN11 sampling time. */ -#define ADC_SMPR2_SMP_AN12(n) ((n) << 6) /**< @brief AN12 sampling time. */ -#define ADC_SMPR2_SMP_AN13(n) ((n) << 9) /**< @brief AN13 sampling time. */ -#define ADC_SMPR2_SMP_AN14(n) ((n) << 12) /**< @brief AN14 sampling time. */ -#define ADC_SMPR2_SMP_AN15(n) ((n) << 15) /**< @brief AN15 sampling time. */ -#define ADC_SMPR2_SMP_AN16(n) ((n) << 18) /**< @brief AN16 sampling time. */ -#define ADC_SMPR2_SMP_AN17(n) ((n) << 21) /**< @brief AN17 sampling time. */ -#define ADC_SMPR2_SMP_AN18(n) ((n) << 24) /**< @brief AN18 sampling time. */ -/** @} */ - -/*===========================================================================*/ -/* External declarations. */ -/*===========================================================================*/ - -#if STM32_ADC_USE_ADC1 && !defined(__DOXYGEN__) -extern ADCDriver ADCD1; -#endif - -#if STM32_ADC_USE_ADC3 && !defined(__DOXYGEN__) -extern ADCDriver ADCD3; -#endif - -#ifdef __cplusplus -extern "C" { -#endif - void adc_lld_init(void); - void adc_lld_start(ADCDriver *adcp); - void adc_lld_stop(ADCDriver *adcp); - void adc_lld_start_conversion(ADCDriver *adcp); - void adc_lld_stop_conversion(ADCDriver *adcp); -#ifdef __cplusplus -} -#endif - -#endif /* HAL_USE_ADC */ - -#endif /* _ADC_LLD_H_ */ - -/** @} */ diff --git a/os/hal/platforms/STM32F30x/ext_lld_isr.c b/os/hal/platforms/STM32F30x/ext_lld_isr.c deleted file mode 100644 index 08af37b19..000000000 --- a/os/hal/platforms/STM32F30x/ext_lld_isr.c +++ /dev/null @@ -1,402 +0,0 @@ -/* - ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file STM32F30x/ext_lld_isr.c - * @brief STM32F30x EXT subsystem low level driver ISR code. - * - * @addtogroup EXT - * @{ - */ - -#include "hal.h" - -#if HAL_USE_EXT || defined(__DOXYGEN__) - -#include "ext_lld_isr.h" - -/*===========================================================================*/ -/* Driver local definitions. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver exported variables. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver local variables. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver local functions. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver interrupt handlers. */ -/*===========================================================================*/ - -#if !defined(STM32_DISABLE_EXTI0_HANDLER) -/** - * @brief EXTI[0] interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(Vector58) { - - OSAL_IRQ_PROLOGUE(); - - EXTI->PR = (1 << 0); - EXTD1.config->channels[0].cb(&EXTD1, 0); - - OSAL_IRQ_EPILOGUE(); -} -#endif - -#if !defined(STM32_DISABLE_EXTI1_HANDLER) -/** - * @brief EXTI[1] interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(Vector5C) { - - OSAL_IRQ_PROLOGUE(); - - EXTI->PR = (1 << 1); - EXTD1.config->channels[1].cb(&EXTD1, 1); - - OSAL_IRQ_EPILOGUE(); -} -#endif - -#if !defined(STM32_DISABLE_EXTI2_HANDLER) -/** - * @brief EXTI[2] interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(Vector60) { - - OSAL_IRQ_PROLOGUE(); - - EXTI->PR = (1 << 2); - EXTD1.config->channels[2].cb(&EXTD1, 2); - - OSAL_IRQ_EPILOGUE(); -} -#endif - -#if !defined(STM32_DISABLE_EXTI3_HANDLER) -/** - * @brief EXTI[3] interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(Vector64) { - - OSAL_IRQ_PROLOGUE(); - - EXTI->PR = (1 << 3); - EXTD1.config->channels[3].cb(&EXTD1, 3); - - OSAL_IRQ_EPILOGUE(); -} -#endif - -#if !defined(STM32_DISABLE_EXTI4_HANDLER) -/** - * @brief EXTI[4] interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(Vector68) { - - OSAL_IRQ_PROLOGUE(); - - EXTI->PR = (1 << 4); - EXTD1.config->channels[4].cb(&EXTD1, 4); - - OSAL_IRQ_EPILOGUE(); -} -#endif - -#if !defined(STM32_DISABLE_EXTI5_9_HANDLER) -/** - * @brief EXTI[5]...EXTI[9] interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(Vector9C) { - uint32_t pr; - - OSAL_IRQ_PROLOGUE(); - - pr = EXTI->PR & ((1 << 5) | (1 << 6) | (1 << 7) | (1 << 8) | (1 << 9)); - EXTI->PR = pr; - if (pr & (1 << 5)) - EXTD1.config->channels[5].cb(&EXTD1, 5); - if (pr & (1 << 6)) - EXTD1.config->channels[6].cb(&EXTD1, 6); - if (pr & (1 << 7)) - EXTD1.config->channels[7].cb(&EXTD1, 7); - if (pr & (1 << 8)) - EXTD1.config->channels[8].cb(&EXTD1, 8); - if (pr & (1 << 9)) - EXTD1.config->channels[9].cb(&EXTD1, 9); - - OSAL_IRQ_EPILOGUE(); -} -#endif - -#if !defined(STM32_DISABLE_EXTI10_15_HANDLER) -/** - * @brief EXTI[10]...EXTI[15] interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(VectorE0) { - uint32_t pr; - - OSAL_IRQ_PROLOGUE(); - - pr = EXTI->PR & ((1 << 10) | (1 << 11) | (1 << 12) | (1 << 13) | (1 << 14) | - (1 << 15)); - EXTI->PR = pr; - if (pr & (1 << 10)) - EXTD1.config->channels[10].cb(&EXTD1, 10); - if (pr & (1 << 11)) - EXTD1.config->channels[11].cb(&EXTD1, 11); - if (pr & (1 << 12)) - EXTD1.config->channels[12].cb(&EXTD1, 12); - if (pr & (1 << 13)) - EXTD1.config->channels[13].cb(&EXTD1, 13); - if (pr & (1 << 14)) - EXTD1.config->channels[14].cb(&EXTD1, 14); - if (pr & (1 << 15)) - EXTD1.config->channels[15].cb(&EXTD1, 15); - - OSAL_IRQ_EPILOGUE(); -} -#endif - -#if !defined(STM32_DISABLE_EXTI16_HANDLER) -/** - * @brief EXTI[16] interrupt handler (PVD). - * - * @isr - */ -OSAL_IRQ_HANDLER(Vector44) { - - OSAL_IRQ_PROLOGUE(); - - EXTI->PR = (1 << 16); - EXTD1.config->channels[16].cb(&EXTD1, 16); - - OSAL_IRQ_EPILOGUE(); -} -#endif - -#if !defined(STM32_DISABLE_EXTI17_HANDLER) -/** - * @brief EXTI[17] interrupt handler (RTC Alarm). - * - * @isr - */ -OSAL_IRQ_HANDLER(VectorE4) { - - OSAL_IRQ_PROLOGUE(); - - EXTI->PR = (1 << 17); - EXTD1.config->channels[17].cb(&EXTD1, 17); - - OSAL_IRQ_EPILOGUE(); -} -#endif - -#if !defined(STM32_DISABLE_EXTI18_HANDLER) -/** - * @brief EXTI[18] interrupt handler (USB Wakeup). - * - * @isr - */ -OSAL_IRQ_HANDLER(VectorE8) { - - OSAL_IRQ_PROLOGUE(); - - EXTI->PR = (1 << 18); - EXTD1.config->channels[18].cb(&EXTD1, 18); - - OSAL_IRQ_EPILOGUE(); -} -#endif - -#if !defined(STM32_DISABLE_EXTI19_HANDLER) -/** - * @brief EXTI[19] interrupt handler (Tamper TimeStamp). - * - * @isr - */ -OSAL_IRQ_HANDLER(Vector48) { - - OSAL_IRQ_PROLOGUE(); - - EXTI->PR = (1 << 19); - EXTD1.config->channels[19].cb(&EXTD1, 19); - - OSAL_IRQ_EPILOGUE(); -} -#endif - -#if !defined(STM32_DISABLE_EXTI20_HANDLER) -/** - * @brief EXTI[20] interrupt handler (RTC Wakeup). - * - * @isr - */ -OSAL_IRQ_HANDLER(Vector4C) { - - OSAL_IRQ_PROLOGUE(); - - EXTI->PR = (1 << 20); - EXTD1.config->channels[20].cb(&EXTD1, 20); - - OSAL_IRQ_EPILOGUE(); -} -#endif - -#if !defined(STM32_DISABLE_EXTI21_22_29_HANDLER) -/** - * @brief EXTI[21],EXTI[22],EXTI[29] interrupt handler (COMP1, COMP2, COMP3). - * - * @isr - */ -OSAL_IRQ_HANDLER(Vector140) { - uint32_t pr; - - OSAL_IRQ_PROLOGUE(); - - pr = EXTI->PR & ((1 << 21) | (1 << 22) | (1 << 29)); - EXTI->PR = pr; - if (pr & (1 << 21)) - EXTD1.config->channels[21].cb(&EXTD1, 21); - if (pr & (1 << 22)) - EXTD1.config->channels[22].cb(&EXTD1, 22); - if (pr & (1 << 29)) - EXTD1.config->channels[29].cb(&EXTD1, 29); - - OSAL_IRQ_EPILOGUE(); -} -#endif - -#if !defined(STM32_DISABLE_EXTI30_32_HANDLER) -/** - * @brief EXTI[30]...EXTI[32] interrupt handler (COMP4, COMP5, COMP6). - * - * @isr - */ -OSAL_IRQ_HANDLER(Vector144) { - uint32_t pr; - - OSAL_IRQ_PROLOGUE(); - - pr = EXTI->PR & ((1 << 30) | (1 << 31)); - EXTI->PR = pr; - if (pr & (1 << 30)) - EXTD1.config->channels[30].cb(&EXTD1, 30); - if (pr & (1 << 31)) - EXTD1.config->channels[31].cb(&EXTD1, 31); - - pr = EXTI->PR2 & (1 << 0); - EXTI->PR2 = pr; - if (pr & (1 << 0)) - EXTD1.config->channels[32].cb(&EXTD1, 32); - - OSAL_IRQ_EPILOGUE(); -} -#endif - -#if !defined(STM32_DISABLE_EXTI33_HANDLER) -/** - * @brief EXTI[33] interrupt handler (COMP7). - * - * @isr - */ -OSAL_IRQ_HANDLER(RTC_WKUP_IRQHandler) { - - OSAL_IRQ_PROLOGUE(); - - EXTI->PR2 = (1 << 1); - EXTD1.config->channels[33].cb(&EXTD1, 33); - - OSAL_IRQ_EPILOGUE(); -} -#endif - -/*===========================================================================*/ -/* Driver exported functions. */ -/*===========================================================================*/ - -/** - * @brief Enables EXTI IRQ sources. - * - * @notapi - */ -void ext_lld_exti_irq_enable(void) { - - nvicEnableVector(EXTI0_IRQn, STM32_EXT_EXTI0_IRQ_PRIORITY); - nvicEnableVector(EXTI1_IRQn, STM32_EXT_EXTI1_IRQ_PRIORITY); - nvicEnableVector(EXTI2_TS_IRQn, STM32_EXT_EXTI2_IRQ_PRIORITY); - nvicEnableVector(EXTI3_IRQn, STM32_EXT_EXTI3_IRQ_PRIORITY); - nvicEnableVector(EXTI4_IRQn, STM32_EXT_EXTI4_IRQ_PRIORITY); - nvicEnableVector(EXTI9_5_IRQn, STM32_EXT_EXTI5_9_IRQ_PRIORITY); - nvicEnableVector(EXTI15_10_IRQn, STM32_EXT_EXTI10_15_IRQ_PRIORITY); - nvicEnableVector(PVD_IRQn, STM32_EXT_EXTI16_IRQ_PRIORITY); - nvicEnableVector(RTC_Alarm_IRQn, STM32_EXT_EXTI17_IRQ_PRIORITY); - nvicEnableVector(USBWakeUp_IRQn, STM32_EXT_EXTI18_IRQ_PRIORITY); - nvicEnableVector(TAMPER_STAMP_IRQn, STM32_EXT_EXTI19_IRQ_PRIORITY); - nvicEnableVector(RTC_WKUP_IRQn, STM32_EXT_EXTI20_IRQ_PRIORITY); - nvicEnableVector(COMP1_2_3_IRQn, STM32_EXT_EXTI21_22_29_IRQ_PRIORITY); - nvicEnableVector(COMP4_5_6_IRQn, STM32_EXT_EXTI30_32_IRQ_PRIORITY); - nvicEnableVector(COMP7_IRQn, STM32_EXT_EXTI33_IRQ_PRIORITY); -} - -/** - * @brief Disables EXTI IRQ sources. - * - * @notapi - */ -void ext_lld_exti_irq_disable(void) { - - nvicDisableVector(EXTI0_IRQn); - nvicDisableVector(EXTI1_IRQn); - nvicDisableVector(EXTI2_TS_IRQn); - nvicDisableVector(EXTI3_IRQn); - nvicDisableVector(EXTI4_IRQn); - nvicDisableVector(EXTI9_5_IRQn); - nvicDisableVector(EXTI15_10_IRQn); - nvicDisableVector(PVD_IRQn); - nvicDisableVector(RTC_Alarm_IRQn); - nvicDisableVector(USBWakeUp_IRQn); - nvicDisableVector(TAMPER_STAMP_IRQn); - nvicDisableVector(RTC_WKUP_IRQn); - nvicDisableVector(COMP1_2_3_IRQn); - nvicDisableVector(COMP4_5_6_IRQn); - nvicDisableVector(COMP7_IRQn); -} - -#endif /* HAL_USE_EXT */ - -/** @} */ diff --git a/os/hal/platforms/STM32F30x/ext_lld_isr.h b/os/hal/platforms/STM32F30x/ext_lld_isr.h deleted file mode 100644 index 42f1e30fe..000000000 --- a/os/hal/platforms/STM32F30x/ext_lld_isr.h +++ /dev/null @@ -1,177 +0,0 @@ -/* - ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file STM32F30x/ext_lld_isr.h - * @brief STM32F30x EXT subsystem low level driver ISR header. - * - * @addtogroup EXT - * @{ - */ - -#ifndef _EXT_LLD_ISR_H_ -#define _EXT_LLD_ISR_H_ - -#if HAL_USE_EXT || defined(__DOXYGEN__) - -/*===========================================================================*/ -/* Driver constants. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver pre-compile time settings. */ -/*===========================================================================*/ - -/** - * @name Configuration options - * @{ - */ -/** - * @brief EXTI0 interrupt priority level setting. - */ -#if !defined(STM32_EXT_EXTI0_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_EXT_EXTI0_IRQ_PRIORITY 6 -#endif - -/** - * @brief EXTI1 interrupt priority level setting. - */ -#if !defined(STM32_EXT_EXTI1_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_EXT_EXTI1_IRQ_PRIORITY 6 -#endif - -/** - * @brief EXTI2 interrupt priority level setting. - */ -#if !defined(STM32_EXT_EXTI2_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_EXT_EXTI2_IRQ_PRIORITY 6 -#endif - -/** - * @brief EXTI3 interrupt priority level setting. - */ -#if !defined(STM32_EXT_EXTI3_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_EXT_EXTI3_IRQ_PRIORITY 6 -#endif - -/** - * @brief EXTI4 interrupt priority level setting. - */ -#if !defined(STM32_EXT_EXTI4_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_EXT_EXTI4_IRQ_PRIORITY 6 -#endif - -/** - * @brief EXTI5..9 interrupt priority level setting. - */ -#if !defined(STM32_EXT_EXTI5_9_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_EXT_EXTI5_9_IRQ_PRIORITY 6 -#endif - -/** - * @brief EXTI10..15 interrupt priority level setting. - */ -#if !defined(STM32_EXT_EXTI10_15_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_EXT_EXTI10_15_IRQ_PRIORITY 6 -#endif - -/** - * @brief EXTI16 interrupt priority level setting. - */ -#if !defined(STM32_EXT_EXTI16_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_EXT_EXTI16_IRQ_PRIORITY 6 -#endif - -/** - * @brief EXTI17 interrupt priority level setting. - */ -#if !defined(STM32_EXT_EXTI17_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_EXT_EXTI17_IRQ_PRIORITY 6 -#endif - -/** - * @brief EXTI18 interrupt priority level setting. - */ -#if !defined(STM32_EXT_EXTI18_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_EXT_EXTI18_IRQ_PRIORITY 6 -#endif - -/** - * @brief EXTI19 interrupt priority level setting. - */ -#if !defined(STM32_EXT_EXTI19_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_EXT_EXTI19_IRQ_PRIORITY 6 -#endif - -/** - * @brief EXTI20 interrupt priority level setting. - */ -#if !defined(STM32_EXT_EXTI20_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_EXT_EXTI20_IRQ_PRIORITY 6 -#endif - -/** - * @brief EXTI21,22,29 interrupt priority level setting. - */ -#if !defined(STM32_EXT_EXTI21_22_29_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_EXT_EXTI21_22_29_IRQ_PRIORITY 6 -#endif - -/** - * @brief EXTI30..32 interrupt priority level setting. - */ -#if !defined(STM32_EXT_EXTI30_32_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_EXT_EXTI30_32_IRQ_PRIORITY 6 -#endif - -/** - * @brief EXTI33 interrupt priority level setting. - */ -#if !defined(STM32_EXT_EXTI33_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_EXT_EXTI33_IRQ_PRIORITY 6 -#endif -/** @} */ - -/*===========================================================================*/ -/* Derived constants and error checks. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver data structures and types. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver macros. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* External declarations. */ -/*===========================================================================*/ - -#ifdef __cplusplus -extern "C" { -#endif - void ext_lld_exti_irq_enable(void); - void ext_lld_exti_irq_disable(void); -#ifdef __cplusplus -} -#endif - -#endif /* HAL_USE_EXT */ - -#endif /* _EXT_LLD_ISR_H_ */ - -/** @} */ diff --git a/os/hal/platforms/STM32F30x/hal_lld.c b/os/hal/platforms/STM32F30x/hal_lld.c deleted file mode 100644 index 4521231d5..000000000 --- a/os/hal/platforms/STM32F30x/hal_lld.c +++ /dev/null @@ -1,197 +0,0 @@ -/* - ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file STM32F30x/hal_lld.c - * @brief STM32F30x HAL subsystem low level driver source. - * - * @addtogroup HAL - * @{ - */ - -#include "hal.h" - -/*===========================================================================*/ -/* Driver local definitions. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver exported variables. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver local variables and types. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver local functions. */ -/*===========================================================================*/ - -/** - * @brief Initializes the backup domain. - * @note WARNING! Changing clock source impossible without resetting - * of the whole BKP domain. - */ -static void hal_lld_backup_domain_init(void) { - - /* Backup domain access enabled and left open.*/ - PWR->CR |= PWR_CR_DBP; - - /* Reset BKP domain if different clock source selected.*/ - if ((RCC->BDCR & STM32_RTCSEL_MASK) != STM32_RTCSEL){ - /* Backup domain reset.*/ - RCC->BDCR = RCC_BDCR_BDRST; - RCC->BDCR = 0; - } - - /* If enabled then the LSE is started.*/ -#if STM32_LSE_ENABLED -#if defined(STM32_LSE_BYPASS) - /* LSE Bypass.*/ - RCC->BDCR = STM32_LSEDRV | RCC_BDCR_LSEON | RCC_BDCR_LSEBYP; -#else - /* No LSE Bypass.*/ - RCC->BDCR = STM32_LSEDRV | RCC_BDCR_LSEON; -#endif - while ((RCC->BDCR & RCC_BDCR_LSERDY) == 0) - ; /* Waits until LSE is stable. */ -#endif - -#if STM32_RTCSEL != STM32_RTCSEL_NOCLOCK - /* If the backup domain hasn't been initialized yet then proceed with - initialization.*/ - if ((RCC->BDCR & RCC_BDCR_RTCEN) == 0) { - /* Selects clock source.*/ - RCC->BDCR |= STM32_RTCSEL; - - /* RTC clock enabled.*/ - RCC->BDCR |= RCC_BDCR_RTCEN; - } -#endif /* STM32_RTCSEL != STM32_RTCSEL_NOCLOCK */ -} - -/*===========================================================================*/ -/* Driver interrupt handlers. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver exported functions. */ -/*===========================================================================*/ - -/** - * @brief Low level HAL driver initialization. - * - * @notapi - */ -void hal_lld_init(void) { - - /* Reset of all peripherals.*/ - rccResetAPB1(0xFFFFFFFF); - rccResetAPB2(0xFFFFFFFF); - - /* PWR clock enabled.*/ - rccEnablePWRInterface(FALSE); - - /* Initializes the backup domain.*/ - hal_lld_backup_domain_init(); - -#if defined(STM32_DMA_REQUIRED) - dmaInit(); -#endif - - /* Programmable voltage detector enable.*/ -#if STM32_PVD_ENABLE - PWR->CR |= PWR_CR_PVDE | (STM32_PLS & STM32_PLS_MASK); -#endif /* STM32_PVD_ENABLE */ - - /* SYSCFG clock enabled here because it is a multi-functional unit shared - among multiple drivers.*/ - rccEnableAPB2(RCC_APB2ENR_SYSCFGEN, TRUE); - - /* USB IRQ relocated to not conflict with CAN.*/ - SYSCFG->CFGR1 |= SYSCFG_CFGR1_USB_IT_RMP; -} - -/** - * @brief STM32 clocks and PLL initialization. - * @note All the involved constants come from the file @p board.h. - * @note This function should be invoked just after the system reset. - * - * @special - */ -void stm32_clock_init(void) { - -#if !STM32_NO_INIT - /* HSI setup, it enforces the reset situation in order to handle possible - problems with JTAG probes and re-initializations.*/ - RCC->CR |= RCC_CR_HSION; /* Make sure HSI is ON. */ - while (!(RCC->CR & RCC_CR_HSIRDY)) - ; /* Wait until HSI is stable. */ - RCC->CR &= RCC_CR_HSITRIM | RCC_CR_HSION; /* CR Reset value. */ - RCC->CFGR = 0; /* CFGR reset value. */ - while ((RCC->CFGR & RCC_CFGR_SWS) != RCC_CFGR_SWS_HSI) - ; /* Waits until HSI is selected. */ - -#if STM32_HSE_ENABLED - /* HSE activation.*/ -#if defined(STM32_HSE_BYPASS) - /* HSE Bypass.*/ - RCC->CR |= RCC_CR_HSEON | RCC_CR_HSEBYP; -#else - /* No HSE Bypass.*/ - RCC->CR |= RCC_CR_HSEON; -#endif - while (!(RCC->CR & RCC_CR_HSERDY)) - ; /* Waits until HSE is stable. */ -#endif - -#if STM32_LSI_ENABLED - /* LSI activation.*/ - RCC->CSR |= RCC_CSR_LSION; - while ((RCC->CSR & RCC_CSR_LSIRDY) == 0) - ; /* Waits until LSI is stable. */ -#endif - - /* Clock settings.*/ - RCC->CFGR = STM32_MCOSEL | STM32_USBPRE | STM32_PLLMUL | - STM32_PLLSRC | STM32_PPRE1 | STM32_PPRE2 | - STM32_HPRE; - RCC->CFGR2 = STM32_ADC34PRES | STM32_ADC12PRES | STM32_PREDIV; - RCC->CFGR3 = STM32_UART5SW | STM32_UART4SW | STM32_USART3SW | - STM32_USART2SW | STM32_TIM8SW | STM32_TIM1SW | - STM32_I2C2SW | STM32_I2C1SW | STM32_USART1SW; - -#if STM32_ACTIVATE_PLL - /* PLL activation.*/ - RCC->CR |= RCC_CR_PLLON; - while (!(RCC->CR & RCC_CR_PLLRDY)) - ; /* Waits until PLL is stable. */ -#endif - - /* Flash setup and final clock selection. */ - FLASH->ACR = STM32_FLASHBITS; - - /* Switching to the configured clock source if it is different from HSI.*/ -#if (STM32_SW != STM32_SW_HSI) - /* Switches clock source.*/ - RCC->CFGR |= STM32_SW; - while ((RCC->CFGR & RCC_CFGR_SWS) != (STM32_SW << 2)) - ; /* Waits selection complete. */ -#endif -#endif /* !STM32_NO_INIT */ -} - -/** @} */ diff --git a/os/hal/platforms/STM32F30x/hal_lld.h b/os/hal/platforms/STM32F30x/hal_lld.h deleted file mode 100644 index 83174e930..000000000 --- a/os/hal/platforms/STM32F30x/hal_lld.h +++ /dev/null @@ -1,1105 +0,0 @@ -/* - ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file STM32F30x/hal_lld.h - * @brief STM32F30x HAL subsystem low level driver header. - * @pre This module requires the following macros to be defined in the - * @p board.h file: - * - STM32_LSECLK. - * - STM32_LSEDRV. - * - STM32_LSE_BYPASS (optionally). - * - STM32_HSECLK. - * - STM32_HSE_BYPASS (optionally). - * . - * One of the following macros must also be defined: - * - STM32F30X for Analog & DSP devices. - * . - * - * @addtogroup HAL - * @{ - */ - -#ifndef _HAL_LLD_H_ -#define _HAL_LLD_H_ - -#include "stm32.h" -#include "stm32_registry.h" - -/*===========================================================================*/ -/* Driver constants. */ -/*===========================================================================*/ - -/** - * @brief Defines the support for realtime counters in the HAL. - */ -#define HAL_IMPLEMENTS_COUNTERS TRUE - -/** - * @name Platform identification - * @{ - */ -#define PLATFORM_NAME "STM32F30x Analog & DSP" -/** @} */ - -/** - * @name Absolute Maximum Ratings - * @{ - */ -/** - * @brief Maximum system clock frequency. - */ -#define STM32_SYSCLK_MAX 72000000 - -/** - * @brief Maximum HSE clock frequency. - */ -#define STM32_HSECLK_MAX 32000000 - -/** - * @brief Minimum HSE clock frequency. - */ -#define STM32_HSECLK_MIN 1000000 - -/** - * @brief Maximum LSE clock frequency. - */ -#define STM32_LSECLK_MAX 1000000 - -/** - * @brief Minimum LSE clock frequency. - */ -#define STM32_LSECLK_MIN 32768 - -/** - * @brief Maximum PLLs input clock frequency. - */ -#define STM32_PLLIN_MAX 24000000 - -/** - * @brief Minimum PLLs input clock frequency. - */ -#define STM32_PLLIN_MIN 1000000 - -/** - * @brief Maximum PLL output clock frequency. - */ -#define STM32_PLLOUT_MAX 72000000 - -/** - * @brief Maximum PLL output clock frequency. - */ -#define STM32_PLLOUT_MIN 16000000 - -/** - * @brief Maximum APB1 clock frequency. - */ -#define STM32_PCLK1_MAX 36000000 - -/** - * @brief Maximum APB2 clock frequency. - */ -#define STM32_PCLK2_MAX 72000000 - -/** - * @brief Maximum ADC clock frequency. - */ -#define STM32_ADCCLK_MAX 72000000 -/** @} */ - -/** - * @name Internal clock sources - * @{ - */ -#define STM32_HSICLK 8000000 /**< High speed internal clock. */ -#define STM32_LSICLK 40000 /**< Low speed internal clock. */ -/** @} */ - -/** - * @name PWR_CR register bits definitions - * @{ - */ -#define STM32_PLS_MASK (7 << 5) /**< PLS bits mask. */ -#define STM32_PLS_LEV0 (0 << 5) /**< PVD level 0. */ -#define STM32_PLS_LEV1 (1 << 5) /**< PVD level 1. */ -#define STM32_PLS_LEV2 (2 << 5) /**< PVD level 2. */ -#define STM32_PLS_LEV3 (3 << 5) /**< PVD level 3. */ -#define STM32_PLS_LEV4 (4 << 5) /**< PVD level 4. */ -#define STM32_PLS_LEV5 (5 << 5) /**< PVD level 5. */ -#define STM32_PLS_LEV6 (6 << 5) /**< PVD level 6. */ -#define STM32_PLS_LEV7 (7 << 5) /**< PVD level 7. */ -/** @} */ - -/** - * @name RCC_CFGR register bits definitions - * @{ - */ -#define STM32_SW_HSI (0 << 0) /**< SYSCLK source is HSI. */ -#define STM32_SW_HSE (1 << 0) /**< SYSCLK source is HSE. */ -#define STM32_SW_PLL (2 << 0) /**< SYSCLK source is PLL. */ - -#define STM32_HPRE_DIV1 (0 << 4) /**< SYSCLK divided by 1. */ -#define STM32_HPRE_DIV2 (8 << 4) /**< SYSCLK divided by 2. */ -#define STM32_HPRE_DIV4 (9 << 4) /**< SYSCLK divided by 4. */ -#define STM32_HPRE_DIV8 (10 << 4) /**< SYSCLK divided by 8. */ -#define STM32_HPRE_DIV16 (11 << 4) /**< SYSCLK divided by 16. */ -#define STM32_HPRE_DIV64 (12 << 4) /**< SYSCLK divided by 64. */ -#define STM32_HPRE_DIV128 (13 << 4) /**< SYSCLK divided by 128. */ -#define STM32_HPRE_DIV256 (14 << 4) /**< SYSCLK divided by 256. */ -#define STM32_HPRE_DIV512 (15 << 4) /**< SYSCLK divided by 512. */ - -#define STM32_PPRE1_DIV1 (0 << 8) /**< HCLK divided by 1. */ -#define STM32_PPRE1_DIV2 (4 << 8) /**< HCLK divided by 2. */ -#define STM32_PPRE1_DIV4 (5 << 8) /**< HCLK divided by 4. */ -#define STM32_PPRE1_DIV8 (6 << 8) /**< HCLK divided by 8. */ -#define STM32_PPRE1_DIV16 (7 << 8) /**< HCLK divided by 16. */ - -#define STM32_PPRE2_DIV1 (0 << 11) /**< HCLK divided by 1. */ -#define STM32_PPRE2_DIV2 (4 << 11) /**< HCLK divided by 2. */ -#define STM32_PPRE2_DIV4 (5 << 11) /**< HCLK divided by 4. */ -#define STM32_PPRE2_DIV8 (6 << 11) /**< HCLK divided by 8. */ -#define STM32_PPRE2_DIV16 (7 << 11) /**< HCLK divided by 16. */ - -#define STM32_PLLSRC_HSI (0 << 16) /**< PLL clock source is HSI/2. */ -#define STM32_PLLSRC_HSE (1 << 16) /**< PLL clock source is - HSE/PREDIV. */ - -#define STM32_USBPRE_DIV1P5 (0 << 22) /**< USB clock is PLLCLK/1.5. */ -#define STM32_USBPRE_DIV1 (1 << 22) /**< USB clock is PLLCLK/1. */ - -#define STM32_MCOSEL_NOCLOCK (0 << 24) /**< No clock on MCO pin. */ -#define STM32_MCOSEL_LSI (2 << 24) /**< LSI clock on MCO pin. */ -#define STM32_MCOSEL_LSE (3 << 24) /**< LSE clock on MCO pin. */ -#define STM32_MCOSEL_SYSCLK (4 << 24) /**< SYSCLK on MCO pin. */ -#define STM32_MCOSEL_HSI (5 << 24) /**< HSI clock on MCO pin. */ -#define STM32_MCOSEL_HSE (6 << 24) /**< HSE clock on MCO pin. */ -#define STM32_MCOSEL_PLLDIV2 (7 << 24) /**< PLL/2 clock on MCO pin. */ -/** @} */ - -/** - * @name RCC_BDCR register bits definitions - * @{ - */ -#define STM32_RTCSEL_MASK (3 << 8) /**< RTC clock source mask. */ -#define STM32_RTCSEL_NOCLOCK (0 << 8) /**< No clock. */ -#define STM32_RTCSEL_LSE (1 << 8) /**< LSE used as RTC clock. */ -#define STM32_RTCSEL_LSI (2 << 8) /**< LSI used as RTC clock. */ -#define STM32_RTCSEL_HSEDIV (3 << 8) /**< HSE divided by 32 used as - RTC clock. */ -/** @} */ - -/** - * @name RCC_CFGR2 register bits definitions - * @{ - */ -#define STM32_PREDIV_MASK (15 << 0) /**< PREDIV divisor mask. */ -#define STM32_ADC12PRES_MASK (31 << 4) /**< ADC12 clock source mask. */ -#define STM32_ADC12PRES_NOCLOCK (0 << 4) /**< ADC12 clock is disabled. */ -#define STM32_ADC12PRES_DIV1 (16 << 4) /**< ADC12 clock is PLL/1. */ -#define STM32_ADC12PRES_DIV2 (17 << 4) /**< ADC12 clock is PLL/2. */ -#define STM32_ADC12PRES_DIV4 (18 << 4) /**< ADC12 clock is PLL/4. */ -#define STM32_ADC12PRES_DIV6 (19 << 4) /**< ADC12 clock is PLL/6. */ -#define STM32_ADC12PRES_DIV8 (20 << 4) /**< ADC12 clock is PLL/8. */ -#define STM32_ADC12PRES_DIV10 (21 << 4) /**< ADC12 clock is PLL/10. */ -#define STM32_ADC12PRES_DIV12 (22 << 4) /**< ADC12 clock is PLL/12. */ -#define STM32_ADC12PRES_DIV16 (23 << 4) /**< ADC12 clock is PLL/16. */ -#define STM32_ADC12PRES_DIV32 (24 << 4) /**< ADC12 clock is PLL/32. */ -#define STM32_ADC12PRES_DIV64 (25 << 4) /**< ADC12 clock is PLL/64. */ -#define STM32_ADC12PRES_DIV128 (26 << 4) /**< ADC12 clock is PLL/128. */ -#define STM32_ADC12PRES_DIV256 (27 << 4) /**< ADC12 clock is PLL/256. */ -#define STM32_ADC34PRES_MASK (31 << 4) /**< ADC34 clock source mask. */ -#define STM32_ADC34PRES_NOCLOCK (0 << 4) /**< ADC34 clock is disabled. */ -#define STM32_ADC34PRES_DIV1 (16 << 4) /**< ADC34 clock is PLL/1. */ -#define STM32_ADC34PRES_DIV2 (17 << 4) /**< ADC34 clock is PLL/2. */ -#define STM32_ADC34PRES_DIV4 (18 << 4) /**< ADC34 clock is PLL/4. */ -#define STM32_ADC34PRES_DIV6 (19 << 4) /**< ADC34 clock is PLL/6. */ -#define STM32_ADC34PRES_DIV8 (20 << 4) /**< ADC34 clock is PLL/8. */ -#define STM32_ADC34PRES_DIV10 (21 << 4) /**< ADC34 clock is PLL/10. */ -#define STM32_ADC34PRES_DIV12 (22 << 4) /**< ADC34 clock is PLL/12. */ -#define STM32_ADC34PRES_DIV16 (23 << 4) /**< ADC34 clock is PLL/16. */ -#define STM32_ADC34PRES_DIV32 (24 << 4) /**< ADC34 clock is PLL/32. */ -#define STM32_ADC34PRES_DIV64 (25 << 4) /**< ADC34 clock is PLL/64. */ -#define STM32_ADC34PRES_DIV128 (26 << 4) /**< ADC34 clock is PLL/128. */ -#define STM32_ADC34PRES_DIV256 (27 << 4) /**< ADC34 clock is PLL/256. */ -/** @} */ - -/** - * @name RCC_CFGR3 register bits definitions - * @{ - */ -#define STM32_USART1SW_MASK (3 << 0) /**< USART1 clock source mask. */ -#define STM32_USART1SW_PCLK (0 << 0) /**< USART1 clock is PCLK. */ -#define STM32_USART1SW_SYSCLK (1 << 0) /**< USART1 clock is SYSCLK. */ -#define STM32_USART1SW_LSE (2 << 0) /**< USART1 clock is LSE. */ -#define STM32_USART1SW_HSI (3 << 0) /**< USART1 clock is HSI. */ -#define STM32_I2C1SW_MASK (1 << 4) /**< I2C1 clock source mask. */ -#define STM32_I2C1SW_HSI (0 << 4) /**< I2C1 clock is HSI. */ -#define STM32_I2C1SW_SYSCLK (1 << 4) /**< I2C1 clock is SYSCLK. */ -#define STM32_I2C2SW_MASK (1 << 5) /**< I2C2 clock source mask. */ -#define STM32_I2C2SW_HSI (0 << 5) /**< I2C2 clock is HSI. */ -#define STM32_I2C2SW_SYSCLK (1 << 5) /**< I2C2 clock is SYSCLK. */ -#define STM32_TIM1SW_MASK (1 << 8) /**< TIM1 clock source mask. */ -#define STM32_TIM1SW_PCLK2 (0 << 8) /**< TIM1 clock is PCLK2. */ -#define STM32_TIM1SW_PLLX2 (1 << 10) /**< TIM1 clock is PLL*2. */ -#define STM32_TIM8SW_MASK (1 << 10) /**< TIM8 clock source mask. */ -#define STM32_TIM8SW_PCLK2 (0 << 10) /**< TIM8 clock is PCLK2. */ -#define STM32_TIM8SW_PLLX2 (1 << 10) /**< TIM8 clock is PLL*2. */ -#define STM32_USART2SW_MASK (3 << 16) /**< USART2 clock source mask. */ -#define STM32_USART2SW_PCLK (0 << 16) /**< USART2 clock is PCLK. */ -#define STM32_USART2SW_SYSCLK (1 << 16) /**< USART2 clock is SYSCLK. */ -#define STM32_USART2SW_LSE (2 << 16) /**< USART2 clock is LSE. */ -#define STM32_USART2SW_HSI (3 << 16) /**< USART2 clock is HSI. */ -#define STM32_USART3SW_MASK (3 << 18) /**< USART3 clock source mask. */ -#define STM32_USART3SW_PCLK (0 << 18) /**< USART3 clock is PCLK. */ -#define STM32_USART3SW_SYSCLK (1 << 18) /**< USART3 clock is SYSCLK. */ -#define STM32_USART3SW_LSE (2 << 18) /**< USART3 clock is LSE. */ -#define STM32_USART3SW_HSI (3 << 18) /**< USART3 clock is HSI. */ -#define STM32_UART4SW_MASK (3 << 20) /**< USART4 clock source mask. */ -#define STM32_UART4SW_PCLK (0 << 20) /**< USART4 clock is PCLK. */ -#define STM32_UART4SW_SYSCLK (1 << 20) /**< USART4 clock is SYSCLK. */ -#define STM32_UART4SW_LSE (2 << 20) /**< USART4 clock is LSE. */ -#define STM32_UART4SW_HSI (3 << 20) /**< USART4 clock is HSI. */ -#define STM32_UART5SW_MASK (3 << 22) /**< USART5 clock source mask. */ -#define STM32_UART5SW_PCLK (0 << 22) /**< USART5 clock is PCLK. */ -#define STM32_UART5SW_SYSCLK (1 << 22) /**< USART5 clock is SYSCLK. */ -#define STM32_UART5SW_LSE (2 << 22) /**< USART5 clock is LSE. */ -#define STM32_UART5SW_HSI (3 << 22) /**< USART5 clock is HSI. */ -/** @} */ - -/*===========================================================================*/ -/* Driver pre-compile time settings. */ -/*===========================================================================*/ - -/** - * @name Configuration options - * @{ - */ -/** - * @brief Disables the PWR/RCC initialization in the HAL. - */ -#if !defined(STM32_NO_INIT) || defined(__DOXYGEN__) -#define STM32_NO_INIT FALSE -#endif - -/** - * @brief Enables or disables the programmable voltage detector. - */ -#if !defined(STM32_PVD_ENABLE) || defined(__DOXYGEN__) -#define STM32_PVD_ENABLE FALSE -#endif - -/** - * @brief Sets voltage level for programmable voltage detector. - */ -#if !defined(STM32_PLS) || defined(__DOXYGEN__) -#define STM32_PLS STM32_PLS_LEV0 -#endif - -/** - * @brief Enables or disables the HSI clock source. - */ -#if !defined(STM32_HSI_ENABLED) || defined(__DOXYGEN__) -#define STM32_HSI_ENABLED TRUE -#endif - -/** - * @brief Enables or disables the LSI clock source. - */ -#if !defined(STM32_LSI_ENABLED) || defined(__DOXYGEN__) -#define STM32_LSI_ENABLED TRUE -#endif - -/** - * @brief Enables or disables the HSE clock source. - */ -#if !defined(STM32_HSE_ENABLED) || defined(__DOXYGEN__) -#define STM32_HSE_ENABLED TRUE -#endif - -/** - * @brief Enables or disables the LSE clock source. - */ -#if !defined(STM32_LSE_ENABLED) || defined(__DOXYGEN__) -#define STM32_LSE_ENABLED FALSE -#endif - -/** - * @brief Main clock source selection. - * @note If the selected clock source is not the PLL then the PLL is not - * initialized and started. - * @note The default value is calculated for a 72MHz system clock from - * a 8MHz crystal using the PLL. - */ -#if !defined(STM32_SW) || defined(__DOXYGEN__) -#define STM32_SW STM32_SW_PLL -#endif - -/** - * @brief Clock source for the PLL. - * @note This setting has only effect if the PLL is selected as the - * system clock source. - * @note The default value is calculated for a 72MHz system clock from - * a 8MHz crystal using the PLL. - */ -#if !defined(STM32_PLLSRC) || defined(__DOXYGEN__) -#define STM32_PLLSRC STM32_PLLSRC_HSE -#endif - -/** - * @brief Crystal PLL pre-divider. - * @note This setting has only effect if the PLL is selected as the - * system clock source. - * @note The default value is calculated for a 72MHz system clock from - * a 8MHz crystal using the PLL. - */ -#if !defined(STM32_PREDIV_VALUE) || defined(__DOXYGEN__) -#define STM32_PREDIV_VALUE 1 -#endif - -/** - * @brief PLL multiplier value. - * @note The allowed range is 2...16. - * @note The default value is calculated for a 72MHz system clock from - * a 8MHz crystal using the PLL. - */ -#if !defined(STM32_PLLMUL_VALUE) || defined(__DOXYGEN__) -#define STM32_PLLMUL_VALUE 9 -#endif - -/** - * @brief AHB prescaler value. - * @note The default value is calculated for a 72MHz system clock from - * a 8MHz crystal using the PLL. - */ -#if !defined(STM32_HPRE) || defined(__DOXYGEN__) -#define STM32_HPRE STM32_HPRE_DIV1 -#endif - -/** - * @brief APB1 prescaler value. - */ -#if !defined(STM32_PPRE1) || defined(__DOXYGEN__) -#define STM32_PPRE1 STM32_PPRE1_DIV2 -#endif - -/** - * @brief APB2 prescaler value. - */ -#if !defined(STM32_PPRE2) || defined(__DOXYGEN__) -#define STM32_PPRE2 STM32_PPRE2_DIV2 -#endif - -/** - * @brief MCO pin setting. - */ -#if !defined(STM32_MCOSEL) || defined(__DOXYGEN__) -#define STM32_MCOSEL STM32_MCOSEL_NOCLOCK -#endif - -/** - * @brief ADC12 prescaler value. - */ -#if !defined(STM32_ADC12PRES) || defined(__DOXYGEN__) -#define STM32_ADC12PRES STM32_ADC12PRES_DIV1 -#endif - -/** - * @brief ADC34 prescaler value. - */ -#if !defined(STM32_ADC34PRES) || defined(__DOXYGEN__) -#define STM32_ADC34PRES STM32_ADC34PRES_DIV1 -#endif - -/** - * @brief USART1 clock source. - */ -#if !defined(STM32_USART1SW) || defined(__DOXYGEN__) -#define STM32_USART1SW STM32_USART1SW_PCLK -#endif - -/** - * @brief USART2 clock source. - */ -#if !defined(STM32_USART2SW) || defined(__DOXYGEN__) -#define STM32_USART2SW STM32_USART2SW_PCLK -#endif - -/** - * @brief USART3 clock source. - */ -#if !defined(STM32_USART3SW) || defined(__DOXYGEN__) -#define STM32_USART3SW STM32_USART3SW_PCLK -#endif - -/** - * @brief UART4 clock source. - */ -#if !defined(STM32_UART4SW) || defined(__DOXYGEN__) -#define STM32_UART4SW STM32_UART4SW_PCLK -#endif - -/** - * @brief UART5 clock source. - */ -#if !defined(STM32_UART5SW) || defined(__DOXYGEN__) -#define STM32_UART5SW STM32_UART5SW_PCLK -#endif - -/** - * @brief I2C1 clock source. - */ -#if !defined(STM32_I2C1SW) || defined(__DOXYGEN__) -#define STM32_I2C1SW STM32_I2C1SW_SYSCLK -#endif - -/** - * @brief I2C2 clock source. - */ -#if !defined(STM32_I2C2SW) || defined(__DOXYGEN__) -#define STM32_I2C2SW STM32_I2C2SW_SYSCLK -#endif - -/** - * @brief TIM1 clock source. - */ -#if !defined(STM32_TIM1SW) || defined(__DOXYGEN__) -#define STM32_TIM1SW STM32_TIM1SW_PCLK2 -#endif - -/** - * @brief TIM8 clock source. - */ -#if !defined(STM32_TIM8SW) || defined(__DOXYGEN__) -#define STM32_TIM8SW STM32_TIM8SW_PCLK2 -#endif - -/** - * @brief RTC clock source. - */ -#if !defined(STM32_RTCSEL) || defined(__DOXYGEN__) -#define STM32_RTCSEL STM32_RTCSEL_LSI -#endif - -/** - * @brief USB clock setting. - */ -#if !defined(STM32_USB_CLOCK_REQUIRED) || defined(__DOXYGEN__) -#define STM32_USB_CLOCK_REQUIRED TRUE -#endif - -/** - * @brief USB prescaler initialization. - */ -#if !defined(STM32_USBPRE) || defined(__DOXYGEN__) -#define STM32_USBPRE STM32_USBPRE_DIV1P5 -#endif -/** @} */ - -/*===========================================================================*/ -/* Derived constants and error checks. */ -/*===========================================================================*/ - -/* - * Configuration-related checks. - */ -#if !defined(STM32F30x_MCUCONF) -#error "Using a wrong mcuconf.h file, STM32F30x_MCUCONF not defined" -#endif - -/* - * HSI related checks. - */ -#if STM32_HSI_ENABLED -#else /* !STM32_HSI_ENABLED */ - -#if STM32_SW == STM32_SW_HSI -#error "HSI not enabled, required by STM32_SW" -#endif - -#if STM32_USART1SW == STM32_USART1SW_HSI -#error "HSI not enabled, required by STM32_USART1SW" -#endif - -#if STM32_USART2SW == STM32_USART2SW_HSI -#error "HSI not enabled, required by STM32_USART2SW" -#endif - -#if STM32_USART3SW == STM32_USART3SW_HSI -#error "HSI not enabled, required by STM32_USART3SW" -#endif - -#if STM32_UART4SW == STM32_UART4SW_HSI -#error "HSI not enabled, required by STM32_UART4SW" -#endif - -#if STM32_UART5SW == STM32_UART5SW_HSI -#error "HSI not enabled, required by STM32_UART5SW" -#endif - -#if STM32_I2C1SW == STM32_I2C1SW_HSI -#error "HSI not enabled, required by STM32_I2C1SW" -#endif - -#if STM32_I2C2SW == STM32_I2C2SW_HSI -#error "HSI not enabled, required by STM32_I2C2SW" -#endif - -#if STM32_TIM1SW == STM32_TIM1SW_HSI -#error "HSI not enabled, required by STM32_TIM1SW" -#endif - -#if STM32_TIM8SW == STM32_TIM8SW_HSI -#error "HSI not enabled, required by STM32_TIM8SW" -#endif - -#if (STM32_SW == STM32_SW_PLL) && (STM32_PLLSRC == STM32_PLLSRC_HSI) -#error "HSI not enabled, required by STM32_SW and STM32_PLLSRC" -#endif - -#if (STM32_MCOSEL == STM32_MCOSEL_HSI) || \ - ((STM32_MCOSEL == STM32_MCOSEL_PLLDIV2) && \ - (STM32_PLLSRC == STM32_PLLSRC_HSI)) -#error "HSI not enabled, required by STM32_MCOSEL" -#endif - -#endif /* !STM32_HSI_ENABLED */ - -/* - * HSE related checks. - */ -#if STM32_HSE_ENABLED - -#if STM32_HSECLK == 0 -#error "HSE frequency not defined" -#elif (STM32_HSECLK < STM32_HSECLK_MIN) || (STM32_HSECLK > STM32_HSECLK_MAX) -#error "STM32_HSECLK outside acceptable range (STM32_HSECLK_MIN...STM32_HSECLK_MAX)" -#endif - -#else /* !STM32_HSE_ENABLED */ - -#if STM32_SW == STM32_SW_HSE -#error "HSE not enabled, required by STM32_SW" -#endif - -#if (STM32_SW == STM32_SW_PLL) && (STM32_PLLSRC == STM32_PLLSRC_HSE) -#error "HSE not enabled, required by STM32_SW and STM32_PLLSRC" -#endif - -#if (STM32_MCOSEL == STM32_MCOSEL_HSE) || \ - ((STM32_MCOSEL == STM32_MCOSEL_PLLDIV2) && \ - (STM32_PLLSRC == STM32_PLLSRC_HSE)) -#error "HSE not enabled, required by STM32_MCOSEL" -#endif - -#if STM32_RTCSEL == STM32_RTCSEL_HSEDIV -#error "HSE not enabled, required by STM32_RTCSEL" -#endif - -#endif /* !STM32_HSE_ENABLED */ - -/* - * LSI related checks. - */ -#if STM32_LSI_ENABLED -#else /* !STM32_LSI_ENABLED */ - -#if STM32_RTCSEL == STM32_RTCSEL_LSI -#error "LSI not enabled, required by STM32_RTCSEL" -#endif - -#endif /* !STM32_LSI_ENABLED */ - -/* - * LSE related checks. - */ -#if STM32_LSE_ENABLED - -#if !defined(STM32_LSECLK) || (STM32_LSECLK == 0) -#error "STM32_LSECLK not defined" -#endif - -#if (STM32_LSECLK < STM32_LSECLK_MIN) || (STM32_LSECLK > STM32_LSECLK_MAX) -#error "STM32_LSECLK outside acceptable range (STM32_LSECLK_MIN...STM32_LSECLK_MAX)" -#endif - -#if !defined(STM32_LSEDRV) -#error "STM32_LSEDRV not defined" -#endif - -#if (STM32_LSEDRV >> 3) > 3 -#error "STM32_LSEDRV outside acceptable range ((0<<3)...(3<<3))" -#endif - -#if STM32_USART1SW == STM32_USART1SW_LSE -#error "LSE not enabled, required by STM32_USART1SW" -#endif - -#if STM32_USART2SW == STM32_USART2SW_LSE -#error "LSE not enabled, required by STM32_USART2SW" -#endif - -#if STM32_USART3SW == STM32_USART3SW_LSE -#error "LSE not enabled, required by STM32_USART3SW" -#endif - -#if STM32_UART4SW == STM32_UART4SW_LSE -#error "LSE not enabled, required by STM32_UART4SW" -#endif - -#if STM32_UART5SW == STM32_UART5SW_LSE -#error "LSE not enabled, required by STM32_UART5SW" -#endif - -#else /* !STM32_LSE_ENABLED */ - -#if STM32_RTCSEL == STM32_RTCSEL_LSE -#error "LSE not enabled, required by STM32_RTCSEL" -#endif - -#endif /* !STM32_LSE_ENABLED */ - -/* PLL activation conditions.*/ -#if (STM32_SW == STM32_SW_PLL) || \ - (STM32_MCOSEL == STM32_MCOSEL_PLLDIV2) || \ - (STM32_TIM1SW == STM32_TIM1SW_PLLX2) || \ - (STM32_TIM8SW == STM32_TIM8SW_PLLX2) || \ - (STM32_ADC12PRES != STM32_ADC12PRES_NOCLOCK) || \ - (STM32_ADC34PRES != STM32_ADC34PRES_NOCLOCK) || \ - STM32_USB_CLOCK_REQUIRED || \ - defined(__DOXYGEN__) -/** - * @brief PLL activation flag. - */ -#define STM32_ACTIVATE_PLL TRUE -#else -#define STM32_ACTIVATE_PLL FALSE -#endif - -/* HSE prescaler setting check.*/ -#if ((STM32_PREDIV_VALUE >= 1) || (STM32_PREDIV_VALUE <= 16)) -#define STM32_PREDIV ((STM32_PREDIV_VALUE - 1) << 0) -#else -#error "invalid STM32_PREDIV value specified" -#endif - -/** - * @brief PLLMUL field. - */ -#if ((STM32_PLLMUL_VALUE >= 2) && (STM32_PLLMUL_VALUE <= 16)) || \ - defined(__DOXYGEN__) -#define STM32_PLLMUL ((STM32_PLLMUL_VALUE - 2) << 18) -#else -#error "invalid STM32_PLLMUL_VALUE value specified" -#endif - -/** - * @brief PLL input clock frequency. - */ -#if (STM32_PLLSRC == STM32_PLLSRC_HSE) || defined(__DOXYGEN__) -#define STM32_PLLCLKIN (STM32_HSECLK / STM32_PREDIV_VALUE) -#elif STM32_PLLSRC == STM32_PLLSRC_HSI -#define STM32_PLLCLKIN (STM32_HSICLK / 2) -#else -#error "invalid STM32_PLLSRC value specified" -#endif - -/* PLL input frequency range check.*/ -#if (STM32_PLLCLKIN < STM32_PLLIN_MIN) || (STM32_PLLCLKIN > STM32_PLLIN_MAX) -#error "STM32_PLLCLKIN outside acceptable range (STM32_PLLIN_MIN...STM32_PLLIN_MAX)" -#endif - -/** - * @brief PLL output clock frequency. - */ -#define STM32_PLLCLKOUT (STM32_PLLCLKIN * STM32_PLLMUL_VALUE) - -/* PLL output frequency range check.*/ -#if (STM32_PLLCLKOUT < STM32_PLLOUT_MIN) || (STM32_PLLCLKOUT > STM32_PLLOUT_MAX) -#error "STM32_PLLCLKOUT outside acceptable range (STM32_PLLOUT_MIN...STM32_PLLOUT_MAX)" -#endif - -/** - * @brief System clock source. - */ -#if (STM32_SW == STM32_SW_PLL) || defined(__DOXYGEN__) -#define STM32_SYSCLK STM32_PLLCLKOUT -#elif (STM32_SW == STM32_SW_HSI) -#define STM32_SYSCLK STM32_HSICLK -#elif (STM32_SW == STM32_SW_HSE) -#define STM32_SYSCLK STM32_HSECLK -#else -#error "invalid STM32_SW value specified" -#endif - -/* Check on the system clock.*/ -#if STM32_SYSCLK > STM32_SYSCLK_MAX -#error "STM32_SYSCLK above maximum rated frequency (STM32_SYSCLK_MAX)" -#endif - -/** - * @brief AHB frequency. - */ -#if (STM32_HPRE == STM32_HPRE_DIV1) || defined(__DOXYGEN__) -#define STM32_HCLK (STM32_SYSCLK / 1) -#elif STM32_HPRE == STM32_HPRE_DIV2 -#define STM32_HCLK (STM32_SYSCLK / 2) -#elif STM32_HPRE == STM32_HPRE_DIV4 -#define STM32_HCLK (STM32_SYSCLK / 4) -#elif STM32_HPRE == STM32_HPRE_DIV8 -#define STM32_HCLK (STM32_SYSCLK / 8) -#elif STM32_HPRE == STM32_HPRE_DIV16 -#define STM32_HCLK (STM32_SYSCLK / 16) -#elif STM32_HPRE == STM32_HPRE_DIV64 -#define STM32_HCLK (STM32_SYSCLK / 64) -#elif STM32_HPRE == STM32_HPRE_DIV128 -#define STM32_HCLK (STM32_SYSCLK / 128) -#elif STM32_HPRE == STM32_HPRE_DIV256 -#define STM32_HCLK (STM32_SYSCLK / 256) -#elif STM32_HPRE == STM32_HPRE_DIV512 -#define STM32_HCLK (STM32_SYSCLK / 512) -#else -#error "invalid STM32_HPRE value specified" -#endif - -/* AHB frequency check.*/ -#if STM32_HCLK > STM32_SYSCLK_MAX -#error "STM32_HCLK exceeding maximum frequency (STM32_SYSCLK_MAX)" -#endif - -/** - * @brief APB1 frequency. - */ -#if (STM32_PPRE1 == STM32_PPRE1_DIV1) || defined(__DOXYGEN__) -#define STM32_PCLK1 (STM32_HCLK / 1) -#elif STM32_PPRE1 == STM32_PPRE1_DIV2 -#define STM32_PCLK1 (STM32_HCLK / 2) -#elif STM32_PPRE1 == STM32_PPRE1_DIV4 -#define STM32_PCLK1 (STM32_HCLK / 4) -#elif STM32_PPRE1 == STM32_PPRE1_DIV8 -#define STM32_PCLK1 (STM32_HCLK / 8) -#elif STM32_PPRE1 == STM32_PPRE1_DIV16 -#define STM32_PCLK1 (STM32_HCLK / 16) -#else -#error "invalid STM32_PPRE1 value specified" -#endif - -/* APB1 frequency check.*/ -#if STM32_PCLK1 > STM32_PCLK1_MAX -#error "STM32_PCLK1 exceeding maximum frequency (STM32_PCLK1_MAX)" -#endif - -/** - * @brief APB2 frequency. - */ -#if (STM32_PPRE2 == STM32_PPRE2_DIV1) || defined(__DOXYGEN__) -#define STM32_PCLK2 (STM32_HCLK / 1) -#elif STM32_PPRE2 == STM32_PPRE2_DIV2 -#define STM32_PCLK2 (STM32_HCLK / 2) -#elif STM32_PPRE2 == STM32_PPRE2_DIV4 -#define STM32_PCLK2 (STM32_HCLK / 4) -#elif STM32_PPRE2 == STM32_PPRE2_DIV8 -#define STM32_PCLK2 (STM32_HCLK / 8) -#elif STM32_PPRE2 == STM32_PPRE2_DIV16 -#define STM32_PCLK2 (STM32_HCLK / 16) -#else -#error "invalid STM32_PPRE2 value specified" -#endif - -/* APB2 frequency check.*/ -#if STM32_PCLK2 > STM32_PCLK2_MAX -#error "STM32_PCLK2 exceeding maximum frequency (STM32_PCLK2_MAX)" -#endif - -/** - * @brief RTC clock. - */ -#if (STM32_RTCSEL == STM32_RTCSEL_LSE) || defined(__DOXYGEN__) -#define STM32_RTCCLK STM32_LSECLK -#elif STM32_RTCSEL == STM32_RTCSEL_LSI -#define STM32_RTCCLK STM32_LSICLK -#elif STM32_RTCSEL == STM32_RTCSEL_HSEDIV -#define STM32_RTCCLK (STM32_HSECLK / 32) -#elif STM32_RTCSEL == STM32_RTCSEL_NOCLOCK -#define STM32_RTCCLK 0 -#else -#error "invalid source selected for RTC clock" -#endif - -/** - * @brief ADC12 frequency. - */ -#if (STM32_ADC12PRES == STM32_ADC12PRES_NOCLOCK) || defined(__DOXYGEN__) -#define STM32_ADC12CLK 0 -#elif STM32_ADC12PRES == STM32_ADC12PRES_DIV1 -#define STM32_ADC12CLK (STM32_PLLCLKOUT / 1) -#elif STM32_ADC12PRES == STM32_ADC12PRES_DIV2 -#define STM32_ADC12CLK (STM32_PLLCLKOUT / 2) -#elif STM32_ADC12PRES == STM32_ADC12PRES_DIV4 -#define STM32_ADC12CLK (STM32_PLLCLKOUT / 4) -#elif STM32_ADC12PRES == STM32_ADC12PRES_DIV6 -#define STM32_ADC12CLK (STM32_PLLCLKOUT / 6) -#elif STM32_ADC12PRES == STM32_ADC12PRES_DIV8 -#define STM32_ADC12CLK (STM32_PLLCLKOUT / 8) -#elif STM32_ADC12PRES == STM32_ADC12PRES_DIV10 -#define STM32_ADC12CLK (STM32_PLLCLKOUT / 10) -#elif STM32_ADC12PRES == STM32_ADC12PRES_DIV12 -#define STM32_ADC12CLK (STM32_PLLCLKOUT / 12) -#elif STM32_ADC12PRES == STM32_ADC12PRES_DIV16 -#define STM32_ADC12CLK (STM32_PLLCLKOUT / 16) -#elif STM32_ADC12PRES == STM32_ADC12PRES_DIV32 -#define STM32_ADC12CLK (STM32_PLLCLKOUT / 32) -#elif STM32_ADC12PRES == STM32_ADC12PRES_DIV64 -#define STM32_ADC12CLK (STM32_PLLCLKOUT / 64) -#elif STM32_ADC12PRES == STM32_ADC12PRES_DIV128 -#define STM32_ADC12CLK (STM32_PLLCLKOUT / 128) -#elif STM32_ADC12PRES == STM32_ADC12PRES_DIV256 -#define STM32_ADC12CLK (STM32_PLLCLKOUT / 256) -#else -#error "invalid STM32_ADC12PRES value specified" -#endif - -/** - * @brief ADC34 frequency. - */ -#if (STM32_ADC43PRES == STM32_ADC34PRES_NOCLOCK) || defined(__DOXYGEN__) -#define STM32_ADC34CLK 0 -#elif STM32_ADC34PRES == STM32_ADC34PRES_DIV1 -#define STM32_ADC34CLK (STM32_PLLCLKOUT / 1) -#elif STM32_ADC34PRES == STM32_ADC34PRES_DIV2 -#define STM32_ADC34CLK (STM32_PLLCLKOUT / 2) -#elif STM32_ADC34PRES == STM32_ADC34PRES_DIV4 -#define STM32_ADC34CLK (STM32_PLLCLKOUT / 4) -#elif STM32_ADC34PRES == STM32_ADC34PRES_DIV6 -#define STM32_ADC34CLK (STM32_PLLCLKOUT / 6) -#elif STM32_ADC34PRES == STM32_ADC34PRES_DIV8 -#define STM32_ADC34CLK (STM32_PLLCLKOUT / 8) -#elif STM32_ADC34PRES == STM32_ADC34PRES_DIV10 -#define STM32_ADC34CLK (STM32_PLLCLKOUT / 10) -#elif STM32_ADC34PRES == STM32_ADC34PRES_DIV12 -#define STM32_ADC34CLK (STM32_PLLCLKOUT / 12) -#elif STM32_ADC34PRES == STM32_ADC34PRES_DIV16 -#define STM32_ADC34CLK (STM32_PLLCLKOUT / 16) -#elif STM32_ADC34PRES == STM32_ADC34PRES_DIV32 -#define STM32_ADC34CLK (STM32_PLLCLKOUT / 32) -#elif STM32_ADC34PRES == STM32_ADC34PRES_DIV64 -#define STM32_ADC34CLK (STM32_PLLCLKOUT / 64) -#elif STM32_ADC34PRES == STM32_ADC34PRES_DIV128 -#define STM32_ADC34CLK (STM32_PLLCLKOUT / 128) -#elif STM32_ADC34PRES == STM32_ADC34PRES_DIV256 -#define STM32_ADC34CLK (STM32_PLLCLKOUT / 256) -#else -#error "invalid STM32_ADC34PRES value specified" -#endif - -/* ADC12 frequency check.*/ -#if STM32_ADC12CLK > STM32_ADCCLK_MAX -#error "STM32_ADC12CLK exceeding maximum frequency (STM32_ADCCLK_MAX)" -#endif - -/* ADC34 frequency check.*/ -#if STM32_ADC34CLK > STM32_ADCCLK_MAX -#error "STM32_ADC34CLK exceeding maximum frequency (STM32_ADCCLK_MAX)" -#endif - -/** - * @brief I2C1 frequency. - */ -#if STM32_I2C1SW == STM32_I2C1SW_HSI -#define STM32_I2C1CLK STM32_HSICLK -#elif STM32_I2C1SW == STM32_I2C1SW_SYSCLK -#define STM32_I2C1CLK STM32_SYSCLK -#else -#error "invalid source selected for I2C1 clock" -#endif - -/** - * @brief I2C2 frequency. - */ -#if STM32_I2C2SW == STM32_I2C2SW_HSI -#define STM32_I2C2CLK STM32_HSICLK -#elif STM32_I2C2SW == STM32_I2C2SW_SYSCLK -#define STM32_I2C2CLK STM32_SYSCLK -#else -#error "invalid source selected for I2C2 clock" -#endif - -/** - * @brief USART1 frequency. - */ -#if STM32_USART1SW == STM32_USART1SW_PCLK -#define STM32_USART1CLK STM32_PCLK2 -#elif STM32_USART1SW == STM32_USART1SW_SYSCLK -#define STM32_USART1CLK STM32_SYSCLK -#elif STM32_USART1SW == STM32_USART1SW_LSECLK -#define STM32_USART1CLK STM32_LSECLK -#elif STM32_USART1SW == STM32_USART1SW_HSICLK -#define STM32_USART1CLK STM32_HSICLK -#else -#error "invalid source selected for USART1 clock" -#endif - -/** - * @brief USART2 frequency. - */ -#if STM32_USART2SW == STM32_USART2SW_PCLK -#define STM32_USART2CLK STM32_PCLK1 -#elif STM32_USART2SW == STM32_USART2SW_SYSCLK -#define STM32_USART2CLK STM32_SYSCLK -#elif STM32_USART2SW == STM32_USART2SW_LSECLK -#define STM32_USART2CLK STM32_LSECLK -#elif STM32_USART2SW == STM32_USART2SW_HSICLK -#define STM32_USART2CLK STM32_HSICLK -#else -#error "invalid source selected for USART2 clock" -#endif - -/** - * @brief USART3 frequency. - */ -#if STM32_USART3SW == STM32_USART3SW_PCLK -#define STM32_USART3CLK STM32_PCLK1 -#elif STM32_USART3SW == STM32_USART3SW_SYSCLK -#define STM32_USART3CLK STM32_SYSCLK -#elif STM32_USART3SW == STM32_USART3SW_LSECLK -#define STM32_USART3CLK STM32_LSECLK -#elif STM32_USART3SW == STM32_USART3SW_HSICLK -#define STM32_USART3CLK STM32_HSICLK -#else -#error "invalid source selected for USART3 clock" -#endif - -/** - * @brief UART4 frequency. - */ -#if STM32_UART4SW == STM32_UART4SW_PCLK -#define STM32_UART4CLK STM32_PCLK1 -#elif STM32_UART4SW == STM32_UART4SW_SYSCLK -#define STM32_UART4CLK STM32_SYSCLK -#elif STM32_UART4SW == STM32_UART4SW_LSECLK -#define STM32_UART4CLK STM32_LSECLK -#elif STM32_UART4SW == STM32_UART4SW_HSICLK -#define STM32_UART4CLK STM32_HSICLK -#else -#error "invalid source selected for UART4 clock" -#endif - -/** - * @brief UART5 frequency. - */ -#if STM32_UART5SW == STM32_UART5SW_PCLK -#define STM32_UART5CLK STM32_PCLK1 -#elif STM32_UART5SW == STM32_UART5SW_SYSCLK -#define STM32_UART5CLK STM32_SYSCLK -#elif STM32_UART5SW == STM32_UART5SW_LSECLK -#define STM32_UART5CLK STM32_LSECLK -#elif STM32_UART5SW == STM32_UART5SW_HSICLK -#define STM32_UART5CLK STM32_HSICLK -#else -#error "invalid source selected for UART5 clock" -#endif - -/** - * @brief TIM1 frequency. - */ -#if STM32_TIM1SW == STM32_TIM1SW_PCLK2 -#define STM32_TIM1CLK STM32_PCLK2 -#elif STM32_TIM1SW == STM32_TIM1SW_PLLX2 -#define STM32_TIM1CLK (STM32_PLLCLKOUT * 2) -#else -#error "invalid source selected for TIM1 clock" -#endif - -/** - * @brief TIM8 frequency. - */ -#if STM32_TIM8SW == STM32_TIM8SW_PCLK2 -#define STM32_TIM8CLK STM32_PCLK2 -#elif STM32_TIM8SW == STM32_TIM8SW_PLLX2 -#define STM32_TIM8CLK (STM32_PLLCLKOUT * 2) -#else -#error "invalid source selected for TIM8 clock" -#endif - -/** - * @brief Timers 2, 3, 4, 6, 7 frequency. - */ -#if (STM32_PPRE1 == STM32_PPRE1_DIV1) || defined(__DOXYGEN__) -#define STM32_TIMCLK1 (STM32_PCLK1 * 1) -#else -#define STM32_TIMCLK1 (STM32_PCLK1 * 2) -#endif - -/** - * @brief Timers 1, 8, 15, 16, 17 frequency. - */ -#if (STM32_PPRE2 == STM32_PPRE2_DIV1) || defined(__DOXYGEN__) -#define STM32_TIMCLK2 (STM32_PCLK2 * 1) -#else -#define STM32_TIMCLK2 (STM32_PCLK2 * 2) -#endif - -/** - * @brief USB frequency. - */ -#if (STM32_USBPRE == STM32_USBPRE_DIV1P5) || defined(__DOXYGEN__) -#define STM32_USBCLK ((STM32_PLLCLKOUT * 2) / 3) -#elif (STM32_USBPRE == STM32_USBPRE_DIV1) -#define STM32_USBCLK STM32_PLLCLKOUT -#else -#error "invalid STM32_USBPRE value specified" -#endif - -/** - * @brief Flash settings. - */ -#if (STM32_HCLK <= 24000000) || defined(__DOXYGEN__) -#define STM32_FLASHBITS 0x00000010 -#elif STM32_HCLK <= 48000000 -#define STM32_FLASHBITS 0x00000011 -#else -#define STM32_FLASHBITS 0x00000012 -#endif - -/*===========================================================================*/ -/* Driver data structures and types. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver macros. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* External declarations. */ -/*===========================================================================*/ - -/* Various helpers.*/ -#include "nvic.h" -#include "stm32_isr.h" -#include "stm32_dma.h" -#include "stm32_rcc.h" - -#ifdef __cplusplus -extern "C" { -#endif - void hal_lld_init(void); - void stm32_clock_init(void); -#ifdef __cplusplus -} -#endif - -#endif /* _HAL_LLD_H_ */ - -/** @} */ diff --git a/os/hal/platforms/STM32F30x/platform.mk b/os/hal/platforms/STM32F30x/platform.mk deleted file mode 100644 index 09d7f1872..000000000 --- a/os/hal/platforms/STM32F30x/platform.mk +++ /dev/null @@ -1,31 +0,0 @@ -# List of all the STM32F30x platform files. -PLATFORMSRC = ${CHIBIOS}/os/hal/platforms/common/ARMCMx/nvic.c \ - ${CHIBIOS}/os/hal/platforms/STM32F30x/stm32_dma.c \ - ${CHIBIOS}/os/hal/platforms/STM32F30x/hal_lld.c \ - ${CHIBIOS}/os/hal/platforms/STM32F30x/adc_lld.c \ - ${CHIBIOS}/os/hal/platforms/STM32F30x/ext_lld_isr.c \ - ${CHIBIOS}/os/hal/platforms/STM32/can_lld.c \ - ${CHIBIOS}/os/hal/platforms/STM32/ext_lld.c \ - ${CHIBIOS}/os/hal/platforms/STM32/GPIOv2/pal_lld.c \ - ${CHIBIOS}/os/hal/platforms/STM32/I2Cv2/i2c_lld.c \ - ${CHIBIOS}/os/hal/platforms/STM32/RTCv2/rtc_lld.c \ - ${CHIBIOS}/os/hal/platforms/STM32/SPIv2/spi_lld.c \ - ${CHIBIOS}/os/hal/platforms/STM32/TIMv1/gpt_lld.c \ - ${CHIBIOS}/os/hal/platforms/STM32/TIMv1/icu_lld.c \ - ${CHIBIOS}/os/hal/platforms/STM32/TIMv1/pwm_lld.c \ - ${CHIBIOS}/os/hal/platforms/STM32/TIMv1/st_lld.c \ - ${CHIBIOS}/os/hal/platforms/STM32/USARTv2/serial_lld.c \ - ${CHIBIOS}/os/hal/platforms/STM32/USARTv2/uart_lld.c \ - ${CHIBIOS}/os/hal/platforms/STM32/USBv1/usb_lld.c - -# Required include directories -PLATFORMINC = ${CHIBIOS}/os/hal/platforms/common/ARMCMx \ - ${CHIBIOS}/os/hal/platforms/STM32F30x \ - ${CHIBIOS}/os/hal/platforms/STM32 \ - ${CHIBIOS}/os/hal/platforms/STM32/GPIOv2 \ - ${CHIBIOS}/os/hal/platforms/STM32/I2Cv2 \ - ${CHIBIOS}/os/hal/platforms/STM32/RTCv2 \ - ${CHIBIOS}/os/hal/platforms/STM32/SPIv2 \ - ${CHIBIOS}/os/hal/platforms/STM32/TIMv1 \ - ${CHIBIOS}/os/hal/platforms/STM32/USARTv2 \ - ${CHIBIOS}/os/hal/platforms/STM32/USBv1 diff --git a/os/hal/platforms/STM32F30x/stm32_dma.c b/os/hal/platforms/STM32F30x/stm32_dma.c deleted file mode 100644 index eb73f1b37..000000000 --- a/os/hal/platforms/STM32F30x/stm32_dma.c +++ /dev/null @@ -1,449 +0,0 @@ -/* - ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file STM32F30x/stm32_dma.c - * @brief DMA helper driver code. - * - * @addtogroup STM32F30x_DMA - * @details DMA sharing helper driver. In the STM32 the DMA streams are a - * shared resource, this driver allows to allocate and free DMA - * streams at runtime in order to allow all the other device - * drivers to coordinate the access to the resource. - * @note The DMA ISR handlers are all declared into this module because - * sharing, the various device drivers can associate a callback to - * ISRs when allocating streams. - * @{ - */ - -#include "hal.h" - -/* The following macro is only defined if some driver requiring DMA services - has been enabled.*/ -#if defined(STM32_DMA_REQUIRED) || defined(__DOXYGEN__) - -/*===========================================================================*/ -/* Driver local definitions. */ -/*===========================================================================*/ - -/** - * @brief Mask of the DMA1 streams in @p dma_streams_mask. - */ -#define STM32_DMA1_STREAMS_MASK 0x0000007F - -/** - * @brief Mask of the DMA2 streams in @p dma_streams_mask. - */ -#define STM32_DMA2_STREAMS_MASK 0x00000F80 - -/** - * @brief Post-reset value of the stream CCR register. - */ -#define STM32_DMA_CCR_RESET_VALUE 0x00000000 - -/*===========================================================================*/ -/* Driver exported variables. */ -/*===========================================================================*/ - -/** - * @brief DMA streams descriptors. - * @details This table keeps the association between an unique stream - * identifier and the involved physical registers. - * @note Don't use this array directly, use the appropriate wrapper macros - * instead: @p STM32_DMA1_STREAM1, @p STM32_DMA1_STREAM2 etc. - */ -const stm32_dma_stream_t _stm32_dma_streams[STM32_DMA_STREAMS] = { - {DMA1_Channel1, &DMA1->IFCR, 0, 0, DMA1_Channel1_IRQn}, - {DMA1_Channel2, &DMA1->IFCR, 4, 1, DMA1_Channel2_IRQn}, - {DMA1_Channel3, &DMA1->IFCR, 8, 2, DMA1_Channel3_IRQn}, - {DMA1_Channel4, &DMA1->IFCR, 12, 3, DMA1_Channel4_IRQn}, - {DMA1_Channel5, &DMA1->IFCR, 16, 4, DMA1_Channel5_IRQn}, - {DMA1_Channel6, &DMA1->IFCR, 20, 5, DMA1_Channel6_IRQn}, - {DMA1_Channel7, &DMA1->IFCR, 24, 6, DMA1_Channel7_IRQn}, - {DMA2_Channel1, &DMA2->IFCR, 0, 7, DMA2_Channel1_IRQn}, - {DMA2_Channel2, &DMA2->IFCR, 4, 8, DMA2_Channel2_IRQn}, - {DMA2_Channel3, &DMA2->IFCR, 8, 9, DMA2_Channel3_IRQn}, - {DMA2_Channel4, &DMA2->IFCR, 12, 10, DMA2_Channel4_IRQn}, - {DMA2_Channel5, &DMA2->IFCR, 16, 11, DMA2_Channel5_IRQn}, -}; - -/*===========================================================================*/ -/* Driver local variables and types. */ -/*===========================================================================*/ - -/** - * @brief DMA ISR redirector type. - */ -typedef struct { - stm32_dmaisr_t dma_func; /**< @brief DMA callback function. */ - void *dma_param; /**< @brief DMA callback parameter. */ -} dma_isr_redir_t; - -/** - * @brief Mask of the allocated streams. - */ -static uint32_t dma_streams_mask; - -/** - * @brief DMA IRQ redirectors. - */ -static dma_isr_redir_t dma_isr_redir[STM32_DMA_STREAMS]; - -/*===========================================================================*/ -/* Driver local functions. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver interrupt handlers. */ -/*===========================================================================*/ - -/** - * @brief DMA1 stream 1 shared interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(Vector6C) { - uint32_t flags; - - OSAL_IRQ_PROLOGUE(); - - flags = (DMA1->ISR >> 0) & STM32_DMA_ISR_MASK; - DMA1->IFCR = STM32_DMA_ISR_MASK << 0; - if (dma_isr_redir[0].dma_func) - dma_isr_redir[0].dma_func(dma_isr_redir[0].dma_param, flags); - - OSAL_IRQ_EPILOGUE(); -} - -/** - * @brief DMA1 stream 2 shared interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(Vector70) { - uint32_t flags; - - OSAL_IRQ_PROLOGUE(); - - flags = (DMA1->ISR >> 4) & STM32_DMA_ISR_MASK; - DMA1->IFCR = STM32_DMA_ISR_MASK << 4; - if (dma_isr_redir[1].dma_func) - dma_isr_redir[1].dma_func(dma_isr_redir[1].dma_param, flags); - - OSAL_IRQ_EPILOGUE(); -} - -/** - * @brief DMA1 stream 3 shared interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(Vector74) { - uint32_t flags; - - OSAL_IRQ_PROLOGUE(); - - flags = (DMA1->ISR >> 8) & STM32_DMA_ISR_MASK; - DMA1->IFCR = STM32_DMA_ISR_MASK << 8; - if (dma_isr_redir[2].dma_func) - dma_isr_redir[2].dma_func(dma_isr_redir[2].dma_param, flags); - - OSAL_IRQ_EPILOGUE(); -} - -/** - * @brief DMA1 stream 4 shared interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(Vector78) { - uint32_t flags; - - OSAL_IRQ_PROLOGUE(); - - flags = (DMA1->ISR >> 12) & STM32_DMA_ISR_MASK; - DMA1->IFCR = STM32_DMA_ISR_MASK << 12; - if (dma_isr_redir[3].dma_func) - dma_isr_redir[3].dma_func(dma_isr_redir[3].dma_param, flags); - - OSAL_IRQ_EPILOGUE(); -} - -/** - * @brief DMA1 stream 5 shared interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(Vector7C) { - uint32_t flags; - - OSAL_IRQ_PROLOGUE(); - - flags = (DMA1->ISR >> 16) & STM32_DMA_ISR_MASK; - DMA1->IFCR = STM32_DMA_ISR_MASK << 16; - if (dma_isr_redir[4].dma_func) - dma_isr_redir[4].dma_func(dma_isr_redir[4].dma_param, flags); - - OSAL_IRQ_EPILOGUE(); -} - -/** - * @brief DMA1 stream 6 shared interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(Vector80) { - uint32_t flags; - - OSAL_IRQ_PROLOGUE(); - - flags = (DMA1->ISR >> 20) & STM32_DMA_ISR_MASK; - DMA1->IFCR = STM32_DMA_ISR_MASK << 20; - if (dma_isr_redir[5].dma_func) - dma_isr_redir[5].dma_func(dma_isr_redir[5].dma_param, flags); - - OSAL_IRQ_EPILOGUE(); -} - -/** - * @brief DMA1 stream 7 shared interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(Vector84) { - uint32_t flags; - - OSAL_IRQ_PROLOGUE(); - - flags = (DMA1->ISR >> 24) & STM32_DMA_ISR_MASK; - DMA1->IFCR = STM32_DMA_ISR_MASK << 24; - if (dma_isr_redir[6].dma_func) - dma_isr_redir[6].dma_func(dma_isr_redir[6].dma_param, flags); - - OSAL_IRQ_EPILOGUE(); -} - -/** - * @brief DMA2 stream 1 shared interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(Vector120) { - uint32_t flags; - - OSAL_IRQ_PROLOGUE(); - - flags = (DMA2->ISR >> 0) & STM32_DMA_ISR_MASK; - DMA2->IFCR = STM32_DMA_ISR_MASK << 0; - if (dma_isr_redir[7].dma_func) - dma_isr_redir[7].dma_func(dma_isr_redir[7].dma_param, flags); - - OSAL_IRQ_EPILOGUE(); -} - -/** - * @brief DMA2 stream 2 shared interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(Vector124) { - uint32_t flags; - - OSAL_IRQ_PROLOGUE(); - - flags = (DMA2->ISR >> 4) & STM32_DMA_ISR_MASK; - DMA2->IFCR = STM32_DMA_ISR_MASK << 4; - if (dma_isr_redir[8].dma_func) - dma_isr_redir[8].dma_func(dma_isr_redir[8].dma_param, flags); - - OSAL_IRQ_EPILOGUE(); -} - -/** - * @brief DMA2 stream 3 shared interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(Vector128) { - uint32_t flags; - - OSAL_IRQ_PROLOGUE(); - - flags = (DMA2->ISR >> 8) & STM32_DMA_ISR_MASK; - DMA2->IFCR = STM32_DMA_ISR_MASK << 8; - if (dma_isr_redir[9].dma_func) - dma_isr_redir[9].dma_func(dma_isr_redir[9].dma_param, flags); - - OSAL_IRQ_EPILOGUE(); -} - -/** - * @brief DMA2 stream 4 shared interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(Vector12C) { - uint32_t flags; - - OSAL_IRQ_PROLOGUE(); - - flags = (DMA2->ISR >> 12) & STM32_DMA_ISR_MASK; - DMA2->IFCR = STM32_DMA_ISR_MASK << 12; - if (dma_isr_redir[10].dma_func) - dma_isr_redir[10].dma_func(dma_isr_redir[10].dma_param, flags); - - OSAL_IRQ_EPILOGUE(); -} - -/** - * @brief DMA2 stream 5 shared interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(Vector130) { - uint32_t flags; - - OSAL_IRQ_PROLOGUE(); - - flags = (DMA2->ISR >> 16) & STM32_DMA_ISR_MASK; - DMA2->IFCR = STM32_DMA_ISR_MASK << 16; - if (dma_isr_redir[11].dma_func) - dma_isr_redir[11].dma_func(dma_isr_redir[11].dma_param, flags); - - OSAL_IRQ_EPILOGUE(); -} - -/*===========================================================================*/ -/* Driver exported functions. */ -/*===========================================================================*/ - -/** - * @brief STM32 DMA helper initialization. - * - * @init - */ -void dmaInit(void) { - int i; - - dma_streams_mask = 0; - for (i = 0; i < STM32_DMA_STREAMS; i++) { - _stm32_dma_streams[i].channel->CCR = 0; - dma_isr_redir[i].dma_func = NULL; - } - DMA1->IFCR = 0xFFFFFFFF; -#if STM32_HAS_DMA2 - DMA2->IFCR = 0xFFFFFFFF; -#endif -} - -/** - * @brief Allocates a DMA stream. - * @details The stream is allocated and, if required, the DMA clock enabled. - * The function also enables the IRQ vector associated to the stream - * and initializes its priority. - * @pre The stream must not be already in use or an error is returned. - * @post The stream is allocated and the default ISR handler redirected - * to the specified function. - * @post The stream ISR vector is enabled and its priority configured. - * @post The stream must be freed using @p dmaStreamRelease() before it can - * be reused with another peripheral. - * @post The stream is in its post-reset state. - * @note This function can be invoked in both ISR or thread context. - * - * @param[in] dmastp pointer to a stm32_dma_stream_t structure - * @param[in] priority IRQ priority mask for the DMA stream - * @param[in] func handling function pointer, can be @p NULL - * @param[in] param a parameter to be passed to the handling function - * @return The operation status. - * @retval FALSE no error, stream taken. - * @retval TRUE error, stream already taken. - * - * @special - */ -bool_t dmaStreamAllocate(const stm32_dma_stream_t *dmastp, - uint32_t priority, - stm32_dmaisr_t func, - void *param) { - - osalDbgCheck(dmastp != NULL); - - /* Checks if the stream is already taken.*/ - if ((dma_streams_mask & (1 << dmastp->selfindex)) != 0) - return TRUE; - - /* Marks the stream as allocated.*/ - dma_isr_redir[dmastp->selfindex].dma_func = func; - dma_isr_redir[dmastp->selfindex].dma_param = param; - dma_streams_mask |= (1 << dmastp->selfindex); - - /* Enabling DMA clocks required by the current streams set.*/ - if ((dma_streams_mask & STM32_DMA1_STREAMS_MASK) != 0) - rccEnableDMA1(FALSE); -#if STM32_HAS_DMA2 - if ((dma_streams_mask & STM32_DMA2_STREAMS_MASK) != 0) - rccEnableDMA2(FALSE); -#endif - - /* Putting the stream in a safe state.*/ - dmaStreamDisable(dmastp); - dmastp->channel->CCR = STM32_DMA_CCR_RESET_VALUE; - - /* Enables the associated IRQ vector if a callback is defined.*/ - if (func != NULL) - nvicEnableVector(dmastp->vector, priority); - - return FALSE; -} - -/** - * @brief Releases a DMA stream. - * @details The stream is freed and, if required, the DMA clock disabled. - * Trying to release a unallocated stream is an illegal operation - * and is trapped if assertions are enabled. - * @pre The stream must have been allocated using @p dmaStreamAllocate(). - * @post The stream is again available. - * @note This function can be invoked in both ISR or thread context. - * - * @param[in] dmastp pointer to a stm32_dma_stream_t structure - * - * @special - */ -void dmaStreamRelease(const stm32_dma_stream_t *dmastp) { - - osalDbgCheck(dmastp != NULL); - - /* Check if the streams is not taken.*/ - osalDbgAssert((dma_streams_mask & (1 << dmastp->selfindex)) != 0, - "not allocated"); - - /* Disables the associated IRQ vector.*/ - nvicDisableVector(dmastp->vector); - - /* Marks the stream as not allocated.*/ - dma_streams_mask &= ~(1 << dmastp->selfindex); - - /* Shutting down clocks that are no more required, if any.*/ - if ((dma_streams_mask & STM32_DMA1_STREAMS_MASK) == 0) - rccDisableDMA1(FALSE); -#if STM32_HAS_DMA2 - if ((dma_streams_mask & STM32_DMA2_STREAMS_MASK) == 0) - rccDisableDMA2(FALSE); -#endif -} - -#endif /* STM32_DMA_REQUIRED */ - -/** @} */ diff --git a/os/hal/platforms/STM32F30x/stm32_dma.h b/os/hal/platforms/STM32F30x/stm32_dma.h deleted file mode 100644 index 2415f00f2..000000000 --- a/os/hal/platforms/STM32F30x/stm32_dma.h +++ /dev/null @@ -1,406 +0,0 @@ -/* - ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file STM32F30x/stm32_dma.h - * @brief DMA helper driver header. - * @note This file requires definitions from the ST header file stm32f30x.h. - * @note This driver uses the new naming convention used for the STM32F2xx - * so the "DMA channels" are referred as "DMA streams". - * - * @addtogroup STM32F30x_DMA - * @{ - */ - -#ifndef _STM32_DMA_H_ -#define _STM32_DMA_H_ - -/*===========================================================================*/ -/* Driver constants. */ -/*===========================================================================*/ - -/** - * @brief Total number of DMA streams. - * @note This is the total number of streams among all the DMA units. - */ -#if STM32_HAS_DMA2 || defined(__DOXYGEN__) -#define STM32_DMA_STREAMS 12 -#else -#define STM32_DMA_STREAMS 7 -#endif - -/** - * @brief Mask of the ISR bits passed to the DMA callback functions. - */ -#define STM32_DMA_ISR_MASK 0x0F - -/** - * @brief Returns the channel associated to the specified stream. - * - * @param[in] n the stream number (0...STM32_DMA_STREAMS-1) - * @param[in] c a stream/channel association word, one channel per - * nibble, not associated channels must be set to 0xF - * @return Always zero, in this platform there is no dynamic - * association between streams and channels. - */ -#define STM32_DMA_GETCHANNEL(n, c) 0 - -/** - * @brief Checks if a DMA priority is within the valid range. - * @param[in] prio DMA priority - * - * @retval The check result. - * @retval FALSE invalid DMA priority. - * @retval TRUE correct DMA priority. - */ -#define STM32_DMA_IS_VALID_PRIORITY(prio) (((prio) >= 0) && ((prio) <= 3)) - -/** - * @brief Returns an unique numeric identifier for a DMA stream. - * - * @param[in] dma the DMA unit number - * @param[in] stream the stream number - * @return An unique numeric stream identifier. - */ -#define STM32_DMA_STREAM_ID(dma, stream) ((((dma) - 1) * 7) + ((stream) - 1)) - -/** - * @brief Returns a DMA stream identifier mask. - * - * - * @param[in] dma the DMA unit number - * @param[in] stream the stream number - * @return A DMA stream identifier mask. - */ -#define STM32_DMA_STREAM_ID_MSK(dma, stream) \ - (1 << STM32_DMA_STREAM_ID(dma, stream)) - -/** - * @brief Checks if a DMA stream unique identifier belongs to a mask. - * @param[in] id the stream numeric identifier - * @param[in] mask the stream numeric identifiers mask - * - * @retval The check result. - * @retval FALSE id does not belong to the mask. - * @retval TRUE id belongs to the mask. - */ -#define STM32_DMA_IS_VALID_ID(id, mask) (((1 << (id)) & (mask))) - -/** - * @name DMA streams identifiers - * @{ - */ -/** - * @brief Returns a pointer to a stm32_dma_stream_t structure. - * - * @param[in] id the stream numeric identifier - * @return A pointer to the stm32_dma_stream_t constant structure - * associated to the DMA stream. - */ -#define STM32_DMA_STREAM(id) (&_stm32_dma_streams[id]) - -#define STM32_DMA1_STREAM1 STM32_DMA_STREAM(0) -#define STM32_DMA1_STREAM2 STM32_DMA_STREAM(1) -#define STM32_DMA1_STREAM3 STM32_DMA_STREAM(2) -#define STM32_DMA1_STREAM4 STM32_DMA_STREAM(3) -#define STM32_DMA1_STREAM5 STM32_DMA_STREAM(4) -#define STM32_DMA1_STREAM6 STM32_DMA_STREAM(5) -#define STM32_DMA1_STREAM7 STM32_DMA_STREAM(6) -#define STM32_DMA2_STREAM1 STM32_DMA_STREAM(7) -#define STM32_DMA2_STREAM2 STM32_DMA_STREAM(8) -#define STM32_DMA2_STREAM3 STM32_DMA_STREAM(9) -#define STM32_DMA2_STREAM4 STM32_DMA_STREAM(10) -#define STM32_DMA2_STREAM5 STM32_DMA_STREAM(11) -/** @} */ - -/** - * @name CR register constants common to all DMA types - * @{ - */ -#define STM32_DMA_CR_EN DMA_CCR_EN -#define STM32_DMA_CR_TEIE DMA_CCR_TEIE -#define STM32_DMA_CR_HTIE DMA_CCR_HTIE -#define STM32_DMA_CR_TCIE DMA_CCR_TCIE -#define STM32_DMA_CR_DIR_MASK (DMA_CCR_DIR | DMA_CCR_MEM2MEM) -#define STM32_DMA_CR_DIR_P2M 0 -#define STM32_DMA_CR_DIR_M2P DMA_CCR_DIR -#define STM32_DMA_CR_DIR_M2M DMA_CCR_MEM2MEM -#define STM32_DMA_CR_CIRC DMA_CCR_CIRC -#define STM32_DMA_CR_PINC DMA_CCR_PINC -#define STM32_DMA_CR_MINC DMA_CCR_MINC -#define STM32_DMA_CR_PSIZE_MASK DMA_CCR_PSIZE -#define STM32_DMA_CR_PSIZE_BYTE 0 -#define STM32_DMA_CR_PSIZE_HWORD DMA_CCR_PSIZE_0 -#define STM32_DMA_CR_PSIZE_WORD DMA_CCR_PSIZE_1 -#define STM32_DMA_CR_MSIZE_MASK DMA_CCR_MSIZE -#define STM32_DMA_CR_MSIZE_BYTE 0 -#define STM32_DMA_CR_MSIZE_HWORD DMA_CCR_MSIZE_0 -#define STM32_DMA_CR_MSIZE_WORD DMA_CCR_MSIZE_1 -#define STM32_DMA_CR_SIZE_MASK (STM32_DMA_CR_PSIZE_MASK | \ - STM32_DMA_CR_MSIZE_MASK) -#define STM32_DMA_CR_PL_MASK DMA_CCR_PL -#define STM32_DMA_CR_PL(n) ((n) << 12) -/** @} */ - -/** - * @name CR register constants only found in enhanced DMA - * @{ - */ -#define STM32_DMA_CR_DMEIE 0 /**< @brief Ignored by normal DMA. */ -#define STM32_DMA_CR_CHSEL_MASK 0 /**< @brief Ignored by normal DMA. */ -#define STM32_DMA_CR_CHSEL(n) 0 /**< @brief Ignored by normal DMA. */ -/** @} */ - -/** - * @name Status flags passed to the ISR callbacks - * @{ - */ -#define STM32_DMA_ISR_FEIF 0 -#define STM32_DMA_ISR_DMEIF 0 -#define STM32_DMA_ISR_TEIF DMA_ISR_TEIF1 -#define STM32_DMA_ISR_HTIF DMA_ISR_HTIF1 -#define STM32_DMA_ISR_TCIF DMA_ISR_TCIF1 -/** @} */ - -/*===========================================================================*/ -/* Driver pre-compile time settings. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Derived constants and error checks. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver data structures and types. */ -/*===========================================================================*/ - -/** - * @brief STM32 DMA stream descriptor structure. - */ -typedef struct { - DMA_Channel_TypeDef *channel; /**< @brief Associated DMA channel. */ - volatile uint32_t *ifcr; /**< @brief Associated IFCR reg. */ - uint8_t ishift; /**< @brief Bits offset in xIFCR - register. */ - uint8_t selfindex; /**< @brief Index to self in array. */ - uint8_t vector; /**< @brief Associated IRQ vector. */ -} stm32_dma_stream_t; - -/** - * @brief STM32 DMA ISR function type. - * - * @param[in] p parameter for the registered function - * @param[in] flags pre-shifted content of the ISR register, the bits - * are aligned to bit zero - */ -typedef void (*stm32_dmaisr_t)(void *p, uint32_t flags); - -/*===========================================================================*/ -/* Driver macros. */ -/*===========================================================================*/ - -/** - * @name Macro Functions - * @{ - */ -/** - * @brief Associates a peripheral data register to a DMA stream. - * @note This function can be invoked in both ISR or thread context. - * @pre The stream must have been allocated using @p dmaStreamAllocate(). - * @post After use the stream can be released using @p dmaStreamRelease(). - * - * @param[in] dmastp pointer to a stm32_dma_stream_t structure - * @param[in] addr value to be written in the CPAR register - * - * @special - */ -#define dmaStreamSetPeripheral(dmastp, addr) { \ - (dmastp)->channel->CPAR = (uint32_t)(addr); \ -} - -/** - * @brief Associates a memory destination to a DMA stream. - * @note This function can be invoked in both ISR or thread context. - * @pre The stream must have been allocated using @p dmaStreamAllocate(). - * @post After use the stream can be released using @p dmaStreamRelease(). - * - * @param[in] dmastp pointer to a stm32_dma_stream_t structure - * @param[in] addr value to be written in the CMAR register - * - * @special - */ -#define dmaStreamSetMemory0(dmastp, addr) { \ - (dmastp)->channel->CMAR = (uint32_t)(addr); \ -} - -/** - * @brief Sets the number of transfers to be performed. - * @note This function can be invoked in both ISR or thread context. - * @pre The stream must have been allocated using @p dmaStreamAllocate(). - * @post After use the stream can be released using @p dmaStreamRelease(). - * - * @param[in] dmastp pointer to a stm32_dma_stream_t structure - * @param[in] size value to be written in the CNDTR register - * - * @special - */ -#define dmaStreamSetTransactionSize(dmastp, size) { \ - (dmastp)->channel->CNDTR = (uint32_t)(size); \ -} - -/** - * @brief Returns the number of transfers to be performed. - * @note This function can be invoked in both ISR or thread context. - * @pre The stream must have been allocated using @p dmaStreamAllocate(). - * @post After use the stream can be released using @p dmaStreamRelease(). - * - * @param[in] dmastp pointer to a stm32_dma_stream_t structure - * @return The number of transfers to be performed. - * - * @special - */ -#define dmaStreamGetTransactionSize(dmastp) ((size_t)((dmastp)->channel->CNDTR)) - -/** - * @brief Programs the stream mode settings. - * @note This function can be invoked in both ISR or thread context. - * @pre The stream must have been allocated using @p dmaStreamAllocate(). - * @post After use the stream can be released using @p dmaStreamRelease(). - * - * @param[in] dmastp pointer to a stm32_dma_stream_t structure - * @param[in] mode value to be written in the CCR register - * - * @special - */ -#define dmaStreamSetMode(dmastp, mode) { \ - (dmastp)->channel->CCR = (uint32_t)(mode); \ -} - -/** - * @brief DMA stream enable. - * @note This function can be invoked in both ISR or thread context. - * @pre The stream must have been allocated using @p dmaStreamAllocate(). - * @post After use the stream can be released using @p dmaStreamRelease(). - * - * @param[in] dmastp pointer to a stm32_dma_stream_t structure - * - * @special - */ -#define dmaStreamEnable(dmastp) { \ - (dmastp)->channel->CCR |= STM32_DMA_CR_EN; \ -} - -/** - * @brief DMA stream disable. - * @details The function disables the specified stream and then clears any - * pending interrupt. - * @note This function can be invoked in both ISR or thread context. - * @note Interrupts enabling flags are set to zero after this call, see - * bug 3607518. - * @pre The stream must have been allocated using @p dmaStreamAllocate(). - * @post After use the stream can be released using @p dmaStreamRelease(). - * - * @param[in] dmastp pointer to a stm32_dma_stream_t structure - * - * @special - */ -#define dmaStreamDisable(dmastp) { \ - (dmastp)->channel->CCR &= ~(STM32_DMA_CR_TCIE | STM32_DMA_CR_HTIE | \ - STM32_DMA_CR_TEIE | STM32_DMA_CR_EN); \ - dmaStreamClearInterrupt(dmastp); \ -} - -/** - * @brief DMA stream interrupt sources clear. - * @note This function can be invoked in both ISR or thread context. - * @pre The stream must have been allocated using @p dmaStreamAllocate(). - * @post After use the stream can be released using @p dmaStreamRelease(). - * - * @param[in] dmastp pointer to a stm32_dma_stream_t structure - * - * @special - */ -#define dmaStreamClearInterrupt(dmastp) { \ - *(dmastp)->ifcr = STM32_DMA_ISR_MASK << (dmastp)->ishift; \ -} - -/** - * @brief Starts a memory to memory operation using the specified stream. - * @note The default transfer data mode is "byte to byte" but it can be - * changed by specifying extra options in the @p mode parameter. - * @pre The stream must have been allocated using @p dmaStreamAllocate(). - * @post After use the stream can be released using @p dmaStreamRelease(). - * - * @param[in] dmastp pointer to a stm32_dma_stream_t structure - * @param[in] mode value to be written in the CCR register, this value - * is implicitly ORed with: - * - @p STM32_DMA_CR_MINC - * - @p STM32_DMA_CR_PINC - * - @p STM32_DMA_CR_DIR_M2M - * - @p STM32_DMA_CR_EN - * . - * @param[in] src source address - * @param[in] dst destination address - * @param[in] n number of data units to copy - */ -#define dmaStartMemCopy(dmastp, mode, src, dst, n) { \ - dmaStreamSetPeripheral(dmastp, src); \ - dmaStreamSetMemory0(dmastp, dst); \ - dmaStreamSetTransactionSize(dmastp, n); \ - dmaStreamSetMode(dmastp, (mode) | \ - STM32_DMA_CR_MINC | STM32_DMA_CR_PINC | \ - STM32_DMA_CR_DIR_M2M | STM32_DMA_CR_EN); \ -} - -/** - * @brief Polled wait for DMA transfer end. - * @pre The stream must have been allocated using @p dmaStreamAllocate(). - * @post After use the stream can be released using @p dmaStreamRelease(). - * - * @param[in] dmastp pointer to a stm32_dma_stream_t structure - */ -#define dmaWaitCompletion(dmastp) { \ - while ((dmastp)->channel->CNDTR > 0) \ - ; \ - dmaStreamDisable(dmastp); \ -} - -/** @} */ - -/*===========================================================================*/ -/* External declarations. */ -/*===========================================================================*/ - -#if !defined(__DOXYGEN__) -extern const stm32_dma_stream_t _stm32_dma_streams[STM32_DMA_STREAMS]; -#endif - -#ifdef __cplusplus -extern "C" { -#endif - void dmaInit(void); - bool_t dmaStreamAllocate(const stm32_dma_stream_t *dmastp, - uint32_t priority, - stm32_dmaisr_t func, - void *param); - void dmaStreamRelease(const stm32_dma_stream_t *dmastp); -#ifdef __cplusplus -} -#endif - -#endif /* _STM32_DMA_H_ */ - -/** @} */ diff --git a/os/hal/platforms/STM32F30x/stm32_isr.h b/os/hal/platforms/STM32F30x/stm32_isr.h deleted file mode 100644 index 94b04b63e..000000000 --- a/os/hal/platforms/STM32F30x/stm32_isr.h +++ /dev/null @@ -1,132 +0,0 @@ -/* - ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file STM32F30x/stm32_isr.h - * @brief ISR remapper driver header. - * - * @addtogroup STM32F30x_ISR - * @{ - */ - -#ifndef _STM32_ISR_H_ -#define _STM32_ISR_H_ - -/*===========================================================================*/ -/* Driver constants. */ -/*===========================================================================*/ - -/** - * @name ISR names and numbers remapping - * @{ - */ -/* - * CAN units. - */ -#define STM32_CAN1_TX_HANDLER Vector8C -#define STM32_CAN1_RX0_HANDLER Vector90 -#define STM32_CAN1_RX1_HANDLER Vector94 -#define STM32_CAN1_SCE_HANDLER Vector98 - -#define STM32_CAN1_TX_NUMBER 19 -#define STM32_CAN1_RX0_NUMBER 20 -#define STM32_CAN1_RX1_NUMBER 21 -#define STM32_CAN1_SCE_NUMBER 22 - -/* - * I2C units. - */ -#define STM32_I2C1_EVENT_HANDLER VectorBC -#define STM32_I2C1_ERROR_HANDLER VectorC0 -#define STM32_I2C1_EVENT_NUMBER 31 -#define STM32_I2C1_ERROR_NUMBER 32 - -#define STM32_I2C2_EVENT_HANDLER VectorC4 -#define STM32_I2C2_ERROR_HANDLER VectorC8 -#define STM32_I2C2_EVENT_NUMBER 33 -#define STM32_I2C2_ERROR_NUMBER 34 - -/* - * TIM units. - */ -#define STM32_TIM1_UP_HANDLER VectorA4 -#define STM32_TIM1_CC_HANDLER VectorAC -#define STM32_TIM2_HANDLER VectorB0 -#define STM32_TIM3_HANDLER VectorB4 -#define STM32_TIM4_HANDLER VectorB8 -#define STM32_TIM6_HANDLER Vector118 -#define STM32_TIM7_HANDLER Vector11C -#define STM32_TIM8_UP_HANDLER VectorF0 -#define STM32_TIM8_CC_HANDLER VectorF8 - -#define STM32_TIM1_UP_NUMBER 25 -#define STM32_TIM1_CC_NUMBER 27 -#define STM32_TIM2_NUMBER 28 -#define STM32_TIM3_NUMBER 29 -#define STM32_TIM4_NUMBER 30 -#define STM32_TIM6_NUMBER 54 -#define STM32_TIM7_NUMBER 55 -#define STM32_TIM8_UP_NUMBER 44 -#define STM32_TIM8_CC_NUMBER 46 - -/* - * USART units. - */ -#define STM32_USART1_HANDLER VectorD4 -#define STM32_USART2_HANDLER VectorD8 -#define STM32_USART3_HANDLER VectorDC -#define STM32_UART4_HANDLER Vector110 -#define STM32_UART5_HANDLER Vector114 - -#define STM32_USART1_NUMBER 37 -#define STM32_USART2_NUMBER 38 -#define STM32_USART3_NUMBER 39 -#define STM32_UART4_NUMBER 52 -#define STM32_UART5_NUMBER 53 - -/* - * USB units. - */ -#define STM32_USB1_HP_HANDLER Vector168 -#define STM32_USB1_LP_HANDLER Vector16C - -#define STM32_USB1_HP_NUMBER 74 -#define STM32_USB1_LP_NUMBER 75 -/** @} */ - -/*===========================================================================*/ -/* Driver pre-compile time settings. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Derived constants and error checks. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver data structures and types. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver macros. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* External declarations. */ -/*===========================================================================*/ - -#endif /* _STM32_ISR_H_ */ - -/** @} */ diff --git a/os/hal/platforms/STM32F30x/stm32_rcc.h b/os/hal/platforms/STM32F30x/stm32_rcc.h deleted file mode 100644 index 9cc2edf52..000000000 --- a/os/hal/platforms/STM32F30x/stm32_rcc.h +++ /dev/null @@ -1,835 +0,0 @@ -/* - ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file STM32F30x/stm32_rcc.h - * @brief RCC helper driver header. - * @note This file requires definitions from the ST header file - * @p stm32f30x.h. - * - * @addtogroup STM32F30x_RCC - * @{ - */ - -#ifndef _STM32_RCC_ -#define _STM32_RCC_ - -/*===========================================================================*/ -/* Driver constants. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver pre-compile time settings. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Derived constants and error checks. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver data structures and types. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver macros. */ -/*===========================================================================*/ - -/** - * @name Generic RCC operations - * @{ - */ -/** - * @brief Enables the clock of one or more peripheral on the APB1 bus. - * - * @param[in] mask APB1 peripherals mask - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableAPB1(mask, lp) { \ - RCC->APB1ENR |= (mask); \ -} - -/** - * @brief Disables the clock of one or more peripheral on the APB1 bus. - * - * @param[in] mask APB1 peripherals mask - * @param[in] lp low power enable flag - * - * @api - */ -#define rccDisableAPB1(mask, lp) { \ - RCC->APB1ENR &= ~(mask); \ -} - -/** - * @brief Resets one or more peripheral on the APB1 bus. - * - * @param[in] mask APB1 peripherals mask - * - * @api - */ -#define rccResetAPB1(mask) { \ - RCC->APB1RSTR |= (mask); \ - RCC->APB1RSTR = 0; \ -} - -/** - * @brief Enables the clock of one or more peripheral on the APB2 bus. - * - * @param[in] mask APB2 peripherals mask - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableAPB2(mask, lp) { \ - RCC->APB2ENR |= (mask); \ -} - -/** - * @brief Disables the clock of one or more peripheral on the APB2 bus. - * - * @param[in] mask APB2 peripherals mask - * @param[in] lp low power enable flag - * - * @api - */ -#define rccDisableAPB2(mask, lp) { \ - RCC->APB2ENR &= ~(mask); \ -} - -/** - * @brief Resets one or more peripheral on the APB2 bus. - * - * @param[in] mask APB2 peripherals mask - * - * @api - */ -#define rccResetAPB2(mask) { \ - RCC->APB2RSTR |= (mask); \ - RCC->APB2RSTR = 0; \ -} - -/** - * @brief Enables the clock of one or more peripheral on the AHB bus. - * - * @param[in] mask AHB peripherals mask - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableAHB(mask, lp) { \ - RCC->AHBENR |= (mask); \ -} - -/** - * @brief Disables the clock of one or more peripheral on the AHB bus. - * - * @param[in] mask AHB peripherals mask - * @param[in] lp low power enable flag - * - * @api - */ -#define rccDisableAHB(mask, lp) { \ - RCC->AHBENR &= ~(mask); \ -} - -/** - * @brief Resets one or more peripheral on the AHB bus. - * - * @param[in] mask AHB peripherals mask - * - * @api - */ -#define rccResetAHB(mask) { \ - RCC->AHBRSTR |= (mask); \ - RCC->AHBRSTR = 0; \ -} -/** @} */ - -/** - * @name ADC peripherals specific RCC operations - * @{ - */ -/** - * @brief Enables the ADC1/ADC2 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableADC12(lp) rccEnableAHB(RCC_AHBENR_ADC12EN, lp) - -/** - * @brief Disables the ADC1/ADC2 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccDisableADC12(lp) rccDisableAHB(RCC_AHBENR_ADC12EN, lp) - -/** - * @brief Resets the ADC1/ADC2 peripheral. - * - * @api - */ -#define rccResetADC12() rccResetAHB(RCC_AHBRSTR_ADC12RST) - -/** - * @brief Enables the ADC3/ADC4 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableADC34(lp) rccEnableAHB(RCC_AHBENR_ADC34EN, lp) - -/** - * @brief Disables the ADC3/ADC4 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccDisableADC34(lp) rccDisableAHB(RCC_AHBENR_ADC34EN, lp) - -/** - * @brief Resets the ADC3/ADC4 peripheral. - * - * @api - */ -#define rccResetADC34() rccResetAHB(RCC_AHBRSTR_ADC34RST) -/** @} */ - -/** - * @name CAN peripherals specific RCC operations - * @{ - */ -/** - * @brief Enables the CAN1 peripheral clock. - * @note The @p lp parameter is ignored in this family. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableCAN1(lp) rccEnableAPB1(RCC_APB1ENR_CAN1EN, lp) - -/** - * @brief Disables the CAN1 peripheral clock. - * @note The @p lp parameter is ignored in this family. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccDisableCAN1(lp) rccDisableAPB1(RCC_APB1ENR_CAN1EN, lp) - -/** - * @brief Resets the CAN1 peripheral. - * - * @api - */ -#define rccResetCAN1() rccResetAPB1(RCC_APB1RSTR_CAN1RST) -/** @} */ - -/** - * @name DMA peripheral specific RCC operations - * @{ - */ -/** - * @brief Enables the DMA1 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableDMA1(lp) rccEnableAHB(RCC_AHBENR_DMA1EN, lp) - -/** - * @brief Disables the DMA1 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccDisableDMA1(lp) rccDisableAHB(RCC_AHBENR_DMA1EN, lp) - -/** - * @brief Resets the DMA1 peripheral. - * - * @api - */ -#define rccResetDMA1() rccResetAHB(RCC_AHBRSTR_DMA1RST) - -/** - * @brief Enables the DMA2 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableDMA2(lp) rccEnableAHB(RCC_AHBENR_DMA2EN, lp) - -/** - * @brief Disables the DMA2 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccDisableDMA2(lp) rccDisableAHB(RCC_AHBENR_DMA2EN, lp) - -/** - * @brief Resets the DMA2 peripheral. - * - * @api - */ -#define rccResetDMA2() rccResetAHB(RCC_AHBRSTR_DMA2RST) -/** @} */ - -/** - * @name PWR interface specific RCC operations - * @{ - */ -/** - * @brief Enables the PWR interface clock. - * @note The @p lp parameter is ignored in this family. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnablePWRInterface(lp) rccEnableAPB1(RCC_APB1ENR_PWREN, lp) - -/** - * @brief Disables PWR interface clock. - * @note The @p lp parameter is ignored in this family. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccDisablePWRInterface(lp) rccDisableAPB1(RCC_APB1ENR_PWREN, lp) - -/** - * @brief Resets the PWR interface. - * - * @api - */ -#define rccResetPWRInterface() rccResetAPB1(RCC_APB1RSTR_PWRRST) -/** @} */ - -/** - * @name I2C peripherals specific RCC operations - * @{ - */ -/** - * @brief Enables the I2C1 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableI2C1(lp) rccEnableAPB1(RCC_APB1ENR_I2C1EN, lp) - -/** - * @brief Disables the I2C1 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccDisableI2C1(lp) rccDisableAPB1(RCC_APB1ENR_I2C1EN, lp) - -/** - * @brief Resets the I2C1 peripheral. - * - * @api - */ -#define rccResetI2C1() rccResetAPB1(RCC_APB1RSTR_I2C1RST) - -/** - * @brief Enables the I2C2 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableI2C2(lp) rccEnableAPB1(RCC_APB1ENR_I2C2EN, lp) - -/** - * @brief Disables the I2C2 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccDisableI2C2(lp) rccDisableAPB1(RCC_APB1ENR_I2C2EN, lp) - -/** - * @brief Resets the I2C2 peripheral. - * - * @api - */ -#define rccResetI2C2() rccResetAPB1(RCC_APB1RSTR_I2C2RST) -/** @} */ - -/** - * @name SPI peripherals specific RCC operations - * @{ - */ -/** - * @brief Enables the SPI1 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableSPI1(lp) rccEnableAPB2(RCC_APB2ENR_SPI1EN, lp) - -/** - * @brief Disables the SPI1 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccDisableSPI1(lp) rccDisableAPB2(RCC_APB2ENR_SPI1EN, lp) - -/** - * @brief Resets the SPI1 peripheral. - * - * @api - */ -#define rccResetSPI1() rccResetAPB2(RCC_APB2RSTR_SPI1RST) - -/** - * @brief Enables the SPI2 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableSPI2(lp) rccEnableAPB1(RCC_APB1ENR_SPI2EN, lp) - -/** - * @brief Disables the SPI2 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccDisableSPI2(lp) rccDisableAPB1(RCC_APB1ENR_SPI2EN, lp) - -/** - * @brief Resets the SPI2 peripheral. - * - * @api - */ -#define rccResetSPI2() rccResetAPB1(RCC_APB1RSTR_SPI2RST) - -/** - * @brief Enables the SPI3 peripheral clock. - * @note The @p lp parameter is ignored in this family. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableSPI3(lp) rccEnableAPB1(RCC_APB1ENR_SPI3EN, lp) - -/** - * @brief Disables the SPI3 peripheral clock. - * @note The @p lp parameter is ignored in this family. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccDisableSPI3(lp) rccDisableAPB1(RCC_APB1ENR_SPI3EN, lp) - -/** - * @brief Resets the SPI3 peripheral. - * - * @api - */ -#define rccResetSPI3() rccResetAPB1(RCC_APB1RSTR_SPI3RST) -/** @} */ - -/** - * @name TIM peripherals specific RCC operations - * @{ - */ -/** - * @brief Enables the TIM1 peripheral clock. - * @note The @p lp parameter is ignored in this family. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableTIM1(lp) rccEnableAPB2(RCC_APB2ENR_TIM1EN, lp) - -/** - * @brief Disables the TIM1 peripheral clock. - * @note The @p lp parameter is ignored in this family. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccDisableTIM1(lp) rccDisableAPB2(RCC_APB2ENR_TIM1EN, lp) - -/** - * @brief Resets the TIM1 peripheral. - * - * @api - */ -#define rccResetTIM1() rccResetAPB2(RCC_APB2RSTR_TIM1RST) - -/** - * @brief Enables the TIM2 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableTIM2(lp) rccEnableAPB1(RCC_APB1ENR_TIM2EN, lp) - -/** - * @brief Disables the TIM2 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccDisableTIM2(lp) rccDisableAPB1(RCC_APB1ENR_TIM2EN, lp) - -/** - * @brief Resets the TIM2 peripheral. - * - * @api - */ -#define rccResetTIM2() rccResetAPB1(RCC_APB1RSTR_TIM2RST) - -/** - * @brief Enables the TIM3 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableTIM3(lp) rccEnableAPB1(RCC_APB1ENR_TIM3EN, lp) - -/** - * @brief Disables the TIM3 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccDisableTIM3(lp) rccDisableAPB1(RCC_APB1ENR_TIM3EN, lp) - -/** - * @brief Resets the TIM3 peripheral. - * - * @api - */ -#define rccResetTIM3() rccResetAPB1(RCC_APB1RSTR_TIM3RST) - -/** - * @brief Enables the TIM4 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableTIM4(lp) rccEnableAPB1(RCC_APB1ENR_TIM4EN, lp) - -/** - * @brief Disables the TIM4 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccDisableTIM4(lp) rccDisableAPB1(RCC_APB1ENR_TIM4EN, lp) - -/** - * @brief Resets the TIM4 peripheral. - * - * @api - */ -#define rccResetTIM4() rccResetAPB1(RCC_APB1RSTR_TIM4RST) - -/** - * @brief Enables the TIM6 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableTIM6(lp) rccEnableAPB1(RCC_APB1ENR_TIM6EN, lp) - -/** - * @brief Disables the TIM6 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccDisableTIM6(lp) rccDisableAPB1(RCC_APB1ENR_TIM6EN, lp) - -/** - * @brief Resets the TIM6 peripheral. - * - * @api - */ -#define rccResetTIM6() rccResetAPB1(RCC_APB1RSTR_TIM6RST) - -/** - * @brief Enables the TIM7 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableTIM7(lp) rccEnableAPB1(RCC_APB1ENR_TIM7EN, lp) - -/** - * @brief Disables the TIM7 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccDisableTIM7(lp) rccDisableAPB1(RCC_APB1ENR_TIM7EN, lp) - -/** - * @brief Resets the TIM7 peripheral. - * - * @api - */ -#define rccResetTIM7() rccResetAPB1(RCC_APB1RSTR_TIM7RST) - -/** - * @brief Enables the TIM8 peripheral clock. - * @note The @p lp parameter is ignored in this family. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableTIM8(lp) rccEnableAPB2(RCC_APB2ENR_TIM8EN, lp) - -/** - * @brief Disables the TIM8 peripheral clock. - * @note The @p lp parameter is ignored in this family. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccDisableTIM8(lp) rccDisableAPB2(RCC_APB2ENR_TIM8EN, lp) - -/** - * @brief Resets the TIM8 peripheral. - * - * @api - */ -#define rccResetTIM8() rccResetAPB2(RCC_APB2RSTR_TIM8RST) -/** @} */ - -/** - * @name USART/UART peripherals specific RCC operations - * @{ - */ -/** - * @brief Enables the USART1 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableUSART1(lp) rccEnableAPB2(RCC_APB2ENR_USART1EN, lp) - -/** - * @brief Disables the USART1 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccDisableUSART1(lp) rccDisableAPB2(RCC_APB2ENR_USART1EN, lp) - -/** - * @brief Resets the USART1 peripheral. - * - * @api - */ -#define rccResetUSART1() rccResetAPB2(RCC_APB2RSTR_USART1RST) - -/** - * @brief Enables the USART2 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableUSART2(lp) rccEnableAPB1(RCC_APB1ENR_USART2EN, lp) - -/** - * @brief Disables the USART2 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccDisableUSART2(lp) rccDisableAPB1(RCC_APB1ENR_USART2EN, lp) - -/** - * @brief Resets the USART2 peripheral. - * - * @api - */ -#define rccResetUSART2() rccResetAPB1(RCC_APB1RSTR_USART2RST) - -/** - * @brief Enables the USART3 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableUSART3(lp) rccEnableAPB1(RCC_APB1ENR_USART3EN, lp) - -/** - * @brief Disables the USART3 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccDisableUSART3(lp) rccDisableAPB1(RCC_APB1ENR_USART3EN, lp) - -/** - * @brief Resets the USART3 peripheral. - * - * @api - */ -#define rccResetUSART3() rccResetAPB1(RCC_APB1RSTR_USART3RST) - -/** - * @brief Enables the UART4 peripheral clock. - * @note The @p lp parameter is ignored in this family. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableUART4(lp) rccEnableAPB1(RCC_APB1ENR_UART4EN, lp) - -/** - * @brief Disables the UART4 peripheral clock. - * @note The @p lp parameter is ignored in this family. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccDisableUART4(lp) rccDisableAPB1(RCC_APB1ENR_UART4EN, lp) - -/** - * @brief Resets the UART4 peripheral. - * - * @api - */ -#define rccResetUART4() rccResetAPB1(RCC_APB1RSTR_UART4RST) - -/** - * @brief Enables the UART5 peripheral clock. - * @note The @p lp parameter is ignored in this family. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableUART5(lp) rccEnableAPB1(RCC_APB1ENR_UART5EN, lp) - -/** - * @brief Disables the UART5 peripheral clock. - * @note The @p lp parameter is ignored in this family. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccDisableUART5(lp) rccDisableAPB1(RCC_APB1ENR_UART5EN, lp) - -/** - * @brief Resets the UART5 peripheral. - * - * @api - */ -#define rccResetUART5() rccResetAPB1(RCC_APB1RSTR_UART5RST) -/** @} */ - -/** - * @name USB peripheral specific RCC operations - * @{ - */ -/** - * @brief Enables the USB peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableUSB(lp) rccEnableAPB1(RCC_APB1ENR_USBEN, lp) - -/** - * @brief Disables the USB peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccDisableUSB(lp) rccDisableAPB1(RCC_APB1ENR_USBEN, lp) - -/** - * @brief Resets the USB peripheral. - * - * @api - */ -#define rccResetUSB() rccResetAPB1(RCC_APB1RSTR_USBRST) -/** @} */ - -/*===========================================================================*/ -/* External declarations. */ -/*===========================================================================*/ - -#ifdef __cplusplus -extern "C" { -#endif -#ifdef __cplusplus -} -#endif - -#endif /* _STM32_RCC_ */ - -/** @} */ diff --git a/os/hal/platforms/STM32F30x/stm32_registry.h b/os/hal/platforms/STM32F30x/stm32_registry.h deleted file mode 100644 index 7487620ef..000000000 --- a/os/hal/platforms/STM32F30x/stm32_registry.h +++ /dev/null @@ -1,194 +0,0 @@ -/* - ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file STM32F30x/stm32_registry.h - * @brief STM32F30x capabilities registry. - * - * @addtogroup HAL - * @{ - */ - -#ifndef _STM32_REGISTRY_H_ -#define _STM32_REGISTRY_H_ - -/*===========================================================================*/ -/* Platform capabilities. */ -/*===========================================================================*/ - -/** - * @name STM32F30x capabilities - * @{ - */ -/* ADC attributes.*/ -#define STM32_HAS_ADC1 TRUE - -#define STM32_HAS_ADC2 TRUE - -#define STM32_HAS_ADC3 TRUE - -#define STM32_HAS_ADC4 TRUE - -#define STM32_HAS_SDADC1 FALSE -#define STM32_HAS_SDADC2 FALSE -#define STM32_HAS_SDADC3 FALSE - -/* CAN attributes.*/ -#define STM32_HAS_CAN1 TRUE -#define STM32_HAS_CAN2 FALSE -#define STM32_CAN_MAX_FILTERS 14 - -/* DAC attributes.*/ -#define STM32_HAS_DAC1 TRUE -#define STM32_HAS_DAC2 TRUE - -/* DMA attributes.*/ -#define STM32_ADVANCED_DMA FALSE -#define STM32_HAS_DMA1 TRUE -#define STM32_HAS_DMA2 TRUE - -/* ETH attributes.*/ -#define STM32_HAS_ETH FALSE - -/* EXTI attributes.*/ -#define STM32_EXTI_NUM_CHANNELS 34 - -/* GPIO attributes.*/ -#define STM32_HAS_GPIOA TRUE -#define STM32_HAS_GPIOB TRUE -#define STM32_HAS_GPIOC TRUE -#define STM32_HAS_GPIOD TRUE -#define STM32_HAS_GPIOE TRUE -#define STM32_HAS_GPIOF TRUE -#define STM32_HAS_GPIOG FALSE -#define STM32_HAS_GPIOH FALSE -#define STM32_HAS_GPIOI FALSE - -/* I2C attributes.*/ -#define STM32_HAS_I2C1 TRUE -#define STM32_I2C_I2C1_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7) -#define STM32_I2C_I2C1_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 6) - -#define STM32_HAS_I2C2 TRUE -#define STM32_I2C_I2C2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 5) -#define STM32_I2C_I2C2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) - -#define STM32_HAS_I2C3 FALSE - -/* RTC attributes.*/ -#define STM32_HAS_RTC TRUE -#define STM32_RTC_HAS_SUBSECONDS TRUE -#define STM32_RTC_IS_CALENDAR TRUE - -/* SDIO attributes.*/ -#define STM32_HAS_SDIO FALSE - -/* SPI attributes.*/ -#define STM32_HAS_SPI1 TRUE -#define STM32_SPI_SPI1_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2) -#define STM32_SPI_SPI1_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 3) - -#define STM32_HAS_SPI2 TRUE -#define STM32_SPI_SPI2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) -#define STM32_SPI_SPI2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 5) - -#define STM32_HAS_SPI3 TRUE -#define STM32_SPI_SPI3_RX_DMA_STREAM STM32_DMA_STREAM_ID(2, 1) -#define STM32_SPI_SPI3_TX_DMA_STREAM STM32_DMA_STREAM_ID(2, 2) - -/* TIM attributes.*/ -#define STM32_TIM_MAX_CHANNELS 6 - -#define STM32_HAS_TIM1 TRUE -#define STM32_TIM1_IS_32BITS FALSE -#define STM32_TIM1_CHANNELS 6 - -#define STM32_HAS_TIM2 TRUE -#define STM32_TIM2_IS_32BITS TRUE -#define STM32_TIM2_CHANNELS 4 - -#define STM32_HAS_TIM3 TRUE -#define STM32_TIM3_IS_32BITS FALSE -#define STM32_TIM3_CHANNELS 4 - -#define STM32_HAS_TIM4 TRUE -#define STM32_TIM4_IS_32BITS FALSE -#define STM32_TIM4_CHANNELS 4 - -#define STM32_HAS_TIM6 TRUE -#define STM32_TIM6_IS_32BITS FALSE -#define STM32_TIM6_CHANNELS 0 - -#define STM32_HAS_TIM7 TRUE -#define STM32_TIM7_IS_32BITS FALSE -#define STM32_TIM7_CHANNELS 0 - -#define STM32_HAS_TIM8 TRUE -#define STM32_TIM8_IS_32BITS FALSE -#define STM32_TIM8_CHANNELS 6 - -#define STM32_HAS_TIM15 TRUE -#define STM32_TIM15_IS_32BITS FALSE -#define STM32_TIM15_CHANNELS 2 - -#define STM32_HAS_TIM16 TRUE -#define STM32_TIM16_IS_32BITS FALSE -#define STM32_TIM16_CHANNELS 2 - -#define STM32_HAS_TIM17 TRUE -#define STM32_TIM17_IS_32BITS FALSE -#define STM32_TIM17_CHANNELS 2 - -#define STM32_HAS_TIM5 FALSE -#define STM32_HAS_TIM9 FALSE -#define STM32_HAS_TIM10 FALSE -#define STM32_HAS_TIM11 FALSE -#define STM32_HAS_TIM12 FALSE -#define STM32_HAS_TIM13 FALSE -#define STM32_HAS_TIM14 FALSE -#define STM32_HAS_TIM18 FALSE -#define STM32_HAS_TIM19 FALSE - -/* USART attributes.*/ -#define STM32_HAS_USART1 TRUE -#define STM32_UART_USART1_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 5) -#define STM32_UART_USART1_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) - -#define STM32_HAS_USART2 TRUE -#define STM32_UART_USART2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 6) -#define STM32_UART_USART2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7) - -#define STM32_HAS_USART3 TRUE -#define STM32_UART_USART3_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 3) -#define STM32_UART_USART3_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2) - -#define STM32_HAS_UART4 TRUE -#define STM32_UART_UART4_RX_DMA_STREAM STM32_DMA_STREAM_ID(2, 3) -#define STM32_UART_UART4_TX_DMA_STREAM STM32_DMA_STREAM_ID(2, 5) - -#define STM32_HAS_UART5 TRUE - -#define STM32_HAS_USART6 FALSE - -/* USB attributes.*/ -#define STM32_HAS_USB TRUE -#define STM32_HAS_OTG1 FALSE -#define STM32_HAS_OTG2 FALSE -/** @} */ - -#endif /* _STM32_REGISTRY_H_ */ - -/** @} */ diff --git a/os/hal/platforms/STM32F4xx/adc_lld.c b/os/hal/platforms/STM32F4xx/adc_lld.c deleted file mode 100644 index 724dc2938..000000000 --- a/os/hal/platforms/STM32F4xx/adc_lld.c +++ /dev/null @@ -1,418 +0,0 @@ -/* - ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file STM32F4xx/adc_lld.c - * @brief STM32F4xx/STM32F2xx ADC subsystem low level driver source. - * - * @addtogroup ADC - * @{ - */ - -#include "hal.h" - -#if HAL_USE_ADC || defined(__DOXYGEN__) - -/*===========================================================================*/ -/* Driver local definitions. */ -/*===========================================================================*/ - -#define ADC1_DMA_CHANNEL \ - STM32_DMA_GETCHANNEL(STM32_ADC_ADC1_DMA_STREAM, STM32_ADC1_DMA_CHN) - -#define ADC2_DMA_CHANNEL \ - STM32_DMA_GETCHANNEL(STM32_ADC_ADC2_DMA_STREAM, STM32_ADC2_DMA_CHN) - -#define ADC3_DMA_CHANNEL \ - STM32_DMA_GETCHANNEL(STM32_ADC_ADC3_DMA_STREAM, STM32_ADC3_DMA_CHN) - -/*===========================================================================*/ -/* Driver exported variables. */ -/*===========================================================================*/ - -/** @brief ADC1 driver identifier.*/ -#if STM32_ADC_USE_ADC1 || defined(__DOXYGEN__) -ADCDriver ADCD1; -#endif - -/** @brief ADC2 driver identifier.*/ -#if STM32_ADC_USE_ADC2 || defined(__DOXYGEN__) -ADCDriver ADCD2; -#endif - -/** @brief ADC3 driver identifier.*/ -#if STM32_ADC_USE_ADC3 || defined(__DOXYGEN__) -ADCDriver ADCD3; -#endif - -/*===========================================================================*/ -/* Driver local variables and types. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver local functions. */ -/*===========================================================================*/ - -/** - * @brief ADC DMA ISR service routine. - * - * @param[in] adcp pointer to the @p ADCDriver object - * @param[in] flags pre-shifted content of the ISR register - */ -static void adc_lld_serve_rx_interrupt(ADCDriver *adcp, uint32_t flags) { - - /* DMA errors handling.*/ - if ((flags & (STM32_DMA_ISR_TEIF | STM32_DMA_ISR_DMEIF)) != 0) { - /* DMA, this could help only if the DMA tries to access an unmapped - address space or violates alignment rules.*/ - _adc_isr_error_code(adcp, ADC_ERR_DMAFAILURE); - } - else { - /* It is possible that the conversion group has already be reset by the - ADC error handler, in this case this interrupt is spurious.*/ - if (adcp->grpp != NULL) { - if ((flags & STM32_DMA_ISR_HTIF) != 0) { - /* Half transfer processing.*/ - _adc_isr_half_code(adcp); - } - if ((flags & STM32_DMA_ISR_TCIF) != 0) { - /* Transfer complete processing.*/ - _adc_isr_full_code(adcp); - } - } - } -} - -/*===========================================================================*/ -/* Driver interrupt handlers. */ -/*===========================================================================*/ - -#if STM32_ADC_USE_ADC1 || STM32_ADC_USE_ADC2 || STM32_ADC_USE_ADC3 || \ - defined(__DOXYGEN__) -/** - * @brief ADC interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(ADC1_2_3_IRQHandler) { - uint32_t sr; - - OSAL_IRQ_PROLOGUE(); - -#if STM32_ADC_USE_ADC1 - sr = ADC1->SR; - ADC1->SR = 0; - /* Note, an overflow may occur after the conversion ended before the driver - is able to stop the ADC, this is why the DMA channel is checked too.*/ - if ((sr & ADC_SR_OVR) && (dmaStreamGetTransactionSize(ADCD1.dmastp) > 0)) { - /* ADC overflow condition, this could happen only if the DMA is unable - to read data fast enough.*/ - if (ADCD1.grpp != NULL) - _adc_isr_error_code(&ADCD1, ADC_ERR_OVERFLOW); - } - /* TODO: Add here analog watchdog handling.*/ -#endif /* STM32_ADC_USE_ADC1 */ - -#if STM32_ADC_USE_ADC2 - sr = ADC2->SR; - ADC2->SR = 0; - /* Note, an overflow may occur after the conversion ended before the driver - is able to stop the ADC, this is why the DMA channel is checked too.*/ - if ((sr & ADC_SR_OVR) && (dmaStreamGetTransactionSize(ADCD2.dmastp) > 0)) { - /* ADC overflow condition, this could happen only if the DMA is unable - to read data fast enough.*/ - if (ADCD2.grpp != NULL) - _adc_isr_error_code(&ADCD2, ADC_ERR_OVERFLOW); - } - /* TODO: Add here analog watchdog handling.*/ -#endif /* STM32_ADC_USE_ADC2 */ - -#if STM32_ADC_USE_ADC3 - sr = ADC3->SR; - ADC3->SR = 0; - /* Note, an overflow may occur after the conversion ended before the driver - is able to stop the ADC, this is why the DMA channel is checked too.*/ - if ((sr & ADC_SR_OVR) && (dmaStreamGetTransactionSize(ADCD3.dmastp) > 0)) { - /* ADC overflow condition, this could happen only if the DMA is unable - to read data fast enough.*/ - if (ADCD3.grpp != NULL) - _adc_isr_error_code(&ADCD3, ADC_ERR_OVERFLOW); - } - /* TODO: Add here analog watchdog handling.*/ -#endif /* STM32_ADC_USE_ADC3 */ - - OSAL_IRQ_EPILOGUE(); -} -#endif - -/*===========================================================================*/ -/* Driver exported functions. */ -/*===========================================================================*/ - -/** - * @brief Low level ADC driver initialization. - * - * @notapi - */ -void adc_lld_init(void) { - -#if STM32_ADC_USE_ADC1 - /* Driver initialization.*/ - adcObjectInit(&ADCD1); - ADCD1.adc = ADC1; - ADCD1.dmastp = STM32_DMA_STREAM(STM32_ADC_ADC1_DMA_STREAM); - ADCD1.dmamode = STM32_DMA_CR_CHSEL(ADC1_DMA_CHANNEL) | - STM32_DMA_CR_PL(STM32_ADC_ADC1_DMA_PRIORITY) | - STM32_DMA_CR_DIR_P2M | - STM32_DMA_CR_MSIZE_HWORD | STM32_DMA_CR_PSIZE_HWORD | - STM32_DMA_CR_MINC | STM32_DMA_CR_TCIE | - STM32_DMA_CR_DMEIE | STM32_DMA_CR_TEIE; -#endif - -#if STM32_ADC_USE_ADC2 - /* Driver initialization.*/ - adcObjectInit(&ADCD2); - ADCD2.adc = ADC2; - ADCD2.dmastp = STM32_DMA_STREAM(STM32_ADC_ADC2_DMA_STREAM); - ADCD2.dmamode = STM32_DMA_CR_CHSEL(ADC2_DMA_CHANNEL) | - STM32_DMA_CR_PL(STM32_ADC_ADC2_DMA_PRIORITY) | - STM32_DMA_CR_DIR_P2M | - STM32_DMA_CR_MSIZE_HWORD | STM32_DMA_CR_PSIZE_HWORD | - STM32_DMA_CR_MINC | STM32_DMA_CR_TCIE | - STM32_DMA_CR_DMEIE | STM32_DMA_CR_TEIE; -#endif - -#if STM32_ADC_USE_ADC3 - /* Driver initialization.*/ - adcObjectInit(&ADCD3); - ADCD3.adc = ADC3; - ADCD3.dmastp = STM32_DMA_STREAM(STM32_ADC_ADC3_DMA_STREAM); - ADCD3.dmamode = STM32_DMA_CR_CHSEL(ADC3_DMA_CHANNEL) | - STM32_DMA_CR_PL(STM32_ADC_ADC3_DMA_PRIORITY) | - STM32_DMA_CR_DIR_P2M | - STM32_DMA_CR_MSIZE_HWORD | STM32_DMA_CR_PSIZE_HWORD | - STM32_DMA_CR_MINC | STM32_DMA_CR_TCIE | - STM32_DMA_CR_DMEIE | STM32_DMA_CR_TEIE; -#endif - - /* The shared vector is initialized on driver initialization and never - disabled.*/ - nvicEnableVector(ADC_IRQn, STM32_ADC_IRQ_PRIORITY); -} - -/** - * @brief Configures and activates the ADC peripheral. - * - * @param[in] adcp pointer to the @p ADCDriver object - * - * @notapi - */ -void adc_lld_start(ADCDriver *adcp) { - - /* If in stopped state then enables the ADC and DMA clocks.*/ - if (adcp->state == ADC_STOP) { -#if STM32_ADC_USE_ADC1 - if (&ADCD1 == adcp) { - bool b; - b = dmaStreamAllocate(adcp->dmastp, - STM32_ADC_ADC1_DMA_IRQ_PRIORITY, - (stm32_dmaisr_t)adc_lld_serve_rx_interrupt, - (void *)adcp); - osalDbgAssert(!b, "stream already allocated"); - dmaStreamSetPeripheral(adcp->dmastp, &ADC1->DR); - rccEnableADC1(FALSE); - } -#endif /* STM32_ADC_USE_ADC1 */ - -#if STM32_ADC_USE_ADC2 - if (&ADCD2 == adcp) { - bool b; - b = dmaStreamAllocate(adcp->dmastp, - STM32_ADC_ADC2_DMA_IRQ_PRIORITY, - (stm32_dmaisr_t)adc_lld_serve_rx_interrupt, - (void *)adcp); - osalDbgAssert(!b, "stream already allocated"); - dmaStreamSetPeripheral(adcp->dmastp, &ADC2->DR); - rccEnableADC2(FALSE); - } -#endif /* STM32_ADC_USE_ADC2 */ - -#if STM32_ADC_USE_ADC3 - if (&ADCD3 == adcp) { - bool b; - b = dmaStreamAllocate(adcp->dmastp, - STM32_ADC_ADC3_DMA_IRQ_PRIORITY, - (stm32_dmaisr_t)adc_lld_serve_rx_interrupt, - (void *)adcp); - osalDbgAssert(!b, "stream already allocated"); - dmaStreamSetPeripheral(adcp->dmastp, &ADC3->DR); - rccEnableADC3(FALSE); - } -#endif /* STM32_ADC_USE_ADC3 */ - - /* This is a common register but apparently it requires that at least one - of the ADCs is clocked in order to allow writing, see bug 3575297.*/ - ADC->CCR = (ADC->CCR & (ADC_CCR_TSVREFE | ADC_CCR_VBATE)) | - (STM32_ADC_ADCPRE << 16); - - /* ADC initial setup, starting the analog part here in order to reduce - the latency when starting a conversion.*/ - adcp->adc->CR1 = 0; - adcp->adc->CR2 = 0; - adcp->adc->CR2 = ADC_CR2_ADON; - } -} - -/** - * @brief Deactivates the ADC peripheral. - * - * @param[in] adcp pointer to the @p ADCDriver object - * - * @notapi - */ -void adc_lld_stop(ADCDriver *adcp) { - - /* If in ready state then disables the ADC clock.*/ - if (adcp->state == ADC_READY) { - dmaStreamRelease(adcp->dmastp); - adcp->adc->CR1 = 0; - adcp->adc->CR2 = 0; - -#if STM32_ADC_USE_ADC1 - if (&ADCD1 == adcp) - rccDisableADC1(FALSE); -#endif - -#if STM32_ADC_USE_ADC2 - if (&ADCD2 == adcp) - rccDisableADC2(FALSE); -#endif - -#if STM32_ADC_USE_ADC3 - if (&ADCD3 == adcp) - rccDisableADC3(FALSE); -#endif - } -} - -/** - * @brief Starts an ADC conversion. - * - * @param[in] adcp pointer to the @p ADCDriver object - * - * @notapi - */ -void adc_lld_start_conversion(ADCDriver *adcp) { - uint32_t mode; - const ADCConversionGroup *grpp = adcp->grpp; - - /* DMA setup.*/ - mode = adcp->dmamode; - if (grpp->circular) { - mode |= STM32_DMA_CR_CIRC; - } - if (adcp->depth > 1) { - /* If the buffer depth is greater than one then the half transfer interrupt - interrupt is enabled in order to allows streaming processing.*/ - mode |= STM32_DMA_CR_HTIE; - } - dmaStreamSetMemory0(adcp->dmastp, adcp->samples); - dmaStreamSetTransactionSize(adcp->dmastp, (uint32_t)grpp->num_channels * - (uint32_t)adcp->depth); - dmaStreamSetMode(adcp->dmastp, mode); - dmaStreamEnable(adcp->dmastp); - - /* ADC setup.*/ - adcp->adc->SR = 0; - adcp->adc->SMPR1 = grpp->smpr1; - adcp->adc->SMPR2 = grpp->smpr2; - adcp->adc->SQR1 = grpp->sqr1; - adcp->adc->SQR2 = grpp->sqr2; - adcp->adc->SQR3 = grpp->sqr3; - - /* ADC configuration and start, the start is performed using the method - specified in the CR2 configuration, usually ADC_CR2_SWSTART.*/ - adcp->adc->CR1 = grpp->cr1 | ADC_CR1_OVRIE | ADC_CR1_SCAN; - if ((grpp->cr2 & ADC_CR2_SWSTART) != 0) - adcp->adc->CR2 = grpp->cr2 | ADC_CR2_CONT | ADC_CR2_DMA | - ADC_CR2_DDS | ADC_CR2_ADON; - else - adcp->adc->CR2 = grpp->cr2 | ADC_CR2_DMA | - ADC_CR2_DDS | ADC_CR2_ADON; -} - -/** - * @brief Stops an ongoing conversion. - * - * @param[in] adcp pointer to the @p ADCDriver object - * - * @notapi - */ -void adc_lld_stop_conversion(ADCDriver *adcp) { - - dmaStreamDisable(adcp->dmastp); - adcp->adc->CR1 = 0; - adcp->adc->CR2 = 0; - adcp->adc->CR2 = ADC_CR2_ADON; -} - -/** - * @brief Enables the TSVREFE bit. - * @details The TSVREFE bit is required in order to sample the internal - * temperature sensor and internal reference voltage. - * @note This is an STM32-only functionality. - */ -void adcSTM32EnableTSVREFE(void) { - - ADC->CCR |= ADC_CCR_TSVREFE; -} - -/** - * @brief Disables the TSVREFE bit. - * @details The TSVREFE bit is required in order to sample the internal - * temperature sensor and internal reference voltage. - * @note This is an STM32-only functionality. - */ -void adcSTM32DisableTSVREFE(void) { - - ADC->CCR &= ~ADC_CCR_TSVREFE; -} - -/** - * @brief Enables the VBATE bit. - * @details The VBATE bit is required in order to sample the VBAT channel. - * @note This is an STM32-only functionality. - * @note This function is meant to be called after @p adcStart(). - */ -void adcSTM32EnableVBATE(void) { - - ADC->CCR |= ADC_CCR_VBATE; -} - -/** - * @brief Disables the VBATE bit. - * @details The VBATE bit is required in order to sample the VBAT channel. - * @note This is an STM32-only functionality. - * @note This function is meant to be called after @p adcStart(). - */ -void adcSTM32DisableVBATE(void) { - - ADC->CCR &= ~ADC_CCR_VBATE; -} - -#endif /* HAL_USE_ADC */ - -/** @} */ diff --git a/os/hal/platforms/STM32F4xx/adc_lld.h b/os/hal/platforms/STM32F4xx/adc_lld.h deleted file mode 100644 index c8f0570eb..000000000 --- a/os/hal/platforms/STM32F4xx/adc_lld.h +++ /dev/null @@ -1,563 +0,0 @@ -/* - ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file STM32F4xx/adc_lld.h - * @brief STM32F4xx/STM32F2xx ADC subsystem low level driver header. - * - * @addtogroup ADC - * @{ - */ - -#ifndef _ADC_LLD_H_ -#define _ADC_LLD_H_ - -#if HAL_USE_ADC || defined(__DOXYGEN__) - -/*===========================================================================*/ -/* Driver constants. */ -/*===========================================================================*/ - -/** - * @name Absolute Maximum Ratings - * @{ - */ -/** - * @brief Minimum ADC clock frequency. - */ -#define STM32_ADCCLK_MIN 600000 - -/** - * @brief Maximum ADC clock frequency. - */ -#if defined(STM32F4XX) || defined(__DOXYGEN__) -#define STM32_ADCCLK_MAX 36000000 -#else -#define STM32_ADCCLK_MAX 30000000 -#endif -/** @} */ - -/** - * @name Triggers selection - * @{ - */ -#define ADC_CR2_EXTSEL_SRC(n) ((n) << 24) /**< @brief Trigger source. */ -/** @} */ - -/** - * @name ADC clock divider settings - * @{ - */ -#define ADC_CCR_ADCPRE_DIV2 0 -#define ADC_CCR_ADCPRE_DIV4 1 -#define ADC_CCR_ADCPRE_DIV6 2 -#define ADC_CCR_ADCPRE_DIV8 3 -/** @} */ - -/** - * @name Available analog channels - * @{ - */ -#define ADC_CHANNEL_IN0 0 /**< @brief External analog input 0. */ -#define ADC_CHANNEL_IN1 1 /**< @brief External analog input 1. */ -#define ADC_CHANNEL_IN2 2 /**< @brief External analog input 2. */ -#define ADC_CHANNEL_IN3 3 /**< @brief External analog input 3. */ -#define ADC_CHANNEL_IN4 4 /**< @brief External analog input 4. */ -#define ADC_CHANNEL_IN5 5 /**< @brief External analog input 5. */ -#define ADC_CHANNEL_IN6 6 /**< @brief External analog input 6. */ -#define ADC_CHANNEL_IN7 7 /**< @brief External analog input 7. */ -#define ADC_CHANNEL_IN8 8 /**< @brief External analog input 8. */ -#define ADC_CHANNEL_IN9 9 /**< @brief External analog input 9. */ -#define ADC_CHANNEL_IN10 10 /**< @brief External analog input 10. */ -#define ADC_CHANNEL_IN11 11 /**< @brief External analog input 11. */ -#define ADC_CHANNEL_IN12 12 /**< @brief External analog input 12. */ -#define ADC_CHANNEL_IN13 13 /**< @brief External analog input 13. */ -#define ADC_CHANNEL_IN14 14 /**< @brief External analog input 14. */ -#define ADC_CHANNEL_IN15 15 /**< @brief External analog input 15. */ -#define ADC_CHANNEL_SENSOR 16 /**< @brief Internal temperature sensor. - @note Available onADC1 only. */ -#define ADC_CHANNEL_VREFINT 17 /**< @brief Internal reference. - @note Available onADC1 only. */ -#define ADC_CHANNEL_VBAT 18 /**< @brief VBAT. - @note Available onADC1 only. */ -/** @} */ - -/** - * @name Sampling rates - * @{ - */ -#define ADC_SAMPLE_3 0 /**< @brief 3 cycles sampling time. */ -#define ADC_SAMPLE_15 1 /**< @brief 15 cycles sampling time. */ -#define ADC_SAMPLE_28 2 /**< @brief 28 cycles sampling time. */ -#define ADC_SAMPLE_56 3 /**< @brief 56 cycles sampling time. */ -#define ADC_SAMPLE_84 4 /**< @brief 84 cycles sampling time. */ -#define ADC_SAMPLE_112 5 /**< @brief 112 cycles sampling time. */ -#define ADC_SAMPLE_144 6 /**< @brief 144 cycles sampling time. */ -#define ADC_SAMPLE_480 7 /**< @brief 480 cycles sampling time. */ -/** @} */ - -/*===========================================================================*/ -/* Driver pre-compile time settings. */ -/*===========================================================================*/ - -/** - * @name Configuration options - * @{ - */ -/** - * @brief ADC common clock divider. - * @note This setting is influenced by the VDDA voltage and other - * external conditions, please refer to the datasheet for more - * info.
- * See section 5.3.20 "12-bit ADC characteristics". - */ -#if !defined(STM32_ADC_ADCPRE) || defined(__DOXYGEN__) -#define STM32_ADC_ADCPRE ADC_CCR_ADCPRE_DIV2 -#endif - -/** - * @brief ADC1 driver enable switch. - * @details If set to @p TRUE the support for ADC1 is included. - * @note The default is @p TRUE. - */ -#if !defined(STM32_ADC_USE_ADC1) || defined(__DOXYGEN__) -#define STM32_ADC_USE_ADC1 FALSE -#endif - -/** - * @brief ADC2 driver enable switch. - * @details If set to @p TRUE the support for ADC2 is included. - * @note The default is @p TRUE. - */ -#if !defined(STM32_ADC_USE_ADC2) || defined(__DOXYGEN__) -#define STM32_ADC_USE_ADC2 FALSE -#endif - -/** - * @brief ADC3 driver enable switch. - * @details If set to @p TRUE the support for ADC3 is included. - * @note The default is @p TRUE. - */ -#if !defined(STM32_ADC_USE_ADC3) || defined(__DOXYGEN__) -#define STM32_ADC_USE_ADC3 FALSE -#endif - -/** - * @brief DMA stream used for ADC1 operations. - */ -#if !defined(STM32_ADC_ADC1_DMA_STREAM) || defined(__DOXYGEN__) -#define STM32_ADC_ADC1_DMA_STREAM STM32_DMA_STREAM_ID(2, 4) -#endif - -/** - * @brief DMA stream used for ADC2 operations. - */ -#if !defined(STM32_ADC_ADC2_DMA_STREAM) || defined(__DOXYGEN__) -#define STM32_ADC_ADC2_DMA_STREAM STM32_DMA_STREAM_ID(2, 2) -#endif - -/** - * @brief DMA stream used for ADC3 operations. - */ -#if !defined(STM32_ADC_ADC3_DMA_STREAM) || defined(__DOXYGEN__) -#define STM32_ADC_ADC3_DMA_STREAM STM32_DMA_STREAM_ID(2, 1) -#endif - -/** - * @brief ADC1 DMA priority (0..3|lowest..highest). - */ -#if !defined(STM32_ADC_ADC1_DMA_PRIORITY) || defined(__DOXYGEN__) -#define STM32_ADC_ADC1_DMA_PRIORITY 2 -#endif - -/** - * @brief ADC2 DMA priority (0..3|lowest..highest). - */ -#if !defined(STM32_ADC_ADC2_DMA_PRIORITY) || defined(__DOXYGEN__) -#define STM32_ADC_ADC2_DMA_PRIORITY 2 -#endif - -/** - * @brief ADC3 DMA priority (0..3|lowest..highest). - */ -#if !defined(STM32_ADC_ADC3_DMA_PRIORITY) || defined(__DOXYGEN__) -#define STM32_ADC_ADC3_DMA_PRIORITY 2 -#endif - -/** - * @brief ADC interrupt priority level setting. - * @note This setting is shared among ADC1, ADC2 and ADC3 because - * all ADCs share the same vector. - */ -#if !defined(STM32_ADC_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_ADC_IRQ_PRIORITY 5 -#endif - -/** - * @brief ADC1 DMA interrupt priority level setting. - */ -#if !defined(STM32_ADC_ADC1_DMA_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_ADC_ADC1_DMA_IRQ_PRIORITY 5 -#endif - -/** - * @brief ADC2 DMA interrupt priority level setting. - */ -#if !defined(STM32_ADC_ADC2_DMA_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_ADC_ADC2_DMA_IRQ_PRIORITY 5 -#endif - -/** - * @brief ADC3 DMA interrupt priority level setting. - */ -#if !defined(STM32_ADC_ADC3_DMA_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_ADC_ADC3_DMA_IRQ_PRIORITY 5 -#endif - -/** @} */ - -/*===========================================================================*/ -/* Derived constants and error checks. */ -/*===========================================================================*/ - -#if STM32_ADC_USE_ADC1 && !STM32_HAS_ADC1 -#error "ADC1 not present in the selected device" -#endif - -#if STM32_ADC_USE_ADC2 && !STM32_HAS_ADC2 -#error "ADC2 not present in the selected device" -#endif - -#if STM32_ADC_USE_ADC3 && !STM32_HAS_ADC3 -#error "ADC3 not present in the selected device" -#endif - -#if !STM32_ADC_USE_ADC1 && !STM32_ADC_USE_ADC2 && !STM32_ADC_USE_ADC3 -#error "ADC driver activated but no ADC peripheral assigned" -#endif - -#if STM32_ADC_USE_ADC1 && \ - !STM32_DMA_IS_VALID_ID(STM32_ADC_ADC1_DMA_STREAM, STM32_ADC1_DMA_MSK) -#error "invalid DMA stream associated to ADC1" -#endif - -#if STM32_ADC_USE_ADC2 && \ - !STM32_DMA_IS_VALID_ID(STM32_ADC_ADC2_DMA_STREAM, STM32_ADC2_DMA_MSK) -#error "invalid DMA stream associated to ADC2" -#endif - -#if STM32_ADC_USE_ADC3 && \ - !STM32_DMA_IS_VALID_ID(STM32_ADC_ADC3_DMA_STREAM, STM32_ADC3_DMA_MSK) -#error "invalid DMA stream associated to ADC3" -#endif - -/* ADC clock related settings and checks.*/ -#if STM32_ADC_ADCPRE == ADC_CCR_ADCPRE_DIV2 -#define STM32_ADCCLK (STM32_PCLK2 / 2) -#elif STM32_ADC_ADCPRE == ADC_CCR_ADCPRE_DIV4 -#define STM32_ADCCLK (STM32_PCLK2 / 4) -#elif STM32_ADC_ADCPRE == ADC_CCR_ADCPRE_DIV6 -#define STM32_ADCCLK (STM32_PCLK2 / 6) -#elif STM32_ADC_ADCPRE == ADC_CCR_ADCPRE_DIV8 -#define STM32_ADCCLK (STM32_PCLK2 / 8) -#else -#error "invalid STM32_ADC_ADCPRE value specified" -#endif - -#if (STM32_ADCCLK < STM32_ADCCLK_MIN) || (STM32_ADCCLK > STM32_ADCCLK_MAX) -#error "STM32_ADCCLK outside acceptable range (STM32_ADCCLK_MIN...STM32_ADCCLK_MAX)" -#endif - -#if !defined(STM32_DMA_REQUIRED) -#define STM32_DMA_REQUIRED -#endif - -/*===========================================================================*/ -/* Driver data structures and types. */ -/*===========================================================================*/ - -/** - * @brief ADC sample data type. - */ -typedef uint16_t adcsample_t; - -/** - * @brief Channels number in a conversion group. - */ -typedef uint16_t adc_channels_num_t; - -/** - * @brief Possible ADC failure causes. - * @note Error codes are architecture dependent and should not relied - * upon. - */ -typedef enum { - ADC_ERR_DMAFAILURE = 0, /**< DMA operations failure. */ - ADC_ERR_OVERFLOW = 1 /**< ADC overflow condition. */ -} adcerror_t; - -/** - * @brief Type of a structure representing an ADC driver. - */ -typedef struct ADCDriver ADCDriver; - -/** - * @brief ADC notification callback type. - * - * @param[in] adcp pointer to the @p ADCDriver object triggering the - * callback - * @param[in] buffer pointer to the most recent samples data - * @param[in] n number of buffer rows available starting from @p buffer - */ -typedef void (*adccallback_t)(ADCDriver *adcp, adcsample_t *buffer, size_t n); - -/** - * @brief ADC error callback type. - * - * @param[in] adcp pointer to the @p ADCDriver object triggering the - * callback - * @param[in] err ADC error code - */ -typedef void (*adcerrorcallback_t)(ADCDriver *adcp, adcerror_t err); - -/** - * @brief Conversion group configuration structure. - * @details This implementation-dependent structure describes a conversion - * operation. - * @note The use of this configuration structure requires knowledge of - * STM32 ADC cell registers interface, please refer to the STM32 - * reference manual for details. - */ -typedef struct { - /** - * @brief Enables the circular buffer mode for the group. - */ - bool_t circular; - /** - * @brief Number of the analog channels belonging to the conversion group. - */ - adc_channels_num_t num_channels; - /** - * @brief Callback function associated to the group or @p NULL. - */ - adccallback_t end_cb; - /** - * @brief Error callback or @p NULL. - */ - adcerrorcallback_t error_cb; - /* End of the mandatory fields.*/ - /** - * @brief ADC CR1 register initialization data. - * @note All the required bits must be defined into this field except - * @p ADC_CR1_SCAN that is enforced inside the driver. - */ - uint32_t cr1; - /** - * @brief ADC CR2 register initialization data. - * @note All the required bits must be defined into this field except - * @p ADC_CR2_DMA, @p ADC_CR2_CONT and @p ADC_CR2_ADON that are - * enforced inside the driver. - */ - uint32_t cr2; - /** - * @brief ADC SMPR1 register initialization data. - * @details In this field must be specified the sample times for channels - * 10...18. - */ - uint32_t smpr1; - /** - * @brief ADC SMPR2 register initialization data. - * @details In this field must be specified the sample times for channels - * 0...9. - */ - uint32_t smpr2; - /** - * @brief ADC SQR1 register initialization data. - * @details Conversion group sequence 13...16 + sequence length. - */ - uint32_t sqr1; - /** - * @brief ADC SQR2 register initialization data. - * @details Conversion group sequence 7...12. - */ - uint32_t sqr2; - /** - * @brief ADC SQR3 register initialization data. - * @details Conversion group sequence 1...6. - */ - uint32_t sqr3; -} ADCConversionGroup; - -/** - * @brief Driver configuration structure. - * @note It could be empty on some architectures. - */ -typedef struct { - uint32_t dummy; -} ADCConfig; - -/** - * @brief Structure representing an ADC driver. - */ -struct ADCDriver { - /** - * @brief Driver state. - */ - adcstate_t state; - /** - * @brief Current configuration data. - */ - const ADCConfig *config; - /** - * @brief Current samples buffer pointer or @p NULL. - */ - adcsample_t *samples; - /** - * @brief Current samples buffer depth or @p 0. - */ - size_t depth; - /** - * @brief Current conversion group pointer or @p NULL. - */ - const ADCConversionGroup *grpp; -#if ADC_USE_WAIT || defined(__DOXYGEN__) - /** - * @brief Waiting thread. - */ - thread_reference_t thread; -#endif -#if ADC_USE_MUTUAL_EXCLUSION || defined(__DOXYGEN__) - /** - * @brief Mutex protecting the peripheral. - */ - mutex_t mutex; -#endif /* ADC_USE_MUTUAL_EXCLUSION */ -#if defined(ADC_DRIVER_EXT_FIELDS) - ADC_DRIVER_EXT_FIELDS -#endif - /* End of the mandatory fields.*/ - /** - * @brief Pointer to the ADCx registers block. - */ - ADC_TypeDef *adc; - /** - * @brief Pointer to associated DMA channel. - */ - const stm32_dma_stream_t *dmastp; - /** - * @brief DMA mode bit mask. - */ - uint32_t dmamode; -}; - -/*===========================================================================*/ -/* Driver macros. */ -/*===========================================================================*/ - -/** - * @name Sequences building helper macros - * @{ - */ -/** - * @brief Number of channels in a conversion sequence. - */ -#define ADC_SQR1_NUM_CH(n) (((n) - 1) << 20) - -#define ADC_SQR3_SQ1_N(n) ((n) << 0) /**< @brief 1st channel in seq. */ -#define ADC_SQR3_SQ2_N(n) ((n) << 5) /**< @brief 2nd channel in seq. */ -#define ADC_SQR3_SQ3_N(n) ((n) << 10) /**< @brief 3rd channel in seq. */ -#define ADC_SQR3_SQ4_N(n) ((n) << 15) /**< @brief 4th channel in seq. */ -#define ADC_SQR3_SQ5_N(n) ((n) << 20) /**< @brief 5th channel in seq. */ -#define ADC_SQR3_SQ6_N(n) ((n) << 25) /**< @brief 6th channel in seq. */ - -#define ADC_SQR2_SQ7_N(n) ((n) << 0) /**< @brief 7th channel in seq. */ -#define ADC_SQR2_SQ8_N(n) ((n) << 5) /**< @brief 8th channel in seq. */ -#define ADC_SQR2_SQ9_N(n) ((n) << 10) /**< @brief 9th channel in seq. */ -#define ADC_SQR2_SQ10_N(n) ((n) << 15) /**< @brief 10th channel in seq.*/ -#define ADC_SQR2_SQ11_N(n) ((n) << 20) /**< @brief 11th channel in seq.*/ -#define ADC_SQR2_SQ12_N(n) ((n) << 25) /**< @brief 12th channel in seq.*/ - -#define ADC_SQR1_SQ13_N(n) ((n) << 0) /**< @brief 13th channel in seq.*/ -#define ADC_SQR1_SQ14_N(n) ((n) << 5) /**< @brief 14th channel in seq.*/ -#define ADC_SQR1_SQ15_N(n) ((n) << 10) /**< @brief 15th channel in seq.*/ -#define ADC_SQR1_SQ16_N(n) ((n) << 15) /**< @brief 16th channel in seq.*/ -/** @} */ - -/** - * @name Sampling rate settings helper macros - * @{ - */ -#define ADC_SMPR2_SMP_AN0(n) ((n) << 0) /**< @brief AN0 sampling time. */ -#define ADC_SMPR2_SMP_AN1(n) ((n) << 3) /**< @brief AN1 sampling time. */ -#define ADC_SMPR2_SMP_AN2(n) ((n) << 6) /**< @brief AN2 sampling time. */ -#define ADC_SMPR2_SMP_AN3(n) ((n) << 9) /**< @brief AN3 sampling time. */ -#define ADC_SMPR2_SMP_AN4(n) ((n) << 12) /**< @brief AN4 sampling time. */ -#define ADC_SMPR2_SMP_AN5(n) ((n) << 15) /**< @brief AN5 sampling time. */ -#define ADC_SMPR2_SMP_AN6(n) ((n) << 18) /**< @brief AN6 sampling time. */ -#define ADC_SMPR2_SMP_AN7(n) ((n) << 21) /**< @brief AN7 sampling time. */ -#define ADC_SMPR2_SMP_AN8(n) ((n) << 24) /**< @brief AN8 sampling time. */ -#define ADC_SMPR2_SMP_AN9(n) ((n) << 27) /**< @brief AN9 sampling time. */ - -#define ADC_SMPR1_SMP_AN10(n) ((n) << 0) /**< @brief AN10 sampling time. */ -#define ADC_SMPR1_SMP_AN11(n) ((n) << 3) /**< @brief AN11 sampling time. */ -#define ADC_SMPR1_SMP_AN12(n) ((n) << 6) /**< @brief AN12 sampling time. */ -#define ADC_SMPR1_SMP_AN13(n) ((n) << 9) /**< @brief AN13 sampling time. */ -#define ADC_SMPR1_SMP_AN14(n) ((n) << 12) /**< @brief AN14 sampling time. */ -#define ADC_SMPR1_SMP_AN15(n) ((n) << 15) /**< @brief AN15 sampling time. */ -#define ADC_SMPR1_SMP_SENSOR(n) ((n) << 18) /**< @brief Temperature Sensor - sampling time. */ -#define ADC_SMPR1_SMP_VREF(n) ((n) << 21) /**< @brief Voltage Reference - sampling time. */ -#define ADC_SMPR1_SMP_VBAT(n) ((n) << 24) /**< @brief VBAT sampling time. */ -/** @} */ - -/*===========================================================================*/ -/* External declarations. */ -/*===========================================================================*/ - -#if STM32_ADC_USE_ADC1 && !defined(__DOXYGEN__) -extern ADCDriver ADCD1; -#endif - -#if STM32_ADC_USE_ADC2 && !defined(__DOXYGEN__) -extern ADCDriver ADCD2; -#endif - -#if STM32_ADC_USE_ADC3 && !defined(__DOXYGEN__) -extern ADCDriver ADCD3; -#endif - -#ifdef __cplusplus -extern "C" { -#endif - void adc_lld_init(void); - void adc_lld_start(ADCDriver *adcp); - void adc_lld_stop(ADCDriver *adcp); - void adc_lld_start_conversion(ADCDriver *adcp); - void adc_lld_stop_conversion(ADCDriver *adcp); - void adcSTM32EnableTSVREFE(void); - void adcSTM32DisableTSVREFE(void); - void adcSTM32EnableVBATE(void); - void adcSTM32DisableVBATE(void); -#ifdef __cplusplus -} -#endif - -#endif /* HAL_USE_ADC */ - -#endif /* _ADC_LLD_H_ */ - -/** @} */ diff --git a/os/hal/platforms/STM32F4xx/ext_lld_isr.c b/os/hal/platforms/STM32F4xx/ext_lld_isr.c deleted file mode 100644 index dd1491557..000000000 --- a/os/hal/platforms/STM32F4xx/ext_lld_isr.c +++ /dev/null @@ -1,338 +0,0 @@ -/* - ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file STM32F4xx/ext_lld_isr.c - * @brief STM32F4xx/STM32F2xx EXT subsystem low level driver ISR code. - * - * @addtogroup EXT - * @{ - */ - -#include "hal.h" - -#if HAL_USE_EXT || defined(__DOXYGEN__) - -#include "ext_lld_isr.h" - -/*===========================================================================*/ -/* Driver local definitions. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver exported variables. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver local variables. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver local functions. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver interrupt handlers. */ -/*===========================================================================*/ - -/** - * @brief EXTI[0] interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(Vector58) { - - OSAL_IRQ_PROLOGUE(); - - EXTI->PR = (1 << 0); - EXTD1.config->channels[0].cb(&EXTD1, 0); - - OSAL_IRQ_EPILOGUE(); -} - -/** - * @brief EXTI[1] interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(Vector5C) { - - OSAL_IRQ_PROLOGUE(); - - EXTI->PR = (1 << 1); - EXTD1.config->channels[1].cb(&EXTD1, 1); - - OSAL_IRQ_EPILOGUE(); -} - -/** - * @brief EXTI[2] interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(Vector60) { - - OSAL_IRQ_PROLOGUE(); - - EXTI->PR = (1 << 2); - EXTD1.config->channels[2].cb(&EXTD1, 2); - - OSAL_IRQ_EPILOGUE(); -} - -/** - * @brief EXTI[3] interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(Vector64) { - - OSAL_IRQ_PROLOGUE(); - - EXTI->PR = (1 << 3); - EXTD1.config->channels[3].cb(&EXTD1, 3); - - OSAL_IRQ_EPILOGUE(); -} - -/** - * @brief EXTI[4] interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(Vector68) { - - OSAL_IRQ_PROLOGUE(); - - EXTI->PR = (1 << 4); - EXTD1.config->channels[4].cb(&EXTD1, 4); - - OSAL_IRQ_EPILOGUE(); -} - -/** - * @brief EXTI[5]...EXTI[9] interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(Vector9C) { - uint32_t pr; - - OSAL_IRQ_PROLOGUE(); - - pr = EXTI->PR & ((1 << 5) | (1 << 6) | (1 << 7) | (1 << 8) | (1 << 9)); - EXTI->PR = pr; - if (pr & (1 << 5)) - EXTD1.config->channels[5].cb(&EXTD1, 5); - if (pr & (1 << 6)) - EXTD1.config->channels[6].cb(&EXTD1, 6); - if (pr & (1 << 7)) - EXTD1.config->channels[7].cb(&EXTD1, 7); - if (pr & (1 << 8)) - EXTD1.config->channels[8].cb(&EXTD1, 8); - if (pr & (1 << 9)) - EXTD1.config->channels[9].cb(&EXTD1, 9); - - OSAL_IRQ_EPILOGUE(); -} - -/** - * @brief EXTI[10]...EXTI[15] interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(VectorE0) { - uint32_t pr; - - OSAL_IRQ_PROLOGUE(); - - pr = EXTI->PR & ((1 << 10) | (1 << 11) | (1 << 12) | (1 << 13) | (1 << 14) | - (1 << 15)); - EXTI->PR = pr; - if (pr & (1 << 10)) - EXTD1.config->channels[10].cb(&EXTD1, 10); - if (pr & (1 << 11)) - EXTD1.config->channels[11].cb(&EXTD1, 11); - if (pr & (1 << 12)) - EXTD1.config->channels[12].cb(&EXTD1, 12); - if (pr & (1 << 13)) - EXTD1.config->channels[13].cb(&EXTD1, 13); - if (pr & (1 << 14)) - EXTD1.config->channels[14].cb(&EXTD1, 14); - if (pr & (1 << 15)) - EXTD1.config->channels[15].cb(&EXTD1, 15); - - OSAL_IRQ_EPILOGUE(); -} - -/** - * @brief EXTI[16] interrupt handler (PVD). - * - * @isr - */ -OSAL_IRQ_HANDLER(Vector44) { - - OSAL_IRQ_PROLOGUE(); - - EXTI->PR = (1 << 16); - EXTD1.config->channels[16].cb(&EXTD1, 16); - - OSAL_IRQ_EPILOGUE(); -} - -/** - * @brief EXTI[17] interrupt handler (RTC_ALARM). - * - * @isr - */ -OSAL_IRQ_HANDLER(VectorE4) { - - OSAL_IRQ_PROLOGUE(); - - EXTI->PR = (1 << 17); - EXTD1.config->channels[17].cb(&EXTD1, 17); - - OSAL_IRQ_EPILOGUE(); -} - -/** - * @brief EXTI[18] interrupt handler (OTG_FS_WKUP). - * - * @isr - */ -OSAL_IRQ_HANDLER(VectorE8) { - - OSAL_IRQ_PROLOGUE(); - - EXTI->PR = (1 << 18); - EXTD1.config->channels[18].cb(&EXTD1, 18); - - OSAL_IRQ_EPILOGUE(); -} - -/** - * @brief EXTI[19] interrupt handler (ETH_WKUP). - * - * @isr - */ -OSAL_IRQ_HANDLER(Vector138) { - - OSAL_IRQ_PROLOGUE(); - - EXTI->PR = (1 << 19); - EXTD1.config->channels[19].cb(&EXTD1, 19); - - OSAL_IRQ_EPILOGUE(); -} - -/** - * @brief EXTI[20] interrupt handler (OTG_HS_WKUP). - * - * @isr - */ -OSAL_IRQ_HANDLER(Vector170) { - - OSAL_IRQ_PROLOGUE(); - - EXTI->PR = (1 << 20); - EXTD1.config->channels[20].cb(&EXTD1, 20); - - OSAL_IRQ_EPILOGUE(); -} - -/** - * @brief EXTI[21] interrupt handler (TAMPER_STAMP). - * - * @isr - */ -OSAL_IRQ_HANDLER(Vector48) { - - OSAL_IRQ_PROLOGUE(); - - EXTI->PR = (1 << 21); - EXTD1.config->channels[21].cb(&EXTD1, 21); - - OSAL_IRQ_EPILOGUE(); -} - -/** - * @brief EXTI[22] interrupt handler (RTC_WKUP). - * - * @isr - */ -OSAL_IRQ_HANDLER(Vector4C) { - - OSAL_IRQ_PROLOGUE(); - - EXTI->PR = (1 << 22); - EXTD1.config->channels[22].cb(&EXTD1, 22); - - OSAL_IRQ_EPILOGUE(); -} - -/*===========================================================================*/ -/* Driver exported functions. */ -/*===========================================================================*/ - -/** - * @brief Enables EXTI IRQ sources. - * - * @notapi - */ -void ext_lld_exti_irq_enable(void) { - - nvicEnableVector(EXTI0_IRQn, STM32_EXT_EXTI0_IRQ_PRIORITY); - nvicEnableVector(EXTI1_IRQn, STM32_EXT_EXTI1_IRQ_PRIORITY); - nvicEnableVector(EXTI2_IRQn, STM32_EXT_EXTI2_IRQ_PRIORITY); - nvicEnableVector(EXTI3_IRQn, STM32_EXT_EXTI3_IRQ_PRIORITY); - nvicEnableVector(EXTI4_IRQn, STM32_EXT_EXTI4_IRQ_PRIORITY); - nvicEnableVector(EXTI9_5_IRQn, STM32_EXT_EXTI5_9_IRQ_PRIORITY); - nvicEnableVector(EXTI15_10_IRQn, STM32_EXT_EXTI10_15_IRQ_PRIORITY); - nvicEnableVector(PVD_IRQn, STM32_EXT_EXTI16_IRQ_PRIORITY); - nvicEnableVector(RTC_Alarm_IRQn, STM32_EXT_EXTI17_IRQ_PRIORITY); - nvicEnableVector(OTG_FS_WKUP_IRQn, STM32_EXT_EXTI18_IRQ_PRIORITY); - nvicEnableVector(ETH_WKUP_IRQn, STM32_EXT_EXTI19_IRQ_PRIORITY); - nvicEnableVector(OTG_HS_WKUP_IRQn, STM32_EXT_EXTI20_IRQ_PRIORITY); - nvicEnableVector(TAMP_STAMP_IRQn, STM32_EXT_EXTI21_IRQ_PRIORITY); - nvicEnableVector(RTC_WKUP_IRQn, STM32_EXT_EXTI22_IRQ_PRIORITY); -} - -/** - * @brief Disables EXTI IRQ sources. - * - * @notapi - */ -void ext_lld_exti_irq_disable(void) { - - nvicDisableVector(EXTI0_IRQn); - nvicDisableVector(EXTI1_IRQn); - nvicDisableVector(EXTI2_IRQn); - nvicDisableVector(EXTI3_IRQn); - nvicDisableVector(EXTI4_IRQn); - nvicDisableVector(EXTI9_5_IRQn); - nvicDisableVector(EXTI15_10_IRQn); - nvicDisableVector(PVD_IRQn); - nvicDisableVector(RTC_Alarm_IRQn); - nvicDisableVector(OTG_FS_WKUP_IRQn); - nvicDisableVector(ETH_WKUP_IRQn); - nvicDisableVector(OTG_HS_WKUP_IRQn); - nvicDisableVector(TAMP_STAMP_IRQn); - nvicDisableVector(RTC_WKUP_IRQn); -} - -#endif /* HAL_USE_EXT */ - -/** @} */ diff --git a/os/hal/platforms/STM32F4xx/ext_lld_isr.h b/os/hal/platforms/STM32F4xx/ext_lld_isr.h deleted file mode 100644 index 33e8e0be1..000000000 --- a/os/hal/platforms/STM32F4xx/ext_lld_isr.h +++ /dev/null @@ -1,170 +0,0 @@ -/* - ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file STM32F4xx/ext_lld_isr.h - * @brief STM32F4xx/STM32F2xx EXT subsystem low level driver ISR header. - * - * @addtogroup EXT - * @{ - */ - -#ifndef _EXT_LLD_ISR_H_ -#define _EXT_LLD_ISR_H_ - -#if HAL_USE_EXT || defined(__DOXYGEN__) - -/*===========================================================================*/ -/* Driver constants. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver pre-compile time settings. */ -/*===========================================================================*/ - -/** - * @name Configuration options - * @{ - */ -/** - * @brief EXTI0 interrupt priority level setting. - */ -#if !defined(STM32_EXT_EXTI0_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_EXT_EXTI0_IRQ_PRIORITY 6 -#endif - -/** - * @brief EXTI1 interrupt priority level setting. - */ -#if !defined(STM32_EXT_EXTI1_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_EXT_EXTI1_IRQ_PRIORITY 6 -#endif - -/** - * @brief EXTI2 interrupt priority level setting. - */ -#if !defined(STM32_EXT_EXTI2_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_EXT_EXTI2_IRQ_PRIORITY 6 -#endif - -/** - * @brief EXTI3 interrupt priority level setting. - */ -#if !defined(STM32_EXT_EXTI3_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_EXT_EXTI3_IRQ_PRIORITY 6 -#endif - -/** - * @brief EXTI4 interrupt priority level setting. - */ -#if !defined(STM32_EXT_EXTI4_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_EXT_EXTI4_IRQ_PRIORITY 6 -#endif - -/** - * @brief EXTI9..5 interrupt priority level setting. - */ -#if !defined(STM32_EXT_EXTI5_9_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_EXT_EXTI5_9_IRQ_PRIORITY 6 -#endif - -/** - * @brief EXTI15..10 interrupt priority level setting. - */ -#if !defined(STM32_EXT_EXTI10_15_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_EXT_EXTI10_15_IRQ_PRIORITY 6 -#endif - -/** - * @brief EXTI16 interrupt priority level setting. - */ -#if !defined(STM32_EXT_EXTI16_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_EXT_EXTI16_IRQ_PRIORITY 6 -#endif - -/** - * @brief EXTI17 interrupt priority level setting. - */ -#if !defined(STM32_EXT_EXTI17_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_EXT_EXTI17_IRQ_PRIORITY 6 -#endif - -/** - * @brief EXTI18 interrupt priority level setting. - */ -#if !defined(STM32_EXT_EXTI18_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_EXT_EXTI18_IRQ_PRIORITY 6 -#endif - -/** - * @brief EXTI19 interrupt priority level setting. - */ -#if !defined(STM32_EXT_EXTI19_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_EXT_EXTI19_IRQ_PRIORITY 6 -#endif - -/** - * @brief EXTI20 interrupt priority level setting. - */ -#if !defined(STM32_EXT_EXTI20_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_EXT_EXTI20_IRQ_PRIORITY 6 -#endif - -/** - * @brief EXTI21 interrupt priority level setting. - */ -#if !defined(STM32_EXT_EXTI21_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_EXT_EXTI21_IRQ_PRIORITY 6 -#endif - -/** - * @brief EXTI22 interrupt priority level setting. - */ -#if !defined(STM32_EXT_EXTI22_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_EXT_EXTI22_IRQ_PRIORITY 6 -#endif -/** @} */ - -/*===========================================================================*/ -/* Derived constants and error checks. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver data structures and types. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver macros. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* External declarations. */ -/*===========================================================================*/ - -#ifdef __cplusplus -extern "C" { -#endif - void ext_lld_exti_irq_enable(void); - void ext_lld_exti_irq_disable(void); -#ifdef __cplusplus -} -#endif - -#endif /* HAL_USE_EXT */ - -#endif /* _EXT_LLD_ISR_H_ */ - -/** @} */ diff --git a/os/hal/platforms/STM32F4xx/hal_lld.c b/os/hal/platforms/STM32F4xx/hal_lld.c deleted file mode 100644 index e414043cc..000000000 --- a/os/hal/platforms/STM32F4xx/hal_lld.c +++ /dev/null @@ -1,225 +0,0 @@ -/* - ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file STM32F4xx/hal_lld.c - * @brief STM32F4xx/STM32F2xx HAL subsystem low level driver source. - * - * @addtogroup HAL - * @{ - */ - -/* TODO: LSEBYP like in F3.*/ - -#include "hal.h" - -/*===========================================================================*/ -/* Driver local definitions. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver exported variables. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver local variables and types. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver local functions. */ -/*===========================================================================*/ - -/** - * @brief Initializes the backup domain. - * @note WARNING! Changing clock source impossible without resetting - * of the whole BKP domain. - */ -static void hal_lld_backup_domain_init(void) { - - /* Backup domain access enabled and left open.*/ - PWR->CR |= PWR_CR_DBP; - - /* Reset BKP domain if different clock source selected.*/ - if ((RCC->BDCR & STM32_RTCSEL_MASK) != STM32_RTCSEL) { - /* Backup domain reset.*/ - RCC->BDCR = RCC_BDCR_BDRST; - RCC->BDCR = 0; - } - -#if STM32_LSE_ENABLED - RCC->BDCR |= RCC_BDCR_LSEON; - while ((RCC->BDCR & RCC_BDCR_LSERDY) == 0) - ; /* Waits until LSE is stable. */ -#endif - -#if HAL_USE_RTC - /* If the backup domain hasn't been initialized yet then proceed with - initialization.*/ - if ((RCC->BDCR & RCC_BDCR_RTCEN) == 0) { - /* Selects clock source.*/ - RCC->BDCR |= STM32_RTCSEL; - - /* RTC clock enabled.*/ - RCC->BDCR |= RCC_BDCR_RTCEN; - } -#endif /* HAL_USE_RTC */ - -#if STM32_BKPRAM_ENABLE - rccEnableBKPSRAM(false); - - PWR->CSR |= PWR_CSR_BRE; - while ((PWR->CSR & PWR_CSR_BRR) == 0) - ; /* Waits until the regulator is stable */ -#else - PWR->CSR &= ~PWR_CSR_BRE; -#endif /* STM32_BKPRAM_ENABLE */ -} - -/*===========================================================================*/ -/* Driver interrupt handlers. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver exported functions. */ -/*===========================================================================*/ - -/** - * @brief Low level HAL driver initialization. - * - * @notapi - */ -void hal_lld_init(void) { - - /* Reset of all peripherals. AHB3 is not reseted because it could have - been initialized in the board initialization file (board.c).*/ - rccResetAHB1(~0); - rccResetAHB2(~0); - rccResetAPB1(~RCC_APB1RSTR_PWRRST); - rccResetAPB2(~0); - - /* PWR clock enabled.*/ - rccEnablePWRInterface(FALSE); - - /* Initializes the backup domain.*/ - hal_lld_backup_domain_init(); - -#if defined(STM32_DMA_REQUIRED) - dmaInit(); -#endif - - /* Programmable voltage detector enable.*/ -#if STM32_PVD_ENABLE - PWR->CR |= PWR_CR_PVDE | (STM32_PLS & STM32_PLS_MASK); -#endif /* STM32_PVD_ENABLE */ -} - -/** - * @brief STM32F2xx clocks and PLL initialization. - * @note All the involved constants come from the file @p board.h. - * @note This function should be invoked just after the system reset. - * - * @special - */ -void stm32_clock_init(void) { - -#if !STM32_NO_INIT - /* PWR clock enable.*/ - RCC->APB1ENR = RCC_APB1ENR_PWREN; - - /* PWR initialization.*/ -#if defined(STM32F4XX) || defined(__DOXYGEN__) - PWR->CR = STM32_VOS; - while ((PWR->CSR & PWR_CSR_VOSRDY) == 0) - ; /* Waits until power regulator is stable. */ -#else - PWR->CR = 0; -#endif - - /* Initial clocks setup and wait for HSI stabilization, the MSI clock is - always enabled because it is the fallback clock when PLL the fails.*/ - RCC->CR |= RCC_CR_HSION; - while ((RCC->CR & RCC_CR_HSIRDY) == 0) - ; /* Waits until HSI is stable. */ - -#if STM32_HSE_ENABLED - /* HSE activation.*/ -#if defined(STM32_HSE_BYPASS) - /* HSE Bypass.*/ - RCC->CR |= RCC_CR_HSEON | RCC_CR_HSEBYP; -#else - /* No HSE Bypass.*/ - RCC->CR |= RCC_CR_HSEON; -#endif - while ((RCC->CR & RCC_CR_HSERDY) == 0) - ; /* Waits until HSE is stable. */ -#endif - -#if STM32_LSI_ENABLED - /* LSI activation.*/ - RCC->CSR |= RCC_CSR_LSION; - while ((RCC->CSR & RCC_CSR_LSIRDY) == 0) - ; /* Waits until LSI is stable. */ -#endif - -#if STM32_ACTIVATE_PLL - /* PLL activation.*/ - RCC->PLLCFGR = STM32_PLLQ | STM32_PLLSRC | STM32_PLLP | STM32_PLLN | - STM32_PLLM; - RCC->CR |= RCC_CR_PLLON; - while (!(RCC->CR & RCC_CR_PLLRDY)) - ; /* Waits until PLL is stable. */ -#endif - -#if STM32_ACTIVATE_PLLI2S - /* PLLI2S activation.*/ - RCC->PLLI2SCFGR = STM32_PLLI2SR | STM32_PLLI2SN; - RCC->CR |= RCC_CR_PLLI2SON; - while (!(RCC->CR & RCC_CR_PLLI2SRDY)) - ; /* Waits until PLLI2S is stable. */ -#endif - - /* Other clock-related settings (dividers, MCO etc).*/ - RCC->CFGR |= STM32_MCO2PRE | STM32_MCO2SEL | STM32_MCO1PRE | STM32_MCO1SEL | - STM32_RTCPRE | STM32_PPRE2 | STM32_PPRE1 | STM32_HPRE; - - /* Flash setup.*/ -#if defined(STM32_USE_REVISION_A_FIX) - /* Some old revisions of F4x MCUs randomly crashes with compiler - optimizations enabled AND flash caches enabled. */ - if ((DBGMCU->IDCODE == 0x20006411) && (SCB->CPUID == 0x410FC241)) - FLASH->ACR = FLASH_ACR_PRFTEN | STM32_FLASHBITS; - else - FLASH->ACR = FLASH_ACR_PRFTEN | FLASH_ACR_ICEN | - FLASH_ACR_DCEN | STM32_FLASHBITS; -#else - FLASH->ACR = FLASH_ACR_PRFTEN | FLASH_ACR_ICEN | - FLASH_ACR_DCEN | STM32_FLASHBITS; -#endif - - /* Switching to the configured clock source if it is different from MSI.*/ -#if (STM32_SW != STM32_SW_HSI) - RCC->CFGR |= STM32_SW; /* Switches on the selected clock source. */ - while ((RCC->CFGR & RCC_CFGR_SWS) != (STM32_SW << 2)) - ; -#endif -#endif /* STM32_NO_INIT */ - - /* SYSCFG clock enabled here because it is a multi-functional unit shared - among multiple drivers.*/ - rccEnableAPB2(RCC_APB2ENR_SYSCFGEN, TRUE); -} - -/** @} */ diff --git a/os/hal/platforms/STM32F4xx/hal_lld.h b/os/hal/platforms/STM32F4xx/hal_lld.h deleted file mode 100644 index ae5378c23..000000000 --- a/os/hal/platforms/STM32F4xx/hal_lld.h +++ /dev/null @@ -1,1232 +0,0 @@ -/* - ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file STM32F4xx/hal_lld.h - * @brief STM32F4xx/STM32F2xx HAL subsystem low level driver header. - * @pre This module requires the following macros to be defined in the - * @p board.h file: - * - STM32_LSECLK. - * - STM32_HSECLK. - * - STM32_HSE_BYPASS (optionally). - * - STM32_VDD (as hundredths of Volt). - * . - * One of the following macros must also be defined: - * - STM32F2XX for High-performance STM32 F-2 devices. - * - STM32F4XX for High-performance STM32 F-4 devices. - * . - * - * @addtogroup HAL - * @{ - */ - -#ifndef _HAL_LLD_H_ -#define _HAL_LLD_H_ - -#include "stm32.h" -#include "stm32_registry.h" - -/*===========================================================================*/ -/* Driver constants. */ -/*===========================================================================*/ - -/** - * @brief Defines the support for realtime counters in the HAL. - */ -#define HAL_IMPLEMENTS_COUNTERS TRUE - -/** - * @name Platform identification - * @{ - */ -#if defined(STM32F4XX) || defined(__DOXYGEN__) -#define PLATFORM_NAME "STM32F4xx High Performance" -#else /* !defined(STM32F4XX) */ -#define PLATFORM_NAME "STM32F2xx High Performance" -#endif /* !defined(STM32F4XX) */ -/** @} */ - -/** - * @name Absolute Maximum Ratings - * @{ - */ -#if defined(STM32F4XX) || defined(__DOXYGEN__) -/** - * @brief Maximum HSE clock frequency. - */ -#define STM32_HSECLK_MAX 26000000 - -/** - * @brief Minimum HSE clock frequency. - */ -#define STM32_HSECLK_MIN 1000000 - -/** - * @brief Maximum LSE clock frequency. - */ -#define STM32_LSECLK_MAX 1000000 - -/** - * @brief Minimum LSE clock frequency. - */ -#define STM32_LSECLK_MIN 32768 - -/** - * @brief Maximum PLLs input clock frequency. - */ -#define STM32_PLLIN_MAX 2000000 - -/** - * @brief Minimum PLLs input clock frequency. - */ -#define STM32_PLLIN_MIN 950000 - -/** - * @brief Maximum PLLs VCO clock frequency. - */ -#define STM32_PLLVCO_MAX 432000000 - -/** - * @brief Maximum PLLs VCO clock frequency. - */ -#define STM32_PLLVCO_MIN 192000000 - -/** - * @brief Maximum PLL output clock frequency. - */ -#define STM32_PLLOUT_MAX 168000000 - -/** - * @brief Minimum PLL output clock frequency. - */ -#define STM32_PLLOUT_MIN 24000000 - -/** - * @brief Maximum APB1 clock frequency. - */ -#define STM32_PCLK1_MAX 42000000 - -/** - * @brief Maximum APB2 clock frequency. - */ -#define STM32_PCLK2_MAX 84000000 - -/** - * @brief Maximum SPI/I2S clock frequency. - */ -#define STM32_SPII2S_MAX 37500000 - -#else /* !defined(STM32F4XX) */ -#define STM32_SYSCLK_MAX 120000000 -#define STM32_HSECLK_MAX 26000000 -#define STM32_HSECLK_MIN 1000000 -#define STM32_LSECLK_MAX 1000000 -#define STM32_LSECLK_MIN 32768 -#define STM32_PLLIN_MAX 2000000 -#define STM32_PLLIN_MIN 950000 -#define STM32_PLLVCO_MAX 432000000 -#define STM32_PLLVCO_MIN 192000000 -#define STM32_PLLOUT_MAX 120000000 -#define STM32_PLLOUT_MIN 24000000 -#define STM32_PCLK1_MAX 30000000 -#define STM32_PCLK2_MAX 60000000 -#define STM32_SPII2S_MAX 37500000 -#endif /* !defined(STM32F4XX) */ -/** @} */ - -/** - * @name Internal clock sources - * @{ - */ -#define STM32_HSICLK 16000000 /**< High speed internal clock. */ -#define STM32_LSICLK 32000 /**< Low speed internal clock. */ -/** @} */ - -/** - * @name PWR_CR register bits definitions - * @{ - */ -#if defined(STM32F4XX) || defined(__DOXYGEN__) -#define STM32_VOS_MASK (1 << 14) /**< Core voltage mask. */ -#define STM32_VOS_LOW (0 << 14) /**< Core voltage set to low. */ -#define STM32_VOS_HIGH (1 << 14) /**< Core voltage set to high. */ -#endif -#define STM32_PLS_MASK (7 << 5) /**< PLS bits mask. */ -#define STM32_PLS_LEV0 (0 << 5) /**< PVD level 0. */ -#define STM32_PLS_LEV1 (1 << 5) /**< PVD level 1. */ -#define STM32_PLS_LEV2 (2 << 5) /**< PVD level 2. */ -#define STM32_PLS_LEV3 (3 << 5) /**< PVD level 3. */ -#define STM32_PLS_LEV4 (4 << 5) /**< PVD level 4. */ -#define STM32_PLS_LEV5 (5 << 5) /**< PVD level 5. */ -#define STM32_PLS_LEV6 (6 << 5) /**< PVD level 6. */ -#define STM32_PLS_LEV7 (7 << 5) /**< PVD level 7. */ -/** @} */ - -/** - * @name RCC_PLLCFGR register bits definitions - * @{ - */ -#define STM32_PLLP_MASK (3 << 16) /**< PLLP mask. */ -#define STM32_PLLP_DIV2 (0 << 16) /**< PLL clock divided by 2. */ -#define STM32_PLLP_DIV4 (1 << 16) /**< PLL clock divided by 4. */ -#define STM32_PLLP_DIV6 (2 << 16) /**< PLL clock divided by 6. */ -#define STM32_PLLP_DIV8 (3 << 16) /**< PLL clock divided by 8. */ - -#define STM32_PLLSRC_HSI (0 << 22) /**< PLL clock source is HSI. */ -#define STM32_PLLSRC_HSE (1 << 22) /**< PLL clock source is HSE. */ -/** @} */ - -/** - * @name RCC_CFGR register bits definitions - * @{ - */ -#define STM32_SW_MASK (3 << 0) /**< SW mask. */ -#define STM32_SW_HSI (0 << 0) /**< SYSCLK source is HSI. */ -#define STM32_SW_HSE (1 << 0) /**< SYSCLK source is HSE. */ -#define STM32_SW_PLL (2 << 0) /**< SYSCLK source is PLL. */ - -#define STM32_HPRE_MASK (15 << 4) /**< HPRE mask. */ -#define STM32_HPRE_DIV1 (0 << 4) /**< SYSCLK divided by 1. */ -#define STM32_HPRE_DIV2 (8 << 4) /**< SYSCLK divided by 2. */ -#define STM32_HPRE_DIV4 (9 << 4) /**< SYSCLK divided by 4. */ -#define STM32_HPRE_DIV8 (10 << 4) /**< SYSCLK divided by 8. */ -#define STM32_HPRE_DIV16 (11 << 4) /**< SYSCLK divided by 16. */ -#define STM32_HPRE_DIV64 (12 << 4) /**< SYSCLK divided by 64. */ -#define STM32_HPRE_DIV128 (13 << 4) /**< SYSCLK divided by 128. */ -#define STM32_HPRE_DIV256 (14 << 4) /**< SYSCLK divided by 256. */ -#define STM32_HPRE_DIV512 (15 << 4) /**< SYSCLK divided by 512. */ - -#define STM32_PPRE1_MASK (7 << 10) /**< PPRE1 mask. */ -#define STM32_PPRE1_DIV1 (0 << 10) /**< HCLK divided by 1. */ -#define STM32_PPRE1_DIV2 (4 << 10) /**< HCLK divided by 2. */ -#define STM32_PPRE1_DIV4 (5 << 10) /**< HCLK divided by 4. */ -#define STM32_PPRE1_DIV8 (6 << 10) /**< HCLK divided by 8. */ -#define STM32_PPRE1_DIV16 (7 << 10) /**< HCLK divided by 16. */ - -#define STM32_PPRE2_MASK (7 << 13) /**< PPRE2 mask. */ -#define STM32_PPRE2_DIV1 (0 << 13) /**< HCLK divided by 1. */ -#define STM32_PPRE2_DIV2 (4 << 13) /**< HCLK divided by 2. */ -#define STM32_PPRE2_DIV4 (5 << 13) /**< HCLK divided by 4. */ -#define STM32_PPRE2_DIV8 (6 << 13) /**< HCLK divided by 8. */ -#define STM32_PPRE2_DIV16 (7 << 13) /**< HCLK divided by 16. */ - -#define STM32_RTCPRE_MASK (31 << 16) /**< RTCPRE mask. */ - -#define STM32_MCO1SEL_MASK (3 << 21) /**< MCO1 mask. */ -#define STM32_MCO1SEL_HSI (0 << 21) /**< HSI clock on MCO1 pin. */ -#define STM32_MCO1SEL_LSE (1 << 21) /**< LSE clock on MCO1 pin. */ -#define STM32_MCO1SEL_HSE (2 << 21) /**< HSE clock on MCO1 pin. */ -#define STM32_MCO1SEL_PLL (3 << 21) /**< PLL clock on MCO1 pin. */ - -#define STM32_I2SSRC_MASK (1 << 23) /**< I2CSRC mask. */ -#define STM32_I2SSRC_PLLI2S (0 << 23) /**< I2SSRC is PLLI2S. */ -#define STM32_I2SSRC_CKIN (1 << 23) /**< I2S_CKIN is PLLI2S. */ - -#define STM32_MCO1PRE_MASK (7 << 24) /**< MCO1PRE mask. */ -#define STM32_MCO1PRE_DIV1 (0 << 24) /**< MCO1 divided by 1. */ -#define STM32_MCO1PRE_DIV2 (4 << 24) /**< MCO1 divided by 2. */ -#define STM32_MCO1PRE_DIV3 (5 << 24) /**< MCO1 divided by 3. */ -#define STM32_MCO1PRE_DIV4 (6 << 24) /**< MCO1 divided by 4. */ -#define STM32_MCO1PRE_DIV5 (7 << 24) /**< MCO1 divided by 5. */ - -#define STM32_MCO2PRE_MASK (7 << 27) /**< MCO2PRE mask. */ -#define STM32_MCO2PRE_DIV1 (0 << 27) /**< MCO2 divided by 1. */ -#define STM32_MCO2PRE_DIV2 (4 << 27) /**< MCO2 divided by 2. */ -#define STM32_MCO2PRE_DIV3 (5 << 27) /**< MCO2 divided by 3. */ -#define STM32_MCO2PRE_DIV4 (6 << 27) /**< MCO2 divided by 4. */ -#define STM32_MCO2PRE_DIV5 (7 << 27) /**< MCO2 divided by 5. */ - -#define STM32_MCO2SEL_MASK (3U << 30) /**< MCO2 mask. */ -#define STM32_MCO2SEL_SYSCLK (0U << 30) /**< SYSCLK clock on MCO2 pin. */ -#define STM32_MCO2SEL_PLLI2S (1U << 30) /**< PLLI2S clock on MCO2 pin. */ -#define STM32_MCO2SEL_HSE (2U << 30) /**< HSE clock on MCO2 pin. */ -#define STM32_MCO2SEL_PLL (3U << 30) /**< PLL clock on MCO2 pin. */ - -#define STM32_RTC_NOCLOCK (0 << 8) /**< No clock. */ -#define STM32_RTC_LSE (1 << 8) /**< LSE used as RTC clock. */ -#define STM32_RTC_LSI (2 << 8) /**< LSI used as RTC clock. */ -#define STM32_RTC_HSE (3 << 8) /**< HSE divided by programmable - prescaler used as RTC clock*/ - -/** - * @name RCC_PLLI2SCFGR register bits definitions - * @{ - */ -#define STM32_PLLI2SN_MASK (511 << 6) /**< PLLI2SN mask. */ -#define STM32_PLLI2SR_MASK (7 << 28) /**< PLLI2SR mask. */ -/** @} */ - -/** - * @name RCC_BDCR register bits definitions - * @{ - */ -#define STM32_RTCSEL_MASK (3 << 8) /**< RTC source mask. */ -#define STM32_RTCSEL_NOCLOCK (0 << 8) /**< No RTC source. */ -#define STM32_RTCSEL_LSE (1 << 8) /**< RTC source is LSE. */ -#define STM32_RTCSEL_LSI (2 << 8) /**< RTC source is LSI. */ -#define STM32_RTCSEL_HSEDIV (3 << 8) /**< RTC source is HSE divided. */ -/** @} */ - -/*===========================================================================*/ -/* Driver pre-compile time settings. */ -/*===========================================================================*/ - -/** - * @name Configuration options - * @{ - */ -/** - * @brief Disables the PWR/RCC initialization in the HAL. - */ -#if !defined(STM32_NO_INIT) || defined(__DOXYGEN__) -#define STM32_NO_INIT FALSE -#endif - -/** - * @brief Enables or disables the programmable voltage detector. - */ -#if !defined(STM32_PVD_ENABLE) || defined(__DOXYGEN__) -#define STM32_PVD_ENABLE FALSE -#endif - -/** - * @brief Sets voltage level for programmable voltage detector. - */ -#if !defined(STM32_PLS) || defined(__DOXYGEN__) -#define STM32_PLS STM32_PLS_LEV0 -#endif - -/** - * @brief Enables or disables the HSI clock source. - */ -#if !defined(STM32_HSI_ENABLED) || defined(__DOXYGEN__) -#define STM32_HSI_ENABLED TRUE -#endif - -/** - * @brief Enables or disables the LSI clock source. - */ -#if !defined(STM32_LSI_ENABLED) || defined(__DOXYGEN__) -#define STM32_LSI_ENABLED FALSE -#endif - -/** - * @brief Enables or disables the HSE clock source. - */ -#if !defined(STM32_HSE_ENABLED) || defined(__DOXYGEN__) -#define STM32_HSE_ENABLED TRUE -#endif - -/** - * @brief Enables or disables the LSE clock source. - */ -#if !defined(STM32_LSE_ENABLED) || defined(__DOXYGEN__) -#define STM32_LSE_ENABLED FALSE -#endif - -/** - * @brief USB/SDIO clock setting. - */ -#if !defined(STM32_CLOCK48_REQUIRED) || defined(__DOXYGEN__) -#define STM32_CLOCK48_REQUIRED TRUE -#endif - -/** - * @brief Main clock source selection. - * @note If the selected clock source is not the PLL then the PLL is not - * initialized and started. - * @note The default value is calculated for a 168MHz system clock from - * an external 8MHz HSE clock. - */ -#if !defined(STM32_SW) || defined(__DOXYGEN__) -#define STM32_SW STM32_SW_PLL -#endif - -#if defined(STM32F4XX) || defined(__DOXYGEN__) -/** - * @brief Core voltage selection. - * @note This setting affects all the performance and clock related - * settings, the maximum performance is only obtainable selecting - * the maximum voltage. - */ -#if !defined(STM32_VOS) || defined(__DOXYGEN__) -#define STM32_VOS STM32_VOS_HIGH -#endif - -/** - * @brief Clock source for the PLLs. - * @note This setting has only effect if the PLL is selected as the - * system clock source. - * @note The default value is calculated for a 168MHz system clock from - * an external 8MHz HSE clock. - */ -#if !defined(STM32_PLLSRC) || defined(__DOXYGEN__) -#define STM32_PLLSRC STM32_PLLSRC_HSE -#endif - -/** - * @brief PLLM divider value. - * @note The allowed values are 2..63. - * @note The default value is calculated for a 168MHz system clock from - * an external 8MHz HSE clock. - */ -#if !defined(STM32_PLLM_VALUE) || defined(__DOXYGEN__) -#define STM32_PLLM_VALUE 8 -#endif - -/** - * @brief PLLN multiplier value. - * @note The allowed values are 192..432. - * @note The default value is calculated for a 168MHz system clock from - * an external 8MHz HSE clock. - */ -#if !defined(STM32_PLLN_VALUE) || defined(__DOXYGEN__) -#define STM32_PLLN_VALUE 336 -#endif - -/** - * @brief PLLP divider value. - * @note The allowed values are 2, 4, 6, 8. - * @note The default value is calculated for a 168MHz system clock from - * an external 8MHz HSE clock. - */ -#if !defined(STM32_PLLP_VALUE) || defined(__DOXYGEN__) -#define STM32_PLLP_VALUE 2 -#endif - -/** - * @brief PLLQ multiplier value. - * @note The allowed values are 2..15. - * @note The default value is calculated for a 168MHz system clock from - * an external 8MHz HSE clock. - */ -#if !defined(STM32_PLLQ_VALUE) || defined(__DOXYGEN__) -#define STM32_PLLQ_VALUE 7 -#endif - -#else /* !defined(STM32F4XX) */ -/** - * @brief Clock source for the PLLs. - * @note This setting has only effect if the PLL is selected as the - * system clock source. - * @note The default value is calculated for a 120MHz system clock from - * an external 8MHz HSE clock. - */ -#if !defined(STM32_PLLSRC) || defined(__DOXYGEN__) -#define STM32_PLLSRC STM32_PLLSRC_HSE -#endif - -/** - * @brief PLLM divider value. - * @note The allowed values are 2..63. - * @note The default value is calculated for a 120MHz system clock from - * an external 8MHz HSE clock. - */ -#if !defined(STM32_PLLM_VALUE) || defined(__DOXYGEN__) -#define STM32_PLLM_VALUE 8 -#endif - -/** - * @brief PLLN multiplier value. - * @note The allowed values are 192..432. - * @note The default value is calculated for a 120MHz system clock from - * an external 8MHz HSE clock. - */ -#if !defined(STM32_PLLN_VALUE) || defined(__DOXYGEN__) -#define STM32_PLLN_VALUE 240 -#endif - -/** - * @brief PLLP divider value. - * @note The allowed values are 2, 4, 6, 8. - * @note The default value is calculated for a 120MHz system clock from - * an external 8MHz HSE clock. - */ -#if !defined(STM32_PLLP_VALUE) || defined(__DOXYGEN__) -#define STM32_PLLP_VALUE 2 -#endif - -/** - * @brief PLLQ multiplier value. - * @note The allowed values are 2..15. - * @note The default value is calculated for a 120MHz system clock from - * an external 8MHz HSE clock. - */ -#if !defined(STM32_PLLQ_VALUE) || defined(__DOXYGEN__) -#define STM32_PLLQ_VALUE 5 -#endif -#endif /* !defined(STM32F4XX) */ - -/** - * @brief AHB prescaler value. - */ -#if !defined(STM32_HPRE) || defined(__DOXYGEN__) -#define STM32_HPRE STM32_HPRE_DIV1 -#endif - -/** - * @brief APB1 prescaler value. - */ -#if !defined(STM32_PPRE1) || defined(__DOXYGEN__) -#define STM32_PPRE1 STM32_PPRE1_DIV4 -#endif - -/** - * @brief APB2 prescaler value. - */ -#if !defined(STM32_PPRE2) || defined(__DOXYGEN__) -#define STM32_PPRE2 STM32_PPRE2_DIV2 -#endif - -/** - * @brief RTC clock source. - */ -#if !defined(STM32_RTCSEL) || defined(__DOXYGEN__) -#define STM32_RTCSEL STM32_RTCSEL_LSE -#endif - -/** - * @brief RTC HSE prescaler value. - */ -#if !defined(STM32_RTCPRE_VALUE) || defined(__DOXYGEN__) -#define STM32_RTCPRE_VALUE 8 -#endif - -/** - * @brief MC01 clock source value. - * @note The default value outputs HSI clock on MC01 pin. - */ -#if !defined(STM32_MCO1SEL) || defined(__DOXYGEN__) -#define STM32_MCO1SEL STM32_MCO1SEL_HSI -#endif - -/** - * @brief MC01 prescaler value. - * @note The default value outputs HSI clock on MC01 pin. - */ -#if !defined(STM32_MCO1PRE) || defined(__DOXYGEN__) -#define STM32_MCO1PRE STM32_MCO1PRE_DIV1 -#endif - -/** - * @brief MC02 clock source value. - * @note The default value outputs SYSCLK / 5 on MC02 pin. - */ -#if !defined(STM32_MCO2SEL) || defined(__DOXYGEN__) -#define STM32_MCO2SEL STM32_MCO2SEL_SYSCLK -#endif - -/** - * @brief MC02 prescaler value. - * @note The default value outputs SYSCLK / 5 on MC02 pin. - */ -#if !defined(STM32_MCO2PRE) || defined(__DOXYGEN__) -#define STM32_MCO2PRE STM32_MCO2PRE_DIV5 -#endif - -/** - * @brief I2S clock source. - */ -#if !defined(STM32_I2SSRC) || defined(__DOXYGEN__) -#define STM32_I2SSRC STM32_I2SSRC_CKIN -#endif - -/** - * @brief PLLI2SN multiplier value. - * @note The allowed values are 192..432. - */ -#if !defined(STM32_PLLI2SN_VALUE) || defined(__DOXYGEN__) -#define STM32_PLLI2SN_VALUE 192 -#endif - -/** - * @brief PLLI2SR multiplier value. - * @note The allowed values are 2..7. - */ -#if !defined(STM32_PLLI2SR_VALUE) || defined(__DOXYGEN__) -#define STM32_PLLI2SR_VALUE 5 -#endif -/** @} */ - -/*===========================================================================*/ -/* Derived constants and error checks. */ -/*===========================================================================*/ - -#if defined(STM32F4XX) || defined(__DOXYGEN__) -/* - * Configuration-related checks. - */ -#if !defined(STM32F4xx_MCUCONF) -#error "Using a wrong mcuconf.h file, STM32F4xx_MCUCONF not defined" -#endif - -/** - * @brief Maximum SYSCLK. - * @note It is a function of the core voltage setting. - */ -#if (STM32_VOS == STM32_VOS_HIGH) || defined(__DOXYGEN__) -#define STM32_SYSCLK_MAX 168000000 -#else -#define STM32_SYSCLK_MAX 144000000 -#endif - -#else /* !defined(STM32F4XX) */ -/* - * Configuration-related checks. - */ -#if !defined(STM32F2xx_MCUCONF) -#error "Using a wrong mcuconf.h file, STM32F2xx_MCUCONF not defined" -#endif -#endif /* !defined(STM32F4XX) */ - -/** - * @brief Maximum frequency thresholds and wait states for flash access. - * @note The values are valid for 2.7V to 3.6V supply range. - */ -#if defined(STM32F4XX) || defined(__DOXYGEN__) -#if ((STM32_VDD >= 270) && (STM32_VDD <= 360)) || defined(__DOXYGEN__) -#define STM32_0WS_THRESHOLD 30000000 -#define STM32_1WS_THRESHOLD 60000000 -#define STM32_2WS_THRESHOLD 90000000 -#define STM32_3WS_THRESHOLD 120000000 -#define STM32_4WS_THRESHOLD 150000000 -#define STM32_5WS_THRESHOLD 168000000 -#define STM32_6WS_THRESHOLD 0 -#define STM32_7WS_THRESHOLD 0 -#elif (STM32_VDD >= 240) && (STM32_VDD < 270) -#define STM32_0WS_THRESHOLD 24000000 -#define STM32_1WS_THRESHOLD 48000000 -#define STM32_2WS_THRESHOLD 72000000 -#define STM32_3WS_THRESHOLD 96000000 -#define STM32_4WS_THRESHOLD 120000000 -#define STM32_5WS_THRESHOLD 144000000 -#define STM32_6WS_THRESHOLD 168000000 -#define STM32_7WS_THRESHOLD 0 -#elif (STM32_VDD >= 210) && (STM32_VDD < 240) -#define STM32_0WS_THRESHOLD 18000000 -#define STM32_1WS_THRESHOLD 36000000 -#define STM32_2WS_THRESHOLD 54000000 -#define STM32_3WS_THRESHOLD 72000000 -#define STM32_4WS_THRESHOLD 90000000 -#define STM32_5WS_THRESHOLD 108000000 -#define STM32_6WS_THRESHOLD 120000000 -#define STM32_7WS_THRESHOLD 138000000 -#elif (STM32_VDD >= 180) && (STM32_VDD < 210) -#define STM32_0WS_THRESHOLD 16000000 -#define STM32_1WS_THRESHOLD 32000000 -#define STM32_2WS_THRESHOLD 48000000 -#define STM32_3WS_THRESHOLD 64000000 -#define STM32_4WS_THRESHOLD 80000000 -#define STM32_5WS_THRESHOLD 96000000 -#define STM32_6WS_THRESHOLD 112000000 -#define STM32_7WS_THRESHOLD 128000000 -#else -#error "invalid VDD voltage specified" -#endif - -#else /* !defined(STM32F4XX) */ -#if ((STM32_VDD >= 270) && (STM32_VDD <= 360)) || defined(__DOXYGEN__) -#define STM32_0WS_THRESHOLD 30000000 -#define STM32_1WS_THRESHOLD 60000000 -#define STM32_2WS_THRESHOLD 90000000 -#define STM32_3WS_THRESHOLD 120000000 -#define STM32_4WS_THRESHOLD 0 -#define STM32_5WS_THRESHOLD 0 -#define STM32_6WS_THRESHOLD 0 -#define STM32_7WS_THRESHOLD 0 -#elif (STM32_VDD >= 240) && (STM32_VDD < 270) -#define STM32_0WS_THRESHOLD 24000000 -#define STM32_1WS_THRESHOLD 48000000 -#define STM32_2WS_THRESHOLD 72000000 -#define STM32_3WS_THRESHOLD 96000000 -#define STM32_4WS_THRESHOLD 120000000 -#define STM32_5WS_THRESHOLD 0 -#define STM32_6WS_THRESHOLD 0 -#define STM32_7WS_THRESHOLD 0 -#elif (STM32_VDD >= 210) && (STM32_VDD < 240) -#define STM32_0WS_THRESHOLD 18000000 -#define STM32_1WS_THRESHOLD 36000000 -#define STM32_2WS_THRESHOLD 54000000 -#define STM32_3WS_THRESHOLD 72000000 -#define STM32_4WS_THRESHOLD 90000000 -#define STM32_5WS_THRESHOLD 108000000 -#define STM32_6WS_THRESHOLD 120000000 -#define STM32_7WS_THRESHOLD 0 -#elif (STM32_VDD >= 180) && (STM32_VDD < 210) -#define STM32_0WS_THRESHOLD 16000000 -#define STM32_1WS_THRESHOLD 32000000 -#define STM32_2WS_THRESHOLD 48000000 -#define STM32_3WS_THRESHOLD 64000000 -#define STM32_4WS_THRESHOLD 80000000 -#define STM32_5WS_THRESHOLD 96000000 -#define STM32_6WS_THRESHOLD 112000000 -#define STM32_7WS_THRESHOLD 120000000 -#else -#error "invalid VDD voltage specified" -#endif -#endif /* !defined(STM32F4XX) */ - -/* - * HSI related checks. - */ -#if STM32_HSI_ENABLED -#else /* !STM32_HSI_ENABLED */ - -#if STM32_SW == STM32_SW_HSI -#error "HSI not enabled, required by STM32_SW" -#endif - -#if (STM32_SW == STM32_SW_PLL) && (STM32_PLLSRC == STM32_PLLSRC_HSI) -#error "HSI not enabled, required by STM32_SW and STM32_PLLSRC" -#endif - -#if (STM32_MCO1SEL == STM32_MCO1SEL_HSI) || \ - ((STM32_MCO1SEL == STM32_MCO1SEL_PLL) && \ - (STM32_PLLSRC == STM32_PLLSRC_HSI)) -#error "HSI not enabled, required by STM32_MCO1SEL" -#endif - -#if (STM32_MCO2SEL == STM32_MCO2SEL_HSI) || \ - ((STM32_MCO2SEL == STM32_MCO2SEL_PLL) && \ - (STM32_PLLSRC == STM32_PLLSRC_HSI)) -#error "HSI not enabled, required by STM32_MCO2SEL" -#endif - -#if (STM32_I2SSRC == STM32_I2SSRC_PLLI2S) && \ - (STM32_PLLSRC == STM32_PLLSRC_HSI) -#error "HSI not enabled, required by STM32_I2SSRC" -#endif - -#endif /* !STM32_HSI_ENABLED */ - -/* - * HSE related checks. - */ -#if STM32_HSE_ENABLED - -#if STM32_HSECLK == 0 -#error "HSE frequency not defined" -#elif (STM32_HSECLK < STM32_HSECLK_MIN) || (STM32_HSECLK > STM32_HSECLK_MAX) -#error "STM32_HSECLK outside acceptable range (STM32_HSECLK_MIN...STM32_HSECLK_MAX)" -#endif - -#else /* !STM32_HSE_ENABLED */ - -#if STM32_SW == STM32_SW_HSE -#error "HSE not enabled, required by STM32_SW" -#endif - -#if (STM32_SW == STM32_SW_PLL) && (STM32_PLLSRC == STM32_PLLSRC_HSE) -#error "HSE not enabled, required by STM32_SW and STM32_PLLSRC" -#endif - -#if (STM32_MCO1SEL == STM32_MCO1SEL_HSE) || \ - ((STM32_MCO1SEL == STM32_MCO1SEL_PLL) && \ - (STM32_PLLSRC == STM32_PLLSRC_HSE)) -#error "HSE not enabled, required by STM32_MCO1SEL" -#endif - -#if (STM32_MCO2SEL == STM32_MCO2SEL_HSE) || \ - ((STM32_MCO2SEL == STM32_MCO2SEL_PLL) && \ - (STM32_PLLSRC == STM32_PLLSRC_HSE)) -#error "HSE not enabled, required by STM32_MCO2SEL" -#endif - -#if (STM32_I2SSRC == STM32_I2SSRC_PLLI2S) && \ - (STM32_PLLSRC == STM32_PLLSRC_HSE) -#error "HSE not enabled, required by STM32_I2SSRC" -#endif - -#if STM32_RTCSEL == STM32_RTCSEL_HSEDIV -#error "HSE not enabled, required by STM32_RTCSEL" -#endif - -#endif /* !STM32_HSE_ENABLED */ - -/* - * LSI related checks. - */ -#if STM32_LSI_ENABLED -#else /* !STM32_LSI_ENABLED */ - -#if STM32_RTCSEL == STM32_RTCSEL_LSI -#error "LSI not enabled, required by STM32_RTCSEL" -#endif - -#endif /* !STM32_LSI_ENABLED */ - -/* - * LSE related checks. - */ -#if STM32_LSE_ENABLED - -#if (STM32_LSECLK == 0) -#error "LSE frequency not defined" -#endif - -#if (STM32_LSECLK < STM32_LSECLK_MIN) || (STM32_LSECLK > STM32_LSECLK_MAX) -#error "STM32_LSECLK outside acceptable range (STM32_LSECLK_MIN...STM32_LSECLK_MAX)" -#endif - -#else /* !STM32_LSE_ENABLED */ - -#if STM32_RTCSEL == STM32_RTCSEL_LSE -#error "LSE not enabled, required by STM32_RTCSEL" -#endif - -#endif /* !STM32_LSE_ENABLED */ - -/** - * @brief STM32_PLLM field. - */ -#if ((STM32_PLLM_VALUE >= 2) && (STM32_PLLM_VALUE <= 63)) || \ - defined(__DOXYGEN__) -#define STM32_PLLM (STM32_PLLM_VALUE << 0) -#else -#error "invalid STM32_PLLM_VALUE value specified" -#endif - -/** - * @brief PLLs input clock frequency. - */ -#if (STM32_PLLSRC == STM32_PLLSRC_HSE) || defined(__DOXYGEN__) -#define STM32_PLLCLKIN (STM32_HSECLK / STM32_PLLM_VALUE) -#elif STM32_PLLSRC == STM32_PLLSRC_HSI -#define STM32_PLLCLKIN (STM32_HSICLK / STM32_PLLM_VALUE) -#else -#error "invalid STM32_PLLSRC value specified" -#endif - -/* - * PLLs input frequency range check. - */ -#if (STM32_PLLCLKIN < STM32_PLLIN_MIN) || (STM32_PLLCLKIN > STM32_PLLIN_MAX) -#error "STM32_PLLCLKIN outside acceptable range (STM32_PLLIN_MIN...STM32_PLLIN_MAX)" -#endif - -/* - * PLL enable check. - */ -#if STM32_CLOCK48_REQUIRED || \ - (STM32_SW == STM32_SW_PLL) || \ - (STM32_MCO1SEL == STM32_MCO1SEL_PLL) || \ - (STM32_MCO2SEL == STM32_MCO2SEL_PLL) || \ - defined(__DOXYGEN__) -/** - * @brief PLL activation flag. - */ -#define STM32_ACTIVATE_PLL TRUE -#else -#define STM32_ACTIVATE_PLL FALSE -#endif - -/** - * @brief STM32_PLLN field. - */ -#if ((STM32_PLLN_VALUE >= 64) && (STM32_PLLN_VALUE <= 432)) || \ - defined(__DOXYGEN__) -#define STM32_PLLN (STM32_PLLN_VALUE << 6) -#else -#error "invalid STM32_PLLN_VALUE value specified" -#endif - -/** - * @brief STM32_PLLP field. - */ -#if (STM32_PLLP_VALUE == 2) || defined(__DOXYGEN__) -#define STM32_PLLP (0 << 16) -#elif STM32_PLLP_VALUE == 4 -#define STM32_PLLP (1 << 16) -#elif STM32_PLLP_VALUE == 6 -#define STM32_PLLP (2 << 16) -#elif STM32_PLLP_VALUE == 8 -#define STM32_PLLP (3 << 16) -#else -#error "invalid STM32_PLLP_VALUE value specified" -#endif - -/** - * @brief STM32_PLLQ field. - */ -#if ((STM32_PLLQ_VALUE >= 2) && (STM32_PLLQ_VALUE <= 15)) || \ - defined(__DOXYGEN__) -#define STM32_PLLQ (STM32_PLLQ_VALUE << 24) -#else -#error "invalid STM32_PLLQ_VALUE value specified" -#endif - -/** - * @brief PLL VCO frequency. - */ -#define STM32_PLLVCO (STM32_PLLCLKIN * STM32_PLLN_VALUE) - -/* - * PLL VCO frequency range check. - */ -#if (STM32_PLLVCO < STM32_PLLVCO_MIN) || (STM32_PLLVCO > STM32_PLLVCO_MAX) -#error "STM32_PLLVCO outside acceptable range (STM32_PLLVCO_MIN...STM32_PLLVCO_MAX)" -#endif - -/** - * @brief PLL output clock frequency. - */ -#define STM32_PLLCLKOUT (STM32_PLLVCO / STM32_PLLP_VALUE) - -/* - * PLL output frequency range check. - */ -#if (STM32_PLLCLKOUT < STM32_PLLOUT_MIN) || (STM32_PLLCLKOUT > STM32_PLLOUT_MAX) -#error "STM32_PLLCLKOUT outside acceptable range (STM32_PLLOUT_MIN...STM32_PLLOUT_MAX)" -#endif - -/** - * @brief System clock source. - */ -#if STM32_NO_INIT || defined(__DOXYGEN__) -#define STM32_SYSCLK STM32_HSICLK -#elif (STM32_SW == STM32_SW_HSI) -#define STM32_SYSCLK STM32_HSICLK -#elif (STM32_SW == STM32_SW_HSE) -#define STM32_SYSCLK STM32_HSECLK -#elif (STM32_SW == STM32_SW_PLL) -#define STM32_SYSCLK STM32_PLLCLKOUT -#else -#error "invalid STM32_SW value specified" -#endif - -/* Check on the system clock.*/ -#if STM32_SYSCLK > STM32_SYSCLK_MAX -#error "STM32_SYSCLK above maximum rated frequency (STM32_SYSCLK_MAX)" -#endif - -/** - * @brief AHB frequency. - */ -#if (STM32_HPRE == STM32_HPRE_DIV1) || defined(__DOXYGEN__) -#define STM32_HCLK (STM32_SYSCLK / 1) -#elif STM32_HPRE == STM32_HPRE_DIV2 -#define STM32_HCLK (STM32_SYSCLK / 2) -#elif STM32_HPRE == STM32_HPRE_DIV4 -#define STM32_HCLK (STM32_SYSCLK / 4) -#elif STM32_HPRE == STM32_HPRE_DIV8 -#define STM32_HCLK (STM32_SYSCLK / 8) -#elif STM32_HPRE == STM32_HPRE_DIV16 -#define STM32_HCLK (STM32_SYSCLK / 16) -#elif STM32_HPRE == STM32_HPRE_DIV64 -#define STM32_HCLK (STM32_SYSCLK / 64) -#elif STM32_HPRE == STM32_HPRE_DIV128 -#define STM32_HCLK (STM32_SYSCLK / 128) -#elif STM32_HPRE == STM32_HPRE_DIV256 -#define STM32_HCLK (STM32_SYSCLK / 256) -#elif STM32_HPRE == STM32_HPRE_DIV512 -#define STM32_HCLK (STM32_SYSCLK / 512) -#else -#error "invalid STM32_HPRE value specified" -#endif - -/* - * AHB frequency check. - */ -#if STM32_HCLK > STM32_SYSCLK_MAX -#error "STM32_HCLK exceeding maximum frequency (STM32_SYSCLK_MAX)" -#endif - -/** - * @brief APB1 frequency. - */ -#if (STM32_PPRE1 == STM32_PPRE1_DIV1) || defined(__DOXYGEN__) -#define STM32_PCLK1 (STM32_HCLK / 1) -#elif STM32_PPRE1 == STM32_PPRE1_DIV2 -#define STM32_PCLK1 (STM32_HCLK / 2) -#elif STM32_PPRE1 == STM32_PPRE1_DIV4 -#define STM32_PCLK1 (STM32_HCLK / 4) -#elif STM32_PPRE1 == STM32_PPRE1_DIV8 -#define STM32_PCLK1 (STM32_HCLK / 8) -#elif STM32_PPRE1 == STM32_PPRE1_DIV16 -#define STM32_PCLK1 (STM32_HCLK / 16) -#else -#error "invalid STM32_PPRE1 value specified" -#endif - -/* - * APB1 frequency check. - */ -#if STM32_PCLK1 > STM32_PCLK1_MAX -#error "STM32_PCLK1 exceeding maximum frequency (STM32_PCLK1_MAX)" -#endif - -/** - * @brief APB2 frequency. - */ -#if (STM32_PPRE2 == STM32_PPRE2_DIV1) || defined(__DOXYGEN__) -#define STM32_PCLK2 (STM32_HCLK / 1) -#elif STM32_PPRE2 == STM32_PPRE2_DIV2 -#define STM32_PCLK2 (STM32_HCLK / 2) -#elif STM32_PPRE2 == STM32_PPRE2_DIV4 -#define STM32_PCLK2 (STM32_HCLK / 4) -#elif STM32_PPRE2 == STM32_PPRE2_DIV8 -#define STM32_PCLK2 (STM32_HCLK / 8) -#elif STM32_PPRE2 == STM32_PPRE2_DIV16 -#define STM32_PCLK2 (STM32_HCLK / 16) -#else -#error "invalid STM32_PPRE2 value specified" -#endif - -/* - * APB2 frequency check. - */ -#if STM32_PCLK2 > STM32_PCLK2_MAX -#error "STM32_PCLK2 exceeding maximum frequency (STM32_PCLK2_MAX)" -#endif - -/* - * PLLI2S enable check. - */ -#if (STM32_I2SSRC == STM32_I2SSRC_PLLI2S) || defined(__DOXYGEN__) -/** - * @brief PLL activation flag. - */ -#define STM32_ACTIVATE_PLLI2S TRUE -#else -#define STM32_ACTIVATE_PLLI2S FALSE -#endif - -/** - * @brief STM32_PLLI2SN field. - */ -#if ((STM32_PLLI2SN_VALUE >= 192) && (STM32_PLLI2SN_VALUE <= 432)) || \ - defined(__DOXYGEN__) -#define STM32_PLLI2SN (STM32_PLLI2SN_VALUE << 6) -#else -#error "invalid STM32_PLLI2SN_VALUE value specified" -#endif - -/** - * @brief STM32_PLLI2SR field. - */ -#if ((STM32_PLLI2SR_VALUE >= 2) && (STM32_PLLI2SR_VALUE <= 7)) || \ - defined(__DOXYGEN__) -#define STM32_PLLI2SR (STM32_PLLI2SR_VALUE << 28) -#else -#error "invalid STM32_PLLI2SR_VALUE value specified" -#endif - -/** - * @brief PLL VCO frequency. - */ -#define STM32_PLLI2SVCO (STM32_PLLCLKIN * STM32_PLLI2SN_VALUE) - -/* - * PLLI2S VCO frequency range check. - */ -#if (STM32_PLLI2SVCO < STM32_PLLVCO_MIN) || \ - (STM32_PLLI2SVCO > STM32_PLLVCO_MAX) -#error "STM32_PLLI2SVCO outside acceptable range (STM32_PLLVCO_MIN...STM32_PLLVCO_MAX)" -#endif - -/** - * @brief PLLI2S output clock frequency. - */ -#define STM32_PLLI2SCLKOUT (STM32_PLLI2SVCO / STM32_PLLI2SR_VALUE) - -/** - * @brief MCO1 divider clock. - */ -#if (STM32_MCO1SEL == STM32_MCO1SEL_HSI) || defined(__DOXYGEN__) -#define STM32_MCO1DIVCLK STM32_HSICLK -#elif STM32_MCO1SEL == STM32_MCO1SEL_LSE -#define STM32_MCO1DIVCLK STM32_LSECLK -#elif STM32_MCO1SEL == STM32_MCO1SEL_HSE -#define STM32_MCO1DIVCLK STM32_HSECLK -#elif STM32_MCO1SEL == STM32_MCO1SEL_PLL -#define STM32_MCO1DIVCLK STM32_PLLCLKOUT -#else -#error "invalid STM32_MCO1SEL value specified" -#endif - -/** - * @brief MCO1 output pin clock. - */ -#if (STM32_MCO1PRE == STM32_MCO1PRE_DIV1) || defined(__DOXYGEN__) -#define STM32_MCO1CLK STM32_MCO1DIVCLK -#elif STM32_MCO1PRE == STM32_MCO1PRE_DIV2 -#define STM32_MCO1CLK (STM32_MCO1DIVCLK / 2) -#elif STM32_MCO1PRE == STM32_MCO1PRE_DIV3 -#define STM32_MCO1CLK (STM32_MCO1DIVCLK / 3) -#elif STM32_MCO1PRE == STM32_MCO1PRE_DIV4 -#define STM32_MCO1CLK (STM32_MCO1DIVCLK / 4) -#elif STM32_MCO1PRE == STM32_MCO1PRE_DIV5 -#define STM32_MCO1CLK (STM32_MCO1DIVCLK / 5) -#else -#error "invalid STM32_MCO1PRE value specified" -#endif - -/** - * @brief MCO2 divider clock. - */ -#if (STM32_MCO2SEL == STM32_MCO2SEL_HSE) || defined(__DOXYGEN__) -#define STM32_MCO2DIVCLK STM32_HSECLK -#elif STM32_MCO2SEL == STM32_MCO2SEL_PLL -#define STM32_MCO2DIVCLK STM32_PLLCLKOUT -#elif STM32_MCO2SEL == STM32_MCO2SEL_SYSCLK -#define STM32_MCO2DIVCLK STM32_SYSCLK -#elif STM32_MCO2SEL == STM32_MCO2SEL_PLLI2S -#define STM32_MCO2DIVCLK STM32_PLLI2S -#else -#error "invalid STM32_MCO2SEL value specified" -#endif - -/** - * @brief MCO2 output pin clock. - */ -#if (STM32_MCO2PRE == STM32_MCO2PRE_DIV1) || defined(__DOXYGEN__) -#define STM32_MCO2CLK STM32_MCO2DIVCLK -#elif STM32_MCO2PRE == STM32_MCO2PRE_DIV2 -#define STM32_MCO2CLK (STM32_MCO2DIVCLK / 2) -#elif STM32_MCO2PRE == STM32_MCO2PRE_DIV3 -#define STM32_MCO2CLK (STM32_MCO2DIVCLK / 3) -#elif STM32_MCO2PRE == STM32_MCO2PRE_DIV4 -#define STM32_MCO2CLK (STM32_MCO2DIVCLK / 4) -#elif STM32_MCO2PRE == STM32_MCO2PRE_DIV5 -#define STM32_MCO2CLK (STM32_MCO2DIVCLK / 5) -#else -#error "invalid STM32_MCO2PRE value specified" -#endif - -/** - * @brief RTC HSE divider setting. - */ -#if ((STM32_RTCPRE_VALUE >= 2) && (STM32_RTCPRE_VALUE <= 31)) || \ - defined(__DOXYGEN__) -#define STM32_RTCPRE (STM32_RTCPRE_VALUE << 16) -#else -#error "invalid STM32_RTCPRE value specified" -#endif - -/** - * @brief HSE divider toward RTC clock. - */ -#if ((STM32_RTCPRE_VALUE >= 2) && (STM32_RTCPRE_VALUE <= 31)) || \ - defined(__DOXYGEN__) -#define STM32_HSEDIVCLK (STM32_HSECLK / STM32_RTCPRE_VALUE) -#else -#error "invalid STM32_RTCPRE value specified" -#endif - -/** - * @brief RTC clock. - */ -#if (STM32_RTCSEL == STM32_RTCSEL_NOCLOCK) || defined(__DOXYGEN__) -#define STM32_RTCCLK 0 -#elif STM32_RTCSEL == STM32_RTCSEL_LSE -#define STM32_RTCCLK STM32_LSECLK -#elif STM32_RTCSEL == STM32_RTCSEL_LSI -#define STM32_RTCCLK STM32_LSICLK -#elif STM32_RTCSEL == STM32_RTCSEL_HSEDIV -#define STM32_RTCCLK STM32_HSEDIVCLK -#else -#error "invalid STM32_RTCSEL value specified" -#endif - -/** - * @brief 48MHz frequency. - */ -#if STM32_CLOCK48_REQUIRED || defined(__DOXYGEN__) -#define STM32_PLL48CLK (STM32_PLLVCO / STM32_PLLQ_VALUE) -#else -#define STM32_PLL48CLK 0 -#endif - -/** - * @brief Timers 2, 3, 4, 5, 6, 7, 9, 10, 11, 12, 13, 14 clock. - */ -#if (STM32_PPRE1 == STM32_PPRE1_DIV1) || defined(__DOXYGEN__) -#define STM32_TIMCLK1 (STM32_PCLK1 * 1) -#else -#define STM32_TIMCLK1 (STM32_PCLK1 * 2) -#endif - -/** - * @brief Timers 1, 8 clock. - */ -#if (STM32_PPRE2 == STM32_PPRE2_DIV1) || defined(__DOXYGEN__) -#define STM32_TIMCLK2 (STM32_PCLK2 * 1) -#else -#define STM32_TIMCLK2 (STM32_PCLK2 * 2) -#endif - -/** - * @brief Flash settings. - */ -#if (STM32_HCLK <= STM32_0WS_THRESHOLD) || defined(__DOXYGEN__) -#define STM32_FLASHBITS 0x00000000 -#elif STM32_HCLK <= STM32_1WS_THRESHOLD -#define STM32_FLASHBITS 0x00000001 -#elif STM32_HCLK <= STM32_2WS_THRESHOLD -#define STM32_FLASHBITS 0x00000002 -#elif STM32_HCLK <= STM32_3WS_THRESHOLD -#define STM32_FLASHBITS 0x00000003 -#elif STM32_HCLK <= STM32_4WS_THRESHOLD -#define STM32_FLASHBITS 0x00000004 -#elif STM32_HCLK <= STM32_5WS_THRESHOLD -#define STM32_FLASHBITS 0x00000005 -#elif STM32_HCLK <= STM32_6WS_THRESHOLD -#define STM32_FLASHBITS 0x00000006 -#else -#define STM32_FLASHBITS 0x00000007 -#endif - -/* There are differences in vector names in the various sub-families, - normalizing.*/ -#if 0 -#define TIM1_BRK_IRQn TIM1_BRK_TIM9_IRQn -#define TIM1_UP_IRQn TIM1_UP_TIM10_IRQn -#define TIM1_TRG_COM_IRQn TIM1_TRG_COM_TIM11_IRQn -#define TIM8_BRK_IRQn TIM8_BRK_TIM12_IRQn -#define TIM8_UP_IRQn TIM8_UP_TIM13_IRQn -#define TIM8_TRG_COM_IRQn TIM8_TRG_COM_TIM14_IRQn -#endif - -/*===========================================================================*/ -/* Driver data structures and types. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver macros. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* External declarations. */ -/*===========================================================================*/ - -/* Various helpers.*/ -#include "nvic.h" -#include "stm32_isr.h" -#include "stm32_dma.h" -#include "stm32_rcc.h" - -#ifdef __cplusplus -extern "C" { -#endif - void hal_lld_init(void); - void stm32_clock_init(void); -#ifdef __cplusplus -} -#endif - -#endif /* _HAL_LLD_H_ */ - -/** @} */ diff --git a/os/hal/platforms/STM32F4xx/platform.mk b/os/hal/platforms/STM32F4xx/platform.mk deleted file mode 100644 index fdd725faf..000000000 --- a/os/hal/platforms/STM32F4xx/platform.mk +++ /dev/null @@ -1,33 +0,0 @@ -# List of all the STM32F2xx/STM32F4xx platform files. -PLATFORMSRC = ${CHIBIOS}/os/hal/platforms/common/ARMCMx/nvic.c \ - ${CHIBIOS}/os/hal/platforms/STM32F4xx/stm32_dma.c \ - ${CHIBIOS}/os/hal/platforms/STM32F4xx/hal_lld.c \ - ${CHIBIOS}/os/hal/platforms/STM32F4xx/adc_lld.c \ - ${CHIBIOS}/os/hal/platforms/STM32F4xx/ext_lld_isr.c \ - ${CHIBIOS}/os/hal/platforms/STM32/can_lld.c \ - ${CHIBIOS}/os/hal/platforms/STM32/ext_lld.c \ - ${CHIBIOS}/os/hal/platforms/STM32/mac_lld.c \ - ${CHIBIOS}/os/hal/platforms/STM32/sdc_lld.c \ - ${CHIBIOS}/os/hal/platforms/STM32/GPIOv2/pal_lld.c \ - ${CHIBIOS}/os/hal/platforms/STM32/I2Cv1/i2c_lld.c \ - ${CHIBIOS}/os/hal/platforms/STM32/OTGv1/usb_lld.c \ - ${CHIBIOS}/os/hal/platforms/STM32/RTCv2/rtc_lld.c \ - ${CHIBIOS}/os/hal/platforms/STM32/SPIv1/spi_lld.c \ - ${CHIBIOS}/os/hal/platforms/STM32/TIMv1/gpt_lld.c \ - ${CHIBIOS}/os/hal/platforms/STM32/TIMv1/icu_lld.c \ - ${CHIBIOS}/os/hal/platforms/STM32/TIMv1/pwm_lld.c \ - ${CHIBIOS}/os/hal/platforms/STM32/TIMv1/st_lld.c \ - ${CHIBIOS}/os/hal/platforms/STM32/USARTv1/serial_lld.c \ - ${CHIBIOS}/os/hal/platforms/STM32/USARTv1/uart_lld.c - -# Required include directories -PLATFORMINC = ${CHIBIOS}/os/hal/platforms/common/ARMCMx \ - ${CHIBIOS}/os/hal/platforms/STM32F4xx \ - ${CHIBIOS}/os/hal/platforms/STM32 \ - ${CHIBIOS}/os/hal/platforms/STM32/GPIOv2 \ - ${CHIBIOS}/os/hal/platforms/STM32/I2Cv1 \ - ${CHIBIOS}/os/hal/platforms/STM32/OTGv1 \ - ${CHIBIOS}/os/hal/platforms/STM32/RTCv2 \ - ${CHIBIOS}/os/hal/platforms/STM32/SPIv1 \ - ${CHIBIOS}/os/hal/platforms/STM32/TIMv1 \ - ${CHIBIOS}/os/hal/platforms/STM32/USARTv1 diff --git a/os/hal/platforms/STM32F4xx/stm32_dma.c b/os/hal/platforms/STM32F4xx/stm32_dma.c deleted file mode 100644 index a3bb26b0d..000000000 --- a/os/hal/platforms/STM32F4xx/stm32_dma.c +++ /dev/null @@ -1,527 +0,0 @@ -/* - ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file STM32F4xx/stm32_dma.c - * @brief Enhanced DMA helper driver code. - * - * @addtogroup STM32F4xx_DMA - * @details DMA sharing helper driver. In the STM32 the DMA streams are a - * shared resource, this driver allows to allocate and free DMA - * streams at runtime in order to allow all the other device - * drivers to coordinate the access to the resource. - * @note The DMA ISR handlers are all declared into this module because - * sharing, the various device drivers can associate a callback to - * ISRs when allocating streams. - * @{ - */ - -#include "hal.h" - -/* The following macro is only defined if some driver requiring DMA services - has been enabled.*/ -#if defined(STM32_DMA_REQUIRED) || defined(__DOXYGEN__) - -/*===========================================================================*/ -/* Driver local definitions. */ -/*===========================================================================*/ - -/** - * @brief Mask of the DMA1 streams in @p dma_streams_mask. - */ -#define STM32_DMA1_STREAMS_MASK 0x000000FF - -/** - * @brief Mask of the DMA2 streams in @p dma_streams_mask. - */ -#define STM32_DMA2_STREAMS_MASK 0x0000FF00 - -/** - * @brief Post-reset value of the stream CR register. - */ -#define STM32_DMA_CR_RESET_VALUE 0x00000000 - -/** - * @brief Post-reset value of the stream FCR register. - */ -#define STM32_DMA_FCR_RESET_VALUE 0x00000021 - -/*===========================================================================*/ -/* Driver exported variables. */ -/*===========================================================================*/ - -/** - * @brief DMA streams descriptors. - * @details This table keeps the association between an unique stream - * identifier and the involved physical registers. - * @note Don't use this array directly, use the appropriate wrapper macros - * instead: @p STM32_DMA1_STREAM0, @p STM32_DMA1_STREAM1 etc. - */ -const stm32_dma_stream_t _stm32_dma_streams[STM32_DMA_STREAMS] = { - {DMA1_Stream0, &DMA1->LIFCR, 0, 0, DMA1_Stream0_IRQn}, - {DMA1_Stream1, &DMA1->LIFCR, 6, 1, DMA1_Stream1_IRQn}, - {DMA1_Stream2, &DMA1->LIFCR, 16, 2, DMA1_Stream2_IRQn}, - {DMA1_Stream3, &DMA1->LIFCR, 22, 3, DMA1_Stream3_IRQn}, - {DMA1_Stream4, &DMA1->HIFCR, 0, 4, DMA1_Stream4_IRQn}, - {DMA1_Stream5, &DMA1->HIFCR, 6, 5, DMA1_Stream5_IRQn}, - {DMA1_Stream6, &DMA1->HIFCR, 16, 6, DMA1_Stream6_IRQn}, - {DMA1_Stream7, &DMA1->HIFCR, 22, 7, DMA1_Stream7_IRQn}, - {DMA2_Stream0, &DMA2->LIFCR, 0, 8, DMA2_Stream0_IRQn}, - {DMA2_Stream1, &DMA2->LIFCR, 6, 9, DMA2_Stream1_IRQn}, - {DMA2_Stream2, &DMA2->LIFCR, 16, 10, DMA2_Stream2_IRQn}, - {DMA2_Stream3, &DMA2->LIFCR, 22, 11, DMA2_Stream3_IRQn}, - {DMA2_Stream4, &DMA2->HIFCR, 0, 12, DMA2_Stream4_IRQn}, - {DMA2_Stream5, &DMA2->HIFCR, 6, 13, DMA2_Stream5_IRQn}, - {DMA2_Stream6, &DMA2->HIFCR, 16, 14, DMA2_Stream6_IRQn}, - {DMA2_Stream7, &DMA2->HIFCR, 22, 15, DMA2_Stream7_IRQn}, -}; - -/*===========================================================================*/ -/* Driver local variables and types. */ -/*===========================================================================*/ - -/** - * @brief DMA ISR redirector type. - */ -typedef struct { - stm32_dmaisr_t dma_func; /**< @brief DMA callback function. */ - void *dma_param; /**< @brief DMA callback parameter. */ -} dma_isr_redir_t; - -/** - * @brief Mask of the allocated streams. - */ -static uint32_t dma_streams_mask; - -/** - * @brief DMA IRQ redirectors. - */ -static dma_isr_redir_t dma_isr_redir[STM32_DMA_STREAMS]; - -/*===========================================================================*/ -/* Driver local functions. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver interrupt handlers. */ -/*===========================================================================*/ - -/** - * @brief DMA1 stream 0 shared interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(Vector6C) { - uint32_t flags; - - OSAL_IRQ_PROLOGUE(); - - flags = (DMA1->LISR >> 0) & STM32_DMA_ISR_MASK; - DMA1->LIFCR = STM32_DMA_ISR_MASK << 0; - if (dma_isr_redir[0].dma_func) - dma_isr_redir[0].dma_func(dma_isr_redir[0].dma_param, flags); - - OSAL_IRQ_EPILOGUE(); -} - -/** - * @brief DMA1 stream 1 shared interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(Vector70) { - uint32_t flags; - - OSAL_IRQ_PROLOGUE(); - - flags = (DMA1->LISR >> 6) & STM32_DMA_ISR_MASK; - DMA1->LIFCR = STM32_DMA_ISR_MASK << 6; - if (dma_isr_redir[1].dma_func) - dma_isr_redir[1].dma_func(dma_isr_redir[1].dma_param, flags); - - OSAL_IRQ_EPILOGUE(); -} - -/** - * @brief DMA1 stream 2 shared interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(Vector74) { - uint32_t flags; - - OSAL_IRQ_PROLOGUE(); - - flags = (DMA1->LISR >> 16) & STM32_DMA_ISR_MASK; - DMA1->LIFCR = STM32_DMA_ISR_MASK << 16; - if (dma_isr_redir[2].dma_func) - dma_isr_redir[2].dma_func(dma_isr_redir[2].dma_param, flags); - - OSAL_IRQ_EPILOGUE(); -} - -/** - * @brief DMA1 stream 3 shared interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(Vector78) { - uint32_t flags; - - OSAL_IRQ_PROLOGUE(); - - flags = (DMA1->LISR >> 22) & STM32_DMA_ISR_MASK; - DMA1->LIFCR = STM32_DMA_ISR_MASK << 22; - if (dma_isr_redir[3].dma_func) - dma_isr_redir[3].dma_func(dma_isr_redir[3].dma_param, flags); - - OSAL_IRQ_EPILOGUE(); -} - -/** - * @brief DMA1 stream 4 shared interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(Vector7C) { - uint32_t flags; - - OSAL_IRQ_PROLOGUE(); - - flags = (DMA1->HISR >> 0) & STM32_DMA_ISR_MASK; - DMA1->HIFCR = STM32_DMA_ISR_MASK << 0; - if (dma_isr_redir[4].dma_func) - dma_isr_redir[4].dma_func(dma_isr_redir[4].dma_param, flags); - - OSAL_IRQ_EPILOGUE(); -} - -/** - * @brief DMA1 stream 5 shared interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(Vector80) { - uint32_t flags; - - OSAL_IRQ_PROLOGUE(); - - flags = (DMA1->HISR >> 6) & STM32_DMA_ISR_MASK; - DMA1->HIFCR = STM32_DMA_ISR_MASK << 6; - if (dma_isr_redir[5].dma_func) - dma_isr_redir[5].dma_func(dma_isr_redir[5].dma_param, flags); - - OSAL_IRQ_EPILOGUE(); -} - -/** - * @brief DMA1 stream 6 shared interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(Vector84) { - uint32_t flags; - - OSAL_IRQ_PROLOGUE(); - - flags = (DMA1->HISR >> 16) & STM32_DMA_ISR_MASK; - DMA1->HIFCR = STM32_DMA_ISR_MASK << 16; - if (dma_isr_redir[6].dma_func) - dma_isr_redir[6].dma_func(dma_isr_redir[6].dma_param, flags); - - OSAL_IRQ_EPILOGUE(); -} - -/** - * @brief DMA1 stream 7 shared interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(VectorFC) { - uint32_t flags; - - OSAL_IRQ_PROLOGUE(); - - flags = (DMA1->HISR >> 22) & STM32_DMA_ISR_MASK; - DMA1->HIFCR = STM32_DMA_ISR_MASK << 22; - if (dma_isr_redir[7].dma_func) - dma_isr_redir[7].dma_func(dma_isr_redir[7].dma_param, flags); - - OSAL_IRQ_EPILOGUE(); -} - -/** - * @brief DMA2 stream 0 shared interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(Vector120) { - uint32_t flags; - - OSAL_IRQ_PROLOGUE(); - - flags = (DMA2->LISR >> 0) & STM32_DMA_ISR_MASK; - DMA2->LIFCR = STM32_DMA_ISR_MASK << 0; - if (dma_isr_redir[8].dma_func) - dma_isr_redir[8].dma_func(dma_isr_redir[8].dma_param, flags); - - OSAL_IRQ_EPILOGUE(); -} - -/** - * @brief DMA2 stream 1 shared interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(Vector124) { - uint32_t flags; - - OSAL_IRQ_PROLOGUE(); - - flags = (DMA2->LISR >> 6) & STM32_DMA_ISR_MASK; - DMA2->LIFCR = STM32_DMA_ISR_MASK << 6; - if (dma_isr_redir[9].dma_func) - dma_isr_redir[9].dma_func(dma_isr_redir[9].dma_param, flags); - - OSAL_IRQ_EPILOGUE(); -} - -/** - * @brief DMA2 stream 2 shared interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(Vector128) { - uint32_t flags; - - OSAL_IRQ_PROLOGUE(); - - flags = (DMA2->LISR >> 16) & STM32_DMA_ISR_MASK; - DMA2->LIFCR = STM32_DMA_ISR_MASK << 16; - if (dma_isr_redir[10].dma_func) - dma_isr_redir[10].dma_func(dma_isr_redir[10].dma_param, flags); - - OSAL_IRQ_EPILOGUE(); -} - -/** - * @brief DMA2 stream 3 shared interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(Vector12C) { - uint32_t flags; - - OSAL_IRQ_PROLOGUE(); - - flags = (DMA2->LISR >> 22) & STM32_DMA_ISR_MASK; - DMA2->LIFCR = STM32_DMA_ISR_MASK << 22; - if (dma_isr_redir[11].dma_func) - dma_isr_redir[11].dma_func(dma_isr_redir[11].dma_param, flags); - - OSAL_IRQ_EPILOGUE(); -} - -/** - * @brief DMA2 stream 4 shared interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(Vector130) { - uint32_t flags; - - OSAL_IRQ_PROLOGUE(); - - flags = (DMA2->HISR >> 0) & STM32_DMA_ISR_MASK; - DMA2->HIFCR = STM32_DMA_ISR_MASK << 0; - if (dma_isr_redir[12].dma_func) - dma_isr_redir[12].dma_func(dma_isr_redir[12].dma_param, flags); - - OSAL_IRQ_EPILOGUE(); -} - -/** - * @brief DMA2 stream 5 shared interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(Vector150) { - uint32_t flags; - - OSAL_IRQ_PROLOGUE(); - - flags = (DMA2->HISR >> 6) & STM32_DMA_ISR_MASK; - DMA2->HIFCR = STM32_DMA_ISR_MASK << 6; - if (dma_isr_redir[13].dma_func) - dma_isr_redir[13].dma_func(dma_isr_redir[13].dma_param, flags); - - OSAL_IRQ_EPILOGUE(); -} - -/** - * @brief DMA2 stream 6 shared interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(Vector154) { - uint32_t flags; - - OSAL_IRQ_PROLOGUE(); - - flags = (DMA2->HISR >> 16) & STM32_DMA_ISR_MASK; - DMA2->HIFCR = STM32_DMA_ISR_MASK << 16; - if (dma_isr_redir[14].dma_func) - dma_isr_redir[14].dma_func(dma_isr_redir[14].dma_param, flags); - - OSAL_IRQ_EPILOGUE(); -} - -/** - * @brief DMA2 stream 7 shared interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(Vector158) { - uint32_t flags; - - OSAL_IRQ_PROLOGUE(); - - flags = (DMA2->HISR >> 22) & STM32_DMA_ISR_MASK; - DMA2->HIFCR = STM32_DMA_ISR_MASK << 22; - if (dma_isr_redir[15].dma_func) - dma_isr_redir[15].dma_func(dma_isr_redir[15].dma_param, flags); - - OSAL_IRQ_EPILOGUE(); -} - -/*===========================================================================*/ -/* Driver exported functions. */ -/*===========================================================================*/ - -/** - * @brief STM32 DMA helper initialization. - * - * @init - */ -void dmaInit(void) { - int i; - - dma_streams_mask = 0; - for (i = 0; i < STM32_DMA_STREAMS; i++) { - _stm32_dma_streams[i].stream->CR = 0; - dma_isr_redir[i].dma_func = NULL; - } - DMA1->LIFCR = 0xFFFFFFFF; - DMA1->HIFCR = 0xFFFFFFFF; - DMA2->LIFCR = 0xFFFFFFFF; - DMA2->HIFCR = 0xFFFFFFFF; -} - -/** - * @brief Allocates a DMA stream. - * @details The stream is allocated and, if required, the DMA clock enabled. - * The function also enables the IRQ vector associated to the stream - * and initializes its priority. - * @pre The stream must not be already in use or an error is returned. - * @post The stream is allocated and the default ISR handler redirected - * to the specified function. - * @post The stream ISR vector is enabled and its priority configured. - * @post The stream must be freed using @p dmaStreamRelease() before it can - * be reused with another peripheral. - * @post The stream is in its post-reset state. - * @note This function can be invoked in both ISR or thread context. - * - * @param[in] dmastp pointer to a stm32_dma_stream_t structure - * @param[in] priority IRQ priority mask for the DMA stream - * @param[in] func handling function pointer, can be @p NULL - * @param[in] param a parameter to be passed to the handling function - * @return The operation status. - * @retval FALSE no error, stream taken. - * @retval TRUE error, stream already taken. - * - * @special - */ -bool_t dmaStreamAllocate(const stm32_dma_stream_t *dmastp, - uint32_t priority, - stm32_dmaisr_t func, - void *param) { - - osalDbgCheck(dmastp != NULL); - - /* Checks if the stream is already taken.*/ - if ((dma_streams_mask & (1 << dmastp->selfindex)) != 0) - return TRUE; - - /* Marks the stream as allocated.*/ - dma_isr_redir[dmastp->selfindex].dma_func = func; - dma_isr_redir[dmastp->selfindex].dma_param = param; - dma_streams_mask |= (1 << dmastp->selfindex); - - /* Enabling DMA clocks required by the current streams set.*/ - if ((dma_streams_mask & STM32_DMA1_STREAMS_MASK) != 0) - rccEnableDMA1(FALSE); - if ((dma_streams_mask & STM32_DMA2_STREAMS_MASK) != 0) - rccEnableDMA2(FALSE); - - /* Putting the stream in a safe state.*/ - dmaStreamDisable(dmastp); - dmastp->stream->CR = STM32_DMA_CR_RESET_VALUE; - dmastp->stream->FCR = STM32_DMA_FCR_RESET_VALUE; - - /* Enables the associated IRQ vector if a callback is defined.*/ - if (func != NULL) - nvicEnableVector(dmastp->vector, priority); - - return FALSE; -} - -/** - * @brief Releases a DMA stream. - * @details The stream is freed and, if required, the DMA clock disabled. - * Trying to release a unallocated stream is an illegal operation - * and is trapped if assertions are enabled. - * @pre The stream must have been allocated using @p dmaStreamAllocate(). - * @post The stream is again available. - * @note This function can be invoked in both ISR or thread context. - * - * @param[in] dmastp pointer to a stm32_dma_stream_t structure - * - * @special - */ -void dmaStreamRelease(const stm32_dma_stream_t *dmastp) { - - osalDbgCheck(dmastp != NULL); - - /* Check if the streams is not taken.*/ - osalDbgAssert((dma_streams_mask & (1 << dmastp->selfindex)) != 0, - "not allocated"); - - /* Disables the associated IRQ vector.*/ - nvicDisableVector(dmastp->vector); - - /* Marks the stream as not allocated.*/ - dma_streams_mask &= ~(1 << dmastp->selfindex); - - /* Shutting down clocks that are no more required, if any.*/ - if ((dma_streams_mask & STM32_DMA1_STREAMS_MASK) == 0) - rccDisableDMA1(FALSE); - if ((dma_streams_mask & STM32_DMA2_STREAMS_MASK) == 0) - rccDisableDMA2(FALSE); -} - -#endif /* STM32_DMA_REQUIRED */ - -/** @} */ diff --git a/os/hal/platforms/STM32F4xx/stm32_dma.h b/os/hal/platforms/STM32F4xx/stm32_dma.h deleted file mode 100644 index 62b0fbd43..000000000 --- a/os/hal/platforms/STM32F4xx/stm32_dma.h +++ /dev/null @@ -1,461 +0,0 @@ -/* - ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file STM32F4xx/stm32_dma.h - * @brief Enhanced-DMA helper driver header. - * @note This file requires definitions from the ST STM32F4xx header file - * stm32f4xx.h. - * - * @addtogroup STM32F4xx_DMA - * @{ - */ - -#ifndef _STM32_DMA_H_ -#define _STM32_DMA_H_ - -/*===========================================================================*/ -/* Driver constants. */ -/*===========================================================================*/ - -/** - * @brief Total number of DMA streams. - * @note This is the total number of streams among all the DMA units. - */ -#define STM32_DMA_STREAMS 16 - -/** - * @brief Mask of the ISR bits passed to the DMA callback functions. - */ -#define STM32_DMA_ISR_MASK 0x3D - -/** - * @brief Returns the channel associated to the specified stream. - * - * @param[in] id the unique numeric stream identifier - * @param[in] c a stream/channel association word, one channel per - * nibble - * @return Returns the channel associated to the stream. - */ -#define STM32_DMA_GETCHANNEL(id, c) (((c) >> (((id) & 7) * 4)) & 7) - -/** - * @brief Checks if a DMA priority is within the valid range. - * @param[in] prio DMA priority - * - * @retval The check result. - * @retval FALSE invalid DMA priority. - * @retval TRUE correct DMA priority. - */ -#define STM32_DMA_IS_VALID_PRIORITY(prio) (((prio) >= 0) && ((prio) <= 3)) - -/** - * @brief Returns an unique numeric identifier for a DMA stream. - * - * @param[in] dma the DMA unit number - * @param[in] stream the stream number - * @return An unique numeric stream identifier. - */ -#define STM32_DMA_STREAM_ID(dma, stream) ((((dma) - 1) * 8) + (stream)) - -/** - * @brief Returns a DMA stream identifier mask. - * - * - * @param[in] dma the DMA unit number - * @param[in] stream the stream number - * @return A DMA stream identifier mask. - */ -#define STM32_DMA_STREAM_ID_MSK(dma, stream) \ - (1 << STM32_DMA_STREAM_ID(dma, stream)) - -/** - * @brief Checks if a DMA stream unique identifier belongs to a mask. - * @param[in] id the stream numeric identifier - * @param[in] mask the stream numeric identifiers mask - * - * @retval The check result. - * @retval FALSE id does not belong to the mask. - * @retval TRUE id belongs to the mask. - */ -#define STM32_DMA_IS_VALID_ID(id, mask) (((1 << (id)) & (mask))) - -/** - * @name DMA streams identifiers - * @{ - */ -/** - * @brief Returns a pointer to a stm32_dma_stream_t structure. - * - * @param[in] id the stream numeric identifier - * @return A pointer to the stm32_dma_stream_t constant structure - * associated to the DMA stream. - */ -#define STM32_DMA_STREAM(id) (&_stm32_dma_streams[id]) - -#define STM32_DMA1_STREAM0 STM32_DMA_STREAM(0) -#define STM32_DMA1_STREAM1 STM32_DMA_STREAM(1) -#define STM32_DMA1_STREAM2 STM32_DMA_STREAM(2) -#define STM32_DMA1_STREAM3 STM32_DMA_STREAM(3) -#define STM32_DMA1_STREAM4 STM32_DMA_STREAM(4) -#define STM32_DMA1_STREAM5 STM32_DMA_STREAM(5) -#define STM32_DMA1_STREAM6 STM32_DMA_STREAM(6) -#define STM32_DMA1_STREAM7 STM32_DMA_STREAM(7) -#define STM32_DMA2_STREAM0 STM32_DMA_STREAM(8) -#define STM32_DMA2_STREAM1 STM32_DMA_STREAM(9) -#define STM32_DMA2_STREAM2 STM32_DMA_STREAM(10) -#define STM32_DMA2_STREAM3 STM32_DMA_STREAM(11) -#define STM32_DMA2_STREAM4 STM32_DMA_STREAM(12) -#define STM32_DMA2_STREAM5 STM32_DMA_STREAM(13) -#define STM32_DMA2_STREAM6 STM32_DMA_STREAM(14) -#define STM32_DMA2_STREAM7 STM32_DMA_STREAM(15) -/** @} */ - -/** - * @name CR register constants common to all DMA types - * @{ - */ -#define STM32_DMA_CR_EN DMA_SxCR_EN -#define STM32_DMA_CR_TEIE DMA_SxCR_TEIE -#define STM32_DMA_CR_HTIE DMA_SxCR_HTIE -#define STM32_DMA_CR_TCIE DMA_SxCR_TCIE -#define STM32_DMA_CR_DIR_MASK DMA_SxCR_DIR -#define STM32_DMA_CR_DIR_P2M 0 -#define STM32_DMA_CR_DIR_M2P DMA_SxCR_DIR_0 -#define STM32_DMA_CR_DIR_M2M DMA_SxCR_DIR_1 -#define STM32_DMA_CR_CIRC DMA_SxCR_CIRC -#define STM32_DMA_CR_PINC DMA_SxCR_PINC -#define STM32_DMA_CR_MINC DMA_SxCR_MINC -#define STM32_DMA_CR_PSIZE_MASK DMA_SxCR_PSIZE -#define STM32_DMA_CR_PSIZE_BYTE 0 -#define STM32_DMA_CR_PSIZE_HWORD DMA_SxCR_PSIZE_0 -#define STM32_DMA_CR_PSIZE_WORD DMA_SxCR_PSIZE_1 -#define STM32_DMA_CR_MSIZE_MASK DMA_SxCR_MSIZE -#define STM32_DMA_CR_MSIZE_BYTE 0 -#define STM32_DMA_CR_MSIZE_HWORD DMA_SxCR_MSIZE_0 -#define STM32_DMA_CR_MSIZE_WORD DMA_SxCR_MSIZE_1 -#define STM32_DMA_CR_SIZE_MASK (STM32_DMA_CR_PSIZE_MASK | \ - STM32_DMA_CR_MSIZE_MASK) -#define STM32_DMA_CR_PL_MASK DMA_SxCR_PL -#define STM32_DMA_CR_PL(n) ((n) << 16) -/** @} */ - -/** - * @name CR register constants only found in STM32F2xx/STM32F4xx - * @{ - */ -#define STM32_DMA_CR_DMEIE DMA_SxCR_DMEIE -#define STM32_DMA_CR_PFCTRL DMA_SxCR_PFCTRL -#define STM32_DMA_CR_PINCOS DMA_SxCR_PINCOS -#define STM32_DMA_CR_DBM DMA_SxCR_DBM -#define STM32_DMA_CR_CT DMA_SxCR_CT -#define STM32_DMA_CR_PBURST_MASK DMA_SxCR_PBURST -#define STM32_DMA_CR_PBURST_SINGLE 0 -#define STM32_DMA_CR_PBURST_INCR4 DMA_SxCR_PBURST_0 -#define STM32_DMA_CR_PBURST_INCR8 DMA_SxCR_PBURST_1 -#define STM32_DMA_CR_PBURST_INCR16 (DMA_SxCR_PBURST_0 | DMA_SxCR_PBURST_1) -#define STM32_DMA_CR_MBURST_MASK DMA_SxCR_MBURST -#define STM32_DMA_CR_MBURST_SINGLE 0 -#define STM32_DMA_CR_MBURST_INCR4 DMA_SxCR_MBURST_0 -#define STM32_DMA_CR_MBURST_INCR8 DMA_SxCR_MBURST_1 -#define STM32_DMA_CR_MBURST_INCR16 (DMA_SxCR_MBURST_0 | DMA_SxCR_MBURST_1) -#define STM32_DMA_CR_CHSEL_MASK DMA_SxCR_CHSEL -#define STM32_DMA_CR_CHSEL(n) ((n) << 25) -/** @} */ - -/** - * @name FCR register constants only found in STM32F2xx/STM32F4xx - * @{ - */ -#define STM32_DMA_FCR_FEIE DMA_SxFCR_FEIE -#define STM32_DMA_FCR_FS_MASK DMA_SxFCR_FS -#define STM32_DMA_FCR_DMDIS DMA_SxFCR_DMDIS -#define STM32_DMA_FCR_FTH_MASK DMA_SxFCR_FTH -#define STM32_DMA_FCR_FTH_1Q 0 -#define STM32_DMA_FCR_FTH_HALF DMA_SxFCR_FTH_0 -#define STM32_DMA_FCR_FTH_3Q DMA_SxFCR_FTH_1 -#define STM32_DMA_FCR_FTH_FULL (DMA_SxFCR_FTH_0 | DMA_SxFCR_FTH_1) -/** @} */ - -/** - * @name Status flags passed to the ISR callbacks - */ -#define STM32_DMA_ISR_FEIF DMA_LISR_FEIF0 -#define STM32_DMA_ISR_DMEIF DMA_LISR_DMEIF0 -#define STM32_DMA_ISR_TEIF DMA_LISR_TEIF0 -#define STM32_DMA_ISR_HTIF DMA_LISR_HTIF0 -#define STM32_DMA_ISR_TCIF DMA_LISR_TCIF0 -/** @} */ - -/*===========================================================================*/ -/* Driver pre-compile time settings. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Derived constants and error checks. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver data structures and types. */ -/*===========================================================================*/ - -/** - * @brief STM32 DMA stream descriptor structure. - */ -typedef struct { - DMA_Stream_TypeDef *stream; /**< @brief Associated DMA stream. */ - volatile uint32_t *ifcr; /**< @brief Associated IFCR reg. */ - uint8_t ishift; /**< @brief Bits offset in xIFCR - register. */ - uint8_t selfindex; /**< @brief Index to self in array. */ - uint8_t vector; /**< @brief Associated IRQ vector. */ -} stm32_dma_stream_t; - -/** - * @brief STM32 DMA ISR function type. - * - * @param[in] p parameter for the registered function - * @param[in] flags pre-shifted content of the xISR register, the bits - * are aligned to bit zero - */ -typedef void (*stm32_dmaisr_t)(void *p, uint32_t flags); - -/*===========================================================================*/ -/* Driver macros. */ -/*===========================================================================*/ - -/** - * @name Macro Functions - * @{ - */ -/** - * @brief Associates a peripheral data register to a DMA stream. - * @note This function can be invoked in both ISR or thread context. - * @pre The stream must have been allocated using @p dmaStreamAllocate(). - * @post After use the stream can be released using @p dmaStreamRelease(). - * - * @param[in] dmastp pointer to a stm32_dma_stream_t structure - * @param[in] addr value to be written in the PAR register - * - * @special - */ -#define dmaStreamSetPeripheral(dmastp, addr) { \ - (dmastp)->stream->PAR = (uint32_t)(addr); \ -} - -/** - * @brief Associates a memory destination to a DMA stream. - * @note This function can be invoked in both ISR or thread context. - * @pre The stream must have been allocated using @p dmaStreamAllocate(). - * @post After use the stream can be released using @p dmaStreamRelease(). - * - * @param[in] dmastp pointer to a stm32_dma_stream_t structure - * @param[in] addr value to be written in the M0AR register - * - * @special - */ -#define dmaStreamSetMemory0(dmastp, addr) { \ - (dmastp)->stream->M0AR = (uint32_t)(addr); \ -} - -/** - * @brief Associates an alternate memory destination to a DMA stream. - * @note This function can be invoked in both ISR or thread context. - * - * @param[in] dmastp pointer to a stm32_dma_stream_t structure - * @param[in] addr value to be written in the M1AR register - * - * @special - */ -#define dmaStreamSetMemory1(dmastp, addr) { \ - (dmastp)->stream->M1AR = (uint32_t)(addr); \ -} - -/** - * @brief Sets the number of transfers to be performed. - * @note This function can be invoked in both ISR or thread context. - * @pre The stream must have been allocated using @p dmaStreamAllocate(). - * @post After use the stream can be released using @p dmaStreamRelease(). - * - * @param[in] dmastp pointer to a stm32_dma_stream_t structure - * @param[in] size value to be written in the CNDTR register - * - * @special - */ -#define dmaStreamSetTransactionSize(dmastp, size) { \ - (dmastp)->stream->NDTR = (uint32_t)(size); \ -} - -/** - * @brief Returns the number of transfers to be performed. - * @note This function can be invoked in both ISR or thread context. - * @pre The stream must have been allocated using @p dmaStreamAllocate(). - * @post After use the stream can be released using @p dmaStreamRelease(). - * - * @param[in] dmastp pointer to a stm32_dma_stream_t structure - * @return The number of transfers to be performed. - * - * @special - */ -#define dmaStreamGetTransactionSize(dmastp) ((size_t)((dmastp)->stream->NDTR)) - -/** - * @brief Programs the stream mode settings. - * @note This function can be invoked in both ISR or thread context. - * @pre The stream must have been allocated using @p dmaStreamAllocate(). - * @post After use the stream can be released using @p dmaStreamRelease(). - * - * @param[in] dmastp pointer to a stm32_dma_stream_t structure - * @param[in] mode value to be written in the CR register - * - * @special - */ -#define dmaStreamSetMode(dmastp, mode) { \ - (dmastp)->stream->CR = (uint32_t)(mode); \ -} - -/** - * @brief Programs the stream FIFO settings. - * @note This function can be invoked in both ISR or thread context. - * @pre The stream must have been allocated using @p dmaStreamAllocate(). - * @post After use the stream can be released using @p dmaStreamRelease(). - * - * @param[in] dmastp pointer to a stm32_dma_stream_t structure - * @param[in] mode value to be written in the FCR register - * - * @special - */ -#define dmaStreamSetFIFO(dmastp, mode) { \ - (dmastp)->stream->FCR = (uint32_t)(mode); \ -} - -/** - * @brief DMA stream enable. - * @note This function can be invoked in both ISR or thread context. - * @pre The stream must have been allocated using @p dmaStreamAllocate(). - * @post After use the stream can be released using @p dmaStreamRelease(). - * - * @param[in] dmastp pointer to a stm32_dma_stream_t structure - * - * @special - */ -#define dmaStreamEnable(dmastp) { \ - (dmastp)->stream->CR |= STM32_DMA_CR_EN; \ -} - -/** - * @brief DMA stream disable. - * @details The function disables the specified stream, waits for the disable - * operation to complete and then clears any pending interrupt. - * @note This function can be invoked in both ISR or thread context. - * @note Interrupts enabling flags are set to zero after this call, see - * bug 3607518. - * @pre The stream must have been allocated using @p dmaStreamAllocate(). - * @post After use the stream can be released using @p dmaStreamRelease(). - * - * @param[in] dmastp pointer to a stm32_dma_stream_t structure - * - * @special - */ -#define dmaStreamDisable(dmastp) { \ - (dmastp)->stream->CR &= ~(STM32_DMA_CR_TCIE | STM32_DMA_CR_HTIE | \ - STM32_DMA_CR_TEIE | STM32_DMA_CR_DMEIE | \ - STM32_DMA_CR_EN); \ - while (((dmastp)->stream->CR & STM32_DMA_CR_EN) != 0) \ - ; \ - dmaStreamClearInterrupt(dmastp); \ -} - -/** - * @brief DMA stream interrupt sources clear. - * @note This function can be invoked in both ISR or thread context. - * @pre The stream must have been allocated using @p dmaStreamAllocate(). - * @post After use the stream can be released using @p dmaStreamRelease(). - * - * @param[in] dmastp pointer to a stm32_dma_stream_t structure - * - * @special - */ -#define dmaStreamClearInterrupt(dmastp) { \ - *(dmastp)->ifcr = STM32_DMA_ISR_MASK << (dmastp)->ishift; \ -} - -/** - * @brief Starts a memory to memory operation using the specified stream. - * @note The default transfer data mode is "byte to byte" but it can be - * changed by specifying extra options in the @p mode parameter. - * @pre The stream must have been allocated using @p dmaStreamAllocate(). - * @post After use the stream can be released using @p dmaStreamRelease(). - * - * @param[in] dmastp pointer to a stm32_dma_stream_t structure - * @param[in] mode value to be written in the CCR register, this value - * is implicitly ORed with: - * - @p STM32_DMA_CR_MINC - * - @p STM32_DMA_CR_PINC - * - @p STM32_DMA_CR_DIR_M2M - * - @p STM32_DMA_CR_EN - * . - * @param[in] src source address - * @param[in] dst destination address - * @param[in] n number of data units to copy - */ -#define dmaStartMemCopy(dmastp, mode, src, dst, n) { \ - dmaStreamSetPeripheral(dmastp, src); \ - dmaStreamSetMemory0(dmastp, dst); \ - dmaStreamSetTransactionSize(dmastp, n); \ - dmaStreamSetMode(dmastp, (mode) | \ - STM32_DMA_CR_MINC | STM32_DMA_CR_PINC | \ - STM32_DMA_CR_DIR_M2M | STM32_DMA_CR_EN); \ -} - -/** - * @brief Polled wait for DMA transfer end. - * @pre The stream must have been allocated using @p dmaStreamAllocate(). - * @post After use the stream can be released using @p dmaStreamRelease(). - * - * @param[in] dmastp pointer to a stm32_dma_stream_t structure - */ -#define dmaWaitCompletion(dmastp) { \ - while ((dmastp)->stream->NDTR > 0) \ - ; \ - dmaStreamDisable(dmastp); \ -} -/** @} */ - -/*===========================================================================*/ -/* External declarations. */ -/*===========================================================================*/ - -#if !defined(__DOXYGEN__) -extern const stm32_dma_stream_t _stm32_dma_streams[STM32_DMA_STREAMS]; -#endif - -#ifdef __cplusplus -extern "C" { -#endif - void dmaInit(void); - bool_t dmaStreamAllocate(const stm32_dma_stream_t *dmastp, - uint32_t priority, - stm32_dmaisr_t func, - void *param); - void dmaStreamRelease(const stm32_dma_stream_t *dmastp); -#ifdef __cplusplus -} -#endif - -#endif /* _STM32_DMA_H_ */ - -/** @} */ diff --git a/os/hal/platforms/STM32F4xx/stm32_isr.h b/os/hal/platforms/STM32F4xx/stm32_isr.h deleted file mode 100644 index 0e936b3d6..000000000 --- a/os/hal/platforms/STM32F4xx/stm32_isr.h +++ /dev/null @@ -1,150 +0,0 @@ -/* - ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file STM32F4xx/stm32_isr.h - * @brief ISR remapper driver header. - * - * @addtogroup STM32F4xx_ISR - * @{ - */ - -#ifndef _STM32_ISR_H_ -#define _STM32_ISR_H_ - -/*===========================================================================*/ -/* Driver constants. */ -/*===========================================================================*/ - -/** - * @name ISR names and numbers remapping - * @{ - */ -/* - * CAN units. - */ -#define STM32_CAN1_TX_HANDLER Vector8C -#define STM32_CAN1_RX0_HANDLER Vector90 -#define STM32_CAN1_RX1_HANDLER Vector94 -#define STM32_CAN1_SCE_HANDLER Vector98 -#define STM32_CAN2_TX_HANDLER Vector13C -#define STM32_CAN2_RX0_HANDLER Vector140 -#define STM32_CAN2_RX1_HANDLER Vector144 -#define STM32_CAN2_SCE_HANDLER Vector148 - -#define STM32_CAN1_TX_NUMBER 19 -#define STM32_CAN1_RX0_NUMBER 20 -#define STM32_CAN1_RX1_NUMBER 21 -#define STM32_CAN1_SCE_NUMBER 22 -#define STM32_CAN2_TX_NUMBER 63 -#define STM32_CAN2_RX0_NUMBER 64 -#define STM32_CAN2_RX1_NUMBER 65 -#define STM32_CAN2_SCE_NUMBER 66 - -/* - * OTG units. - */ -#define STM32_OTG1_HANDLER Vector14C -#define STM32_OTG2_HANDLER Vector174 -#define STM32_OTG2_EP1OUT_HANDLER Vector168 -#define STM32_OTG2_EP1IN_HANDLER Vector16C - -#define STM32_OTG1_NUMBER 67 -#define STM32_OTG2_NUMBER 77 -#define STM32_OTG2_EP1OUT_NUMBER 74 -#define STM32_OTG2_EP1IN_NUMBER 75 - -/* - * SDIO unit. - */ -#define STM32_SDIO_HANDLER Vector104 - -#define STM32_SDIO_NUMBER 49 - -/* - * TIM units. - */ -#define STM32_TIM1_UP_HANDLER VectorA4 -#define STM32_TIM1_CC_HANDLER VectorAC -#define STM32_TIM2_HANDLER VectorB0 -#define STM32_TIM3_HANDLER VectorB4 -#define STM32_TIM4_HANDLER VectorB8 -#define STM32_TIM5_HANDLER Vector108 -#define STM32_TIM6_HANDLER Vector118 -#define STM32_TIM7_HANDLER Vector11C -#define STM32_TIM8_UP_HANDLER VectorF0 -#define STM32_TIM8_CC_HANDLER VectorF8 -#define STM32_TIM9_HANDLER VectorA0 -#define STM32_TIM11_HANDLER VectorA8 -#define STM32_TIM12_HANDLER VectorEC -#define STM32_TIM14_HANDLER VectorF4 - -#define STM32_TIM1_UP_NUMBER 25 -#define STM32_TIM1_CC_NUMBER 27 -#define STM32_TIM2_NUMBER 28 -#define STM32_TIM3_NUMBER 29 -#define STM32_TIM4_NUMBER 30 -#define STM32_TIM5_NUMBER 50 -#define STM32_TIM6_NUMBER 54 -#define STM32_TIM7_NUMBER 55 -#define STM32_TIM8_UP_NUMBER 44 -#define STM32_TIM8_CC_NUMBER 46 -#define STM32_TIM9_NUMBER 24 -#define STM32_TIM11_NUMBER 26 -#define STM32_TIM12_NUMBER 43 -#define STM32_TIM14_NUMBER 45 - -/* - * USART units. - */ -#define STM32_USART1_HANDLER VectorD4 -#define STM32_USART2_HANDLER VectorD8 -#define STM32_USART3_HANDLER VectorDC -#define STM32_UART4_HANDLER Vector110 -#define STM32_UART5_HANDLER Vector114 -#define STM32_USART6_HANDLER Vector15C - -#define STM32_USART1_NUMBER 37 -#define STM32_USART2_NUMBER 38 -#define STM32_USART3_NUMBER 39 -#define STM32_UART4_NUMBER 52 -#define STM32_UART5_NUMBER 53 -#define STM32_USART6_NUMBER 71 -/** @} */ - -/*===========================================================================*/ -/* Driver pre-compile time settings. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Derived constants and error checks. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver data structures and types. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver macros. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* External declarations. */ -/*===========================================================================*/ - -#endif /* _STM32_ISR_H_ */ - -/** @} */ diff --git a/os/hal/platforms/STM32F4xx/stm32_rcc.h b/os/hal/platforms/STM32F4xx/stm32_rcc.h deleted file mode 100644 index 25a9bb037..000000000 --- a/os/hal/platforms/STM32F4xx/stm32_rcc.h +++ /dev/null @@ -1,1254 +0,0 @@ -/* - ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file STM32F4xx/stm32_rcc.h - * @brief RCC helper driver header. - * @note This file requires definitions from the ST header file - * @p stm32f4xx.h. - * - * @addtogroup STM32F4xx_RCC - * @{ - */ -#ifndef _STM32_RCC_ -#define _STM32_RCC_ - -/*===========================================================================*/ -/* Driver constants. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver pre-compile time settings. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Derived constants and error checks. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver data structures and types. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver macros. */ -/*===========================================================================*/ - -/** - * @name Generic RCC operations - * @{ - */ -/** - * @brief Enables the clock of one or more peripheral on the APB1 bus. - * - * @param[in] mask APB1 peripherals mask - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableAPB1(mask, lp) { \ - RCC->APB1ENR |= (mask); \ - if (lp) \ - RCC->APB1LPENR |= (mask); \ -} - -/** - * @brief Disables the clock of one or more peripheral on the APB1 bus. - * - * @param[in] mask APB1 peripherals mask - * @param[in] lp low power enable flag - * - * @api - */ -#define rccDisableAPB1(mask, lp) { \ - RCC->APB1ENR &= ~(mask); \ - if (lp) \ - RCC->APB1LPENR &= ~(mask); \ -} - -/** - * @brief Resets one or more peripheral on the APB1 bus. - * - * @param[in] mask APB1 peripherals mask - * - * @api - */ -#define rccResetAPB1(mask) { \ - RCC->APB1RSTR |= (mask); \ - RCC->APB1RSTR = 0; \ -} - -/** - * @brief Enables the clock of one or more peripheral on the APB2 bus. - * - * @param[in] mask APB2 peripherals mask - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableAPB2(mask, lp) { \ - RCC->APB2ENR |= (mask); \ - if (lp) \ - RCC->APB2LPENR |= (mask); \ -} - -/** - * @brief Disables the clock of one or more peripheral on the APB2 bus. - * - * @param[in] mask APB2 peripherals mask - * @param[in] lp low power enable flag - * - * @api - */ -#define rccDisableAPB2(mask, lp) { \ - RCC->APB2ENR &= ~(mask); \ - if (lp) \ - RCC->APB2LPENR &= ~(mask); \ -} - -/** - * @brief Resets one or more peripheral on the APB2 bus. - * - * @param[in] mask APB2 peripherals mask - * - * @api - */ -#define rccResetAPB2(mask) { \ - RCC->APB2RSTR |= (mask); \ - RCC->APB2RSTR = 0; \ -} - -/** - * @brief Enables the clock of one or more peripheral on the AHB1 bus. - * - * @param[in] mask AHB1 peripherals mask - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableAHB1(mask, lp) { \ - RCC->AHB1ENR |= (mask); \ - if (lp) \ - RCC->AHB1LPENR |= (mask); \ -} - -/** - * @brief Disables the clock of one or more peripheral on the AHB1 bus. - * - * @param[in] mask AHB1 peripherals mask - * @param[in] lp low power enable flag - * - * @api - */ -#define rccDisableAHB1(mask, lp) { \ - RCC->AHB1ENR &= ~(mask); \ - if (lp) \ - RCC->AHB1LPENR &= ~(mask); \ -} - -/** - * @brief Resets one or more peripheral on the AHB1 bus. - * - * @param[in] mask AHB1 peripherals mask - * - * @api - */ -#define rccResetAHB1(mask) { \ - RCC->AHB1RSTR |= (mask); \ - RCC->AHB1RSTR = 0; \ -} - -/** - * @brief Enables the clock of one or more peripheral on the AHB2 bus. - * - * @param[in] mask AHB2 peripherals mask - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableAHB2(mask, lp) { \ - RCC->AHB2ENR |= (mask); \ - if (lp) \ - RCC->AHB2LPENR |= (mask); \ -} - -/** - * @brief Disables the clock of one or more peripheral on the AHB2 bus. - * - * @param[in] mask AHB2 peripherals mask - * @param[in] lp low power enable flag - * - * @api - */ -#define rccDisableAHB2(mask, lp) { \ - RCC->AHB2ENR &= ~(mask); \ - if (lp) \ - RCC->AHB2LPENR &= ~(mask); \ -} - -/** - * @brief Resets one or more peripheral on the AHB2 bus. - * - * @param[in] mask AHB2 peripherals mask - * - * @api - */ -#define rccResetAHB2(mask) { \ - RCC->AHB2RSTR |= (mask); \ - RCC->AHB2RSTR = 0; \ -} - -/** - * @brief Enables the clock of one or more peripheral on the AHB3 (FSMC) bus. - * - * @param[in] mask AHB3 peripherals mask - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableAHB3(mask, lp) { \ - RCC->AHB3ENR |= (mask); \ - if (lp) \ - RCC->AHB3LPENR |= (mask); \ -} - -/** - * @brief Disables the clock of one or more peripheral on the AHB3 (FSMC) bus. - * - * @param[in] mask AHB3 peripherals mask - * @param[in] lp low power enable flag - * - * @api - */ -#define rccDisableAHB3(mask, lp) { \ - RCC->AHB3ENR &= ~(mask); \ - if (lp) \ - RCC->AHB3LPENR &= ~(mask); \ -} - -/** - * @brief Resets one or more peripheral on the AHB3 (FSMC) bus. - * - * @param[in] mask AHB3 peripherals mask - * - * @api - */ -#define rccResetAHB3(mask) { \ - RCC->AHB3RSTR |= (mask); \ - RCC->AHB3RSTR = 0; \ -} -/** @} */ - -/** - * @name ADC peripherals specific RCC operations - * @{ - */ -/** - * @brief Enables the ADC1 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableADC1(lp) rccEnableAPB2(RCC_APB2ENR_ADC1EN, lp) - -/** - * @brief Disables the ADC1 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccDisableADC1(lp) rccDisableAPB2(RCC_APB2ENR_ADC1EN, lp) - -/** - * @brief Resets the ADC1 peripheral. - * - * @api - */ -#define rccResetADC1() rccResetAPB2(RCC_APB2RSTR_ADC1RST) - -/** - * @brief Enables the ADC2 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableADC2(lp) rccEnableAPB2(RCC_APB2ENR_ADC2EN, lp) - -/** - * @brief Disables the ADC2 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccDisableADC2(lp) rccDisableAPB2(RCC_APB2ENR_ADC2EN, lp) - -/** - * @brief Resets the ADC2 peripheral. - * - * @api - */ -#define rccResetADC2() rccResetAPB2(RCC_APB2RSTR_ADC2RST) - -/** - * @brief Enables the ADC3 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableADC3(lp) rccEnableAPB2(RCC_APB2ENR_ADC3EN, lp) - -/** - * @brief Disables the ADC3 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccDisableADC3(lp) rccDisableAPB2(RCC_APB2ENR_ADC3EN, lp) - -/** - * @brief Resets the ADC3 peripheral. - * - * @api - */ -#define rccResetADC3() rccResetAPB2(RCC_APB2RSTR_ADC3RST) -/** @} */ - -/** - * @name DMA peripheral specific RCC operations - * @{ - */ -/** - * @brief Enables the DMA1 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableDMA1(lp) rccEnableAHB1(RCC_AHB1ENR_DMA1EN, lp) - -/** - * @brief Disables the DMA1 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccDisableDMA1(lp) rccDisableAHB1(RCC_AHB1ENR_DMA1EN, lp) - -/** - * @brief Resets the DMA1 peripheral. - * - * @api - */ -#define rccResetDMA1() rccResetAHB1(RCC_AHB1RSTR_DMA1RST) - -/** - * @brief Enables the DMA2 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableDMA2(lp) rccEnableAHB1(RCC_AHB1ENR_DMA2EN, lp) - -/** - * @brief Disables the DMA2 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccDisableDMA2(lp) rccDisableAHB1(RCC_AHB1ENR_DMA2EN, lp) - -/** - * @brief Resets the DMA2 peripheral. - * - * @api - */ -#define rccResetDMA2() rccResetAHB1(RCC_AHB1RSTR_DMA2RST) -/** @} */ - -/** - * @name PWR interface specific RCC operations - * @{ - */ -/** - * @brief Enables the PWR interface clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnablePWRInterface(lp) rccEnableAPB1(RCC_APB1ENR_PWREN, lp) - -/** - * @brief Disables PWR interface clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccDisablePWRInterface(lp) rccDisableAPB1(RCC_APB1ENR_PWREN, lp) - -/** - * @brief Resets the PWR interface. - * - * @api - */ -#define rccResetPWRInterface() rccResetAPB1(RCC_APB1RSTR_PWRRST) -/** @} */ - - -/** - * @name CAN peripherals specific RCC operations - * @{ - */ -/** - * @brief Enables the CAN1 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableCAN1(lp) rccEnableAPB1(RCC_APB1ENR_CAN1EN, lp) - -/** - * @brief Disables the CAN1 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccDisableCAN1(lp) rccDisableAPB1(RCC_APB1ENR_CAN1EN, lp) - -/** - * @brief Resets the CAN1 peripheral. - * - * @api - */ -#define rccResetCAN1() rccResetAPB1(RCC_APB1RSTR_CAN1RST) - -/** - * @brief Enables the CAN2 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableCAN2(lp) rccEnableAPB1(RCC_APB1ENR_CAN2EN, lp) - -/** - * @brief Disables the CAN2 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccDisableCAN2(lp) rccDisableAPB1(RCC_APB1ENR_CAN2EN, lp) - -/** - * @brief Resets the CAN2 peripheral. - * - * @api - */ -#define rccResetCAN2() rccResetAPB1(RCC_APB1RSTR_CAN2RST) -/** @} */ - -/** - * @name ETH peripheral specific RCC operations - * @{ - */ -/** - * @brief Enables the ETH peripheral clock. - * @note The @p lp parameter is ignored in this family. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableETH(lp) rccEnableAHB1(RCC_AHB1ENR_ETHMACEN | \ - RCC_AHB1ENR_ETHMACTXEN | \ - RCC_AHB1ENR_ETHMACRXEN, lp) - -/** - * @brief Disables the ETH peripheral clock. - * @note The @p lp parameter is ignored in this family. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccDisableETH(lp) rccDisableAHB1(RCC_AHB1ENR_ETHMACEN | \ - RCC_AHB1ENR_ETHMACTXEN | \ - RCC_AHB1ENR_ETHMACRXEN, lp) - -/** - * @brief Resets the ETH peripheral. - * - * @api - */ -#define rccResetETH() rccResetAHB1(RCC_AHB1RSTR_ETHMACRST) -/** @} */ - -/** - * @name I2C peripherals specific RCC operations - * @{ - */ -/** - * @brief Enables the I2C1 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableI2C1(lp) rccEnableAPB1(RCC_APB1ENR_I2C1EN, lp) - -/** - * @brief Disables the I2C1 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccDisableI2C1(lp) rccDisableAPB1(RCC_APB1ENR_I2C1EN, lp) - -/** - * @brief Resets the I2C1 peripheral. - * - * @api - */ -#define rccResetI2C1() rccResetAPB1(RCC_APB1RSTR_I2C1RST) - -/** - * @brief Enables the I2C2 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableI2C2(lp) rccEnableAPB1(RCC_APB1ENR_I2C2EN, lp) - -/** - * @brief Disables the I2C2 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccDisableI2C2(lp) rccDisableAPB1(RCC_APB1ENR_I2C2EN, lp) - -/** - * @brief Resets the I2C2 peripheral. - * - * @api - */ -#define rccResetI2C2() rccResetAPB1(RCC_APB1RSTR_I2C2RST) - -/** - * @brief Enables the I2C3 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableI2C3(lp) rccEnableAPB1(RCC_APB1ENR_I2C3EN, lp) - -/** - * @brief Disables the I2C3 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccDisableI2C3(lp) rccDisableAPB1(RCC_APB1ENR_I2C3EN, lp) - -/** - * @brief Resets the I2C3 peripheral. - * - * @api - */ -#define rccResetI2C3() rccResetAPB1(RCC_APB1RSTR_I2C3RST) -/** @} */ - -/** - * @name OTG peripherals specific RCC operations - * @{ - */ -/** - * @brief Enables the OTG_FS peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableOTG_FS(lp) rccEnableAHB2(RCC_AHB2ENR_OTGFSEN, lp) - -/** - * @brief Disables the OTG_FS peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccDisableOTG_FS(lp) rccDisableAHB2(RCC_AHB2ENR_OTGFSEN, lp) - -/** - * @brief Resets the OTG_FS peripheral. - * - * @api - */ -#define rccResetOTG_FS() rccResetAHB2(RCC_AHB2RSTR_OTGFSRST) - -/** - * @brief Enables the OTG_HS peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableOTG_HS(lp) rccEnableAHB1(RCC_AHB1ENR_OTGHSEN, lp) - -/** - * @brief Disables the OTG_HS peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccDisableOTG_HS(lp) rccDisableAHB1(RCC_AHB1ENR_OTGHSEN, lp) - -/** - * @brief Resets the OTG_HS peripheral. - * - * @api - */ -#define rccResetOTG_HS() rccResetAHB1(RCC_AHB1RSTR_OTGHSRST) -/** @} */ - -/** - * @name SDIO peripheral specific RCC operations - * @{ - */ -/** - * @brief Enables the SDIO peripheral clock. - * @note The @p lp parameter is ignored in this family. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableSDIO(lp) rccEnableAPB2(RCC_APB2ENR_SDIOEN, lp) - -/** - * @brief Disables the SDIO peripheral clock. - * @note The @p lp parameter is ignored in this family. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccDisableSDIO(lp) rccDisableAPB2(RCC_APB2ENR_SDIOEN, lp) - -/** - * @brief Resets the SDIO peripheral. - * @note Not supported in this family, does nothing. - * - * @api - */ -#define rccResetSDIO() rccResetAPB2(RCC_APB2RSTR_SDIORST) -/** @} */ - -/** - * @name SPI peripherals specific RCC operations - * @{ - */ -/** - * @brief Enables the SPI1 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableSPI1(lp) rccEnableAPB2(RCC_APB2ENR_SPI1EN, lp) - -/** - * @brief Disables the SPI1 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccDisableSPI1(lp) rccDisableAPB2(RCC_APB2ENR_SPI1EN, lp) - -/** - * @brief Resets the SPI1 peripheral. - * - * @api - */ -#define rccResetSPI1() rccResetAPB2(RCC_APB2RSTR_SPI1RST) - -/** - * @brief Enables the SPI2 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableSPI2(lp) rccEnableAPB1(RCC_APB1ENR_SPI2EN, lp) - -/** - * @brief Disables the SPI2 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccDisableSPI2(lp) rccDisableAPB1(RCC_APB1ENR_SPI2EN, lp) - -/** - * @brief Resets the SPI2 peripheral. - * - * @api - */ -#define rccResetSPI2() rccResetAPB1(RCC_APB1RSTR_SPI2RST) - -/** - * @brief Enables the SPI3 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableSPI3(lp) rccEnableAPB1(RCC_APB1ENR_SPI3EN, lp) - -/** - * @brief Disables the SPI3 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccDisableSPI3(lp) rccDisableAPB1(RCC_APB1ENR_SPI3EN, lp) - -/** - * @brief Resets the SPI3 peripheral. - * - * @api - */ -#define rccResetSPI3() rccResetAPB1(RCC_APB1RSTR_SPI3RST) -/** @} */ - -/** - * @name TIM peripherals specific RCC operations - * @{ - */ -/** - * @brief Enables the TIM1 peripheral clock. - * @note The @p lp parameter is ignored in this family. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableTIM1(lp) rccEnableAPB2(RCC_APB2ENR_TIM1EN, lp) - -/** - * @brief Disables the TIM1 peripheral clock. - * @note The @p lp parameter is ignored in this family. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccDisableTIM1(lp) rccDisableAPB2(RCC_APB2ENR_TIM1EN, lp) - -/** - * @brief Resets the TIM1 peripheral. - * - * @api - */ -#define rccResetTIM1() rccResetAPB2(RCC_APB2RSTR_TIM1RST) - -/** - * @brief Enables the TIM2 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableTIM2(lp) rccEnableAPB1(RCC_APB1ENR_TIM2EN, lp) - -/** - * @brief Disables the TIM2 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccDisableTIM2(lp) rccDisableAPB1(RCC_APB1ENR_TIM2EN, lp) - -/** - * @brief Resets the TIM2 peripheral. - * - * @api - */ -#define rccResetTIM2() rccResetAPB1(RCC_APB1RSTR_TIM2RST) - -/** - * @brief Enables the TIM3 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableTIM3(lp) rccEnableAPB1(RCC_APB1ENR_TIM3EN, lp) - -/** - * @brief Disables the TIM3 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccDisableTIM3(lp) rccDisableAPB1(RCC_APB1ENR_TIM3EN, lp) - -/** - * @brief Resets the TIM3 peripheral. - * - * @api - */ -#define rccResetTIM3() rccResetAPB1(RCC_APB1RSTR_TIM3RST) - -/** - * @brief Enables the TIM4 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableTIM4(lp) rccEnableAPB1(RCC_APB1ENR_TIM4EN, lp) - -/** - * @brief Disables the TIM4 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccDisableTIM4(lp) rccDisableAPB1(RCC_APB1ENR_TIM4EN, lp) - -/** - * @brief Resets the TIM4 peripheral. - * - * @api - */ -#define rccResetTIM4() rccResetAPB1(RCC_APB1RSTR_TIM4RST) - -/** - * @brief Enables the TIM5 peripheral clock. - * @note The @p lp parameter is ignored in this family. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableTIM5(lp) rccEnableAPB1(RCC_APB1ENR_TIM5EN, lp) - -/** - * @brief Disables the TIM5 peripheral clock. - * @note The @p lp parameter is ignored in this family. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccDisableTIM5(lp) rccDisableAPB1(RCC_APB1ENR_TIM5EN, lp) - -/** - * @brief Resets the TIM5 peripheral. - * - * @api - */ -#define rccResetTIM5() rccResetAPB1(RCC_APB1RSTR_TIM5RST) - -/** - * @brief Enables the TIM6 peripheral clock. - * @note The @p lp parameter is ignored in this family. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableTIM6(lp) rccEnableAPB1(RCC_APB1ENR_TIM6EN, lp) - -/** - * @brief Disables the TIM6 peripheral clock. - * @note The @p lp parameter is ignored in this family. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccDisableTIM6(lp) rccDisableAPB1(RCC_APB1ENR_TIM6EN, lp) - -/** - * @brief Resets the TIM6 peripheral. - * - * @api - */ -#define rccResetTIM6() rccResetAPB1(RCC_APB1RSTR_TIM6RST) - -/** - * @brief Enables the TIM7 peripheral clock. - * @note The @p lp parameter is ignored in this family. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableTIM7(lp) rccEnableAPB1(RCC_APB1ENR_TIM7EN, lp) - -/** - * @brief Disables the TIM7 peripheral clock. - * @note The @p lp parameter is ignored in this family. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccDisableTIM7(lp) rccDisableAPB1(RCC_APB1ENR_TIM7EN, lp) - -/** - * @brief Resets the TIM7 peripheral. - * - * @api - */ -#define rccResetTIM7() rccResetAPB1(RCC_APB1RSTR_TIM7RST) - -/** - * @brief Enables the TIM8 peripheral clock. - * @note The @p lp parameter is ignored in this family. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableTIM8(lp) rccEnableAPB2(RCC_APB2ENR_TIM8EN, lp) - -/** - * @brief Disables the TIM8 peripheral clock. - * @note The @p lp parameter is ignored in this family. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccDisableTIM8(lp) rccDisableAPB2(RCC_APB2ENR_TIM8EN, lp) - -/** - * @brief Resets the TIM8 peripheral. - * - * @api - */ -#define rccResetTIM8() rccResetAPB2(RCC_APB2RSTR_TIM8RST) - -/** - * @brief Enables the TIM9peripheral clock. - * @note The @p lp parameter is ignored in this family. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableTIM9(lp) rccEnableAPB2(RCC_APB2ENR_TIM9EN, lp) - -/** - * @brief Disables the TIM9 peripheral clock. - * @note The @p lp parameter is ignored in this family. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccDisableTIM9(lp) rccDisableAPB2(RCC_APB2ENR_TIM9EN, lp) - -/** - * @brief Resets the TIM9 peripheral. - * - * @api - */ -#define rccResetTIM9() rccResetAPB2(RCC_APB2RSTR_TIM9RST) - -/** - * @brief Enables the TIM11 peripheral clock. - * @note The @p lp parameter is ignored in this family. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableTIM11(lp) rccEnableAPB2(RCC_APB2ENR_TIM11EN, lp) - -/** - * @brief Disables the TIM11 peripheral clock. - * @note The @p lp parameter is ignored in this family. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccDisableTIM11(lp) rccDisableAPB2(RCC_APB2ENR_TIM11EN, lp) - -/** - * @brief Resets the TIM11 peripheral. - * - * @api - */ -#define rccResetTIM11() rccResetAPB2(RCC_APB2RSTR_TIM11RST) - -/** - * @brief Enables the TIM12 peripheral clock. - * @note The @p lp parameter is ignored in this family. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableTIM12(lp) rccEnableAPB1(RCC_APB1ENR_TIM12EN, lp) - -/** - * @brief Disables the TIM12 peripheral clock. - * @note The @p lp parameter is ignored in this family. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccDisableTIM12(lp) rccDisableAPB1(RCC_APB1ENR_TIM12EN, lp) - -/** - * @brief Resets the TIM12 peripheral. - * - * @api - */ -#define rccResetTIM12() rccResetAPB1(RCC_APB1RSTR_TIM12RST) - -/** - * @brief Enables the TIM14 peripheral clock. - * @note The @p lp parameter is ignored in this family. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableTIM14(lp) rccEnableAPB1(RCC_APB1ENR_TIM14EN, lp) - -/** - * @brief Disables the TIM14 peripheral clock. - * @note The @p lp parameter is ignored in this family. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccDisableTIM14(lp) rccDisableAPB1(RCC_APB1ENR_TIM14EN, lp) - -/** - * @brief Resets the TIM14 peripheral. - * - * @api - */ -#define rccResetTIM14() rccResetAPB1(RCC_APB1RSTR_TIM14RST) -/** @} */ - -/** - * @name USART/UART peripherals specific RCC operations - * @{ - */ -/** - * @brief Enables the USART1 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableUSART1(lp) rccEnableAPB2(RCC_APB2ENR_USART1EN, lp) - -/** - * @brief Disables the USART1 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccDisableUSART1(lp) rccDisableAPB2(RCC_APB2ENR_USART1EN, lp) - -/** - * @brief Resets the USART1 peripheral. - * - * @api - */ -#define rccResetUSART1() rccResetAPB2(RCC_APB2RSTR_USART1RST) - -/** - * @brief Enables the USART2 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableUSART2(lp) rccEnableAPB1(RCC_APB1ENR_USART2EN, lp) - -/** - * @brief Disables the USART2 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccDisableUSART2(lp) rccDisableAPB1(RCC_APB1ENR_USART2EN, lp) - -/** - * @brief Resets the USART2 peripheral. - * - * @api - */ -#define rccResetUSART2() rccResetAPB1(RCC_APB1RSTR_USART2RST) - -/** - * @brief Enables the USART3 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableUSART3(lp) rccEnableAPB1(RCC_APB1ENR_USART3EN, lp) - -/** - * @brief Disables the USART3 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccDisableUSART3(lp) rccDisableAPB1(RCC_APB1ENR_USART3EN, lp) - -/** - * @brief Resets the USART3 peripheral. - * - * @api - */ -#define rccResetUSART3() rccResetAPB1(RCC_APB1RSTR_USART3RST) - -/** - * @brief Enables the USART6 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableUSART6(lp) rccEnableAPB2(RCC_APB2ENR_USART6EN, lp) - -/** - * @brief Disables the USART6 peripheral clock. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccDisableUSART6(lp) rccDisableAPB2(RCC_APB2ENR_USART6EN, lp) - -/** - * @brief Enables the UART4 peripheral clock. - * @note The @p lp parameter is ignored in this family. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableUART4(lp) rccEnableAPB1(RCC_APB1ENR_UART4EN, lp) - -/** - * @brief Disables the UART4 peripheral clock. - * @note The @p lp parameter is ignored in this family. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccDisableUART4(lp) rccDisableAPB1(RCC_APB1ENR_UART4EN, lp) - -/** - * @brief Resets the UART4 peripheral. - * - * @api - */ -#define rccResetUART4() rccResetAPB1(RCC_APB1RSTR_UART4RST) - -/** - * @brief Enables the UART5 peripheral clock. - * @note The @p lp parameter is ignored in this family. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccEnableUART5(lp) rccEnableAPB1(RCC_APB1ENR_UART5EN, lp) - -/** - * @brief Disables the UART5 peripheral clock. - * @note The @p lp parameter is ignored in this family. - * - * @param[in] lp low power enable flag - * - * @api - */ -#define rccDisableUART5(lp) rccDisableAPB1(RCC_APB1ENR_UART5EN, lp) - -/** - * @brief Resets the UART5 peripheral. - * - * @api - */ -#define rccResetUART5() rccResetAPB1(RCC_APB1RSTR_UART5RST) - -/** - * @brief Resets the USART6 peripheral. - * - * @api - */ -#define rccResetUSART6() rccResetAPB2(RCC_APB2RSTR_USART6RST) -/** @} */ - -/*===========================================================================*/ -/* External declarations. */ -/*===========================================================================*/ - -#ifdef __cplusplus -extern "C" { -#endif -#ifdef __cplusplus -} -#endif - -#endif /* _STM32_RCC_ */ - -/** @} */ diff --git a/os/hal/platforms/STM32F4xx/stm32_registry.h b/os/hal/platforms/STM32F4xx/stm32_registry.h deleted file mode 100644 index ba462175c..000000000 --- a/os/hal/platforms/STM32F4xx/stm32_registry.h +++ /dev/null @@ -1,265 +0,0 @@ -/* - ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file STM32F4xx/stm32_registry.h - * @brief STM32F4xx capabilities registry. - * - * @addtogroup HAL - * @{ - */ - -#ifndef _STM32_REGISTRY_H_ -#define _STM32_REGISTRY_H_ - -#if defined(STM32F40XX) || defined(STM32F427X) -#define STM32F4XX -#endif - -/*===========================================================================*/ -/* Platform capabilities. */ -/*===========================================================================*/ - -/** - * @name STM32F30x capabilities - * @{ - */ -/* ADC attributes.*/ -#define STM32_HAS_ADC1 TRUE -#define STM32_ADC1_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 0) |\ - STM32_DMA_STREAM_ID_MSK(2, 4)) -#define STM32_ADC1_DMA_CHN 0x00000000 - -#define STM32_HAS_ADC2 TRUE -#define STM32_ADC2_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 2) |\ - STM32_DMA_STREAM_ID_MSK(2, 3)) -#define STM32_ADC2_DMA_CHN 0x00001100 - -#define STM32_HAS_ADC3 TRUE -#define STM32_ADC3_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 0) |\ - STM32_DMA_STREAM_ID_MSK(2, 1)) -#define STM32_ADC3_DMA_CHN 0x00000022 - -#define STM32_HAS_ADC4 FALSE - -#define STM32_HAS_SDADC1 FALSE -#define STM32_HAS_SDADC2 FALSE -#define STM32_HAS_SDADC3 FALSE - -/* CAN attributes.*/ -#define STM32_HAS_CAN1 TRUE -#define STM32_HAS_CAN2 TRUE -#define STM32_CAN_MAX_FILTERS 28 - -/* DAC attributes.*/ -#define STM32_HAS_DAC1 TRUE -#define STM32_HAS_DAC2 FALSE - -/* DMA attributes.*/ -#define STM32_ADVANCED_DMA TRUE -#define STM32_HAS_DMA1 TRUE -#define STM32_HAS_DMA2 TRUE - -/* ETH attributes.*/ -#define STM32_HAS_ETH TRUE - -/* EXTI attributes.*/ -#define STM32_EXTI_NUM_CHANNELS 23 - -/* GPIO attributes.*/ -#define STM32_HAS_GPIOA TRUE -#define STM32_HAS_GPIOB TRUE -#define STM32_HAS_GPIOC TRUE -#define STM32_HAS_GPIOD TRUE -#define STM32_HAS_GPIOE TRUE -#define STM32_HAS_GPIOF TRUE -#define STM32_HAS_GPIOG TRUE -#define STM32_HAS_GPIOH TRUE -#define STM32_HAS_GPIOI TRUE - -/* I2C attributes.*/ -#define STM32_HAS_I2C1 TRUE -#define STM32_I2C1_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 0) |\ - STM32_DMA_STREAM_ID_MSK(1, 5)) -#define STM32_I2C1_RX_DMA_CHN 0x00100001 -#define STM32_I2C1_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 7) |\ - STM32_DMA_STREAM_ID_MSK(1, 6)) -#define STM32_I2C1_TX_DMA_CHN 0x11000000 - -#define STM32_HAS_I2C2 TRUE -#define STM32_I2C2_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 2) |\ - STM32_DMA_STREAM_ID_MSK(1, 3)) -#define STM32_I2C2_RX_DMA_CHN 0x00007700 -#define STM32_I2C2_TX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 7) -#define STM32_I2C2_TX_DMA_CHN 0x70000000 - -#define STM32_HAS_I2C3 TRUE -#define STM32_I2C3_RX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 2) -#define STM32_I2C3_RX_DMA_CHN 0x00000300 -#define STM32_I2C3_TX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 4) -#define STM32_I2C3_TX_DMA_CHN 0x00030000 - -/* RTC attributes.*/ -#define STM32_HAS_RTC TRUE -#if defined(STM32F4XX) || defined(__DOXYGEN__) -#define STM32_RTC_HAS_SUBSECONDS TRUE -#else -#define STM32_RTC_HAS_SUBSECONDS FALSE -#endif -#define STM32_RTC_IS_CALENDAR TRUE - -/* SDIO attributes.*/ -#define STM32_HAS_SDIO TRUE -#define STM32_SDC_SDIO_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 3) |\ - STM32_DMA_STREAM_ID_MSK(2, 6)) -#define STM32_SDC_SDIO_DMA_CHN 0x04004000 - -/* SPI attributes.*/ -#define STM32_HAS_SPI1 TRUE -#define STM32_SPI1_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 0) |\ - STM32_DMA_STREAM_ID_MSK(2, 2)) -#define STM32_SPI1_RX_DMA_CHN 0x00000303 -#define STM32_SPI1_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 3) |\ - STM32_DMA_STREAM_ID_MSK(2, 5)) -#define STM32_SPI1_TX_DMA_CHN 0x00303000 - -#define STM32_HAS_SPI2 TRUE -#define STM32_SPI2_RX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 3) -#define STM32_SPI2_RX_DMA_CHN 0x00000000 -#define STM32_SPI2_TX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 4) -#define STM32_SPI2_TX_DMA_CHN 0x00000000 - -#define STM32_HAS_SPI3 TRUE -#define STM32_SPI3_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 0) |\ - STM32_DMA_STREAM_ID_MSK(1, 2)) -#define STM32_SPI3_RX_DMA_CHN 0x00000000 -#define STM32_SPI3_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 5) |\ - STM32_DMA_STREAM_ID_MSK(1, 7)) -#define STM32_SPI3_TX_DMA_CHN 0x00000000 - -/* TIM attributes.*/ -#define STM32_HAS_TIM1 TRUE -#define STM32_TIM1_IS_32BITS FALSE -#define STM32_TIM1_CHANNELS 4 - -#define STM32_HAS_TIM2 TRUE -#define STM32_TIM2_IS_32BITS TRUE -#define STM32_TIM2_CHANNELS 4 - -#define STM32_HAS_TIM3 TRUE -#define STM32_TIM3_IS_32BITS FALSE -#define STM32_TIM3_CHANNELS 4 - -#define STM32_HAS_TIM4 TRUE -#define STM32_TIM4_IS_32BITS FALSE -#define STM32_TIM4_CHANNELS 4 - -#define STM32_HAS_TIM5 TRUE -#define STM32_TIM5_IS_32BITS TRUE -#define STM32_TIM5_CHANNELS 4 - -#define STM32_HAS_TIM6 TRUE -#define STM32_TIM6_IS_32BITS FALSE -#define STM32_TIM6_CHANNELS 0 - -#define STM32_HAS_TIM7 TRUE -#define STM32_TIM7_IS_32BITS FALSE -#define STM32_TIM7_CHANNELS 0 - -#define STM32_HAS_TIM8 TRUE -#define STM32_TIM8_IS_32BITS FALSE -#define STM32_TIM8_CHANNELS 6 - -#define STM32_HAS_TIM9 TRUE -#define STM32_TIM9_IS_32BITS FALSE -#define STM32_TIM9_CHANNELS 2 - -#define STM32_HAS_TIM10 TRUE -#define STM32_TIM10_IS_32BITS FALSE -#define STM32_TIM10_CHANNELS 2 - -#define STM32_HAS_TIM11 TRUE -#define STM32_TIM11_IS_32BITS FALSE -#define STM32_TIM11_CHANNELS 2 - -#define STM32_HAS_TIM12 TRUE -#define STM32_TIM12_IS_32BITS FALSE -#define STM32_TIM12_CHANNELS 2 - -#define STM32_HAS_TIM13 TRUE -#define STM32_TIM13_IS_32BITS FALSE -#define STM32_TIM13_CHANNELS 2 - -#define STM32_HAS_TIM14 TRUE -#define STM32_TIM14_IS_32BITS FALSE -#define STM32_TIM14_CHANNELS 2 - -#define STM32_HAS_TIM15 FALSE -#define STM32_HAS_TIM16 FALSE -#define STM32_HAS_TIM17 FALSE -#define STM32_HAS_TIM18 FALSE -#define STM32_HAS_TIM19 FALSE - -/* USART attributes.*/ -#define STM32_HAS_USART1 TRUE -#define STM32_USART1_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 2) |\ - STM32_DMA_STREAM_ID_MSK(2, 5)) -#define STM32_USART1_RX_DMA_CHN 0x00400400 -#define STM32_USART1_TX_DMA_MSK STM32_DMA_STREAM_ID_MSK(2, 7) -#define STM32_USART1_TX_DMA_CHN 0x40000000 - -#define STM32_HAS_USART2 TRUE -#define STM32_USART2_RX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 5) -#define STM32_USART2_RX_DMA_CHN 0x00400000 -#define STM32_USART2_TX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 6) -#define STM32_USART2_TX_DMA_CHN 0x04000000 - -#define STM32_HAS_USART3 TRUE -#define STM32_USART3_RX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 1) -#define STM32_USART3_RX_DMA_CHN 0x00000040 -#define STM32_USART3_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 3) |\ - STM32_DMA_STREAM_ID_MSK(1, 4)) -#define STM32_USART3_TX_DMA_CHN 0x00074000 - -#define STM32_HAS_UART4 TRUE -#define STM32_UART4_RX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 2) -#define STM32_UART4_RX_DMA_CHN 0x00000400 -#define STM32_UART4_TX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 4) -#define STM32_UART4_TX_DMA_CHN 0x00040000 - -#define STM32_HAS_UART5 TRUE -#define STM32_UART5_RX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 0) -#define STM32_UART5_RX_DMA_CHN 0x00000004 -#define STM32_UART5_TX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 7) -#define STM32_UART5_TX_DMA_CHN 0x40000000 - -#define STM32_HAS_USART6 TRUE -#define STM32_USART6_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 1) |\ - STM32_DMA_STREAM_ID_MSK(2, 2)) -#define STM32_USART6_RX_DMA_CHN 0x00000550 -#define STM32_USART6_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 6) |\ - STM32_DMA_STREAM_ID_MSK(2, 7)) -#define STM32_USART6_TX_DMA_CHN 0x55000000 - -/* USB attributes.*/ -#define STM32_HAS_USB FALSE -#define STM32_HAS_OTG1 TRUE -#define STM32_HAS_OTG2 TRUE -/** @} */ - -#endif /* _STM32_REGISTRY_H_ */ - -/** @} */ diff --git a/os/hal/platforms/common/ARMCMx/nvic.c b/os/hal/platforms/common/ARMCMx/nvic.c deleted file mode 100644 index c45366396..000000000 --- a/os/hal/platforms/common/ARMCMx/nvic.c +++ /dev/null @@ -1,89 +0,0 @@ -/* - ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file common/ARMCMx/nvic.c - * @brief Cortex-Mx NVIC support code. - * - * @addtogroup COMMON_ARMCMx_NVIC - * @{ - */ - -#include "hal.h" - -/*===========================================================================*/ -/* Driver local definitions. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver exported variables. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver local types. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver local variables. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver local functions. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver exported functions. */ -/*===========================================================================*/ - -/** - * @brief Sets the priority of an interrupt handler and enables it. - * @note The parameters are not tested for correctness. - * - * @param[in] n the interrupt number - * @param[in] prio the interrupt priority mask - */ -void nvicEnableVector(IRQn_Type n, uint32_t prio) { - - NVIC->IP[n] = NVIC_PRIORITY_MASK(prio); - NVIC->ICPR[n >> 5] = 1 << (n & 0x1F); - NVIC->ISER[n >> 5] = 1 << (n & 0x1F); -} - -/** - * @brief Disables an interrupt handler. - * @note The parameters are not tested for correctness. - * - * @param[in] n the interrupt number - */ -void nvicDisableVector(IRQn_Type n) { - - NVIC->ICER[n >> 5] = 1 << (n & 0x1F); - NVIC->IP[n] = 0; -} - -/** - * @brief Changes the priority of a system handler. - * @note The parameters are not tested for correctness. - * - * @param[in] handler the system handler number - * @param[in] prio the system handler priority mask - */ -void nvicSetSystemHandlerPriority(IRQn_Type handler, uint32_t prio) { - - SCB->SHP[((uint32_t)(handler) & 15) - 4] = NVIC_PRIORITY_MASK(prio); -} - -/** @} */ diff --git a/os/hal/platforms/common/ARMCMx/nvic.h b/os/hal/platforms/common/ARMCMx/nvic.h deleted file mode 100644 index 82fde801c..000000000 --- a/os/hal/platforms/common/ARMCMx/nvic.h +++ /dev/null @@ -1,69 +0,0 @@ -/* - ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file common/ARMCMx/nvic.h - * @brief Cortex-Mx NVIC support macros and structures. - * - * @addtogroup COMMON_ARMCMx_NVIC - * @{ - */ - -#ifndef _NVIC_H_ -#define _NVIC_H_ - -/*===========================================================================*/ -/* Driver constants. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver pre-compile time settings. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Derived constants and error checks. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver data structures and types. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver macros. */ -/*===========================================================================*/ - -/** - * @brief Priority level to priority mask conversion macro. - */ -#define NVIC_PRIORITY_MASK(prio) ((prio) << (8 - __NVIC_PRIO_BITS)) - -/*===========================================================================*/ -/* External declarations. */ -/*===========================================================================*/ - -#ifdef __cplusplus -extern "C" { -#endif - void nvicEnableVector(IRQn_Type n, uint32_t prio); - void nvicDisableVector(IRQn_Type n); - void nvicSetSystemHandlerPriority(IRQn_Type handler, uint32_t prio); -#ifdef __cplusplus -} -#endif - -#endif /* _NVIC_H_ */ - -/** @} */ diff --git a/os/hal/ports/STM32/GPIOv1/pal_lld.c b/os/hal/ports/STM32/GPIOv1/pal_lld.c new file mode 100644 index 000000000..31eec7883 --- /dev/null +++ b/os/hal/ports/STM32/GPIOv1/pal_lld.c @@ -0,0 +1,184 @@ +/* + ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file STM32/GPIOv1/pal_lld.c + * @brief STM32F1xx GPIO low level driver code. + * + * @addtogroup PAL + * @{ + */ + +#include "ch.h" +#include "hal.h" + +#if HAL_USE_PAL || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver local definitions. */ +/*===========================================================================*/ + +#if STM32_HAS_GPIOG +#define APB2_EN_MASK (RCC_APB2ENR_IOPAEN | RCC_APB2ENR_IOPBEN | \ + RCC_APB2ENR_IOPCEN | RCC_APB2ENR_IOPDEN | \ + RCC_APB2ENR_IOPEEN | RCC_APB2ENR_IOPFEN | \ + RCC_APB2ENR_IOPGEN | RCC_APB2ENR_AFIOEN) +#elif STM32_HAS_GPIOE +#define APB2_EN_MASK (RCC_APB2ENR_IOPAEN | RCC_APB2ENR_IOPBEN | \ + RCC_APB2ENR_IOPCEN | RCC_APB2ENR_IOPDEN | \ + RCC_APB2ENR_IOPEEN | RCC_APB2ENR_AFIOEN) +#else +#define APB2_EN_MASK (RCC_APB2ENR_IOPAEN | RCC_APB2ENR_IOPBEN | \ + RCC_APB2ENR_IOPCEN | RCC_APB2ENR_IOPDEN | \ + RCC_APB2ENR_AFIOEN) +#endif + +/*===========================================================================*/ +/* Driver exported variables. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local variables and types. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local functions. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver interrupt handlers. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver exported functions. */ +/*===========================================================================*/ + +/** + * @brief STM32 I/O ports configuration. + * @details Ports A-D(E, F, G) clocks enabled, AFIO clock enabled. + * + * @param[in] config the STM32 ports configuration + * + * @notapi + */ +void _pal_lld_init(const PALConfig *config) { + + /* + * Enables the GPIO related clocks. + */ + rccEnableAPB2(APB2_EN_MASK, FALSE); + + /* + * Initial GPIO setup. + */ + GPIOA->ODR = config->PAData.odr; + GPIOA->CRH = config->PAData.crh; + GPIOA->CRL = config->PAData.crl; + GPIOB->ODR = config->PBData.odr; + GPIOB->CRH = config->PBData.crh; + GPIOB->CRL = config->PBData.crl; + GPIOC->ODR = config->PCData.odr; + GPIOC->CRH = config->PCData.crh; + GPIOC->CRL = config->PCData.crl; + GPIOD->ODR = config->PDData.odr; + GPIOD->CRH = config->PDData.crh; + GPIOD->CRL = config->PDData.crl; +#if STM32_HAS_GPIOE || defined(__DOXYGEN__) + GPIOE->ODR = config->PEData.odr; + GPIOE->CRH = config->PEData.crh; + GPIOE->CRL = config->PEData.crl; +#if STM32_HAS_GPIOF || defined(__DOXYGEN__) + GPIOF->ODR = config->PFData.odr; + GPIOF->CRH = config->PFData.crh; + GPIOF->CRL = config->PFData.crl; +#if STM32_HAS_GPIOG || defined(__DOXYGEN__) + GPIOG->ODR = config->PGData.odr; + GPIOG->CRH = config->PGData.crh; + GPIOG->CRL = config->PGData.crl; +#endif +#endif +#endif +} + +/** + * @brief Pads mode setup. + * @details This function programs a pads group belonging to the same port + * with the specified mode. + * @note @p PAL_MODE_UNCONNECTED is implemented as push pull output at 2MHz. + * @note Writing on pads programmed as pull-up or pull-down has the side + * effect to modify the resistor setting because the output latched + * data is used for the resistor selection. + * + * @param[in] port the port identifier + * @param[in] mask the group mask + * @param[in] mode the mode + * + * @notapi + */ +void _pal_lld_setgroupmode(ioportid_t port, + ioportmask_t mask, + iomode_t mode) { + static const uint8_t cfgtab[] = { + 4, /* PAL_MODE_RESET, implemented as input.*/ + 2, /* PAL_MODE_UNCONNECTED, implemented as push pull output 2MHz.*/ + 4, /* PAL_MODE_INPUT */ + 8, /* PAL_MODE_INPUT_PULLUP */ + 8, /* PAL_MODE_INPUT_PULLDOWN */ + 0, /* PAL_MODE_INPUT_ANALOG */ + 3, /* PAL_MODE_OUTPUT_PUSHPULL, 50MHz.*/ + 7, /* PAL_MODE_OUTPUT_OPENDRAIN, 50MHz.*/ + 8, /* Reserved.*/ + 8, /* Reserved.*/ + 8, /* Reserved.*/ + 8, /* Reserved.*/ + 8, /* Reserved.*/ + 8, /* Reserved.*/ + 8, /* Reserved.*/ + 8, /* Reserved.*/ + 0xB, /* PAL_MODE_STM32_ALTERNATE_PUSHPULL, 50MHz.*/ + 0xF, /* PAL_MODE_STM32_ALTERNATE_OPENDRAIN, 50MHz.*/ + }; + uint32_t mh, ml, crh, crl, cfg; + unsigned i; + + if (mode == PAL_MODE_INPUT_PULLUP) + port->BSRR = mask; + else if (mode == PAL_MODE_INPUT_PULLDOWN) + port->BRR = mask; + cfg = cfgtab[mode]; + mh = ml = crh = crl = 0; + for (i = 0; i < 8; i++) { + ml <<= 4; + mh <<= 4; + crl <<= 4; + crh <<= 4; + if ((mask & 0x0080) == 0) + ml |= 0xf; + else + crl |= cfg; + if ((mask & 0x8000) == 0) + mh |= 0xf; + else + crh |= cfg; + mask <<= 1; + } + port->CRH = (port->CRH & mh) | crh; + port->CRL = (port->CRL & ml) | crl; +} + +#endif /* HAL_USE_PAL */ + +/** @} */ diff --git a/os/hal/ports/STM32/GPIOv1/pal_lld.h b/os/hal/ports/STM32/GPIOv1/pal_lld.h new file mode 100644 index 000000000..56255ed1a --- /dev/null +++ b/os/hal/ports/STM32/GPIOv1/pal_lld.h @@ -0,0 +1,334 @@ +/* + ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file STM32/GPIOv1/pal_lld.h + * @brief STM32F1xx GPIO low level driver header. + * + * @addtogroup PAL + * @{ + */ + +#ifndef _PAL_LLD_H_ +#define _PAL_LLD_H_ + +#if HAL_USE_PAL || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Unsupported modes and specific modes */ +/*===========================================================================*/ + +/** + * @name STM32-specific I/O mode flags + * @{ + */ +/** + * @brief STM32 specific alternate push-pull output mode. + */ +#define PAL_MODE_STM32_ALTERNATE_PUSHPULL 16 + +/** + * @brief STM32 specific alternate open-drain output mode. + */ +#define PAL_MODE_STM32_ALTERNATE_OPENDRAIN 17 +/** @} */ + +/*===========================================================================*/ +/* I/O Ports Types and constants. */ +/*===========================================================================*/ + +/** + * @brief GPIO port setup info. + */ +typedef struct { + /** Initial value for ODR register.*/ + uint32_t odr; + /** Initial value for CRL register.*/ + uint32_t crl; + /** Initial value for CRH register.*/ + uint32_t crh; +} stm32_gpio_setup_t; + +/** + * @brief STM32 GPIO static initializer. + * @details An instance of this structure must be passed to @p palInit() at + * system startup time in order to initialize the digital I/O + * subsystem. This represents only the initial setup, specific pads + * or whole ports can be reprogrammed at later time. + */ +typedef struct { + /** @brief Port A setup data.*/ + stm32_gpio_setup_t PAData; + /** @brief Port B setup data.*/ + stm32_gpio_setup_t PBData; + /** @brief Port C setup data.*/ + stm32_gpio_setup_t PCData; + /** @brief Port D setup data.*/ + stm32_gpio_setup_t PDData; +#if STM32_HAS_GPIOE || defined(__DOXYGEN__) + /** @brief Port E setup data.*/ + stm32_gpio_setup_t PEData; +#if STM32_HAS_GPIOF || defined(__DOXYGEN__) + /** @brief Port F setup data.*/ + stm32_gpio_setup_t PFData; +#if STM32_HAS_GPIOG || defined(__DOXYGEN__) + /** @brief Port G setup data.*/ + stm32_gpio_setup_t PGData; +#endif +#endif +#endif +} PALConfig; + +/** + * @brief Width, in bits, of an I/O port. + */ +#define PAL_IOPORTS_WIDTH 16 + +/** + * @brief Whole port mask. + * @details This macro specifies all the valid bits into a port. + */ +#define PAL_WHOLE_PORT ((ioportmask_t)0xFFFF) + +/** + * @brief Digital I/O port sized unsigned type. + */ +typedef uint32_t ioportmask_t; + +/** + * @brief Digital I/O modes. + */ +typedef uint32_t iomode_t; + +/** + * @brief Port Identifier. + * @details This type can be a scalar or some kind of pointer, do not make + * any assumption about it, use the provided macros when populating + * variables of this type. + */ +typedef GPIO_TypeDef * ioportid_t; + +/*===========================================================================*/ +/* I/O Ports Identifiers. */ +/* The low level driver wraps the definitions already present in the STM32 */ +/* firmware library. */ +/*===========================================================================*/ + +/** + * @brief GPIO port A identifier. + */ +#if STM32_HAS_GPIOA || defined(__DOXYGEN__) +#define IOPORT1 GPIOA +#endif + +/** + * @brief GPIO port B identifier. + */ +#if STM32_HAS_GPIOB || defined(__DOXYGEN__) +#define IOPORT2 GPIOB +#endif + +/** + * @brief GPIO port C identifier. + */ +#if STM32_HAS_GPIOC || defined(__DOXYGEN__) +#define IOPORT3 GPIOC +#endif + +/** + * @brief GPIO port D identifier. + */ +#if STM32_HAS_GPIOD || defined(__DOXYGEN__) +#define IOPORT4 GPIOD +#endif + +/** + * @brief GPIO port E identifier. + */ +#if STM32_HAS_GPIOE || defined(__DOXYGEN__) +#define IOPORT5 GPIOE +#endif + +/** + * @brief GPIO port F identifier. + */ +#if STM32_HAS_GPIOF || defined(__DOXYGEN__) +#define IOPORT6 GPIOF +#endif + +/** + * @brief GPIO port G identifier. + */ +#if STM32_HAS_GPIOG || defined(__DOXYGEN__) +#define IOPORT7 GPIOG +#endif + +/*===========================================================================*/ +/* Implementation, some of the following macros could be implemented as */ +/* functions, if so please put them in pal_lld.c. */ +/*===========================================================================*/ + +/** + * @brief GPIO ports subsystem initialization. + * + * @notapi + */ +#define pal_lld_init(config) _pal_lld_init(config) + +/** + * @brief Reads an I/O port. + * @details This function is implemented by reading the GPIO IDR register, the + * implementation has no side effects. + * @note This function is not meant to be invoked directly by the application + * code. + * + * @param[in] port port identifier + * @return The port bits. + * + * @notapi + */ +#define pal_lld_readport(port) ((port)->IDR) + +/** + * @brief Reads the output latch. + * @details This function is implemented by reading the GPIO ODR register, the + * implementation has no side effects. + * @note This function is not meant to be invoked directly by the application + * code. + * + * @param[in] port port identifier + * @return The latched logical states. + * + * @notapi + */ +#define pal_lld_readlatch(port) ((port)->ODR) + +/** + * @brief Writes on a I/O port. + * @details This function is implemented by writing the GPIO ODR register, the + * implementation has no side effects. + * @note Writing on pads programmed as pull-up or pull-down has the side + * effect to modify the resistor setting because the output latched + * data is used for the resistor selection. + * + * @param[in] port port identifier + * @param[in] bits bits to be written on the specified port + * + * @notapi + */ +#define pal_lld_writeport(port, bits) ((port)->ODR = (bits)) + +/** + * @brief Sets a bits mask on a I/O port. + * @details This function is implemented by writing the GPIO BSRR register, the + * implementation has no side effects. + * @note Writing on pads programmed as pull-up or pull-down has the side + * effect to modify the resistor setting because the output latched + * data is used for the resistor selection. + * + * @param[in] port port identifier + * @param[in] bits bits to be ORed on the specified port + * + * @notapi + */ +#define pal_lld_setport(port, bits) ((port)->BSRR = (bits)) + +/** + * @brief Clears a bits mask on a I/O port. + * @details This function is implemented by writing the GPIO BRR register, the + * implementation has no side effects. + * @note Writing on pads programmed as pull-up or pull-down has the side + * effect to modify the resistor setting because the output latched + * data is used for the resistor selection. + * + * @param[in] port port identifier + * @param[in] bits bits to be cleared on the specified port + * + * @notapi + */ +#define pal_lld_clearport(port, bits) ((port)->BRR = (bits)) + +/** + * @brief Writes a group of bits. + * @details This function is implemented by writing the GPIO BSRR register, the + * implementation has no side effects. + * @note Writing on pads programmed as pull-up or pull-down has the side + * effect to modify the resistor setting because the output latched + * data is used for the resistor selection. + * + * @param[in] port port identifier + * @param[in] mask group mask + * @param[in] offset the group bit offset within the port + * @param[in] bits bits to be written. Values exceeding the group + * width are masked. + * + * @notapi + */ +#define pal_lld_writegroup(port, mask, offset, bits) \ + ((port)->BSRR = ((~(bits) & (mask)) << (16 + (offset))) | \ + (((bits) & (mask)) << (offset))) + +/** + * @brief Pads group mode setup. + * @details This function programs a pads group belonging to the same port + * with the specified mode. + * @note Writing on pads programmed as pull-up or pull-down has the side + * effect to modify the resistor setting because the output latched + * data is used for the resistor selection. + * + * @param[in] port port identifier + * @param[in] mask group mask + * @param[in] offset group bit offset within the port + * @param[in] mode group mode + * + * @notapi + */ +#define pal_lld_setgroupmode(port, mask, offset, mode) \ + _pal_lld_setgroupmode(port, mask << offset, mode) + +/** + * @brief Writes a logical state on an output pad. + * @note Writing on pads programmed as pull-up or pull-down has the side + * effect to modify the resistor setting because the output latched + * data is used for the resistor selection. + * + * @param[in] port port identifier + * @param[in] pad pad number within the port + * @param[in] bit logical value, the value must be @p PAL_LOW or + * @p PAL_HIGH + * + * @notapi + */ +#define pal_lld_writepad(port, pad, bit) pal_lld_writegroup(port, 1, pad, bit) + +extern const PALConfig pal_default_config; + +#ifdef __cplusplus +extern "C" { +#endif + void _pal_lld_init(const PALConfig *config); + void _pal_lld_setgroupmode(ioportid_t port, + ioportmask_t mask, + iomode_t mode); +#ifdef __cplusplus +} +#endif + +#endif /* HAL_USE_PAL */ + +#endif /* _PAL_LLD_H_ */ + +/** @} */ diff --git a/os/hal/ports/STM32/GPIOv2/pal_lld.c b/os/hal/ports/STM32/GPIOv2/pal_lld.c new file mode 100644 index 000000000..017b340a0 --- /dev/null +++ b/os/hal/ports/STM32/GPIOv2/pal_lld.c @@ -0,0 +1,237 @@ +/* + ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file STM32/GPIOv2/pal_lld.c + * @brief STM32L1xx/STM32F2xx/STM32F4xx GPIO low level driver code. + * + * @addtogroup PAL + * @{ + */ + +#include "hal.h" + +#if HAL_USE_PAL || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver local definitions. */ +/*===========================================================================*/ + +#if defined(STM32L1XX_MD) +#define AHB_EN_MASK (RCC_AHBENR_GPIOAEN | RCC_AHBENR_GPIOBEN | \ + RCC_AHBENR_GPIOCEN | RCC_AHBENR_GPIODEN | \ + RCC_AHBENR_GPIOEEN | RCC_AHBENR_GPIOHEN) +#define AHB_LPEN_MASK AHB_EN_MASK +#elif defined(STM32F0XX) +#define AHB_EN_MASK (RCC_AHBENR_GPIOAEN | RCC_AHBENR_GPIOBEN | \ + RCC_AHBENR_GPIOCEN | RCC_AHBENR_GPIODEN | \ + RCC_AHBENR_GPIOFEN) +#elif defined(STM32F2XX) +#define AHB1_EN_MASK (RCC_AHB1ENR_GPIOAEN | RCC_AHB1ENR_GPIOBEN | \ + RCC_AHB1ENR_GPIOCEN | RCC_AHB1ENR_GPIODEN | \ + RCC_AHB1ENR_GPIOEEN | RCC_AHB1ENR_GPIOFEN | \ + RCC_AHB1ENR_GPIOGEN | RCC_AHB1ENR_GPIOHEN | \ + RCC_AHB1ENR_GPIOIEN) +#define AHB1_LPEN_MASK AHB1_EN_MASK +#elif defined(STM32F30X) || defined(STM32F37X) +#define AHB_EN_MASK (RCC_AHBENR_GPIOAEN | RCC_AHBENR_GPIOBEN | \ + RCC_AHBENR_GPIOCEN | RCC_AHBENR_GPIODEN | \ + RCC_AHBENR_GPIOEEN | RCC_AHBENR_GPIOFEN) +#elif defined(STM32F4XX) +#define AHB1_EN_MASK (RCC_AHB1ENR_GPIOAEN | RCC_AHB1ENR_GPIOBEN | \ + RCC_AHB1ENR_GPIOCEN | RCC_AHB1ENR_GPIODEN | \ + RCC_AHB1ENR_GPIOEEN | RCC_AHB1ENR_GPIOFEN | \ + RCC_AHB1ENR_GPIOGEN | RCC_AHB1ENR_GPIOHEN | \ + RCC_AHB1ENR_GPIOIEN) +#define AHB1_LPEN_MASK AHB1_EN_MASK +#else +#error "missing or unsupported platform for GPIOv2 PAL driver" +#endif + +/*===========================================================================*/ +/* Driver exported variables. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local variables and types. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local functions. */ +/*===========================================================================*/ + +static void initgpio(stm32_gpio_t *gpiop, const stm32_gpio_setup_t *config) { + + gpiop->OTYPER = config->otyper; + gpiop->OSPEEDR = config->ospeedr; + gpiop->PUPDR = config->pupdr; + gpiop->ODR = config->odr; + gpiop->AFRL = config->afrl; + gpiop->AFRH = config->afrh; + gpiop->MODER = config->moder; +} + +/*===========================================================================*/ +/* Driver interrupt handlers. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver exported functions. */ +/*===========================================================================*/ + +/** + * @brief STM32 I/O ports configuration. + * @details Ports A-D(E, F, G, H) clocks enabled. + * + * @param[in] config the STM32 ports configuration + * + * @notapi + */ +void _pal_lld_init(const PALConfig *config) { + + /* + * Enables the GPIO related clocks. + */ +#if defined(STM32L1XX_MD) + rccEnableAHB(AHB_EN_MASK, TRUE); + RCC->AHBLPENR |= AHB_LPEN_MASK; +#elif defined(STM32F0XX) + rccEnableAHB(AHB_EN_MASK, TRUE); +#elif defined(STM32F30X) || defined(STM32F37X) + rccEnableAHB(AHB_EN_MASK, TRUE); +#elif defined(STM32F2XX) || defined(STM32F4XX) + RCC->AHB1ENR |= AHB1_EN_MASK; + RCC->AHB1LPENR |= AHB1_LPEN_MASK; +#endif + + /* + * Initial GPIO setup. + */ + initgpio(GPIOA, &config->PAData); + initgpio(GPIOB, &config->PBData); + initgpio(GPIOC, &config->PCData); + initgpio(GPIOD, &config->PDData); +#if STM32_HAS_GPIOE + initgpio(GPIOE, &config->PEData); +#endif +#if STM32_HAS_GPIOF + initgpio(GPIOF, &config->PFData); +#endif +#if STM32_HAS_GPIOG + initgpio(GPIOG, &config->PGData); +#endif +#if STM32_HAS_GPIOH + initgpio(GPIOH, &config->PHData); +#endif +#if STM32_HAS_GPIOI + initgpio(GPIOI, &config->PIData); +#endif +} + +/** + * @brief Pads mode setup. + * @details This function programs a pads group belonging to the same port + * with the specified mode. + * @note @p PAL_MODE_UNCONNECTED is implemented as push pull at minimum + * speed. + * + * @param[in] port the port identifier + * @param[in] mask the group mask + * @param[in] mode the mode + * + * @notapi + */ +#if 1 +void _pal_lld_setgroupmode(ioportid_t port, + ioportmask_t mask, + iomode_t mode) { + + uint32_t moder = (mode & PAL_STM32_MODE_MASK) >> 0; + uint32_t otyper = (mode & PAL_STM32_OTYPE_MASK) >> 2; + uint32_t ospeedr = (mode & PAL_STM32_OSPEED_MASK) >> 3; + uint32_t pupdr = (mode & PAL_STM32_PUDR_MASK) >> 5; + uint32_t altr = (mode & PAL_STM32_ALTERNATE_MASK) >> 7; + uint32_t bit = 0; + while (TRUE) { + if ((mask & 1) != 0) { + uint32_t altrmask, m1, m2, m4; + + altrmask = altr << ((bit & 7) * 4); + m4 = 15 << ((bit & 7) * 4); + if (bit < 8) + port->AFRL = (port->AFRL & ~m4) | altrmask; + else + port->AFRH = (port->AFRH & ~m4) | altrmask; + m1 = 1 << bit; + port->OTYPER = (port->OTYPER & ~m1) | otyper; + m2 = 3 << (bit * 2); + port->OSPEEDR = (port->OSPEEDR & ~m2) | ospeedr; + port->PUPDR = (port->PUPDR & ~m2) | pupdr; + port->MODER = (port->MODER & ~m2) | moder; + } + mask >>= 1; + if (!mask) + return; + otyper <<= 1; + ospeedr <<= 2; + pupdr <<= 2; + moder <<= 2; + bit++; + } +} +#else +void _pal_lld_setgroupmode(ioportid_t port, + ioportmask_t mask, + iomode_t mode) { + uint32_t afrm, moderm, pupdrm, otyperm, ospeedrm; + uint32_t m1 = (uint32_t)mask; + uint32_t m2 = 0; + uint32_t m4l = 0; + uint32_t m4h = 0; + uint32_t bit = 0; + do { + if ((mask & 1) != 0) { + m2 |= 3 << bit; + if (bit < 16) + m4l |= 15 << ((bit & 14) * 2); + else + m4h |= 15 << ((bit & 14) * 2); + } + bit += 2; + mask >>= 1; + } while (mask); + + afrm = ((mode & PAL_STM32_ALTERNATE_MASK) >> 7) * 0x1111; + port->AFRL = (port->AFRL & ~m4l) | (afrm & m4l); + port->AFRH = (port->AFRH & ~m4h) | (afrm & m4h); + + ospeedrm = ((mode & PAL_STM32_OSPEED_MASK) >> 3) * 0x5555; + port->OSPEEDR = (port->OSPEEDR & ~m2) | (ospeedrm & m2); + + otyperm = ((mode & PAL_STM32_OTYPE_MASK) >> 2) * 0xffff; + port->OTYPER = (port->OTYPER & ~m1) | (otyperm & m1); + + pupdrm = ((mode & PAL_STM32_PUDR_MASK) >> 5) * 0x5555; + port->PUPDR = (port->PUPDR & ~m2) | (pupdrm & m2); + + moderm = ((mode & PAL_STM32_MODE_MASK) >> 0) * 0x5555; + port->MODER = (port->MODER & ~m2) | (moderm & m2); +} +#endif + +#endif /* HAL_USE_PAL */ + +/** @} */ diff --git a/os/hal/ports/STM32/GPIOv2/pal_lld.h b/os/hal/ports/STM32/GPIOv2/pal_lld.h new file mode 100644 index 000000000..5349507df --- /dev/null +++ b/os/hal/ports/STM32/GPIOv2/pal_lld.h @@ -0,0 +1,469 @@ +/* + ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file STM32/GPIOv2/pal_lld.h + * @brief STM32L1xx/STM32F2xx/STM32F4xx GPIO low level driver header. + * + * @addtogroup PAL + * @{ + */ + +#ifndef _PAL_LLD_H_ +#define _PAL_LLD_H_ + +#if HAL_USE_PAL || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Unsupported modes and specific modes */ +/*===========================================================================*/ + +#undef PAL_MODE_RESET +#undef PAL_MODE_UNCONNECTED +#undef PAL_MODE_INPUT +#undef PAL_MODE_INPUT_PULLUP +#undef PAL_MODE_INPUT_PULLDOWN +#undef PAL_MODE_INPUT_ANALOG +#undef PAL_MODE_OUTPUT_PUSHPULL +#undef PAL_MODE_OUTPUT_OPENDRAIN + +/** + * @name STM32-specific I/O mode flags + * @{ + */ +#define PAL_STM32_MODE_MASK (3 << 0) +#define PAL_STM32_MODE_INPUT (0 << 0) +#define PAL_STM32_MODE_OUTPUT (1 << 0) +#define PAL_STM32_MODE_ALTERNATE (2 << 0) +#define PAL_STM32_MODE_ANALOG (3 << 0) + +#define PAL_STM32_OTYPE_MASK (1 << 2) +#define PAL_STM32_OTYPE_PUSHPULL (0 << 2) +#define PAL_STM32_OTYPE_OPENDRAIN (1 << 2) + +#define PAL_STM32_OSPEED_MASK (3 << 3) +#define PAL_STM32_OSPEED_LOWEST (0 << 3) +#if defined(STM32F0XX) || defined(STM32F30X) || defined(STM32F37X) +#define PAL_STM32_OSPEED_MID (1 << 3) +#else +#define PAL_STM32_OSPEED_MID1 (1 << 3) +#define PAL_STM32_OSPEED_MID2 (2 << 3) +#endif +#define PAL_STM32_OSPEED_HIGHEST (3 << 3) + +#define PAL_STM32_PUDR_MASK (3 << 5) +#define PAL_STM32_PUDR_FLOATING (0 << 5) +#define PAL_STM32_PUDR_PULLUP (1 << 5) +#define PAL_STM32_PUDR_PULLDOWN (2 << 5) + +#define PAL_STM32_ALTERNATE_MASK (15 << 7) +#define PAL_STM32_ALTERNATE(n) ((n) << 7) + +/** + * @brief Alternate function. + * + * @param[in] n alternate function selector + */ +#define PAL_MODE_ALTERNATE(n) (PAL_STM32_MODE_ALTERNATE | \ + PAL_STM32_ALTERNATE(n)) +/** @} */ + +/** + * @name Standard I/O mode flags + * @{ + */ +/** + * @brief This mode is implemented as input. + */ +#define PAL_MODE_RESET PAL_STM32_MODE_INPUT + +/** + * @brief This mode is implemented as input with pull-up. + */ +#define PAL_MODE_UNCONNECTED PAL_MODE_INPUT_PULLUP + +/** + * @brief Regular input high-Z pad. + */ +#define PAL_MODE_INPUT PAL_STM32_MODE_INPUT + +/** + * @brief Input pad with weak pull up resistor. + */ +#define PAL_MODE_INPUT_PULLUP (PAL_STM32_MODE_INPUT | \ + PAL_STM32_PUDR_PULLUP) + +/** + * @brief Input pad with weak pull down resistor. + */ +#define PAL_MODE_INPUT_PULLDOWN (PAL_STM32_MODE_INPUT | \ + PAL_STM32_PUDR_PULLDOWN) + +/** + * @brief Analog input mode. + */ +#define PAL_MODE_INPUT_ANALOG PAL_STM32_MODE_ANALOG + +/** + * @brief Push-pull output pad. + */ +#define PAL_MODE_OUTPUT_PUSHPULL (PAL_STM32_MODE_OUTPUT | \ + PAL_STM32_OTYPE_PUSHPULL) + +/** + * @brief Open-drain output pad. + */ +#define PAL_MODE_OUTPUT_OPENDRAIN (PAL_STM32_MODE_OUTPUT | \ + PAL_STM32_OTYPE_OPENDRAIN) +/** @} */ + +/** + * @name GPIO ports definitions + * @{ + */ +#define GPIOA ((stm32_gpio_t *)GPIOA_BASE) +#define GPIOB ((stm32_gpio_t *)GPIOB_BASE) +#define GPIOC ((stm32_gpio_t *)GPIOC_BASE) +#define GPIOD ((stm32_gpio_t *)GPIOD_BASE) +#define GPIOE ((stm32_gpio_t *)GPIOE_BASE) +#define GPIOF ((stm32_gpio_t *)GPIOF_BASE) +#define GPIOG ((stm32_gpio_t *)GPIOG_BASE) +#define GPIOH ((stm32_gpio_t *)GPIOH_BASE) +#define GPIOI ((stm32_gpio_t *)GPIOI_BASE) +/** @} */ + +/*===========================================================================*/ +/* I/O Ports Types and constants. */ +/*===========================================================================*/ + +/** + * @brief STM32 GPIO registers block. + */ +typedef struct { + + volatile uint32_t MODER; + volatile uint32_t OTYPER; + volatile uint32_t OSPEEDR; + volatile uint32_t PUPDR; + volatile uint32_t IDR; + volatile uint32_t ODR; + volatile union { + uint32_t W; + struct { + uint16_t set; + uint16_t clear; + } H; + } BSRR; + volatile uint32_t LCKR; + volatile uint32_t AFRL; + volatile uint32_t AFRH; + volatile uint32_t BRR; +} stm32_gpio_t; + +/** + * @brief GPIO port setup info. + */ +typedef struct { + /** Initial value for MODER register.*/ + uint32_t moder; + /** Initial value for OTYPER register.*/ + uint32_t otyper; + /** Initial value for OSPEEDR register.*/ + uint32_t ospeedr; + /** Initial value for PUPDR register.*/ + uint32_t pupdr; + /** Initial value for ODR register.*/ + uint32_t odr; + /** Initial value for AFRL register.*/ + uint32_t afrl; + /** Initial value for AFRH register.*/ + uint32_t afrh; +} stm32_gpio_setup_t; + +/** + * @brief STM32 GPIO static initializer. + * @details An instance of this structure must be passed to @p palInit() at + * system startup time in order to initialize the digital I/O + * subsystem. This represents only the initial setup, specific pads + * or whole ports can be reprogrammed at later time. + */ +typedef struct { + /** @brief Port A setup data.*/ + stm32_gpio_setup_t PAData; + /** @brief Port B setup data.*/ + stm32_gpio_setup_t PBData; + /** @brief Port C setup data.*/ + stm32_gpio_setup_t PCData; + /** @brief Port D setup data.*/ + stm32_gpio_setup_t PDData; +#if STM32_HAS_GPIOE + /** @brief Port E setup data.*/ + stm32_gpio_setup_t PEData; +#endif +#if STM32_HAS_GPIOF + /** @brief Port F setup data.*/ + stm32_gpio_setup_t PFData; +#endif +#if STM32_HAS_GPIOG + /** @brief Port G setup data.*/ + stm32_gpio_setup_t PGData; +#endif +#if STM32_HAS_GPIOH + /** @brief Port H setup data.*/ + stm32_gpio_setup_t PHData; +#endif +#if STM32_HAS_GPIOI + /** @brief Port I setup data.*/ + stm32_gpio_setup_t PIData; +#endif +} PALConfig; + +/** + * @brief Width, in bits, of an I/O port. + */ +#define PAL_IOPORTS_WIDTH 16 + +/** + * @brief Whole port mask. + * @details This macro specifies all the valid bits into a port. + */ +#define PAL_WHOLE_PORT ((ioportmask_t)0xFFFF) + +/** + * @brief Digital I/O port sized unsigned type. + */ +typedef uint32_t ioportmask_t; + +/** + * @brief Digital I/O modes. + */ +typedef uint32_t iomode_t; + +/** + * @brief Port Identifier. + * @details This type can be a scalar or some kind of pointer, do not make + * any assumption about it, use the provided macros when populating + * variables of this type. + */ +typedef stm32_gpio_t * ioportid_t; + +/*===========================================================================*/ +/* I/O Ports Identifiers. */ +/* The low level driver wraps the definitions already present in the STM32 */ +/* firmware library. */ +/*===========================================================================*/ + +/** + * @brief GPIO port A identifier. + */ +#if STM32_HAS_GPIOA || defined(__DOXYGEN__) +#define IOPORT1 GPIOA +#endif + +/** + * @brief GPIO port B identifier. + */ +#if STM32_HAS_GPIOB || defined(__DOXYGEN__) +#define IOPORT2 GPIOB +#endif + +/** + * @brief GPIO port C identifier. + */ +#if STM32_HAS_GPIOC || defined(__DOXYGEN__) +#define IOPORT3 GPIOC +#endif + +/** + * @brief GPIO port D identifier. + */ +#if STM32_HAS_GPIOD || defined(__DOXYGEN__) +#define IOPORT4 GPIOD +#endif + +/** + * @brief GPIO port E identifier. + */ +#if STM32_HAS_GPIOE || defined(__DOXYGEN__) +#define IOPORT5 GPIOE +#endif + +/** + * @brief GPIO port F identifier. + */ +#if STM32_HAS_GPIOF || defined(__DOXYGEN__) +#define IOPORT6 GPIOF +#endif + +/** + * @brief GPIO port G identifier. + */ +#if STM32_HAS_GPIOG || defined(__DOXYGEN__) +#define IOPORT7 GPIOG +#endif + +/** + * @brief GPIO port H identifier. + */ +#if STM32_HAS_GPIOH || defined(__DOXYGEN__) +#define IOPORT8 GPIOH +#endif + +/** + * @brief GPIO port I identifier. + */ +#if STM32_HAS_GPIOI || defined(__DOXYGEN__) +#define IOPORT9 GPIOI +#endif + +/*===========================================================================*/ +/* Implementation, some of the following macros could be implemented as */ +/* functions, if so please put them in pal_lld.c. */ +/*===========================================================================*/ + +/** + * @brief GPIO ports subsystem initialization. + * + * @notapi + */ +#define pal_lld_init(config) _pal_lld_init(config) + +/** + * @brief Reads an I/O port. + * @details This function is implemented by reading the GPIO IDR register, the + * implementation has no side effects. + * @note This function is not meant to be invoked directly by the application + * code. + * + * @param[in] port port identifier + * @return The port bits. + * + * @notapi + */ +#define pal_lld_readport(port) ((port)->IDR) + +/** + * @brief Reads the output latch. + * @details This function is implemented by reading the GPIO ODR register, the + * implementation has no side effects. + * @note This function is not meant to be invoked directly by the application + * code. + * + * @param[in] port port identifier + * @return The latched logical states. + * + * @notapi + */ +#define pal_lld_readlatch(port) ((port)->ODR) + +/** + * @brief Writes on a I/O port. + * @details This function is implemented by writing the GPIO ODR register, the + * implementation has no side effects. + * + * @param[in] port port identifier + * @param[in] bits bits to be written on the specified port + * + * @notapi + */ +#define pal_lld_writeport(port, bits) ((port)->ODR = (bits)) + +/** + * @brief Sets a bits mask on a I/O port. + * @details This function is implemented by writing the GPIO BSRR register, the + * implementation has no side effects. + * + * @param[in] port port identifier + * @param[in] bits bits to be ORed on the specified port + * + * @notapi + */ +#define pal_lld_setport(port, bits) ((port)->BSRR.H.set = (uint16_t)(bits)) + +/** + * @brief Clears a bits mask on a I/O port. + * @details This function is implemented by writing the GPIO BSRR register, the + * implementation has no side effects. + * + * @param[in] port port identifier + * @param[in] bits bits to be cleared on the specified port + * + * @notapi + */ +#define pal_lld_clearport(port, bits) ((port)->BSRR.H.clear = (uint16_t)(bits)) + +/** + * @brief Writes a group of bits. + * @details This function is implemented by writing the GPIO BSRR register, the + * implementation has no side effects. + * + * @param[in] port port identifier + * @param[in] mask group mask + * @param[in] offset the group bit offset within the port + * @param[in] bits bits to be written. Values exceeding the group + * width are masked. + * + * @notapi + */ +#define pal_lld_writegroup(port, mask, offset, bits) \ + ((port)->BSRR.W = ((~(bits) & (mask)) << (16 + (offset))) | \ + (((bits) & (mask)) << (offset))) + +/** + * @brief Pads group mode setup. + * @details This function programs a pads group belonging to the same port + * with the specified mode. + * + * @param[in] port port identifier + * @param[in] mask group mask + * @param[in] offset group bit offset within the port + * @param[in] mode group mode + * + * @notapi + */ +#define pal_lld_setgroupmode(port, mask, offset, mode) \ + _pal_lld_setgroupmode(port, mask << offset, mode) + +/** + * @brief Writes a logical state on an output pad. + * + * @param[in] port port identifier + * @param[in] pad pad number within the port + * @param[in] bit logical value, the value must be @p PAL_LOW or + * @p PAL_HIGH + * + * @notapi + */ +#define pal_lld_writepad(port, pad, bit) pal_lld_writegroup(port, 1, pad, bit) + +extern const PALConfig pal_default_config; + +#ifdef __cplusplus +extern "C" { +#endif + void _pal_lld_init(const PALConfig *config); + void _pal_lld_setgroupmode(ioportid_t port, + ioportmask_t mask, + iomode_t mode); +#ifdef __cplusplus +} +#endif + +#endif /* HAL_USE_PAL */ + +#endif /* _PAL_LLD_H_ */ + +/** @} */ diff --git a/os/hal/ports/STM32/I2Cv1/i2c_lld.c b/os/hal/ports/STM32/I2Cv1/i2c_lld.c new file mode 100644 index 000000000..35c607330 --- /dev/null +++ b/os/hal/ports/STM32/I2Cv1/i2c_lld.c @@ -0,0 +1,849 @@ +/* + ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ +/* + Concepts and parts of this file have been contributed by Uladzimir Pylinsky + aka barthess. + */ + +/** + * @file STM32/I2Cv1/i2c_lld.c + * @brief STM32 I2C subsystem low level driver source. + * + * @addtogroup I2C + * @{ + */ + +#include "hal.h" + +#if HAL_USE_I2C || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver local definitions. */ +/*===========================================================================*/ + +#define I2C1_RX_DMA_CHANNEL \ + STM32_DMA_GETCHANNEL(STM32_I2C_I2C1_RX_DMA_STREAM, \ + STM32_I2C1_RX_DMA_CHN) + +#define I2C1_TX_DMA_CHANNEL \ + STM32_DMA_GETCHANNEL(STM32_I2C_I2C1_TX_DMA_STREAM, \ + STM32_I2C1_TX_DMA_CHN) + +#define I2C2_RX_DMA_CHANNEL \ + STM32_DMA_GETCHANNEL(STM32_I2C_I2C2_RX_DMA_STREAM, \ + STM32_I2C2_RX_DMA_CHN) + +#define I2C2_TX_DMA_CHANNEL \ + STM32_DMA_GETCHANNEL(STM32_I2C_I2C2_TX_DMA_STREAM, \ + STM32_I2C2_TX_DMA_CHN) + +#define I2C3_RX_DMA_CHANNEL \ + STM32_DMA_GETCHANNEL(STM32_I2C_I2C3_RX_DMA_STREAM, \ + STM32_I2C3_RX_DMA_CHN) + +#define I2C3_TX_DMA_CHANNEL \ + STM32_DMA_GETCHANNEL(STM32_I2C_I2C3_TX_DMA_STREAM, \ + STM32_I2C3_TX_DMA_CHN) + +/*===========================================================================*/ +/* Driver constants. */ +/*===========================================================================*/ + +#define I2C_EV5_MASTER_MODE_SELECT \ + ((uint32_t)(((I2C_SR2_MSL | I2C_SR2_BUSY) << 16) | I2C_SR1_SB)) + +#define I2C_EV6_MASTER_TRA_MODE_SELECTED \ + ((uint32_t)(((I2C_SR2_MSL | I2C_SR2_BUSY | I2C_SR2_TRA) << 16) | \ + I2C_SR1_ADDR | I2C_SR1_TXE)) + +#define I2C_EV6_MASTER_REC_MODE_SELECTED \ + ((uint32_t)(((I2C_SR2_MSL | I2C_SR2_BUSY)<< 16) | I2C_SR1_ADDR)) + +#define I2C_EV8_2_MASTER_BYTE_TRANSMITTED \ + ((uint32_t)(((I2C_SR2_MSL | I2C_SR2_BUSY | I2C_SR2_TRA) << 16) | \ + I2C_SR1_BTF | I2C_SR1_TXE)) + +#define I2C_EV_MASK 0x00FFFFFF + +#define I2C_ERROR_MASK \ + ((uint16_t)(I2C_SR1_BERR | I2C_SR1_ARLO | I2C_SR1_AF | I2C_SR1_OVR | \ + I2C_SR1_PECERR | I2C_SR1_TIMEOUT | I2C_SR1_SMBALERT)) + +/*===========================================================================*/ +/* Driver exported variables. */ +/*===========================================================================*/ + +/** @brief I2C1 driver identifier.*/ +#if STM32_I2C_USE_I2C1 || defined(__DOXYGEN__) +I2CDriver I2CD1; +#endif + +/** @brief I2C2 driver identifier.*/ +#if STM32_I2C_USE_I2C2 || defined(__DOXYGEN__) +I2CDriver I2CD2; +#endif + +/** @brief I2C3 driver identifier.*/ +#if STM32_I2C_USE_I2C3 || defined(__DOXYGEN__) +I2CDriver I2CD3; +#endif + +/*===========================================================================*/ +/* Driver local variables and types. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local functions. */ +/*===========================================================================*/ + +/** + * @brief Aborts an I2C transaction. + * + * @param[in] i2cp pointer to the @p I2CDriver object + * + * @notapi + */ +static void i2c_lld_abort_operation(I2CDriver *i2cp) { + I2C_TypeDef *dp = i2cp->i2c; + + /* Stops the I2C peripheral.*/ + dp->CR1 = I2C_CR1_SWRST; + dp->CR1 = 0; + dp->CR2 = 0; + dp->SR1 = 0; + + /* Stops the associated DMA streams.*/ + dmaStreamDisable(i2cp->dmatx); + dmaStreamDisable(i2cp->dmarx); +} + +/** + * @brief Set clock speed. + * + * @param[in] i2cp pointer to the @p I2CDriver object + * + * @notapi + */ +static void i2c_lld_set_clock(I2CDriver *i2cp) { + I2C_TypeDef *dp = i2cp->i2c; + uint16_t regCCR, clock_div; + int32_t clock_speed = i2cp->config->clock_speed; + i2cdutycycle_t duty = i2cp->config->duty_cycle; + + osalDbgCheck((i2cp != NULL) && + (clock_speed > 0) && + (clock_speed <= 4000000)); + + /* CR2 Configuration.*/ + dp->CR2 &= (uint16_t)~I2C_CR2_FREQ; + dp->CR2 |= (uint16_t)I2C_CLK_FREQ; + + /* CCR Configuration.*/ + regCCR = 0; + clock_div = I2C_CCR_CCR; + + if (clock_speed <= 100000) { + /* Configure clock_div in standard mode.*/ + osalDbgAssert(duty == STD_DUTY_CYCLE, "invalid standard mode duty cycle"); + + /* Standard mode clock_div calculate: Tlow/Thigh = 1/1.*/ + osalDbgAssert((STM32_PCLK1 % (clock_speed * 2)) == 0, + "PCLK1 must be divisible without remainder"); + clock_div = (uint16_t)(STM32_PCLK1 / (clock_speed * 2)); + + osalDbgAssert(clock_div >= 0x04, + "clock divider less then 0x04 not allowed"); + regCCR |= (clock_div & I2C_CCR_CCR); + + /* Sets the Maximum Rise Time for standard mode.*/ + dp->TRISE = I2C_CLK_FREQ + 1; + } + else if (clock_speed <= 400000) { + /* Configure clock_div in fast mode.*/ + osalDbgAssert((duty == FAST_DUTY_CYCLE_2) || + (duty == FAST_DUTY_CYCLE_16_9), + "invalid fast mode duty cycle"); + + if (duty == FAST_DUTY_CYCLE_2) { + /* Fast mode clock_div calculate: Tlow/Thigh = 2/1.*/ + osalDbgAssert((STM32_PCLK1 % (clock_speed * 3)) == 0, + "PCLK1 must be divided without remainder"); + clock_div = (uint16_t)(STM32_PCLK1 / (clock_speed * 3)); + } + else if (duty == FAST_DUTY_CYCLE_16_9) { + /* Fast mode clock_div calculate: Tlow/Thigh = 16/9.*/ + osalDbgAssert((STM32_PCLK1 % (clock_speed * 25)) == 0, + "PCLK1 must be divided without remainder"); + clock_div = (uint16_t)(STM32_PCLK1 / (clock_speed * 25)); + regCCR |= I2C_CCR_DUTY; + } + + osalDbgAssert(clock_div >= 0x01, + "clock divider less then 0x04 not allowed"); + regCCR |= (I2C_CCR_FS | (clock_div & I2C_CCR_CCR)); + + /* Sets the Maximum Rise Time for fast mode.*/ + dp->TRISE = (I2C_CLK_FREQ * 300 / 1000) + 1; + } + + osalDbgAssert((clock_div <= I2C_CCR_CCR), "the selected clock is too low"); + + dp->CCR = regCCR; +} + +/** + * @brief Set operation mode of I2C hardware. + * + * @param[in] i2cp pointer to the @p I2CDriver object + * + * @notapi + */ +static void i2c_lld_set_opmode(I2CDriver *i2cp) { + I2C_TypeDef *dp = i2cp->i2c; + i2copmode_t opmode = i2cp->config->op_mode; + uint16_t regCR1; + + regCR1 = dp->CR1; + switch (opmode) { + case OPMODE_I2C: + regCR1 &= (uint16_t)~(I2C_CR1_SMBUS|I2C_CR1_SMBTYPE); + break; + case OPMODE_SMBUS_DEVICE: + regCR1 |= I2C_CR1_SMBUS; + regCR1 &= (uint16_t)~(I2C_CR1_SMBTYPE); + break; + case OPMODE_SMBUS_HOST: + regCR1 |= (I2C_CR1_SMBUS|I2C_CR1_SMBTYPE); + break; + } + dp->CR1 = regCR1; +} + +/** + * @brief I2C shared ISR code. + * + * @param[in] i2cp pointer to the @p I2CDriver object + * + * @notapi + */ +static void i2c_lld_serve_event_interrupt(I2CDriver *i2cp) { + I2C_TypeDef *dp = i2cp->i2c; + uint32_t regSR2 = dp->SR2; + uint32_t event = dp->SR1; + + /* Interrupts are disabled just before dmaStreamEnable() because there + is no need of interrupts until next transaction begin. All the work is + done by the DMA.*/ + switch (I2C_EV_MASK & (event | (regSR2 << 16))) { + case I2C_EV5_MASTER_MODE_SELECT: + dp->DR = i2cp->addr; + break; + case I2C_EV6_MASTER_REC_MODE_SELECTED: + dp->CR2 &= ~I2C_CR2_ITEVTEN; + dmaStreamEnable(i2cp->dmarx); + dp->CR2 |= I2C_CR2_LAST; /* Needed in receiver mode. */ + if (dmaStreamGetTransactionSize(i2cp->dmarx) < 2) + dp->CR1 &= ~I2C_CR1_ACK; + break; + case I2C_EV6_MASTER_TRA_MODE_SELECTED: + dp->CR2 &= ~I2C_CR2_ITEVTEN; + dmaStreamEnable(i2cp->dmatx); + break; + case I2C_EV8_2_MASTER_BYTE_TRANSMITTED: + /* Catches BTF event after the end of transmission.*/ + if (dmaStreamGetTransactionSize(i2cp->dmarx) > 0) { + /* Starts "read after write" operation, LSB = 1 -> receive.*/ + i2cp->addr |= 0x01; + dp->CR1 |= I2C_CR1_START | I2C_CR1_ACK; + return; + } + dp->CR2 &= ~I2C_CR2_ITEVTEN; + dp->CR1 |= I2C_CR1_STOP; + _i2c_wakeup_isr(i2cp); + break; + default: + break; + } + /* Clear ADDR flag. */ + if (event & (I2C_SR1_ADDR | I2C_SR1_ADD10)) + (void)dp->SR2; +} + +/** + * @brief DMA RX end IRQ handler. + * + * @param[in] i2cp pointer to the @p I2CDriver object + * @param[in] flags pre-shifted content of the ISR register + * + * @notapi + */ +static void i2c_lld_serve_rx_end_irq(I2CDriver *i2cp, uint32_t flags) { + I2C_TypeDef *dp = i2cp->i2c; + + /* DMA errors handling.*/ +#if defined(STM32_I2C_DMA_ERROR_HOOK) + if ((flags & (STM32_DMA_ISR_TEIF | STM32_DMA_ISR_DMEIF)) != 0) { + STM32_I2C_DMA_ERROR_HOOK(i2cp); + } +#else + (void)flags; +#endif + + dmaStreamDisable(i2cp->dmarx); + + dp->CR2 &= ~I2C_CR2_LAST; + dp->CR1 &= ~I2C_CR1_ACK; + dp->CR1 |= I2C_CR1_STOP; + _i2c_wakeup_isr(i2cp); +} + +/** + * @brief DMA TX end IRQ handler. + * + * @param[in] i2cp pointer to the @p I2CDriver object + * + * @notapi + */ +static void i2c_lld_serve_tx_end_irq(I2CDriver *i2cp, uint32_t flags) { + I2C_TypeDef *dp = i2cp->i2c; + + /* DMA errors handling.*/ +#if defined(STM32_I2C_DMA_ERROR_HOOK) + if ((flags & (STM32_DMA_ISR_TEIF | STM32_DMA_ISR_DMEIF)) != 0) { + STM32_I2C_DMA_ERROR_HOOK(i2cp); + } +#else + (void)flags; +#endif + + dmaStreamDisable(i2cp->dmatx); + /* Enables interrupts to catch BTF event meaning transmission part complete. + Interrupt handler will decide to generate STOP or to begin receiving part + of R/W transaction itself.*/ + dp->CR2 |= I2C_CR2_ITEVTEN; +} + +/** + * @brief I2C error handler. + * + * @param[in] i2cp pointer to the @p I2CDriver object + * @param[in] sr content of the SR1 register to be decoded + * + * @notapi + */ +static void i2c_lld_serve_error_interrupt(I2CDriver *i2cp, uint16_t sr) { + + /* Clears interrupt flags just to be safe.*/ + dmaStreamDisable(i2cp->dmatx); + dmaStreamDisable(i2cp->dmarx); + + i2cp->errors = I2C_NO_ERROR; + + if (sr & I2C_SR1_BERR) /* Bus error. */ + i2cp->errors |= I2C_BUS_ERROR; + + if (sr & I2C_SR1_ARLO) /* Arbitration lost. */ + i2cp->errors |= I2C_ARBITRATION_LOST; + + if (sr & I2C_SR1_AF) { /* Acknowledge fail. */ + i2cp->i2c->CR2 &= ~I2C_CR2_ITEVTEN; + i2cp->i2c->CR1 |= I2C_CR1_STOP; /* Setting stop bit. */ + i2cp->errors |= I2C_ACK_FAILURE; + } + + if (sr & I2C_SR1_OVR) /* Overrun. */ + i2cp->errors |= I2C_OVERRUN; + + if (sr & I2C_SR1_TIMEOUT) /* SMBus Timeout. */ + i2cp->errors |= I2C_TIMEOUT; + + if (sr & I2C_SR1_PECERR) /* PEC error. */ + i2cp->errors |= I2C_PEC_ERROR; + + if (sr & I2C_SR1_SMBALERT) /* SMBus alert. */ + i2cp->errors |= I2C_SMB_ALERT; + + /* If some error has been identified then sends wakes the waiting thread.*/ + if (i2cp->errors != I2C_NO_ERROR) + _i2c_wakeup_error_isr(i2cp); +} + +/*===========================================================================*/ +/* Driver interrupt handlers. */ +/*===========================================================================*/ + +#if STM32_I2C_USE_I2C1 || defined(__DOXYGEN__) +/** + * @brief I2C1 event interrupt handler. + * + * @notapi + */ +OSAL_IRQ_HANDLER(I2C1_EV_IRQHandler) { + + OSAL_IRQ_PROLOGUE(); + + i2c_lld_serve_event_interrupt(&I2CD1); + + OSAL_IRQ_EPILOGUE(); +} + +/** + * @brief I2C1 error interrupt handler. + */ +OSAL_IRQ_HANDLER(I2C1_ER_IRQHandler) { + uint16_t sr = I2CD1.i2c->SR1; + + OSAL_IRQ_PROLOGUE(); + + I2CD1.i2c->SR1 = ~(sr & I2C_ERROR_MASK); + i2c_lld_serve_error_interrupt(&I2CD1, sr); + + OSAL_IRQ_EPILOGUE(); +} +#endif /* STM32_I2C_USE_I2C1 */ + +#if STM32_I2C_USE_I2C2 || defined(__DOXYGEN__) +/** + * @brief I2C2 event interrupt handler. + * + * @notapi + */ +OSAL_IRQ_HANDLER(I2C2_EV_IRQHandler) { + + OSAL_IRQ_PROLOGUE(); + + i2c_lld_serve_event_interrupt(&I2CD2); + + OSAL_IRQ_EPILOGUE(); +} + +/** + * @brief I2C2 error interrupt handler. + * + * @notapi + */ +OSAL_IRQ_HANDLER(I2C2_ER_IRQHandler) { + uint16_t sr = I2CD2.i2c->SR1; + + OSAL_IRQ_PROLOGUE(); + + I2CD2.i2c->SR1 = ~(sr & I2C_ERROR_MASK); + i2c_lld_serve_error_interrupt(&I2CD2, sr); + + OSAL_IRQ_EPILOGUE(); +} +#endif /* STM32_I2C_USE_I2C2 */ + +#if STM32_I2C_USE_I2C3 || defined(__DOXYGEN__) +/** + * @brief I2C3 event interrupt handler. + * + * @notapi + */ +OSAL_IRQ_HANDLER(I2C3_EV_IRQHandler) { + + OSAL_IRQ_PROLOGUE(); + + i2c_lld_serve_event_interrupt(&I2CD3); + + OSAL_IRQ_EPILOGUE(); +} + +/** + * @brief I2C3 error interrupt handler. + * + * @notapi + */ +OSAL_IRQ_HANDLER(I2C3_ER_IRQHandler) { + uint16_t sr = I2CD3.i2c->SR1; + + OSAL_IRQ_PROLOGUE(); + + I2CD3.i2c->SR1 = ~(sr & I2C_ERROR_MASK); + i2c_lld_serve_error_interrupt(&I2CD3, sr); + + OSAL_IRQ_EPILOGUE(); +} +#endif /* STM32_I2C_USE_I2C3 */ + +/*===========================================================================*/ +/* Driver exported functions. */ +/*===========================================================================*/ + +/** + * @brief Low level I2C driver initialization. + * + * @notapi + */ +void i2c_lld_init(void) { + +#if STM32_I2C_USE_I2C1 + i2cObjectInit(&I2CD1); + I2CD1.thread = NULL; + I2CD1.i2c = I2C1; + I2CD1.dmarx = STM32_DMA_STREAM(STM32_I2C_I2C1_RX_DMA_STREAM); + I2CD1.dmatx = STM32_DMA_STREAM(STM32_I2C_I2C1_TX_DMA_STREAM); +#endif /* STM32_I2C_USE_I2C1 */ + +#if STM32_I2C_USE_I2C2 + i2cObjectInit(&I2CD2); + I2CD2.thread = NULL; + I2CD2.i2c = I2C2; + I2CD2.dmarx = STM32_DMA_STREAM(STM32_I2C_I2C2_RX_DMA_STREAM); + I2CD2.dmatx = STM32_DMA_STREAM(STM32_I2C_I2C2_TX_DMA_STREAM); +#endif /* STM32_I2C_USE_I2C2 */ + +#if STM32_I2C_USE_I2C3 + i2cObjectInit(&I2CD3); + I2CD3.thread = NULL; + I2CD3.i2c = I2C3; + I2CD3.dmarx = STM32_DMA_STREAM(STM32_I2C_I2C3_RX_DMA_STREAM); + I2CD3.dmatx = STM32_DMA_STREAM(STM32_I2C_I2C3_TX_DMA_STREAM); +#endif /* STM32_I2C_USE_I2C3 */ +} + +/** + * @brief Configures and activates the I2C peripheral. + * + * @param[in] i2cp pointer to the @p I2CDriver object + * + * @notapi + */ +void i2c_lld_start(I2CDriver *i2cp) { + I2C_TypeDef *dp = i2cp->i2c; + + i2cp->txdmamode = STM32_DMA_CR_PSIZE_BYTE | STM32_DMA_CR_MSIZE_BYTE | + STM32_DMA_CR_MINC | STM32_DMA_CR_DMEIE | + STM32_DMA_CR_TEIE | STM32_DMA_CR_TCIE | + STM32_DMA_CR_DIR_M2P; + i2cp->rxdmamode = STM32_DMA_CR_PSIZE_BYTE | STM32_DMA_CR_MSIZE_BYTE | + STM32_DMA_CR_MINC | STM32_DMA_CR_DMEIE | + STM32_DMA_CR_TEIE | STM32_DMA_CR_TCIE | + STM32_DMA_CR_DIR_P2M; + + /* If in stopped state then enables the I2C and DMA clocks.*/ + if (i2cp->state == I2C_STOP) { + +#if STM32_I2C_USE_I2C1 + if (&I2CD1 == i2cp) { + bool b; + + rccResetI2C1(); + b = dmaStreamAllocate(i2cp->dmarx, + STM32_I2C_I2C1_IRQ_PRIORITY, + (stm32_dmaisr_t)i2c_lld_serve_rx_end_irq, + (void *)i2cp); + osalDbgAssert(!b, "stream already allocated"); + b = dmaStreamAllocate(i2cp->dmatx, + STM32_I2C_I2C1_IRQ_PRIORITY, + (stm32_dmaisr_t)i2c_lld_serve_tx_end_irq, + (void *)i2cp); + osalDbgAssert(!b, "stream already allocated"); + rccEnableI2C1(FALSE); + nvicEnableVector(I2C1_EV_IRQn, STM32_I2C_I2C1_IRQ_PRIORITY); + nvicEnableVector(I2C1_ER_IRQn, STM32_I2C_I2C1_IRQ_PRIORITY); + + i2cp->rxdmamode |= STM32_DMA_CR_CHSEL(I2C1_RX_DMA_CHANNEL) | + STM32_DMA_CR_PL(STM32_I2C_I2C1_DMA_PRIORITY); + i2cp->txdmamode |= STM32_DMA_CR_CHSEL(I2C1_TX_DMA_CHANNEL) | + STM32_DMA_CR_PL(STM32_I2C_I2C1_DMA_PRIORITY); + } +#endif /* STM32_I2C_USE_I2C1 */ + +#if STM32_I2C_USE_I2C2 + if (&I2CD2 == i2cp) { + bool b; + + rccResetI2C2(); + b = dmaStreamAllocate(i2cp->dmarx, + STM32_I2C_I2C2_IRQ_PRIORITY, + (stm32_dmaisr_t)i2c_lld_serve_rx_end_irq, + (void *)i2cp); + osalDbgAssert(!b, "stream already allocated"); + b = dmaStreamAllocate(i2cp->dmatx, + STM32_I2C_I2C2_IRQ_PRIORITY, + (stm32_dmaisr_t)i2c_lld_serve_tx_end_irq, + (void *)i2cp); + osalDbgAssert(!b, "stream already allocated"); + rccEnableI2C2(FALSE); + nvicEnableVector(I2C2_EV_IRQn, STM32_I2C_I2C2_IRQ_PRIORITY); + nvicEnableVector(I2C2_ER_IRQn, STM32_I2C_I2C2_IRQ_PRIORITY); + + i2cp->rxdmamode |= STM32_DMA_CR_CHSEL(I2C2_RX_DMA_CHANNEL) | + STM32_DMA_CR_PL(STM32_I2C_I2C2_DMA_PRIORITY); + i2cp->txdmamode |= STM32_DMA_CR_CHSEL(I2C2_TX_DMA_CHANNEL) | + STM32_DMA_CR_PL(STM32_I2C_I2C2_DMA_PRIORITY); + } +#endif /* STM32_I2C_USE_I2C2 */ + +#if STM32_I2C_USE_I2C3 + if (&I2CD3 == i2cp) { + bool b; + + rccResetI2C3(); + b = dmaStreamAllocate(i2cp->dmarx, + STM32_I2C_I2C3_IRQ_PRIORITY, + (stm32_dmaisr_t)i2c_lld_serve_rx_end_irq, + (void *)i2cp); + osalDbgAssert(!b, "stream already allocated"); + b = dmaStreamAllocate(i2cp->dmatx, + STM32_I2C_I2C3_IRQ_PRIORITY, + (stm32_dmaisr_t)i2c_lld_serve_tx_end_irq, + (void *)i2cp); + osalDbgAssert(!b, "stream already allocated"); + rccEnableI2C3(FALSE); + nvicEnableVector(I2C3_EV_IRQn, STM32_I2C_I2C3_IRQ_PRIORITY); + nvicEnableVector(I2C3_ER_IRQn, STM32_I2C_I2C3_IRQ_PRIORITY); + + i2cp->rxdmamode |= STM32_DMA_CR_CHSEL(I2C3_RX_DMA_CHANNEL) | + STM32_DMA_CR_PL(STM32_I2C_I2C3_DMA_PRIORITY); + i2cp->txdmamode |= STM32_DMA_CR_CHSEL(I2C3_TX_DMA_CHANNEL) | + STM32_DMA_CR_PL(STM32_I2C_I2C3_DMA_PRIORITY); + } +#endif /* STM32_I2C_USE_I2C3 */ + } + + /* I2C registers pointed by the DMA.*/ + dmaStreamSetPeripheral(i2cp->dmarx, &dp->DR); + dmaStreamSetPeripheral(i2cp->dmatx, &dp->DR); + + /* Reset i2c peripheral.*/ + dp->CR1 = I2C_CR1_SWRST; + dp->CR1 = 0; + dp->CR2 = I2C_CR2_ITERREN | I2C_CR2_DMAEN; + + /* Setup I2C parameters.*/ + i2c_lld_set_clock(i2cp); + i2c_lld_set_opmode(i2cp); + + /* Ready to go.*/ + dp->CR1 |= I2C_CR1_PE; +} + +/** + * @brief Deactivates the I2C peripheral. + * + * @param[in] i2cp pointer to the @p I2CDriver object + * + * @notapi + */ +void i2c_lld_stop(I2CDriver *i2cp) { + + /* If not in stopped state then disables the I2C clock.*/ + if (i2cp->state != I2C_STOP) { + + /* I2C disable.*/ + i2c_lld_abort_operation(i2cp); + dmaStreamRelease(i2cp->dmatx); + dmaStreamRelease(i2cp->dmarx); + +#if STM32_I2C_USE_I2C1 + if (&I2CD1 == i2cp) { + nvicDisableVector(I2C1_EV_IRQn); + nvicDisableVector(I2C1_ER_IRQn); + rccDisableI2C1(FALSE); + } +#endif + +#if STM32_I2C_USE_I2C2 + if (&I2CD2 == i2cp) { + nvicDisableVector(I2C2_EV_IRQn); + nvicDisableVector(I2C2_ER_IRQn); + rccDisableI2C2(FALSE); + } +#endif + +#if STM32_I2C_USE_I2C3 + if (&I2CD3 == i2cp) { + nvicDisableVector(I2C3_EV_IRQn); + nvicDisableVector(I2C3_ER_IRQn); + rccDisableI2C3(FALSE); + } +#endif + } +} + +/** + * @brief Receives data via the I2C bus as master. + * @details Number of receiving bytes must be more than 1 on STM32F1x. This is + * hardware restriction. + * + * @param[in] i2cp pointer to the @p I2CDriver object + * @param[in] addr slave device address + * @param[out] rxbuf pointer to the receive buffer + * @param[in] rxbytes number of bytes to be received + * @param[in] timeout the number of ticks before the operation timeouts, + * the following special values are allowed: + * - @a TIME_INFINITE no timeout. + * . + * @return The operation status. + * @retval MSG_OK if the function succeeded. + * @retval MSG_RESET if one or more I2C errors occurred, the errors can + * be retrieved using @p i2cGetErrors(). + * @retval MSG_TIMEOUT if a timeout occurred before operation end. After a + * timeout the driver must be stopped and restarted + * because the bus is in an uncertain state. + * + * @notapi + */ +msg_t i2c_lld_master_receive_timeout(I2CDriver *i2cp, i2caddr_t addr, + uint8_t *rxbuf, size_t rxbytes, + systime_t timeout) { + I2C_TypeDef *dp = i2cp->i2c; + systime_t start, end; + +#if defined(STM32F1XX_I2C) + osalDbgCheck((rxbytes > 1), "i2c_lld_master_receive_timeout"); +#endif + + /* Resetting error flags for this transfer.*/ + i2cp->errors = I2C_NO_ERROR; + + /* Initializes driver fields, LSB = 1 -> receive.*/ + i2cp->addr = (addr << 1) | 0x01; + + /* Releases the lock from high level driver.*/ + osalSysUnlock(); + + /* RX DMA setup.*/ + dmaStreamSetMode(i2cp->dmarx, i2cp->rxdmamode); + dmaStreamSetMemory0(i2cp->dmarx, rxbuf); + dmaStreamSetTransactionSize(i2cp->dmarx, rxbytes); + + /* Calculating the time window for the timeout on the busy bus condition.*/ + start = osalOsGetSystemTimeX(); + end = start + OSAL_MS2ST(STM32_I2C_BUSY_TIMEOUT); + + /* Waits until BUSY flag is reset or, alternatively, for a timeout + condition.*/ + while (true) { + osalSysLock(); + + /* If the bus is not busy then the operation can continue, note, the + loop is exited in the locked state.*/ + if (!(dp->SR2 & I2C_SR2_BUSY) && !(dp->CR1 & I2C_CR1_STOP)) + break; + + /* If the system time went outside the allowed window then a timeout + condition is returned.*/ + if (!osalOsIsTimeWithinX(osalOsGetSystemTimeX(), start, end)) + return MSG_TIMEOUT; + + osalSysUnlock(); + } + + /* This lock will be released in high level driver.*/ + osalSysLock(); + + /* Starts the operation.*/ + dp->CR2 |= I2C_CR2_ITEVTEN; + dp->CR1 |= I2C_CR1_START | I2C_CR1_ACK; + + /* Waits for the operation completion or a timeout.*/ + return osalThreadSuspendTimeoutS(&i2cp->thread, timeout); +} + +/** + * @brief Transmits data via the I2C bus as master. + * @details Number of receiving bytes must be 0 or more than 1 on STM32F1x. + * This is hardware restriction. + * + * @param[in] i2cp pointer to the @p I2CDriver object + * @param[in] addr slave device address + * @param[in] txbuf pointer to the transmit buffer + * @param[in] txbytes number of bytes to be transmitted + * @param[out] rxbuf pointer to the receive buffer + * @param[in] rxbytes number of bytes to be received + * @param[in] timeout the number of ticks before the operation timeouts, + * the following special values are allowed: + * - @a TIME_INFINITE no timeout. + * . + * @return The operation status. + * @retval MSG_OK if the function succeeded. + * @retval MSG_RESET if one or more I2C errors occurred, the errors can + * be retrieved using @p i2cGetErrors(). + * @retval MSG_TIMEOUT if a timeout occurred before operation end. After a + * timeout the driver must be stopped and restarted + * because the bus is in an uncertain state. + * + * @notapi + */ +msg_t i2c_lld_master_transmit_timeout(I2CDriver *i2cp, i2caddr_t addr, + const uint8_t *txbuf, size_t txbytes, + uint8_t *rxbuf, size_t rxbytes, + systime_t timeout) { + I2C_TypeDef *dp = i2cp->i2c; + systime_t start, end; + +#if defined(STM32F1XX_I2C) + osalDbgCheck(((rxbytes == 0) || ((rxbytes > 1) && (rxbuf != NULL)))); +#endif + + /* Resetting error flags for this transfer.*/ + i2cp->errors = I2C_NO_ERROR; + + /* Initializes driver fields, LSB = 1 -> receive.*/ + i2cp->addr = (addr << 1) | 0x01; + + /* Releases the lock from high level driver.*/ + osalSysUnlock(); + + /* TX DMA setup.*/ + dmaStreamSetMode(i2cp->dmatx, i2cp->txdmamode); + dmaStreamSetMemory0(i2cp->dmatx, txbuf); + dmaStreamSetTransactionSize(i2cp->dmatx, txbytes); + + /* RX DMA setup.*/ + dmaStreamSetMode(i2cp->dmarx, i2cp->rxdmamode); + dmaStreamSetMemory0(i2cp->dmarx, rxbuf); + dmaStreamSetTransactionSize(i2cp->dmarx, rxbytes); + + /* Calculating the time window for the timeout on the busy bus condition.*/ + start = osalOsGetSystemTimeX(); + end = start + OSAL_MS2ST(STM32_I2C_BUSY_TIMEOUT); + + /* Waits until BUSY flag is reset or, alternatively, for a timeout + condition.*/ + while (true) { + osalSysLock(); + + /* If the bus is not busy then the operation can continue, note, the + loop is exited in the locked state.*/ + if (!(dp->SR2 & I2C_SR2_BUSY) && !(dp->CR1 & I2C_CR1_STOP)) + break; + + /* If the system time went outside the allowed window then a timeout + condition is returned.*/ + if (!osalOsIsTimeWithinX(osalOsGetSystemTimeX(), start, end)) + return MSG_TIMEOUT; + + osalSysUnlock(); + } + + /* This lock will be released in high level driver.*/ + osalSysLock(); + + /* Starts the operation.*/ + dp->CR2 |= I2C_CR2_ITEVTEN; + dp->CR1 |= I2C_CR1_START; + + /* Waits for the operation completion or a timeout.*/ + return osalThreadSuspendTimeoutS(&i2cp->thread, timeout); +} + +#endif /* HAL_USE_I2C */ + +/** @} */ diff --git a/os/hal/ports/STM32/I2Cv1/i2c_lld.h b/os/hal/ports/STM32/I2Cv1/i2c_lld.h new file mode 100644 index 000000000..a92e48e26 --- /dev/null +++ b/os/hal/ports/STM32/I2Cv1/i2c_lld.h @@ -0,0 +1,466 @@ +/* + ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ +/* + Concepts and parts of this file have been contributed by Uladzimir Pylinsky + aka barthess. + */ + +/** + * @file STM32/I2Cv1/i2c_lld.h + * @brief STM32 I2C subsystem low level driver header. + * + * @addtogroup I2C + * @{ + */ + +#ifndef _I2C_LLD_H_ +#define _I2C_LLD_H_ + +#if HAL_USE_I2C || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver constants. */ +/*===========================================================================*/ + +/** + * @brief Peripheral clock frequency. + */ +#define I2C_CLK_FREQ ((STM32_PCLK1) / 1000000) + +/*===========================================================================*/ +/* Driver pre-compile time settings. */ +/*===========================================================================*/ + +/** + * @name Configuration options + * @{ + */ +/** + * @brief I2C1 driver enable switch. + * @details If set to @p TRUE the support for I2C1 is included. + * @note The default is @p FALSE. + */ +#if !defined(STM32_I2C_USE_I2C1) || defined(__DOXYGEN__) +#define STM32_I2C_USE_I2C1 FALSE +#endif + +/** + * @brief I2C2 driver enable switch. + * @details If set to @p TRUE the support for I2C2 is included. + * @note The default is @p FALSE. + */ +#if !defined(STM32_I2C_USE_I2C2) || defined(__DOXYGEN__) +#define STM32_I2C_USE_I2C2 FALSE +#endif + +/** + * @brief I2C3 driver enable switch. + * @details If set to @p TRUE the support for I2C3 is included. + * @note The default is @p FALSE. + */ +#if !defined(STM32_I2C_USE_I2C3) || defined(__DOXYGEN__) +#define STM32_I2C_USE_I2C3 FALSE +#endif + +/** + * @brief I2C timeout on busy condition in milliseconds. + */ +#if !defined(STM32_I2C_BUSY_TIMEOUT) || defined(__DOXYGEN__) +#define STM32_I2C_BUSY_TIMEOUT 50 +#endif + +/** + * @brief I2C1 interrupt priority level setting. + */ +#if !defined(STM32_I2C_I2C1_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_I2C_I2C1_IRQ_PRIORITY 10 +#endif + +/** + * @brief I2C2 interrupt priority level setting. + */ +#if !defined(STM32_I2C_I2C2_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_I2C_I2C2_IRQ_PRIORITY 10 +#endif + +/** + * @brief I2C3 interrupt priority level setting. + */ +#if !defined(STM32_I2C_I2C3_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_I2C_I2C3_IRQ_PRIORITY 10 +#endif + +/** +* @brief I2C1 DMA priority (0..3|lowest..highest). +* @note The priority level is used for both the TX and RX DMA streams but +* because of the streams ordering the RX stream has always priority +* over the TX stream. +*/ +#if !defined(STM32_I2C_I2C1_DMA_PRIORITY) || defined(__DOXYGEN__) +#define STM32_I2C_I2C1_DMA_PRIORITY 1 +#endif + +/** +* @brief I2C2 DMA priority (0..3|lowest..highest). +* @note The priority level is used for both the TX and RX DMA streams but +* because of the streams ordering the RX stream has always priority +* over the TX stream. +*/ +#if !defined(STM32_I2C_I2C2_DMA_PRIORITY) || defined(__DOXYGEN__) +#define STM32_I2C_I2C2_DMA_PRIORITY 1 +#endif + +/** +* @brief I2C3 DMA priority (0..3|lowest..highest). +* @note The priority level is used for both the TX and RX DMA streams but +* because of the streams ordering the RX stream has always priority +* over the TX stream. +*/ +#if !defined(STM32_I2C_I2C3_DMA_PRIORITY) || defined(__DOXYGEN__) +#define STM32_I2C_I2C3_DMA_PRIORITY 1 +#endif + +/** + * @brief I2C DMA error hook. + * @note The default action for DMA errors is a system halt because DMA + * error can only happen because programming errors. + */ +#if !defined(STM32_I2C_DMA_ERROR_HOOK) || defined(__DOXYGEN__) +#define STM32_I2C_DMA_ERROR_HOOK(i2cp) chSysHalt("DMA failure") +#endif + +#if STM32_ADVANCED_DMA || defined(__DOXYGEN__) + +/** + * @brief DMA stream used for I2C1 RX operations. + * @note This option is only available on platforms with enhanced DMA. + */ +#if !defined(STM32_I2C_I2C1_RX_DMA_STREAM) || defined(__DOXYGEN__) +#define STM32_I2C_I2C1_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 0) +#endif + +/** + * @brief DMA stream used for I2C1 TX operations. + * @note This option is only available on platforms with enhanced DMA. + */ +#if !defined(STM32_I2C_I2C1_TX_DMA_STREAM) || defined(__DOXYGEN__) +#define STM32_I2C_I2C1_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 6) +#endif + +/** + * @brief DMA stream used for I2C2 RX operations. + * @note This option is only available on platforms with enhanced DMA. + */ +#if !defined(STM32_I2C_I2C2_RX_DMA_STREAM) || defined(__DOXYGEN__) +#define STM32_I2C_I2C2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2) +#endif + +/** + * @brief DMA stream used for I2C2 TX operations. + * @note This option is only available on platforms with enhanced DMA. + */ +#if !defined(STM32_I2C_I2C2_TX_DMA_STREAM) || defined(__DOXYGEN__) +#define STM32_I2C_I2C2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7) +#endif + +/** + * @brief DMA stream used for I2C3 RX operations. + * @note This option is only available on platforms with enhanced DMA. + */ +#if !defined(STM32_I2C_I2C3_RX_DMA_STREAM) || defined(__DOXYGEN__) +#define STM32_I2C_I2C3_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2) +#endif + +/** + * @brief DMA stream used for I2C3 TX operations. + * @note This option is only available on platforms with enhanced DMA. + */ +#if !defined(STM32_I2C_I2C3_TX_DMA_STREAM) || defined(__DOXYGEN__) +#define STM32_I2C_I2C3_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) +#endif + +#else /* !STM32_ADVANCED_DMA */ + +/* Fixed streams for platforms using the old DMA peripheral, the values are + valid for both STM32F1xx and STM32L1xx.*/ +#define STM32_I2C_I2C1_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7) +#define STM32_I2C_I2C1_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 6) +#define STM32_I2C_I2C2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 5) +#define STM32_I2C_I2C2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) + +#endif /* !STM32_ADVANCED_DMA*/ + +/* Flag for the whole STM32F1XX family. */ +#if defined(STM32F10X_LD_VL) || defined(STM32F10X_MD_VL) || \ + defined(STM32F10X_LD) || defined(STM32F10X_MD) || \ + defined(STM32F10X_HD) || defined(STM32F10X_XL) || \ + defined(STM32F10X_CL) +#define STM32F1XX_I2C +#endif +/** @} */ + +/*===========================================================================*/ +/* Derived constants and error checks. */ +/*===========================================================================*/ + +/** @brief error checks */ +#if STM32_I2C_USE_I2C1 && !STM32_HAS_I2C1 +#error "I2C1 not present in the selected device" +#endif + +#if STM32_I2C_USE_I2C2 && !STM32_HAS_I2C2 +#error "I2C2 not present in the selected device" +#endif + +#if STM32_I2C_USE_I2C3 && !STM32_HAS_I2C3 +#error "I2C3 not present in the selected device" +#endif + +#if !STM32_I2C_USE_I2C1 && !STM32_I2C_USE_I2C2 && \ + !STM32_I2C_USE_I2C3 +#error "I2C driver activated but no I2C peripheral assigned" +#endif + +#if STM32_I2C_USE_I2C1 && \ + !STM32_DMA_IS_VALID_ID(STM32_I2C_I2C1_RX_DMA_STREAM, \ + STM32_I2C1_RX_DMA_MSK) +#error "invalid DMA stream associated to I2C1 RX" +#endif + +#if STM32_I2C_USE_I2C1 && \ + !STM32_DMA_IS_VALID_ID(STM32_I2C_I2C1_TX_DMA_STREAM, \ + STM32_I2C1_TX_DMA_MSK) +#error "invalid DMA stream associated to I2C1 TX" +#endif + +#if STM32_I2C_USE_I2C2 && \ + !STM32_DMA_IS_VALID_ID(STM32_I2C_I2C2_RX_DMA_STREAM, \ + STM32_I2C2_RX_DMA_MSK) +#error "invalid DMA stream associated to I2C2 RX" +#endif + +#if STM32_I2C_USE_I2C2 && \ + !STM32_DMA_IS_VALID_ID(STM32_I2C_I2C2_TX_DMA_STREAM, \ + STM32_I2C2_TX_DMA_MSK) +#error "invalid DMA stream associated to I2C2 TX" +#endif + +#if STM32_I2C_USE_I2C3 && \ + !STM32_DMA_IS_VALID_ID(STM32_I2C_I2C3_RX_DMA_STREAM, \ + STM32_I2C3_RX_DMA_MSK) +#error "invalid DMA stream associated to I2C3 RX" +#endif + +#if STM32_I2C_USE_I2C3 && \ + !STM32_DMA_IS_VALID_ID(STM32_I2C_I2C3_TX_DMA_STREAM, \ + STM32_I2C3_TX_DMA_MSK) +#error "invalid DMA stream associated to I2C3 TX" +#endif + +#if !defined(STM32_DMA_REQUIRED) +#define STM32_DMA_REQUIRED +#endif + +/* Check clock range. */ +#if defined(STM32F4XX) +#if !(I2C_CLK_FREQ >= 2) && (I2C_CLK_FREQ <= 42) +#error "I2C peripheral clock frequency out of range." +#endif + +#elif defined(STM32L1XX_MD) +#if !(I2C_CLK_FREQ >= 2) && (I2C_CLK_FREQ <= 32) +#error "I2C peripheral clock frequency out of range." +#endif + +#elif defined(STM32F2XX) +#if !(I2C_CLK_FREQ >= 2) && (I2C_CLK_FREQ <= 30) +#error "I2C peripheral clock frequency out of range." +#endif + +#elif defined(STM32F10X_LD_VL) || defined(STM32F10X_MD_VL) || \ + defined(STM32F10X_HD_VL) +#if !(I2C_CLK_FREQ >= 2) && (I2C_CLK_FREQ <= 24) +#error "I2C peripheral clock frequency out of range." +#endif + +#elif defined(STM32F10X_LD) || defined(STM32F10X_MD) || \ + defined(STM32F10X_HD) || defined(STM32F10X_XL) || \ + defined(STM32F10X_CL) +#if !(I2C_CLK_FREQ >= 2) && (I2C_CLK_FREQ <= 36) +#error "I2C peripheral clock frequency out of range." +#endif +#else +#error "unspecified, unsupported or invalid STM32 platform" +#endif + +/*===========================================================================*/ +/* Driver data structures and types. */ +/*===========================================================================*/ + +/** + * @brief Type representing I2C address. + */ +typedef uint16_t i2caddr_t; + +/** + * @brief I2C Driver condition flags type. + */ +typedef uint32_t i2cflags_t; + +/** + * @brief Supported modes for the I2C bus. + */ +typedef enum { + OPMODE_I2C = 1, + OPMODE_SMBUS_DEVICE = 2, + OPMODE_SMBUS_HOST = 3, +} i2copmode_t; + +/** + * @brief Supported duty cycle modes for the I2C bus. + */ +typedef enum { + STD_DUTY_CYCLE = 1, + FAST_DUTY_CYCLE_2 = 2, + FAST_DUTY_CYCLE_16_9 = 3, +} i2cdutycycle_t; + +/** + * @brief Driver configuration structure. + */ +typedef struct { + i2copmode_t op_mode; /**< @brief Specifies the I2C mode. */ + uint32_t clock_speed; /**< @brief Specifies the clock frequency. + @note Must be set to a value lower + than 400kHz. */ + i2cdutycycle_t duty_cycle; /**< @brief Specifies the I2C fast mode + duty cycle. */ +} I2CConfig; + +/** + * @brief Type of a structure representing an I2C driver. + */ +typedef struct I2CDriver I2CDriver; + +/** + * @brief Structure representing an I2C driver. + */ +struct I2CDriver { + /** + * @brief Driver state. + */ + i2cstate_t state; + /** + * @brief Current configuration data. + */ + const I2CConfig *config; + /** + * @brief Error flags. + */ + i2cflags_t errors; +#if I2C_USE_MUTUAL_EXCLUSION || defined(__DOXYGEN__) + /** + * @brief Mutex protecting the bus. + */ + mutex_t mutex; +#endif /* I2C_USE_MUTUAL_EXCLUSION */ +#if defined(I2C_DRIVER_EXT_FIELDS) + I2C_DRIVER_EXT_FIELDS +#endif + /* End of the mandatory fields.*/ + /** + * @brief Thread waiting for I/O completion. + */ + thread_reference_t thread; + /** + * @brief Current slave address without R/W bit. + */ + i2caddr_t addr; + /** + * @brief RX DMA mode bit mask. + */ + uint32_t rxdmamode; + /** + * @brief TX DMA mode bit mask. + */ + uint32_t txdmamode; + /** + * @brief Receive DMA channel. + */ + const stm32_dma_stream_t *dmarx; + /** + * @brief Transmit DMA channel. + */ + const stm32_dma_stream_t *dmatx; + /** + * @brief Pointer to the I2Cx registers block. + */ + I2C_TypeDef *i2c; +}; + +/*===========================================================================*/ +/* Driver macros. */ +/*===========================================================================*/ + +/** + * @brief Get errors from I2C driver. + * + * @param[in] i2cp pointer to the @p I2CDriver object + * + * @notapi + */ +#define i2c_lld_get_errors(i2cp) ((i2cp)->errors) + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +#if !defined(__DOXYGEN__) +#if STM32_I2C_USE_I2C1 +extern I2CDriver I2CD1; +#endif + +#if STM32_I2C_USE_I2C2 +extern I2CDriver I2CD2; +#endif + +#if STM32_I2C_USE_I2C3 +extern I2CDriver I2CD3; +#endif +#endif /* !defined(__DOXYGEN__) */ + +#ifdef __cplusplus +extern "C" { +#endif + void i2c_lld_init(void); + void i2c_lld_start(I2CDriver *i2cp); + void i2c_lld_stop(I2CDriver *i2cp); + msg_t i2c_lld_master_transmit_timeout(I2CDriver *i2cp, i2caddr_t addr, + const uint8_t *txbuf, size_t txbytes, + uint8_t *rxbuf, size_t rxbytes, + systime_t timeout); + msg_t i2c_lld_master_receive_timeout(I2CDriver *i2cp, i2caddr_t addr, + uint8_t *rxbuf, size_t rxbytes, + systime_t timeout); +#ifdef __cplusplus +} +#endif + +#endif /* HAL_USE_I2C */ + +#endif /* _I2C_LLD_H_ */ + +/** @} */ diff --git a/os/hal/ports/STM32/I2Cv2/i2c_lld.c b/os/hal/ports/STM32/I2Cv2/i2c_lld.c new file mode 100644 index 000000000..249a6f54b --- /dev/null +++ b/os/hal/ports/STM32/I2Cv2/i2c_lld.c @@ -0,0 +1,720 @@ +/* + ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file STM32/I2Cv2/i2c_lld.c + * @brief STM32 I2C subsystem low level driver source. + * + * @addtogroup I2C + * @{ + */ + +#include "hal.h" + +#if HAL_USE_I2C || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver local definitions. */ +/*===========================================================================*/ + +#define DMAMODE_COMMON \ + (STM32_DMA_CR_PSIZE_BYTE | STM32_DMA_CR_MSIZE_BYTE | \ + STM32_DMA_CR_MINC | STM32_DMA_CR_DMEIE | \ + STM32_DMA_CR_TEIE | STM32_DMA_CR_TCIE) + +#define I2C1_RX_DMA_CHANNEL \ + STM32_DMA_GETCHANNEL(STM32_I2C_I2C1_RX_DMA_STREAM, \ + STM32_I2C1_RX_DMA_CHN) + +#define I2C1_TX_DMA_CHANNEL \ + STM32_DMA_GETCHANNEL(STM32_I2C_I2C1_TX_DMA_STREAM, \ + STM32_I2C1_TX_DMA_CHN) + +#define I2C2_RX_DMA_CHANNEL \ + STM32_DMA_GETCHANNEL(STM32_I2C_I2C2_RX_DMA_STREAM, \ + STM32_I2C2_RX_DMA_CHN) + +#define I2C2_TX_DMA_CHANNEL \ + STM32_DMA_GETCHANNEL(STM32_I2C_I2C2_TX_DMA_STREAM, \ + STM32_I2C2_TX_DMA_CHN) + +/*===========================================================================*/ +/* Driver constants. */ +/*===========================================================================*/ + +#define I2C_MASTER_TC \ + ((uint32_t)(I2C_ISR_BUSY | I2C_ISR_TC)) + +#define I2C_ERROR_MASK \ + ((uint32_t)(I2C_ISR_BERR | I2C_ISR_ARLO | I2C_ISR_OVR | I2C_ISR_PECERR | \ + I2C_ISR_TIMEOUT | I2C_ISR_ALERT)) + +#define I2C_INT_MASK \ + ((uint32_t)(I2C_ISR_TCR | I2C_ISR_TC | I2C_ISR_STOPF | I2C_ISR_NACKF | \ + I2C_ISR_ADDR | I2C_ISR_RXNE | I2C_ISR_TXIS)) + +/*===========================================================================*/ +/* Driver exported variables. */ +/*===========================================================================*/ + +/** @brief I2C1 driver identifier.*/ +#if STM32_I2C_USE_I2C1 || defined(__DOXYGEN__) +I2CDriver I2CD1; +#endif + +/** @brief I2C2 driver identifier.*/ +#if STM32_I2C_USE_I2C2 || defined(__DOXYGEN__) +I2CDriver I2CD2; +#endif + +/*===========================================================================*/ +/* Driver local variables. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local functions. */ +/*===========================================================================*/ + +/** + * @brief Aborts an I2C transaction. + * + * @param[in] i2cp pointer to the @p I2CDriver object + * + * @notapi + */ +static void i2c_lld_abort_operation(I2CDriver *i2cp) { + I2C_TypeDef *dp = i2cp->i2c; + + if (dp->CR1 & I2C_CR1_PE) { + /* Stops the I2C peripheral.*/ + dp->CR1 &= ~I2C_CR1_PE; + while (dp->CR1 & I2C_CR1_PE) + dp->CR1 &= ~I2C_CR1_PE; + dp->CR1 |= I2C_CR1_PE; + } + + /* Stops the associated DMA streams.*/ + dmaStreamDisable(i2cp->dmatx); + dmaStreamDisable(i2cp->dmarx); +} + +/** + * @brief I2C shared ISR code. + * + * @param[in] i2cp pointer to the @p I2CDriver object + * @param[in] isr content of the ISR register to be decoded + * + * @notapi + */ +static void i2c_lld_serve_interrupt(I2CDriver *i2cp, uint32_t isr) { + I2C_TypeDef *dp = i2cp->i2c; + + if ((isr & I2C_ISR_TC) && (i2cp->state == I2C_ACTIVE_TX)) { + size_t rxbytes; + + /* Make sure no more 'Transfer complete' interrupts.*/ + dp->CR1 &= ~I2C_CR1_TCIE; + + rxbytes = dmaStreamGetTransactionSize(i2cp->dmarx); + if (rxbytes > 0) { + i2cp->state = I2C_ACTIVE_RX; + + /* Enable RX DMA */ + dmaStreamEnable(i2cp->dmarx); + + dp->CR2 &= ~I2C_CR2_NBYTES; + dp->CR2 |= rxbytes << 16; + + /* Starts the read operation.*/ + dp->CR2 |= I2C_CR2_RD_WRN; + dp->CR2 |= I2C_CR2_START; + } + else { + /* Nothing to receive - send STOP immediately.*/ + dp->CR2 |= I2C_CR2_STOP; + } + } + if (isr & I2C_ISR_NACKF) { + /* Starts a STOP sequence immediately on error.*/ + dp->CR2 |= I2C_CR2_STOP; + + i2cp->errors |= I2C_ACK_FAILURE; + } + if (isr & I2C_ISR_STOPF) { + /* Stops the associated DMA streams.*/ + dmaStreamDisable(i2cp->dmatx); + dmaStreamDisable(i2cp->dmarx); + + /* The wake up message depends on the presence of errors.*/ + if (i2cp->errors) + _i2c_wakeup_error_isr(i2cp); + else + _i2c_wakeup_isr(i2cp); + } +} + +/** + * @brief DMA RX end IRQ handler. + * + * @param[in] i2cp pointer to the @p I2CDriver object + * @param[in] flags pre-shifted content of the ISR register + * + * @notapi + */ +static void i2c_lld_serve_rx_end_irq(I2CDriver *i2cp, uint32_t flags) { + I2C_TypeDef *dp = i2cp->i2c; + + /* DMA errors handling.*/ +#if defined(STM32_I2C_DMA_ERROR_HOOK) + if ((flags & (STM32_DMA_ISR_TEIF | STM32_DMA_ISR_DMEIF)) != 0) { + STM32_I2C_DMA_ERROR_HOOK(i2cp); + } +#else + (void)flags; +#endif + + dmaStreamDisable(i2cp->dmarx); + dp->CR2 |= I2C_CR2_STOP; + _i2c_wakeup_isr(i2cp); +} + +/** + * @brief DMA TX end IRQ handler. + * + * @param[in] i2cp pointer to the @p I2CDriver object + * + * @notapi + */ +static void i2c_lld_serve_tx_end_irq(I2CDriver *i2cp, uint32_t flags) { + + /* DMA errors handling.*/ +#if defined(STM32_I2C_DMA_ERROR_HOOK) + if ((flags & (STM32_DMA_ISR_TEIF | STM32_DMA_ISR_DMEIF)) != 0) { + STM32_I2C_DMA_ERROR_HOOK(i2cp); + } +#else + (void)flags; +#endif + + dmaStreamDisable(i2cp->dmatx); +} + +/** + * @brief I2C error handler. + * + * @param[in] i2cp pointer to the @p I2CDriver object + * @param[in] isr content of the ISR register to be decoded + * + * @notapi + */ +static void i2c_lld_serve_error_interrupt(I2CDriver *i2cp, uint32_t isr) { + + /* Clears interrupt flags just to be safe.*/ + dmaStreamDisable(i2cp->dmatx); + dmaStreamDisable(i2cp->dmarx); + + if (isr & I2C_ISR_BERR) + i2cp->errors |= I2C_BUS_ERROR; + + if (isr & I2C_ISR_ARLO) + i2cp->errors |= I2C_ARBITRATION_LOST; + + if (isr & I2C_ISR_OVR) + i2cp->errors |= I2C_OVERRUN; + + if (isr & I2C_ISR_TIMEOUT) + i2cp->errors |= I2C_TIMEOUT; + + /* If some error has been identified then sends wakes the waiting thread.*/ + if (i2cp->errors != I2C_NO_ERROR) + _i2c_wakeup_error_isr(i2cp); +} + +/*===========================================================================*/ +/* Driver interrupt handlers. */ +/*===========================================================================*/ + +#if STM32_I2C_USE_I2C1 || defined(__DOXYGEN__) +#if defined(STM32_I2C1_GLOBAL_HANDLER) || defined(__DOXYGEN__) +/** + * @brief I2C1 event interrupt handler. + * + * @notapi + */ +CH_IRQ_HANDLER(STM32_I2C1_GLOBAL_HANDLER) { + uint32_t isr = I2CD1.i2c->ISR; + + CH_IRQ_PROLOGUE(); + + /* Clearing IRQ bits.*/ + I2CD1.i2c->ICR = isr; + + if (isr & I2C_ERROR_MASK) + i2c_lld_serve_error_interrupt(&I2CD1, isr); + else if (isr & I2C_INT_MASK) + i2c_lld_serve_interrupt(&I2CD1, isr); + + CH_IRQ_EPILOGUE(); +} + +#elif defined(STM32_I2C1_EVENT_HANDLER) && defined(STM32_I2C1_ERROR_HANDLER) +CH_IRQ_HANDLER(STM32_I2C1_EVENT_HANDLER) { + uint32_t isr = I2CD1.i2c->ISR; + + CH_IRQ_PROLOGUE(); + + /* Clearing IRQ bits.*/ + I2CD1.i2c->ICR = isr & I2C_INT_MASK; + + i2c_lld_serve_interrupt(&I2CD1, isr); + + CH_IRQ_EPILOGUE(); +} + +CH_IRQ_HANDLER(STM32_I2C1_ERROR_HANDLER) { + uint32_t isr = I2CD1.i2c->ISR; + + CH_IRQ_PROLOGUE(); + + /* Clearing IRQ bits.*/ + I2CD1.i2c->ICR = isr & I2C_ERROR_MASK; + + i2c_lld_serve_error_interrupt(&I2CD1, isr); + + CH_IRQ_EPILOGUE(); +} + +#else +#error "I2C1 interrupt handlers not defined" +#endif +#endif /* STM32_I2C_USE_I2C1 */ + +#if STM32_I2C_USE_I2C2 || defined(__DOXYGEN__) +#if defined(STM32_I2C2_GLOBAL_HANDLER) || defined(__DOXYGEN__) +/** + * @brief I2C2 event interrupt handler. + * + * @notapi + */ +CH_IRQ_HANDLER(STM32_I2C2_GLOBAL_HANDLER) { + uint32_t isr = I2CD2.i2c->ISR; + + CH_IRQ_PROLOGUE(); + + /* Clearing IRQ bits.*/ + I2CD2.i2c->ICR = isr; + + if (isr & I2C_ERROR_MASK) + i2c_lld_serve_error_interrupt(&I2CD2, isr); + else if (isr & I2C_INT_MASK) + i2c_lld_serve_interrupt(&I2CD2, isr); + + CH_IRQ_EPILOGUE(); +} + +#elif defined(STM32_I2C2_EVENT_HANDLER) && defined(STM32_I2C2_ERROR_HANDLER) +CH_IRQ_HANDLER(STM32_I2C2_EVENT_HANDLER) { + uint32_t isr = I2CD2.i2c->ISR; + + CH_IRQ_PROLOGUE(); + + /* Clearing IRQ bits.*/ + I2CD2.i2c->ICR = isr & I2C_INT_MASK; + + i2c_lld_serve_interrupt(&I2CD2, isr); + + CH_IRQ_EPILOGUE(); +} + +CH_IRQ_HANDLER(STM32_I2C2_ERROR_HANDLER) { + uint32_t isr = I2CD2.i2c->ISR; + + CH_IRQ_PROLOGUE(); + + /* Clearing IRQ bits.*/ + I2CD2.i2c->ICR = isr & I2C_ERROR_MASK; + + i2c_lld_serve_error_interrupt(&I2CD2, isr); + + CH_IRQ_EPILOGUE(); +} + +#else +#error "I2C2 interrupt handlers not defined" +#endif +#endif /* STM32_I2C_USE_I2C2 */ + +/*===========================================================================*/ +/* Driver exported functions. */ +/*===========================================================================*/ + +/** + * @brief Low level I2C driver initialization. + * + * @notapi + */ +void i2c_lld_init(void) { + +#if STM32_I2C_USE_I2C1 + i2cObjectInit(&I2CD1); + I2CD1.thread = NULL; + I2CD1.i2c = I2C1; + I2CD1.dmarx = STM32_DMA_STREAM(STM32_I2C_I2C1_RX_DMA_STREAM); + I2CD1.dmatx = STM32_DMA_STREAM(STM32_I2C_I2C1_TX_DMA_STREAM); +#endif /* STM32_I2C_USE_I2C1 */ + +#if STM32_I2C_USE_I2C2 + i2cObjectInit(&I2CD2); + I2CD2.thread = NULL; + I2CD2.i2c = I2C2; + I2CD2.dmarx = STM32_DMA_STREAM(STM32_I2C_I2C2_RX_DMA_STREAM); + I2CD2.dmatx = STM32_DMA_STREAM(STM32_I2C_I2C2_TX_DMA_STREAM); +#endif /* STM32_I2C_USE_I2C2 */ +} + +/** + * @brief Configures and activates the I2C peripheral. + * + * @param[in] i2cp pointer to the @p I2CDriver object + * + * @notapi + */ +void i2c_lld_start(I2CDriver *i2cp) { + I2C_TypeDef *dp = i2cp->i2c; + + i2cp->txdmamode = DMAMODE_COMMON | STM32_DMA_CR_DIR_M2P; + i2cp->rxdmamode = DMAMODE_COMMON | STM32_DMA_CR_DIR_P2M; + + /* Make sure I2C peripheral is disabled */ + dp->CR1 &= ~I2C_CR1_PE; + + /* If in stopped state then enables the I2C and DMA clocks.*/ + if (i2cp->state == I2C_STOP) { + +#if STM32_I2C_USE_I2C1 + if (&I2CD1 == i2cp) { + bool b; + + rccResetI2C1(); + b = dmaStreamAllocate(i2cp->dmarx, + STM32_I2C_I2C1_IRQ_PRIORITY, + (stm32_dmaisr_t)i2c_lld_serve_rx_end_irq, + (void *)i2cp); + osalDbgAssert(!b, "stream already allocated"); + b = dmaStreamAllocate(i2cp->dmatx, + STM32_I2C_I2C1_IRQ_PRIORITY, + (stm32_dmaisr_t)i2c_lld_serve_tx_end_irq, + (void *)i2cp); + osalDbgAssert(!b, "stream already allocated"); + rccEnableI2C1(FALSE); + +#if defined(STM32_I2C1_GLOBAL_NUMBER) || defined(__DOXYGEN__) + nvicEnableVector(STM32_I2C1_GLOBAL_NUMBER, + CORTEX_PRIORITY_MASK(STM32_I2C_I2C1_IRQ_PRIORITY)); +#elif defined(STM32_I2C1_EVENT_NUMBER) && defined(STM32_I2C1_ERROR_NUMBER) + nvicEnableVector(STM32_I2C1_EVENT_NUMBER, STM32_I2C_I2C1_IRQ_PRIORITY); + nvicEnableVector(STM32_I2C1_ERROR_NUMBER, STM32_I2C_I2C1_IRQ_PRIORITY); +#else +#error "I2C1 interrupt numbers not defined" +#endif + + i2cp->rxdmamode |= STM32_DMA_CR_CHSEL(I2C1_RX_DMA_CHANNEL) | + STM32_DMA_CR_PL(STM32_I2C_I2C1_DMA_PRIORITY); + i2cp->txdmamode |= STM32_DMA_CR_CHSEL(I2C1_TX_DMA_CHANNEL) | + STM32_DMA_CR_PL(STM32_I2C_I2C1_DMA_PRIORITY); + } +#endif /* STM32_I2C_USE_I2C1 */ + +#if STM32_I2C_USE_I2C2 + if (&I2CD2 == i2cp) { + bool b; + + rccResetI2C2(); + b = dmaStreamAllocate(i2cp->dmarx, + STM32_I2C_I2C2_IRQ_PRIORITY, + (stm32_dmaisr_t)i2c_lld_serve_rx_end_irq, + (void *)i2cp); + osalDbgAssert(!b, "stream already allocated"); + b = dmaStreamAllocate(i2cp->dmatx, + STM32_I2C_I2C2_IRQ_PRIORITY, + (stm32_dmaisr_t)i2c_lld_serve_tx_end_irq, + (void *)i2cp); + osalDbgAssert(!b, "stream already allocated"); + rccEnableI2C2(FALSE); + +#if defined(STM32_I2C2_GLOBAL_NUMBER) || defined(__DOXYGEN__) + nvicEnableVector(STM32_I2C2_GLOBAL_NUMBER, + CORTEX_PRIORITY_MASK(STM32_I2C_I2C2_IRQ_PRIORITY)); +#elif defined(STM32_I2C2_EVENT_NUMBER) && defined(STM32_I2C2_ERROR_NUMBER) + nvicEnableVector(STM32_I2C2_EVENT_NUMBER, STM32_I2C_I2C2_IRQ_PRIORITY); + nvicEnableVector(STM32_I2C2_ERROR_NUMBER, STM32_I2C_I2C2_IRQ_PRIORITY); +#else +#error "I2C2 interrupt numbers not defined" +#endif + + i2cp->rxdmamode |= STM32_DMA_CR_CHSEL(I2C2_RX_DMA_CHANNEL) | + STM32_DMA_CR_PL(STM32_I2C_I2C2_DMA_PRIORITY); + i2cp->txdmamode |= STM32_DMA_CR_CHSEL(I2C2_TX_DMA_CHANNEL) | + STM32_DMA_CR_PL(STM32_I2C_I2C2_DMA_PRIORITY); + } +#endif /* STM32_I2C_USE_I2C2 */ + } + + /* I2C registers pointed by the DMA.*/ + dmaStreamSetPeripheral(i2cp->dmarx, &dp->RXDR); + dmaStreamSetPeripheral(i2cp->dmatx, &dp->TXDR); + + /* Reset i2c peripheral, the TCIE bit will be handled separately.*/ + dp->CR1 = i2cp->config->cr1 | I2C_CR1_ERRIE | I2C_CR1_STOPIE | + I2C_CR1_NACKIE | I2C_CR1_TXDMAEN | I2C_CR1_RXDMAEN; + + /* Set slave address field (master mode) */ + dp->CR2 = (i2cp->config->cr2 & ~I2C_CR2_SADD); + + /* Setup I2C parameters.*/ + dp->TIMINGR = i2cp->config->timingr; + + /* Ready to go.*/ + dp->CR1 |= I2C_CR1_PE; +} + +/** + * @brief Deactivates the I2C peripheral. + * + * @param[in] i2cp pointer to the @p I2CDriver object + * + * @notapi + */ +void i2c_lld_stop(I2CDriver *i2cp) { + + /* If not in stopped state then disables the I2C clock.*/ + if (i2cp->state != I2C_STOP) { + + /* I2C disable.*/ + i2c_lld_abort_operation(i2cp); + dmaStreamRelease(i2cp->dmatx); + dmaStreamRelease(i2cp->dmarx); + +#if STM32_I2C_USE_I2C1 + if (&I2CD1 == i2cp) { +#if defined(STM32_I2C1_GLOBAL_NUMBER) || defined(__DOXYGEN__) + nvicDisableVector(STM32_I2C1_GLOBAL_NUMBER); +#elif defined(STM32_I2C1_EVENT_NUMBER) && defined(STM32_I2C1_ERROR_NUMBER) + nvicDisableVector(STM32_I2C1_EVENT_NUMBER); + nvicDisableVector(STM32_I2C1_ERROR_NUMBER); +#else +#error "I2C1 interrupt numbers not defined" +#endif + + rccDisableI2C1(FALSE); + } +#endif + +#if STM32_I2C_USE_I2C2 + if (&I2CD2 == i2cp) { +#if defined(STM32_I2C2_GLOBAL_NUMBER) || defined(__DOXYGEN__) + nvicDisableVector(STM32_I2C2_GLOBAL_NUMBER); +#elif defined(STM32_I2C2_EVENT_NUMBER) && defined(STM32_I2C2_ERROR_NUMBER) + nvicDisableVector(STM32_I2C2_EVENT_NUMBER); + nvicDisableVector(STM32_I2C2_ERROR_NUMBER); +#else +#error "I2C2 interrupt numbers not defined" +#endif + + rccDisableI2C2(FALSE); + } +#endif + } +} + +/** + * @brief Receives data via the I2C bus as master. + * @details Number of receiving bytes must be more than 1 on STM32F1x. This is + * hardware restriction. + * + * @param[in] i2cp pointer to the @p I2CDriver object + * @param[in] addr slave device address + * @param[out] rxbuf pointer to the receive buffer + * @param[in] rxbytes number of bytes to be received + * @param[in] timeout the number of ticks before the operation timeouts, + * the following special values are allowed: + * - @a TIME_INFINITE no timeout. + * . + * @return The operation status. + * @retval MSG_OK if the function succeeded. + * @retval MSG_RESET if one or more I2C errors occurred, the errors can + * be retrieved using @p i2cGetErrors(). + * @retval MSG_TIMEOUT if a timeout occurred before operation end. After a + * timeout the driver must be stopped and restarted + * because the bus is in an uncertain state. + * + * @notapi + */ +msg_t i2c_lld_master_receive_timeout(I2CDriver *i2cp, i2caddr_t addr, + uint8_t *rxbuf, size_t rxbytes, + systime_t timeout) { + I2C_TypeDef *dp = i2cp->i2c; + uint32_t addr_cr2 = addr & I2C_CR2_SADD; + systime_t start, end; + + /* Resetting error flags for this transfer.*/ + i2cp->errors = I2C_NO_ERROR; + + /* Releases the lock from high level driver.*/ + osalSysUnlock(); + + /* RX DMA setup.*/ + dmaStreamSetMode(i2cp->dmarx, i2cp->rxdmamode); + dmaStreamSetMemory0(i2cp->dmarx, rxbuf); + dmaStreamSetTransactionSize(i2cp->dmarx, rxbytes); + + /* Calculating the time window for the timeout on the busy bus condition.*/ + start = osalOsGetSystemTimeX(); + end = start + OSAL_MS2ST(STM32_I2C_BUSY_TIMEOUT); + + /* Waits until BUSY flag is reset or, alternatively, for a timeout + condition.*/ + while (true) { + osalSysLock(); + + /* If the bus is not busy then the operation can continue, note, the + loop is exited in the locked state.*/ + if ((dp->ISR & I2C_ISR_BUSY) == 0) + break; + + /* If the system time went outside the allowed window then a timeout + condition is returned.*/ + if (!osalOsIsTimeWithinX(osalOsGetSystemTimeX(), start, end)) + return MSG_TIMEOUT; + + osalSysUnlock(); + } + + /* Adjust slave address (master mode) for 7-bit address mode */ + if ((i2cp->config->cr2 & I2C_CR2_ADD10) == 0) + addr_cr2 = (addr_cr2 & 0x7f) << 1; + + /* Set slave address field (master mode) */ + dp->CR2 &= ~(I2C_CR2_SADD | I2C_CR2_NBYTES); + dp->CR2 |= (rxbytes << 16) | addr_cr2; + + /* Enable RX DMA */ + dmaStreamEnable(i2cp->dmarx); + + /* Starts the operation.*/ + dp->CR2 |= I2C_CR2_RD_WRN; + dp->CR2 |= I2C_CR2_START; + + /* Waits for the operation completion or a timeout.*/ + return osalThreadSuspendTimeoutS(&i2cp->thread, timeout); +} + +/** + * @brief Transmits data via the I2C bus as master. + * @details Number of receiving bytes must be 0 or more than 1 on STM32F1x. + * This is hardware restriction. + * + * @param[in] i2cp pointer to the @p I2CDriver object + * @param[in] addr slave device address + * @param[in] txbuf pointer to the transmit buffer + * @param[in] txbytes number of bytes to be transmitted + * @param[out] rxbuf pointer to the receive buffer + * @param[in] rxbytes number of bytes to be received + * @param[in] timeout the number of ticks before the operation timeouts, + * the following special values are allowed: + * - @a TIME_INFINITE no timeout. + * . + * @return The operation status. + * @retval MSG_OK if the function succeeded. + * @retval MSG_RESET if one or more I2C errors occurred, the errors can + * be retrieved using @p i2cGetErrors(). + * @retval MSG_TIMEOUT if a timeout occurred before operation end. After a + * timeout the driver must be stopped and restarted + * because the bus is in an uncertain state. + * + * @notapi + */ +msg_t i2c_lld_master_transmit_timeout(I2CDriver *i2cp, i2caddr_t addr, + const uint8_t *txbuf, size_t txbytes, + uint8_t *rxbuf, size_t rxbytes, + systime_t timeout) { + I2C_TypeDef *dp = i2cp->i2c; + uint32_t addr_cr2 = addr & I2C_CR2_SADD; + systime_t start, end; + + /* Resetting error flags for this transfer.*/ + i2cp->errors = I2C_NO_ERROR; + + /* Releases the lock from high level driver.*/ + osalSysUnlock(); + + /* TX DMA setup.*/ + dmaStreamSetMode(i2cp->dmatx, i2cp->txdmamode); + dmaStreamSetMemory0(i2cp->dmatx, txbuf); + dmaStreamSetTransactionSize(i2cp->dmatx, txbytes); + + /* RX DMA setup.*/ + dmaStreamSetMode(i2cp->dmarx, i2cp->rxdmamode); + dmaStreamSetMemory0(i2cp->dmarx, rxbuf); + dmaStreamSetTransactionSize(i2cp->dmarx, rxbytes); + + /* Calculating the time window for the timeout on the busy bus condition.*/ + start = osalOsGetSystemTimeX(); + end = start + OSAL_MS2ST(STM32_I2C_BUSY_TIMEOUT); + + /* Waits until BUSY flag is reset or, alternatively, for a timeout + condition.*/ + while (true) { + osalSysLock(); + + /* If the bus is not busy then the operation can continue, note, the + loop is exited in the locked state.*/ + if ((dp->ISR & I2C_ISR_BUSY) == 0) + break; + + /* If the system time went outside the allowed window then a timeout + condition is returned.*/ + if (!osalOsIsTimeWithinX(osalOsGetSystemTimeX(), start, end)) + return MSG_TIMEOUT; + + osalSysUnlock(); + } + + /* Adjust slave address (master mode) for 7-bit address mode */ + if ((i2cp->config->cr2 & I2C_CR2_ADD10) == 0) + addr_cr2 = (addr_cr2 & 0x7f) << 1; + + /* Set slave address field (master mode) */ + dp->CR2 &= ~(I2C_CR2_SADD | I2C_CR2_NBYTES); + dp->CR2 |= (txbytes << 16) | addr_cr2; + + /* Enable TX DMA */ + dmaStreamEnable(i2cp->dmatx); + + /* Transmission complete interrupt enabled.*/ + dp->CR1 |= I2C_CR1_TCIE; + + /* Starts the operation as the very last thing.*/ + dp->CR2 &= ~I2C_CR2_RD_WRN; + dp->CR2 |= I2C_CR2_START; + + /* Waits for the operation completion or a timeout.*/ + return osalThreadSuspendTimeoutS(&i2cp->thread, timeout); +} + +#endif /* HAL_USE_I2C */ + +/** @} */ diff --git a/os/hal/ports/STM32/I2Cv2/i2c_lld.h b/os/hal/ports/STM32/I2Cv2/i2c_lld.h new file mode 100644 index 000000000..ca654d582 --- /dev/null +++ b/os/hal/ports/STM32/I2Cv2/i2c_lld.h @@ -0,0 +1,365 @@ +/* + ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ +/* + Concepts and parts of this file have been contributed by Uladzimir Pylinsky + aka barthess. + */ + +/** + * @file STM32/I2Cv2/i2c_lld.h + * @brief STM32 I2C subsystem low level driver header. + * + * @addtogroup I2C + * @{ + */ + +#ifndef _I2C_LLD_H_ +#define _I2C_LLD_H_ + +#if HAL_USE_I2C || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver constants. */ +/*===========================================================================*/ + +/** + * @name TIMINGR register definitions + * @{ + */ +#define STM32_TIMINGR_PRESC_MASK (15U << 28) +#define STM32_TIMINGR_PRESC(n) ((n) << 28) +#define STM32_TIMINGR_SCLDEL_MASK (15U << 20) +#define STM32_TIMINGR_SCLDEL(n) ((n) << 20) +#define STM32_TIMINGR_SDADEL_MASK (15U << 16) +#define STM32_TIMINGR_SDADEL(n) ((n) << 16) +#define STM32_TIMINGR_SCLH_MASK (255U << 8) +#define STM32_TIMINGR_SCLH(n) ((n) << 8) +#define STM32_TIMINGR_SCLL_MASK (255U << 0) +#define STM32_TIMINGR_SCLL(n) ((n) << 0) +/** @} */ + +/*===========================================================================*/ +/* Driver pre-compile time settings. */ +/*===========================================================================*/ + +/** + * @name Configuration options + * @{ + */ +/** + * @brief I2C1 driver enable switch. + * @details If set to @p TRUE the support for I2C1 is included. + * @note The default is @p FALSE. + */ +#if !defined(STM32_I2C_USE_I2C1) || defined(__DOXYGEN__) +#define STM32_I2C_USE_I2C1 FALSE +#endif + +/** + * @brief I2C2 driver enable switch. + * @details If set to @p TRUE the support for I2C2 is included. + * @note The default is @p FALSE. + */ +#if !defined(STM32_I2C_USE_I2C2) || defined(__DOXYGEN__) +#define STM32_I2C_USE_I2C2 FALSE +#endif + +/** + * @brief I2C timeout on busy condition in milliseconds. + */ +#if !defined(STM32_I2C_BUSY_TIMEOUT) || defined(__DOXYGEN__) +#define STM32_I2C_BUSY_TIMEOUT 50 +#endif + +/** + * @brief I2C1 interrupt priority level setting. + */ +#if !defined(STM32_I2C_I2C1_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_I2C_I2C1_IRQ_PRIORITY 10 +#endif + +/** + * @brief I2C2 interrupt priority level setting. + */ +#if !defined(STM32_I2C_I2C2_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_I2C_I2C2_IRQ_PRIORITY 10 +#endif + +/** + * @brief I2C1 DMA priority (0..3|lowest..highest). + * @note The priority level is used for both the TX and RX DMA streams but + * because of the streams ordering the RX stream has always priority + * over the TX stream. + */ +#if !defined(STM32_I2C_I2C1_DMA_PRIORITY) || defined(__DOXYGEN__) +#define STM32_I2C_I2C1_DMA_PRIORITY 1 +#endif + +/** + * @brief I2C2 DMA priority (0..3|lowest..highest). + * @note The priority level is used for both the TX and RX DMA streams but + * because of the streams ordering the RX stream has always priority + * over the TX stream. + */ +#if !defined(STM32_I2C_I2C2_DMA_PRIORITY) || defined(__DOXYGEN__) +#define STM32_I2C_I2C2_DMA_PRIORITY 1 +#endif + +/** + * @brief I2C DMA error hook. + * @note The default action for DMA errors is a system halt because DMA + * error can only happen because programming errors. + */ +#if !defined(STM32_I2C_DMA_ERROR_HOOK) || defined(__DOXYGEN__) +#define STM32_I2C_DMA_ERROR_HOOK(i2cp) osalSysHalt("DMA failure") +#endif +/** @} */ + +/*===========================================================================*/ +/* Derived constants and error checks. */ +/*===========================================================================*/ + +/* TODO: Move the following DMA settings in the STM32F37X registry.*/ +#if defined(STM32F37X) +#define STM32_I2C_I2C1_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7) +#define STM32_I2C_I2C1_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 6) +#define STM32_I2C_I2C2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 5) +#define STM32_I2C_I2C2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) +#endif + +/** @brief error checks */ +#if STM32_I2C_USE_I2C1 && !STM32_HAS_I2C1 +#error "I2C1 not present in the selected device" +#endif + +#if STM32_I2C_USE_I2C2 && !STM32_HAS_I2C2 +#error "I2C2 not present in the selected device" +#endif + +#if !STM32_I2C_USE_I2C1 && !STM32_I2C_USE_I2C2 +#error "I2C driver activated but no I2C peripheral assigned" +#endif + +#if STM32_I2C_USE_I2C1 && \ + !CORTEX_IS_VALID_KERNEL_PRIORITY(STM32_I2C_I2C1_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to I2C1" +#endif + +#if STM32_I2C_USE_I2C2 && \ + !CORTEX_IS_VALID_KERNEL_PRIORITY(STM32_I2C_I2C2_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to I2C2" +#endif + +#if STM32_I2C_USE_I2C1 && \ + !STM32_DMA_IS_VALID_PRIORITY(STM32_I2C_I2C1_DMA_PRIORITY) +#error "Invalid DMA priority assigned to I2C1" +#endif + +#if STM32_I2C_USE_I2C2 && \ + !STM32_DMA_IS_VALID_PRIORITY(STM32_I2C_I2C2_DMA_PRIORITY) +#error "Invalid DMA priority assigned to I2C2" +#endif + +/* The following checks are only required when there is a DMA able to + reassign streams to different channels.*/ +#if STM32_ADVANCED_DMA +/* Check on the presence of the DMA streams settings in mcuconf.h.*/ +#if STM32_I2C_USE_I2C1 && (!defined(STM32_I2C_I2C1_RX_DMA_STREAM) || \ + !defined(STM32_I2C_I2C1_TX_DMA_STREAM)) +#error "I2C1 DMA streams not defined" +#endif + +#if STM32_I2C_USE_I2C2 && (!defined(STM32_I2C_I2C2_RX_DMA_STREAM) || \ + !defined(STM32_I2C_I2C2_TX_DMA_STREAM)) +#error "I2C2 DMA streams not defined" +#endif + +/* Check on the validity of the assigned DMA channels.*/ +#if STM32_I2C_USE_I2C1 && \ + !STM32_DMA_IS_VALID_ID(STM32_I2C_I2C1_RX_DMA_STREAM, \ + STM32_I2C1_RX_DMA_MSK) +#error "invalid DMA stream associated to I2C1 RX" +#endif + +#if STM32_I2C_USE_I2C1 && \ + !STM32_DMA_IS_VALID_ID(STM32_I2C_I2C1_TX_DMA_STREAM, \ + STM32_I2C1_TX_DMA_MSK) +#error "invalid DMA stream associated to I2C1 TX" +#endif + +#if STM32_I2C_USE_I2C2 && \ + !STM32_DMA_IS_VALID_ID(STM32_I2C_I2C2_RX_DMA_STREAM, \ + STM32_I2C2_RX_DMA_MSK) +#error "invalid DMA stream associated to I2C2 RX" +#endif + +#if STM32_I2C_USE_I2C2 && \ + !STM32_DMA_IS_VALID_ID(STM32_I2C_I2C2_TX_DMA_STREAM, \ + STM32_I2C2_TX_DMA_MSK) +#error "invalid DMA stream associated to I2C2 TX" +#endif +#endif /* STM32_ADVANCED_DMA */ + +#if !defined(STM32_DMA_REQUIRED) +#define STM32_DMA_REQUIRED +#endif + +/* Check clock range. */ + +/*===========================================================================*/ +/* Driver data structures and types. */ +/*===========================================================================*/ + +/** + * @brief Type representing I2C address. + */ +typedef uint16_t i2caddr_t; + +/** + * @brief I2C Driver condition flags type. + */ +typedef uint32_t i2cflags_t; + +/** + * @brief Driver configuration structure. + */ +typedef struct { + /** + * @brief TIMINGR register initialization. + * @note Refer to the STM32 reference manual, the values are affected + * by the system clock settings in mcuconf.h. + */ + uint32_t timingr; + /** + * @brief CR1 register initialization. + * @note Leave to zero unless you know what you are doing. + */ + uint32_t cr1; + /** + * @brief CR2 register initialization. + * @note Only the ADD10 bit can eventually be specified here. + */ + uint32_t cr2; +} I2CConfig; + +/** + * @brief Type of a structure representing an I2C driver. + */ +typedef struct I2CDriver I2CDriver; + +/** + * @brief Structure representing an I2C driver. + */ +struct I2CDriver{ + /** + * @brief Driver state. + */ + i2cstate_t state; + /** + * @brief Current configuration data. + */ + const I2CConfig *config; + /** + * @brief Error flags. + */ + i2cflags_t errors; +#if I2C_USE_MUTUAL_EXCLUSION || defined(__DOXYGEN__) + mutex_t mutex; +#endif /* I2C_USE_MUTUAL_EXCLUSION */ +#if defined(I2C_DRIVER_EXT_FIELDS) + I2C_DRIVER_EXT_FIELDS +#endif + /* End of the mandatory fields.*/ + /** + * @brief Thread waiting for I/O completion. + */ + thread_reference_t thread; + /** + * @brief Current slave address without R/W bit. + */ + i2caddr_t addr; + /** + * @brief RX DMA mode bit mask. + */ + uint32_t rxdmamode; + /** + * @brief TX DMA mode bit mask. + */ + uint32_t txdmamode; + /** + * @brief Receive DMA channel. + */ + const stm32_dma_stream_t *dmarx; + /** + * @brief Transmit DMA channel. + */ + const stm32_dma_stream_t *dmatx; + /** + * @brief Pointer to the I2Cx registers block. + */ + I2C_TypeDef *i2c; +}; + +/*===========================================================================*/ +/* Driver macros. */ +/*===========================================================================*/ + +/** + * @brief Get errors from I2C driver. + * + * @param[in] i2cp pointer to the @p I2CDriver object + * + * @notapi + */ +#define i2c_lld_get_errors(i2cp) ((i2cp)->errors) + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +#if !defined(__DOXYGEN__) +#if STM32_I2C_USE_I2C1 +extern I2CDriver I2CD1; +#endif + +#if STM32_I2C_USE_I2C2 +extern I2CDriver I2CD2; +#endif + +#endif /* !defined(__DOXYGEN__) */ + +#ifdef __cplusplus +extern "C" { +#endif + void i2c_lld_init(void); + void i2c_lld_start(I2CDriver *i2cp); + void i2c_lld_stop(I2CDriver *i2cp); + msg_t i2c_lld_master_transmit_timeout(I2CDriver *i2cp, i2caddr_t addr, + const uint8_t *txbuf, size_t txbytes, + uint8_t *rxbuf, size_t rxbytes, + systime_t timeout); + msg_t i2c_lld_master_receive_timeout(I2CDriver *i2cp, i2caddr_t addr, + uint8_t *rxbuf, size_t rxbytes, + systime_t timeout); +#ifdef __cplusplus +} +#endif + +#endif /* HAL_USE_I2C */ + +#endif /* _I2C_LLD_H_ */ + +/** @} */ diff --git a/os/hal/ports/STM32/OTGv1/stm32_otg.h b/os/hal/ports/STM32/OTGv1/stm32_otg.h new file mode 100644 index 000000000..a78ba57e4 --- /dev/null +++ b/os/hal/ports/STM32/OTGv1/stm32_otg.h @@ -0,0 +1,916 @@ +/* + ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file stm32_otg.h + * @brief STM32 OTG registers layout header. + * + * @addtogroup USB + * @{ + */ + +#ifndef _STM32_OTG_H_ +#define _STM32_OTG_H_ + +/** + * @brief Number of the implemented endpoints in OTG_FS. + * @details This value does not include the endpoint 0 that is always present. + */ +#define STM32_OTG1_ENDOPOINTS_NUMBER 3 + +/** + * @brief Number of the implemented endpoints in OTG_HS. + * @details This value does not include the endpoint 0 that is always present. + */ +#define STM32_OTG2_ENDOPOINTS_NUMBER 5 + +/** + * @brief OTG_FS FIFO memory size in words. + */ +#define STM32_OTG1_FIFO_MEM_SIZE 384 + +/** + * @brief OTG_HS FIFO memory size in words. + */ +#define STM32_OTG2_FIFO_MEM_SIZE 1024 + +/** + * @brief Host channel registers group. + */ +typedef struct { + volatile uint32_t HCCHAR; /**< @brief Host channel characteristics + register. */ + volatile uint32_t resvd8; + volatile uint32_t HCINT; /**< @brief Host channel interrupt register.*/ + volatile uint32_t HCINTMSK; /**< @brief Host channel interrupt mask + register. */ + volatile uint32_t HCTSIZ; /**< @brief Host channel transfer size + register. */ + volatile uint32_t resvd14; + volatile uint32_t resvd18; + volatile uint32_t resvd1c; +} stm32_otg_host_chn_t; + +/** + * @brief Device input endpoint registers group. + */ +typedef struct { + volatile uint32_t DIEPCTL; /**< @brief Device control IN endpoint + control register. */ + volatile uint32_t resvd4; + volatile uint32_t DIEPINT; /**< @brief Device IN endpoint interrupt + register. */ + volatile uint32_t resvdC; + volatile uint32_t DIEPTSIZ; /**< @brief Device IN endpoint transfer size + register. */ + volatile uint32_t resvd14; + volatile uint32_t DTXFSTS; /**< @brief Device IN endpoint transmit FIFO + status register. */ + volatile uint32_t resvd1C; +} stm32_otg_in_ep_t; + +/** + * @brief Device output endpoint registers group. + */ +typedef struct { + volatile uint32_t DOEPCTL; /**< @brief Device control OUT endpoint + control register. */ + volatile uint32_t resvd4; + volatile uint32_t DOEPINT; /**< @brief Device OUT endpoint interrupt + register. */ + volatile uint32_t resvdC; + volatile uint32_t DOEPTSIZ; /**< @brief Device OUT endpoint transfer + size register. */ + volatile uint32_t resvd14; + volatile uint32_t resvd18; + volatile uint32_t resvd1C; +} stm32_otg_out_ep_t; + +/** + * @brief USB registers memory map. + */ +typedef struct { + volatile uint32_t GOTGCTL; /**< @brief OTG control and status register.*/ + volatile uint32_t GOTGINT; /**< @brief OTG interrupt register. */ + volatile uint32_t GAHBCFG; /**< @brief AHB configuration register. */ + volatile uint32_t GUSBCFG; /**< @brief USB configuration register. */ + volatile uint32_t GRSTCTL; /**< @brief Reset register size. */ + volatile uint32_t GINTSTS; /**< @brief Interrupt register. */ + volatile uint32_t GINTMSK; /**< @brief Interrupt mask register. */ + volatile uint32_t GRXSTSR; /**< @brief Receive status debug read + register. */ + volatile uint32_t GRXSTSP; /**< @brief Receive status read/pop + register. */ + volatile uint32_t GRXFSIZ; /**< @brief Receive FIFO size register. */ + volatile uint32_t DIEPTXF0; /**< @brief Endpoint 0 transmit FIFO size + register. */ + volatile uint32_t HNPTXSTS; /**< @brief Non-periodic transmit FIFO/queue + status register. */ + volatile uint32_t resvd30; + volatile uint32_t resvd34; + volatile uint32_t GCCFG; /**< @brief General core configuration. */ + volatile uint32_t CID; /**< @brief Core ID register. */ + volatile uint32_t resvd58[48]; + volatile uint32_t HPTXFSIZ; /**< @brief Host periodic transmit FIFO size + register. */ + volatile uint32_t DIEPTXF[15];/**< @brief Device IN endpoint transmit FIFO + size registers. */ + volatile uint32_t resvd140[176]; + volatile uint32_t HCFG; /**< @brief Host configuration register. */ + volatile uint32_t HFIR; /**< @brief Host frame interval register. */ + volatile uint32_t HFNUM; /**< @brief Host frame number/frame time + Remaining register. */ + volatile uint32_t resvd40C; + volatile uint32_t HPTXSTS; /**< @brief Host periodic transmit FIFO/queue + status register. */ + volatile uint32_t HAINT; /**< @brief Host all channels interrupt + register. */ + volatile uint32_t HAINTMSK; /**< @brief Host all channels interrupt mask + register. */ + volatile uint32_t resvd41C[9]; + volatile uint32_t HPRT; /**< @brief Host port control and status + register. */ + volatile uint32_t resvd444[47]; + stm32_otg_host_chn_t hc[16]; /**< @brief Host channels array. */ + volatile uint32_t resvd700[64]; + volatile uint32_t DCFG; /**< @brief Device configuration register. */ + volatile uint32_t DCTL; /**< @brief Device control register. */ + volatile uint32_t DSTS; /**< @brief Device status register. */ + volatile uint32_t resvd80C; + volatile uint32_t DIEPMSK; /**< @brief Device IN endpoint common + interrupt mask register. */ + volatile uint32_t DOEPMSK; /**< @brief Device OUT endpoint common + interrupt mask register. */ + volatile uint32_t DAINT; /**< @brief Device all endpoints interrupt + register. */ + volatile uint32_t DAINTMSK; /**< @brief Device all endpoints interrupt + mask register. */ + volatile uint32_t resvd820; + volatile uint32_t resvd824; + volatile uint32_t DVBUSDIS; /**< @brief Device VBUS discharge time + register. */ + volatile uint32_t DVBUSPULSE; /**< @brief Device VBUS pulsing time + register. */ + volatile uint32_t resvd830; + volatile uint32_t DIEPEMPMSK; /**< @brief Device IN endpoint FIFO empty + interrupt mask register. */ + volatile uint32_t resvd838; + volatile uint32_t resvd83C; + volatile uint32_t resvd840[16]; + volatile uint32_t resvd880[16]; + volatile uint32_t resvd8C0[16]; + stm32_otg_in_ep_t ie[16]; /**< @brief Input endpoints. */ + stm32_otg_out_ep_t oe[16]; /**< @brief Output endpoints. */ + volatile uint32_t resvdD00[64]; + volatile uint32_t PCGCCTL; /**< @brief Power and clock gating control + register. */ + volatile uint32_t resvdE04[127]; + volatile uint32_t FIFO[16][1024]; +} stm32_otg_t; + +/** + * @name GOTGCTL register bit definitions + * @{ + */ +#define GOTGCTL_BSVLD (1U<<19) /**< B-Session Valid. */ +#define GOTGCTL_ASVLD (1U<<18) /**< A-Session Valid. */ +#define GOTGCTL_DBCT (1U<<17) /**< Long/Short debounce time. */ +#define GOTGCTL_CIDSTS (1U<<16) /**< Connector ID status. */ +#define GOTGCTL_DHNPEN (1U<<11) /**< Device HNP enabled. */ +#define GOTGCTL_HSHNPEN (1U<<10) /**< Host Set HNP enable. */ +#define GOTGCTL_HNPRQ (1U<<9) /**< HNP request. */ +#define GOTGCTL_HNGSCS (1U<<8) /**< Host negotiation success. */ +#define GOTGCTL_SRQ (1U<<1) /**< Session request. */ +#define GOTGCTL_SRQSCS (1U<<0) /**< Session request success. */ +/** @} */ + +/** + * @name GOTGINT register bit definitions + * @{ + */ +#define GOTGINT_DBCDNE (1U<<19) /**< Debounce done. */ +#define GOTGINT_ADTOCHG (1U<<18) /**< A-Device timeout change. */ +#define GOTGINT_HNGDET (1U<<17) /**< Host negotiation detected. */ +#define GOTGINT_HNSSCHG (1U<<9) /**< Host negotiation success + status change. */ +#define GOTGINT_SRSSCHG (1U<<8) /**< Session request success + status change. */ +#define GOTGINT_SEDET (1U<<2) /**< Session end detected. */ +/** @} */ + +/** + * @name GAHBCFG register bit definitions + * @{ + */ +#define GAHBCFG_PTXFELVL (1U<<8) /**< Periodic TxFIFO empty + level. */ +#define GAHBCFG_TXFELVL (1U<<7) /**< Non-periodic TxFIFO empty + level. */ +#define GAHBCFG_DMAEN (1U<<5) /**< DMA enable (HS only). */ +#define GAHBCFG_HBSTLEN_MASK (15U<<1) /**< Burst length/type mask (HS + only). */ +#define GAHBCFG_HBSTLEN(n) ((n)<<1) /**< Burst length/type (HS + only). */ +#define GAHBCFG_GINTMSK (1U<<0) /**< Global interrupt mask. */ +/** @} */ + +/** + * @name GUSBCFG register bit definitions + * @{ + */ +#define GUSBCFG_CTXPKT (1U<<31) /**< Corrupt Tx packet. */ +#define GUSBCFG_FDMOD (1U<<30) /**< Force Device Mode. */ +#define GUSBCFG_FHMOD (1U<<29) /**< Force Host Mode. */ +#define GUSBCFG_TRDT_MASK (15U<<10) /**< USB Turnaround time field + mask. */ +#define GUSBCFG_TRDT(n) ((n)<<10) /**< USB Turnaround time field + value. */ +#define GUSBCFG_HNPCAP (1U<<9) /**< HNP-Capable. */ +#define GUSBCFG_SRPCAP (1U<<8) /**< SRP-Capable. */ +#define GUSBCFG_PHYSEL (1U<<6) /**< USB 2.0 High-Speed PHY or + USB 1.1 Full-Speed serial + transceiver Select. */ +#define GUSBCFG_TOCAL_MASK (7U<<0) /**< HS/FS timeout calibration + field mask. */ +#define GUSBCFG_TOCAL(n) ((n)<<0) /**< HS/FS timeout calibration + field value. */ +/** @} */ + +/** + * @name GRSTCTL register bit definitions + * @{ + */ +#define GRSTCTL_AHBIDL (1U<<31) /**< AHB Master Idle. */ +#define GRSTCTL_TXFNUM_MASK (31U<<6) /**< TxFIFO number field mask. */ +#define GRSTCTL_TXFNUM(n) ((n)<<6) /**< TxFIFO number field value. */ +#define GRSTCTL_TXFFLSH (1U<<5) /**< TxFIFO flush. */ +#define GRSTCTL_RXFFLSH (1U<<4) /**< RxFIFO flush. */ +#define GRSTCTL_FCRST (1U<<2) /**< Host frame counter reset. */ +#define GRSTCTL_HSRST (1U<<1) /**< HClk soft reset. */ +#define GRSTCTL_CSRST (1U<<0) /**< Core soft reset. */ +/** @} */ + +/** + * @name GINTSTS register bit definitions + * @{ + */ +#define GINTSTS_WKUPINT (1U<<31) /**< Resume/Remote wakeup + detected interrupt. */ +#define GINTSTS_SRQINT (1U<<30) /**< Session request/New session + detected interrupt. */ +#define GINTSTS_DISCINT (1U<<29) /**< Disconnect detected + interrupt. */ +#define GINTSTS_CIDSCHG (1U<<28) /**< Connector ID status change.*/ +#define GINTSTS_PTXFE (1U<<26) /**< Periodic TxFIFO empty. */ +#define GINTSTS_HCINT (1U<<25) /**< Host channels interrupt. */ +#define GINTSTS_HPRTINT (1U<<24) /**< Host port interrupt. */ +#define GINTSTS_IPXFR (1U<<21) /**< Incomplete periodic + transfer. */ +#define GINTSTS_IISOOXFR (1U<<21) /**< Incomplete isochronous OUT + transfer. */ +#define GINTSTS_IISOIXFR (1U<<20) /**< Incomplete isochronous IN + transfer. */ +#define GINTSTS_OEPINT (1U<<19) /**< OUT endpoints interrupt. */ +#define GINTSTS_IEPINT (1U<<18) /**< IN endpoints interrupt. */ +#define GINTSTS_EOPF (1U<<15) /**< End of periodic frame + interrupt. */ +#define GINTSTS_ISOODRP (1U<<14) /**< Isochronous OUT packet + dropped interrupt. */ +#define GINTSTS_ENUMDNE (1U<<13) /**< Enumeration done. */ +#define GINTSTS_USBRST (1U<<12) /**< USB reset. */ +#define GINTSTS_USBSUSP (1U<<11) /**< USB suspend. */ +#define GINTSTS_ESUSP (1U<<10) /**< Early suspend. */ +#define GINTSTS_GONAKEFF (1U<<7) /**< Global OUT NAK effective. */ +#define GINTSTS_GINAKEFF (1U<<6) /**< Global IN non-periodic NAK + effective. */ +#define GINTSTS_NPTXFE (1U<<5) /**< Non-periodic TxFIFO empty. */ +#define GINTSTS_RXFLVL (1U<<4) /**< RxFIFO non-empty. */ +#define GINTSTS_SOF (1U<<3) /**< Start of frame. */ +#define GINTSTS_OTGINT (1U<<2) /**< OTG interrupt. */ +#define GINTSTS_MMIS (1U<<1) /**< Mode Mismatch interrupt. */ +#define GINTSTS_CMOD (1U<<0) /**< Current mode of operation. */ +/** @} */ + +/** + * @name GINTMSK register bit definitions + * @{ + */ +#define GINTMSK_WKUM (1U<<31) /**< Resume/remote wakeup + detected interrupt mask. */ +#define GINTMSK_SRQM (1U<<30) /**< Session request/New session + detected interrupt mask. */ +#define GINTMSK_DISCM (1U<<29) /**< Disconnect detected + interrupt mask. */ +#define GINTMSK_CIDSCHGM (1U<<28) /**< Connector ID status change + mask. */ +#define GINTMSK_PTXFEM (1U<<26) /**< Periodic TxFIFO empty mask.*/ +#define GINTMSK_HCM (1U<<25) /**< Host channels interrupt + mask. */ +#define GINTMSK_HPRTM (1U<<24) /**< Host port interrupt mask. */ +#define GINTMSK_IPXFRM (1U<<21) /**< Incomplete periodic + transfer mask. */ +#define GINTMSK_IISOOXFRM (1U<<21) /**< Incomplete isochronous OUT + transfer mask. */ +#define GINTMSK_IISOIXFRM (1U<<20) /**< Incomplete isochronous IN + transfer mask. */ +#define GINTMSK_OEPM (1U<<19) /**< OUT endpoints interrupt + mask. */ +#define GINTMSK_IEPM (1U<<18) /**< IN endpoints interrupt + mask. */ +#define GINTMSK_EOPFM (1U<<15) /**< End of periodic frame + interrupt mask. */ +#define GINTMSK_ISOODRPM (1U<<14) /**< Isochronous OUT packet + dropped interrupt mask. */ +#define GINTMSK_ENUMDNEM (1U<<13) /**< Enumeration done mask. */ +#define GINTMSK_USBRSTM (1U<<12) /**< USB reset mask. */ +#define GINTMSK_USBSUSPM (1U<<11) /**< USB suspend mask. */ +#define GINTMSK_ESUSPM (1U<<10) /**< Early suspend mask. */ +#define GINTMSK_GONAKEFFM (1U<<7) /**< Global OUT NAK effective + mask. */ +#define GINTMSK_GINAKEFFM (1U<<6) /**< Global non-periodic IN NAK + effective mask. */ +#define GINTMSK_NPTXFEM (1U<<5) /**< Non-periodic TxFIFO empty + mask. */ +#define GINTMSK_RXFLVLM (1U<<4) /**< Receive FIFO non-empty + mask. */ +#define GINTMSK_SOFM (1U<<3) /**< Start of (micro)frame mask.*/ +#define GINTMSK_OTGM (1U<<2) /**< OTG interrupt mask. */ +#define GINTMSK_MMISM (1U<<1) /**< Mode Mismatch interrupt + mask. */ +/** @} */ + +/** + * @name GRXSTSR register bit definitions + * @{ + */ +#define GRXSTSR_PKTSTS_MASK (15U<<17) /**< Packet status mask. */ +#define GRXSTSR_PKTSTS(n) ((n)<<17) /**< Packet status value. */ +#define GRXSTSR_OUT_GLOBAL_NAK GRXSTSR_PKTSTS(1) +#define GRXSTSR_OUT_DATA GRXSTSR_PKTSTS(2) +#define GRXSTSR_OUT_COMP GRXSTSR_PKTSTS(3) +#define GRXSTSR_SETUP_COMP GRXSTSR_PKTSTS(4) +#define GRXSTSR_SETUP_DATA GRXSTSR_PKTSTS(6) +#define GRXSTSR_DPID_MASK (3U<<15) /**< Data PID mask. */ +#define GRXSTSR_DPID(n) ((n)<<15) /**< Data PID value. */ +#define GRXSTSR_BCNT_MASK (0x7FF<<4) /**< Byte count mask. */ +#define GRXSTSR_BCNT(n) ((n)<<4) /**< Byte count value. */ +#define GRXSTSR_CHNUM_MASK (15U<<0) /**< Channel number mask. */ +#define GRXSTSR_CHNUM(n) ((n)<<0) /**< Channel number value. */ +#define GRXSTSR_EPNUM_MASK (15U<<0) /**< Endpoint number mask. */ +#define GRXSTSR_EPNUM(n) ((n)<<0) /**< Endpoint number value. */ +/** @} */ + +/** + * @name GRXSTSP register bit definitions + * @{ + */ +#define GRXSTSP_PKTSTS_MASK (15<<17) /**< Packet status mask. */ +#define GRXSTSP_PKTSTS(n) ((n)<<17) /**< Packet status value. */ +#define GRXSTSP_OUT_GLOBAL_NAK GRXSTSP_PKTSTS(1) +#define GRXSTSP_OUT_DATA GRXSTSP_PKTSTS(2) +#define GRXSTSP_OUT_COMP GRXSTSP_PKTSTS(3) +#define GRXSTSP_SETUP_COMP GRXSTSP_PKTSTS(4) +#define GRXSTSP_SETUP_DATA GRXSTSP_PKTSTS(6) +#define GRXSTSP_DPID_MASK (3U<<15) /**< Data PID mask. */ +#define GRXSTSP_DPID(n) ((n)<<15) /**< Data PID value. */ +#define GRXSTSP_BCNT_MASK (0x7FF<<4) /**< Byte count mask. */ +#define GRXSTSP_BCNT_OFF 4 /**< Byte count offset. */ +#define GRXSTSP_BCNT(n) ((n)<<4) /**< Byte count value. */ +#define GRXSTSP_CHNUM_MASK (15U<<0) /**< Channel number mask. */ +#define GRXSTSP_CHNUM(n) ((n)<<0) /**< Channel number value. */ +#define GRXSTSP_EPNUM_MASK (15U<<0) /**< Endpoint number mask. */ +#define GRXSTSP_EPNUM_OFF 0 /**< Endpoint number offset. */ +#define GRXSTSP_EPNUM(n) ((n)<<0) /**< Endpoint number value. */ +/** @} */ + +/** + * @name GRXFSIZ register bit definitions + * @{ + */ +#define GRXFSIZ_RXFD_MASK (0xFFFF<<0) /**< RxFIFO depth mask. */ +#define GRXFSIZ_RXFD(n) ((n)<<0) /**< RxFIFO depth value. */ +/** @} */ + +/** + * @name DIEPTXFx register bit definitions + * @{ + */ +#define DIEPTXF_INEPTXFD_MASK (0xFFFFU<<16)/**< IN endpoint TxFIFO depth + mask. */ +#define DIEPTXF_INEPTXFD(n) ((n)<<16) /**< IN endpoint TxFIFO depth + value. */ +#define DIEPTXF_INEPTXSA_MASK (0xFFFF<<0) /**< IN endpoint FIFOx transmit + RAM start address mask. */ +#define DIEPTXF_INEPTXSA(n) ((n)<<0) /**< IN endpoint FIFOx transmit + RAM start address value. */ +/** @} */ + +/** + * @name GCCFG register bit definitions + * @{ + */ +#define GCCFG_NOVBUSSENS (1U<<21) /**< VBUS sensing disable. */ +#define GCCFG_SOFOUTEN (1U<<20) /**< SOF output enable. */ +#define GCCFG_VBUSBSEN (1U<<19) /**< Enable the VBUS sensing "B" + device. */ +#define GCCFG_VBUSASEN (1U<<18) /**< Enable the VBUS sensing "A" + device. */ +#define GCCFG_PWRDWN (1U<<16) /**< Power down. */ +/** @} */ + +/** + * @name HPTXFSIZ register bit definitions + * @{ + */ +#define HPTXFSIZ_PTXFD_MASK (0xFFFFU<<16)/**< Host periodic TxFIFO + depth mask. */ +#define HPTXFSIZ_PTXFD(n) ((n)<<16) /**< Host periodic TxFIFO + depth value. */ +#define HPTXFSIZ_PTXSA_MASK (0xFFFFU<<0)/**< Host periodic TxFIFO + Start address mask. */ +#define HPTXFSIZ_PTXSA(n) ((n)<<0) /**< Host periodic TxFIFO + start address value. */ +/** @} */ + +/** + * @name HCFG register bit definitions + * @{ + */ +#define HCFG_FSLSS (1U<<2) /**< FS- and LS-only support. */ +#define HCFG_FSLSPCS_MASK (3U<<0) /**< FS/LS PHY clock select + mask. */ +#define HCFG_FSLSPCS_48 (1U<<0) /**< PHY clock is running at + 48 MHz. */ +#define HCFG_FSLSPCS_6 (2U<<0) /**< PHY clock is running at + 6 MHz. */ +/** @} */ + +/** + * @name HFIR register bit definitions + * @{ + */ +#define HFIR_FRIVL_MASK (0xFFFFU<<0)/**< Frame interval mask. */ +#define HFIR_FRIVL(n) ((n)<<0) /**< Frame interval value. */ +/** @} */ + +/** + * @name HFNUM register bit definitions + * @{ + */ +#define HFNUM_FTREM_MASK (0xFFFFU<<16)/**< Frame time Remaining mask.*/ +#define HFNUM_FTREM(n) ((n)<<16) /**< Frame time Remaining value.*/ +#define HFNUM_FRNUM_MASK (0xFFFFU<<0)/**< Frame number mask. */ +#define HFNUM_FRNUM(n) ((n)<<0) /**< Frame number value. */ +/** @} */ + +/** + * @name HPTXSTS register bit definitions + * @{ + */ +#define HPTXSTS_PTXQTOP_MASK (0xFFU<<24) /**< Top of the periodic + transmit request queue + mask. */ +#define HPTXSTS_PTXQTOP(n) ((n)<<24) /**< Top of the periodic + transmit request queue + value. */ +#define HPTXSTS_PTXQSAV_MASK (0xFF<<16) /**< Periodic transmit request + queue Space Available + mask. */ +#define HPTXSTS_PTXQSAV(n) ((n)<<16) /**< Periodic transmit request + queue Space Available + value. */ +#define HPTXSTS_PTXFSAVL_MASK (0xFFFF<<0) /**< Periodic transmit Data + FIFO Space Available + mask. */ +#define HPTXSTS_PTXFSAVL(n) ((n)<<0) /**< Periodic transmit Data + FIFO Space Available + value. */ +/** @} */ + +/** + * @name HAINT register bit definitions + * @{ + */ +#define HAINT_HAINT_MASK (0xFFFFU<<0)/**< Channel interrupts mask. */ +#define HAINT_HAINT(n) ((n)<<0) /**< Channel interrupts value. */ +/** @} */ + +/** + * @name HAINTMSK register bit definitions + * @{ + */ +#define HAINTMSK_HAINTM_MASK (0xFFFFU<<0)/**< Channel interrupt mask + mask. */ +#define HAINTMSK_HAINTM(n) ((n)<<0) /**< Channel interrupt mask + value. */ +/** @} */ + +/** + * @name HPRT register bit definitions + * @{ + */ +#define HPRT_PSPD_MASK (3U<<17) /**< Port speed mask. */ +#define HPRT_PSPD_FS (1U<<17) /**< Full speed value. */ +#define HPRT_PSPD_LS (2U<<17) /**< Low speed value. */ +#define HPRT_PTCTL_MASK (15<<13) /**< Port Test control mask. */ +#define HPRT_PTCTL(n) ((n)<<13) /**< Port Test control value. */ +#define HPRT_PPWR (1U<<12) /**< Port power. */ +#define HPRT_PLSTS_MASK (3U<<11) /**< Port Line status mask. */ +#define HPRT_PLSTS_DM (1U<<11) /**< Logic level of D-. */ +#define HPRT_PLSTS_DP (1U<<10) /**< Logic level of D+. */ +#define HPRT_PRST (1U<<8) /**< Port reset. */ +#define HPRT_PSUSP (1U<<7) /**< Port suspend. */ +#define HPRT_PRES (1U<<6) /**< Port Resume. */ +#define HPRT_POCCHNG (1U<<5) /**< Port overcurrent change. */ +#define HPRT_POCA (1U<<4) /**< Port overcurrent active. */ +#define HPRT_PENCHNG (1U<<3) /**< Port enable/disable change.*/ +#define HPRT_PENA (1U<<2) /**< Port enable. */ +#define HPRT_PCDET (1U<<1) /**< Port Connect detected. */ +#define HPRT_PCSTS (1U<<0) /**< Port connect status. */ +/** @} */ + +/** + * @name HCCHAR register bit definitions + * @{ + */ +#define HCCHAR_CHENA (1U<<31) /**< Channel enable. */ +#define HCCHAR_CHDIS (1U<<30) /**< Channel Disable. */ +#define HCCHAR_ODDFRM (1U<<29) /**< Odd frame. */ +#define HCCHAR_DAD_MASK (0x7FU<<22) /**< Device Address mask. */ +#define HCCHAR_DAD(n) ((n)<<22) /**< Device Address value. */ +#define HCCHAR_MCNT_MASK (3U<<20) /**< Multicount mask. */ +#define HCCHAR_MCNT(n) ((n)<<20) /**< Multicount value. */ +#define HCCHAR_EPTYP_MASK (3U<<18) /**< Endpoint type mask. */ +#define HCCHAR_EPTYP(n) ((n)<<18) /**< Endpoint type value. */ +#define HCCHAR_EPTYP_CTL (0U<<18) /**< Control endpoint value. */ +#define HCCHAR_EPTYP_ISO (1U<<18) /**< Isochronous endpoint value.*/ +#define HCCHAR_EPTYP_BULK (2U<<18) /**< Bulk endpoint value. */ +#define HCCHAR_EPTYP_INTR (3U<<18) /**< Interrupt endpoint value. */ +#define HCCHAR_LSDEV (1U<<17) /**< Low-Speed device. */ +#define HCCHAR_EPDIR (1U<<15) /**< Endpoint direction. */ +#define HCCHAR_EPNUM_MASK (15U<<11) /**< Endpoint number mask. */ +#define HCCHAR_EPNUM(n) ((n)<<11) /**< Endpoint number value. */ +#define HCCHAR_MPS_MASK (11U<<0) /**< Maximum packet size mask. */ +#define HCCHAR_MPS(n) (11U<<0) /**< Maximum packet size value. */ +/** @} */ + +/** + * @name HCINT register bit definitions + * @{ + */ +#define HCINT_DTERR (1U<<10) /**< Data toggle error. */ +#define HCINT_FRMOR (1U<<9) /**< Frame overrun. */ +#define HCINT_BBERR (1U<<8) /**< Babble error. */ +#define HCINT_TRERR (1U<<7) /**< Transaction Error. */ +#define HCINT_ACK (1U<<5) /**< ACK response + received/transmitted + interrupt. */ +#define HCINT_NAK (1U<<4) /**< NAK response received + interrupt. */ +#define HCINT_STALL (1U<<3) /**< STALL response received + interrupt. */ +#define HCINT_CHH (1U<<1) /**< Channel halted. */ +#define HCINT_XFRC (1U<<0) /**< Transfer completed. */ +/** @} */ + +/** + * @name HCINTMSK register bit definitions + * @{ + */ +#define HCINTMSK_DTERRM (1U<<10) /**< Data toggle error mask. */ +#define HCINTMSK_FRMORM (1U<<9) /**< Frame overrun mask. */ +#define HCINTMSK_BBERRM (1U<<8) /**< Babble error mask. */ +#define HCINTMSK_TRERRM (1U<<7) /**< Transaction error mask. */ +#define HCINTMSK_NYET (1U<<6) /**< NYET response received + interrupt mask. */ +#define HCINTMSK_ACKM (1U<<5) /**< ACK Response + received/transmitted + interrupt mask. */ +#define HCINTMSK_NAKM (1U<<4) /**< NAK response received + interrupt mask. */ +#define HCINTMSK_STALLM (1U<<3) /**< STALL response received + interrupt mask. */ +#define HCINTMSK_CHHM (1U<<1) /**< Channel halted mask. */ +#define HCINTMSK_XFRCM (1U<<0) /**< Transfer completed mask. */ +/** @} */ + +/** + * @name HCTSIZ register bit definitions + * @{ + */ +#define HCTSIZ_DPID_MASK (3U<<29) /**< PID mask. */ +#define HCTSIZ_DPID_DATA0 (0U<<29) /**< DATA0. */ +#define HCTSIZ_DPID_DATA2 (1U<<29) /**< DATA2. */ +#define HCTSIZ_DPID_DATA1 (2U<<29) /**< DATA1. */ +#define HCTSIZ_DPID_MDATA (3U<<29) /**< MDATA. */ +#define HCTSIZ_PKTCNT_MASK (0x3FFU<<19)/**< Packet count mask. */ +#define HCTSIZ_PKTCNT(n) ((n)<<19) /**< Packet count value. */ +#define HCTSIZ_XFRSIZ_MASK (0x7FFFF<<0)/**< Transfer size mask. */ +#define HCTSIZ_XFRSIZ(n) ((n)<<0) /**< Transfer size value. */ +/** @} */ + +/** + * @name DCFG register bit definitions + * @{ + */ +#define DCFG_PFIVL_MASK (3U<<11) /**< Periodic frame interval + mask. */ +#define DCFG_PFIVL(n) ((n)<<11) /**< Periodic frame interval + value. */ +#define DCFG_DAD_MASK (0x7FU<<4) /**< Device address mask. */ +#define DCFG_DAD(n) ((n)<<4) /**< Device address value. */ +#define DCFG_NZLSOHSK (1U<<2) /**< Non-Zero-Length status + OUT handshake. */ +#define DCFG_DSPD_MASK (3U<<0) /**< Device speed mask. */ +#define DCFG_DSPD_HS (0U<<0) /**< High speed (USB 2.0). */ +#define DCFG_DSPD_HS_FS (1U<<0) /**< High speed (USB 2.0) in FS + mode. */ +#define DCFG_DSPD_FS11 (3U<<0) /**< Full speed (USB 1.1 + transceiver clock is 48 + MHz). */ +/** @} */ + +/** + * @name DCTL register bit definitions + * @{ + */ +#define DCTL_POPRGDNE (1U<<11) /**< Power-on programming done. */ +#define DCTL_CGONAK (1U<<10) /**< Clear global OUT NAK. */ +#define DCTL_SGONAK (1U<<9) /**< Set global OUT NAK. */ +#define DCTL_CGINAK (1U<<8) /**< Clear global non-periodic + IN NAK. */ +#define DCTL_SGINAK (1U<<7) /**< Set global non-periodic + IN NAK. */ +#define DCTL_TCTL_MASK (7U<<4) /**< Test control mask. */ +#define DCTL_TCTL(n) ((n)<<4 /**< Test control value. */ +#define DCTL_GONSTS (1U<<3) /**< Global OUT NAK status. */ +#define DCTL_GINSTS (1U<<2) /**< Global non-periodic IN + NAK status. */ +#define DCTL_SDIS (1U<<1) /**< Soft disconnect. */ +#define DCTL_RWUSIG (1U<<0) /**< Remote wakeup signaling. */ +/** @} */ + +/** + * @name DSTS register bit definitions + * @{ + */ +#define DSTS_FNSOF_MASK (0x3FFU<<8) /**< Frame number of the received + SOF mask. */ +#define DSTS_FNSOF(n) ((n)<<8) /**< Frame number of the received + SOF value. */ +#define DSTS_EERR (1U<<3) /**< Erratic error. */ +#define DSTS_ENUMSPD_MASK (3U<<1) /**< Enumerated speed mask. */ +#define DSTS_ENUMSPD_FS_48 (3U<<1) /**< Full speed (PHY clock is + running at 48 MHz). */ +#define DSTS_SUSPSTS (1U<<0) /**< Suspend status. */ +/** @} */ + +/** + * @name DIEPMSK register bit definitions + * @{ + */ +#define DIEPMSK_TXFEM (1U<<6) /**< Transmit FIFO empty mask. */ +#define DIEPMSK_INEPNEM (1U<<6) /**< IN endpoint NAK effective + mask. */ +#define DIEPMSK_ITTXFEMSK (1U<<4) /**< IN token received when + TxFIFO empty mask. */ +#define DIEPMSK_TOCM (1U<<3) /**< Timeout condition mask. */ +#define DIEPMSK_EPDM (1U<<1) /**< Endpoint disabled + interrupt mask. */ +#define DIEPMSK_XFRCM (1U<<0) /**< Transfer completed + interrupt mask. */ +/** @} */ + +/** + * @name DOEPMSK register bit definitions + * @{ + */ +#define DOEPMSK_OTEPDM (1U<<4) /**< OUT token received when + endpoint disabled mask. */ +#define DOEPMSK_STUPM (1U<<3) /**< SETUP phase done mask. */ +#define DOEPMSK_EPDM (1U<<1) /**< Endpoint disabled + interrupt mask. */ +#define DOEPMSK_XFRCM (1U<<0) /**< Transfer completed + interrupt mask. */ +/** @} */ + +/** + * @name DAINT register bit definitions + * @{ + */ +#define DAINT_OEPINT_MASK (0xFFFFU<<16)/**< OUT endpoint interrupt + bits mask. */ +#define DAINT_OEPINT(n) ((n)<<16) /**< OUT endpoint interrupt + bits value. */ +#define DAINT_IEPINT_MASK (0xFFFFU<<0)/**< IN endpoint interrupt + bits mask. */ +#define DAINT_IEPINT(n) ((n)<<0) /**< IN endpoint interrupt + bits value. */ +/** @} */ + +/** + * @name DAINTMSK register bit definitions + * @{ + */ +#define DAINTMSK_OEPM_MASK (0xFFFFU<<16)/**< OUT EP interrupt mask + bits mask. */ +#define DAINTMSK_OEPM(n) (1U<<(16+(n)))/**< OUT EP interrupt mask + bits value. */ +#define DAINTMSK_IEPM_MASK (0xFFFFU<<0)/**< IN EP interrupt mask + bits mask. */ +#define DAINTMSK_IEPM(n) (1U<<(n)) /**< IN EP interrupt mask + bits value. */ +/** @} */ + +/** + * @name DVBUSDIS register bit definitions + * @{ + */ +#define DVBUSDIS_VBUSDT_MASK (0xFFFFU<<0)/**< Device VBUS discharge + time mask. */ +#define DVBUSDIS_VBUSDT(n) ((n)<<0) /**< Device VBUS discharge + time value. */ +/** @} */ + +/** + * @name DVBUSPULSE register bit definitions + * @{ + */ +#define DVBUSPULSE_DVBUSP_MASK (0xFFFU<<0) /**< Device VBUSpulsing time + mask. */ +#define DVBUSPULSE_DVBUSP(n) ((n)<<0) /**< Device VBUS pulsing time + value. */ +/** @} */ + +/** + * @name DIEPEMPMSK register bit definitions + * @{ + */ +#define DIEPEMPMSK_INEPTXFEM(n) (1U<<(n)) /**< IN EP Tx FIFO empty + interrupt mask bit. */ +/** @} */ + +/** + * @name DIEPCTL register bit definitions + * @{ + */ +#define DIEPCTL_EPENA (1U<<31) /**< Endpoint enable. */ +#define DIEPCTL_EPDIS (1U<<30) /**< Endpoint disable. */ +#define DIEPCTL_SD1PID (1U<<29) /**< Set DATA1 PID. */ +#define DIEPCTL_SODDFRM (1U<<29) /**< Set odd frame. */ +#define DIEPCTL_SD0PID (1U<<28) /**< Set DATA0 PID. */ +#define DIEPCTL_SEVNFRM (1U<<28) /**< Set even frame. */ +#define DIEPCTL_SNAK (1U<<27) /**< Set NAK. */ +#define DIEPCTL_CNAK (1U<<26) /**< Clear NAK. */ +#define DIEPCTL_TXFNUM_MASK (15U<<22) /**< TxFIFO number mask. */ +#define DIEPCTL_TXFNUM(n) ((n)<<22) /**< TxFIFO number value. */ +#define DIEPCTL_STALL (1U<<21) /**< STALL handshake. */ +#define DIEPCTL_SNPM (1U<<20) /**< Snoop mode. */ +#define DIEPCTL_EPTYP_MASK (3<<18) /**< Endpoint type mask. */ +#define DIEPCTL_EPTYP_CTRL (0U<<18) /**< Control. */ +#define DIEPCTL_EPTYP_ISO (1U<<18) /**< Isochronous. */ +#define DIEPCTL_EPTYP_BULK (2U<<18) /**< Bulk. */ +#define DIEPCTL_EPTYP_INTR (3U<<18) /**< Interrupt. */ +#define DIEPCTL_NAKSTS (1U<<17) /**< NAK status. */ +#define DIEPCTL_EONUM (1U<<16) /**< Even/odd frame. */ +#define DIEPCTL_DPID (1U<<16) /**< Endpoint data PID. */ +#define DIEPCTL_USBAEP (1U<<15) /**< USB active endpoint. */ +#define DIEPCTL_MPSIZ_MASK (0x3FFU<<0) /**< Maximum Packet size mask. */ +#define DIEPCTL_MPSIZ(n) ((n)<<0) /**< Maximum Packet size value. */ +/** @} */ + +/** + * @name DIEPINT register bit definitions + * @{ + */ +#define DIEPINT_TXFE (1U<<7) /**< Transmit FIFO empty. */ +#define DIEPINT_INEPNE (1U<<6) /**< IN endpoint NAK effective. */ +#define DIEPINT_ITTXFE (1U<<4) /**< IN Token received when + TxFIFO is empty. */ +#define DIEPINT_TOC (1U<<3) /**< Timeout condition. */ +#define DIEPINT_EPDISD (1U<<1) /**< Endpoint disabled + interrupt. */ +#define DIEPINT_XFRC (1U<<0) /**< Transfer completed. */ +/** @} */ + +/** + * @name DIEPTSIZ register bit definitions + * @{ + */ +#define DIEPTSIZ_MCNT_MASK (3U<<29) /**< Multi count mask. */ +#define DIEPTSIZ_MCNT(n) ((n)<<29) /**< Multi count value. */ +#define DIEPTSIZ_PKTCNT_MASK (0x3FF<<19) /**< Packet count mask. */ +#define DIEPTSIZ_PKTCNT(n) ((n)<<19) /**< Packet count value. */ +#define DIEPTSIZ_XFRSIZ_MASK (0x7FFFFU<<0)/**< Transfer size mask. */ +#define DIEPTSIZ_XFRSIZ(n) ((n)<<0) /**< Transfer size value. */ +/** @} */ + +/** + * @name DTXFSTS register bit definitions. + * @{ + */ +#define DTXFSTS_INEPTFSAV_MASK (0xFFFF<<0) /**< IN endpoint TxFIFO space + available. */ +/** @} */ + +/** + * @name DOEPCTL register bit definitions. + * @{ + */ +#define DOEPCTL_EPENA (1U<<31) /**< Endpoint enable. */ +#define DOEPCTL_EPDIS (1U<<30) /**< Endpoint disable. */ +#define DOEPCTL_SD1PID (1U<<29) /**< Set DATA1 PID. */ +#define DOEPCTL_SODDFRM (1U<<29) /**< Set odd frame. */ +#define DOEPCTL_SD0PID (1U<<28) /**< Set DATA0 PID. */ +#define DOEPCTL_SEVNFRM (1U<<28) /**< Set even frame. */ +#define DOEPCTL_SNAK (1U<<27) /**< Set NAK. */ +#define DOEPCTL_CNAK (1U<<26) /**< Clear NAK. */ +#define DOEPCTL_STALL (1U<<21) /**< STALL handshake. */ +#define DOEPCTL_SNPM (1U<<20) /**< Snoop mode. */ +#define DOEPCTL_EPTYP_MASK (3U<<18) /**< Endpoint type mask. */ +#define DOEPCTL_EPTYP_CTRL (0U<<18) /**< Control. */ +#define DOEPCTL_EPTYP_ISO (1U<<18) /**< Isochronous. */ +#define DOEPCTL_EPTYP_BULK (2U<<18) /**< Bulk. */ +#define DOEPCTL_EPTYP_INTR (3U<<18) /**< Interrupt. */ +#define DOEPCTL_NAKSTS (1U<<17) /**< NAK status. */ +#define DOEPCTL_EONUM (1U<<16) /**< Even/odd frame. */ +#define DOEPCTL_DPID (1U<<16) /**< Endpoint data PID. */ +#define DOEPCTL_USBAEP (1U<<15) /**< USB active endpoint. */ +#define DOEPCTL_MPSIZ_MASK (0x3FFU<<0) /**< Maximum Packet size mask. */ +#define DOEPCTL_MPSIZ(n) ((n)<<0) /**< Maximum Packet size value. */ +/** @} */ + +/** + * @name DOEPINT register bit definitions + * @{ + */ +#define DOEPINT_B2BSTUP (1U<<6) /**< Back-to-back SETUP packets + received. */ +#define DOEPINT_OTEPDIS (1U<<4) /**< OUT token received when + endpoint disabled. */ +#define DOEPINT_STUP (1U<<3) /**< SETUP phase done. */ +#define DOEPINT_EPDISD (1U<<1) /**< Endpoint disabled + interrupt. */ +#define DOEPINT_XFRC (1U<<0) /**< Transfer completed + interrupt. */ +/** @} */ + +/** + * @name DOEPTSIZ register bit definitions + * @{ + */ +#define DOEPTSIZ_RXDPID_MASK (3U<<29) /**< Received data PID mask. */ +#define DOEPTSIZ_RXDPID(n) ((n)<<29) /**< Received data PID value. */ +#define DOEPTSIZ_STUPCNT_MASK (3U<<29) /**< SETUP packet count mask. */ +#define DOEPTSIZ_STUPCNT(n) ((n)<<29) /**< SETUP packet count value. */ +#define DOEPTSIZ_PKTCNT_MASK (0x3FFU<<19)/**< Packet count mask. */ +#define DOEPTSIZ_PKTCNT(n) ((n)<<19) /**< Packet count value. */ +#define DOEPTSIZ_XFRSIZ_MASK (0x7FFFFU<<0)/**< Transfer size mask. */ +#define DOEPTSIZ_XFRSIZ(n) ((n)<<0) /**< Transfer size value. */ +/** @} */ + +/** + * @name PCGCCTL register bit definitions + * @{ + */ +#define PCGCCTL_PHYSUSP (1U<<4) /**< PHY Suspended. */ +#define PCGCCTL_GATEHCLK (1U<<1) /**< Gate HCLK. */ +#define PCGCCTL_STPPCLK (1U<<0) /**< Stop PCLK. */ +/** @} */ + +/** + * @brief OTG_FS registers block memory address. + */ +#define OTG_FS_ADDR 0x50000000 + +/** + * @brief OTG_HS registers block memory address. + */ +#define OTG_HS_ADDR 0x40040000 + +/** + * @brief Accesses to the OTG_FS registers block. + */ +#define OTG_FS ((stm32_otg_t *)OTG_FS_ADDR) + +/** + * @brief Accesses to the OTG_HS registers block. + */ +#define OTG_HS ((stm32_otg_t *)OTG_HS_ADDR) + +#endif /* _STM32_OTG_H_ */ + +/** @} */ diff --git a/os/hal/ports/STM32/OTGv1/usb_lld.c b/os/hal/ports/STM32/OTGv1/usb_lld.c new file mode 100644 index 000000000..f6287a49c --- /dev/null +++ b/os/hal/ports/STM32/OTGv1/usb_lld.c @@ -0,0 +1,1300 @@ +/* + ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file STM32/OTGv1/usb_lld.c + * @brief STM32 USB subsystem low level driver source. + * + * @addtogroup USB + * @{ + */ + +#include + +#include "ch.h" +#include "hal.h" + +#if HAL_USE_USB || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver local definitions. */ +/*===========================================================================*/ + +#define TRDT_VALUE 5 + +/*===========================================================================*/ +/* Driver exported variables. */ +/*===========================================================================*/ + +/** @brief OTG_FS driver identifier.*/ +#if STM32_USB_USE_OTG1 || defined(__DOXYGEN__) +USBDriver USBD1; +#endif + +/** @brief OTG_HS driver identifier.*/ +#if STM32_USB_USE_OTG2 || defined(__DOXYGEN__) +USBDriver USBD2; +#endif + +/*===========================================================================*/ +/* Driver local variables and types. */ +/*===========================================================================*/ + +/** + * @brief EP0 state. + * @note It is an union because IN and OUT endpoints are never used at the + * same time for EP0. + */ +static union { + /** + * @brief IN EP0 state. + */ + USBInEndpointState in; + /** + * @brief OUT EP0 state. + */ + USBOutEndpointState out; +} ep0_state; + +/** + * @brief Buffer for the EP0 setup packets. + */ +static uint8_t ep0setup_buffer[8]; + +/** + * @brief EP0 initialization structure. + */ +static const USBEndpointConfig ep0config = { + USB_EP_MODE_TYPE_CTRL, + _usb_ep0setup, + _usb_ep0in, + _usb_ep0out, + 0x40, + 0x40, + &ep0_state.in, + &ep0_state.out, + 1, + ep0setup_buffer +}; + +#if STM32_USB_USE_OTG1 +static const stm32_otg_params_t fsparams = { + STM32_USB_OTG1_RX_FIFO_SIZE / 4, + STM32_OTG1_FIFO_MEM_SIZE, + STM32_OTG1_ENDOPOINTS_NUMBER +}; +#endif + +#if STM32_USB_USE_OTG2 +static const stm32_otg_params_t hsparams = { + STM32_USB_OTG2_RX_FIFO_SIZE / 4, + STM32_OTG2_FIFO_MEM_SIZE, + STM32_OTG2_ENDOPOINTS_NUMBER +}; +#endif + +/*===========================================================================*/ +/* Driver local functions. */ +/*===========================================================================*/ + +/** + * @brief Wakes up the pump thread. + * + * @param[in] usbp pointer to the @p USBDriver object + * + * @notapi + */ +static void usb_lld_wakeup_pump(USBDriver *usbp) { + + if (usbp->thd_wait != NULL) { + chThdResumeI(usbp->thd_wait); + usbp->thd_wait = NULL; + } +} + +static void otg_core_reset(USBDriver *usbp) { + stm32_otg_t *otgp = usbp->otg; + + /* Core reset and delay of at least 3 PHY cycles.*/ + otgp->GRSTCTL = GRSTCTL_CSRST; + while ((otgp->GRSTCTL & GRSTCTL_CSRST) != 0) + ; + halPolledDelay(12); + /* Wait AHB idle condition.*/ + while ((otgp->GRSTCTL & GRSTCTL_AHBIDL) == 0) + ; +} + +static void otg_disable_ep(USBDriver *usbp) { + stm32_otg_t *otgp = usbp->otg; + unsigned i; + + for (i = 0; i <= usbp->otgparams->num_endpoints; i++) { + /* Disable only if enabled because this sentence in the manual: + "The application must set this bit only if Endpoint Enable is + already set for this endpoint".*/ + if ((otgp->ie[i].DIEPCTL & DIEPCTL_EPENA) != 0) { + otgp->ie[i].DIEPCTL = DIEPCTL_EPDIS; + /* Wait for endpoint disable.*/ + while (!(otgp->ie[i].DIEPINT & DIEPINT_EPDISD)) + ; + } + else + otgp->ie[i].DIEPCTL = 0; + otgp->ie[i].DIEPTSIZ = 0; + otgp->ie[i].DIEPINT = 0xFFFFFFFF; + /* Disable only if enabled because this sentence in the manual: + "The application must set this bit only if Endpoint Enable is + already set for this endpoint". + Note that the attempt to disable the OUT EP0 is ignored by the + hardware but the code is simpler this way.*/ + if ((otgp->oe[i].DOEPCTL & DOEPCTL_EPENA) != 0) { + otgp->oe[i].DOEPCTL = DOEPCTL_EPDIS; + /* Wait for endpoint disable.*/ + while (!(otgp->oe[i].DOEPINT & DOEPINT_OTEPDIS)) + ; + } + else + otgp->oe[i].DOEPCTL = 0; + otgp->oe[i].DOEPTSIZ = 0; + otgp->oe[i].DOEPINT = 0xFFFFFFFF; + } + otgp->DAINTMSK = DAINTMSK_OEPM(0) | DAINTMSK_IEPM(0); +} + +static void otg_rxfifo_flush(USBDriver *usbp) { + stm32_otg_t *otgp = usbp->otg; + + otgp->GRSTCTL = GRSTCTL_RXFFLSH; + while ((otgp->GRSTCTL & GRSTCTL_RXFFLSH) != 0) + ; + /* Wait for 3 PHY Clocks.*/ + halPolledDelay(12); +} + +static void otg_txfifo_flush(USBDriver *usbp, uint32_t fifo) { + stm32_otg_t *otgp = usbp->otg; + + otgp->GRSTCTL = GRSTCTL_TXFNUM(fifo) | GRSTCTL_TXFFLSH; + while ((otgp->GRSTCTL & GRSTCTL_TXFFLSH) != 0) + ; + /* Wait for 3 PHY Clocks.*/ + halPolledDelay(12); +} + +/** + * @brief Resets the FIFO RAM memory allocator. + * + * @param[in] usbp pointer to the @p USBDriver object + * + * @notapi + */ +static void otg_ram_reset(USBDriver *usbp) { + + usbp->pmnext = usbp->otgparams->rx_fifo_size; +} + +/** + * @brief Allocates a block from the FIFO RAM memory. + * + * @param[in] usbp pointer to the @p USBDriver object + * @param[in] size size of the packet buffer to allocate in words + * + * @notapi + */ +static uint32_t otg_ram_alloc(USBDriver *usbp, size_t size) { + uint32_t next; + + next = usbp->pmnext; + usbp->pmnext += size; + chDbgAssert(usbp->pmnext <= usbp->otgparams->otg_ram_size, + "otg_fifo_alloc(), #1", "OTG FIFO memory overflow"); + return next; +} + +/** + * @brief Pushes a series of words into a FIFO. + * + * @param[in] fifop pointer to the FIFO register + * @param[in] buf pointer to the words buffer, not necessarily word + * aligned + * @param[in] n number of words to push + * + * @return A pointer after the last word pushed. + * + * @notapi + */ +static uint8_t *otg_do_push(volatile uint32_t *fifop, uint8_t *buf, size_t n) { + + while (n > 0) { + /* Note, this line relies on the Cortex-M3/M4 ability to perform + unaligned word accesses and on the LSB-first memory organization.*/ + *fifop = *((uint32_t *)buf); + buf += 4; + n--; + } + return buf; +} + +/** + * @brief Writes to a TX FIFO. + * + * @param[in] fifop pointer to the FIFO register + * @param[in] buf buffer where to copy the endpoint data + * @param[in] n maximum number of bytes to copy + * + * @notapi + */ +static void otg_fifo_write_from_buffer(volatile uint32_t *fifop, + const uint8_t *buf, + size_t n) { + + otg_do_push(fifop, (uint8_t *)buf, (n + 3) / 4); +} + +/** + * @brief Writes to a TX FIFO fetching data from a queue. + * + * @param[in] fifop pointer to the FIFO register + * @param[in] oqp pointer to an @p OutputQueue object + * @param[in] n maximum number of bytes to copy + * + * @notapi + */ +static void otg_fifo_write_from_queue(volatile uint32_t *fifop, + OutputQueue *oqp, + size_t n) { + size_t ntogo; + + ntogo = n; + while (ntogo > 0) { + uint32_t w, i; + size_t nw = ntogo / 4; + + if (nw > 0) { + size_t streak; + uint32_t nw2end = (oqp->q_top - oqp->q_rdptr) / 4; + + ntogo -= (streak = nw <= nw2end ? nw : nw2end) * 4; + oqp->q_rdptr = otg_do_push(fifop, oqp->q_rdptr, streak); + if (oqp->q_rdptr >= oqp->q_top) { + oqp->q_rdptr = oqp->q_buffer; + continue; + } + } + + /* If this condition is not satisfied then there is a word lying across + queue circular buffer boundary or there are some remaining bytes.*/ + if (ntogo <= 0) + break; + + /* One byte at time.*/ + w = 0; + i = 0; + while ((ntogo > 0) && (i < 4)) { + w |= (uint32_t)*oqp->q_rdptr++ << (i * 8); + if (oqp->q_rdptr >= oqp->q_top) + oqp->q_rdptr = oqp->q_buffer; + ntogo--; + i++; + } + *fifop = w; + } + + /* Updating queue.*/ + chSysLock(); + oqp->q_counter += n; + while (notempty(&oqp->q_waiting)) + chSchReadyI(fifo_remove(&oqp->q_waiting))->p_u.rdymsg = Q_OK; + chSchRescheduleS(); + chSysUnlock(); +} + +/** + * @brief Pops a series of words from a FIFO. + * + * @param[in] fifop pointer to the FIFO register + * @param[in] buf pointer to the words buffer, not necessarily word + * aligned + * @param[in] n number of words to push + * + * @return A pointer after the last word pushed. + * + * @notapi + */ +static uint8_t *otg_do_pop(volatile uint32_t *fifop, uint8_t *buf, size_t n) { + + while (n > 0) { + uint32_t w = *fifop; + /* Note, this line relies on the Cortex-M3/M4 ability to perform + unaligned word accesses and on the LSB-first memory organization.*/ + *((uint32_t *)buf) = w; + buf += 4; + n--; + } + return buf; +} + +/** + * @brief Reads a packet from the RXFIFO. + * + * @param[in] fifop pointer to the FIFO register + * @param[out] buf buffer where to copy the endpoint data + * @param[in] n number of bytes to pull from the FIFO + * @param[in] max number of bytes to copy into the buffer + * + * @notapi + */ +static void otg_fifo_read_to_buffer(volatile uint32_t *fifop, + uint8_t *buf, + size_t n, + size_t max) { + + n = (n + 3) / 4; + max = (max + 3) / 4; + while (n) { + uint32_t w = *fifop; + if (max) { + /* Note, this line relies on the Cortex-M3/M4 ability to perform + unaligned word accesses and on the LSB-first memory organization.*/ + *((uint32_t *)buf) = w; + buf += 4; + max--; + } + n--; + } +} + +/** + * @brief Reads a packet from the RXFIFO. + * + * @param[in] fifop pointer to the FIFO register + * @param[in] iqp pointer to an @p InputQueue object + * @param[in] n number of bytes to pull from the FIFO + * + * @notapi + */ +static void otg_fifo_read_to_queue(volatile uint32_t *fifop, + InputQueue *iqp, + size_t n) { + size_t ntogo; + + ntogo = n; + while (ntogo > 0) { + uint32_t w, i; + size_t nw = ntogo / 4; + + if (nw > 0) { + size_t streak; + uint32_t nw2end = (iqp->q_wrptr - iqp->q_wrptr) / 4; + + ntogo -= (streak = nw <= nw2end ? nw : nw2end) * 4; + iqp->q_wrptr = otg_do_pop(fifop, iqp->q_wrptr, streak); + if (iqp->q_wrptr >= iqp->q_top) { + iqp->q_wrptr = iqp->q_buffer; + continue; + } + } + + /* If this condition is not satisfied then there is a word lying across + queue circular buffer boundary or there are some remaining bytes.*/ + if (ntogo <= 0) + break; + + /* One byte at time.*/ + w = *fifop; + i = 0; + while ((ntogo > 0) && (i < 4)) { + *iqp->q_wrptr++ = (uint8_t)(w >> (i * 8)); + if (iqp->q_wrptr >= iqp->q_top) + iqp->q_wrptr = iqp->q_buffer; + ntogo--; + i++; + } + } + + /* Updating queue.*/ + chSysLock(); + iqp->q_counter += n; + while (notempty(&iqp->q_waiting)) + chSchReadyI(fifo_remove(&iqp->q_waiting))->p_u.rdymsg = Q_OK; + chSchRescheduleS(); + chSysUnlock(); +} + +/** + * @brief Incoming packets handler. + * + * @param[in] usbp pointer to the @p USBDriver object + * + * @notapi + */ +static void otg_rxfifo_handler(USBDriver *usbp) { + uint32_t sts, cnt, ep; + + sts = usbp->otg->GRXSTSP; + switch (sts & GRXSTSP_PKTSTS_MASK) { + case GRXSTSP_SETUP_COMP: + break; + case GRXSTSP_SETUP_DATA: + cnt = (sts & GRXSTSP_BCNT_MASK) >> GRXSTSP_BCNT_OFF; + ep = (sts & GRXSTSP_EPNUM_MASK) >> GRXSTSP_EPNUM_OFF; + otg_fifo_read_to_buffer(usbp->otg->FIFO[0], usbp->epc[ep]->setup_buf, + cnt, 8); + break; + case GRXSTSP_OUT_DATA: + cnt = (sts & GRXSTSP_BCNT_MASK) >> GRXSTSP_BCNT_OFF; + ep = (sts & GRXSTSP_EPNUM_MASK) >> GRXSTSP_EPNUM_OFF; + if (usbp->epc[ep]->out_state->rxqueued) { + /* Queue associated.*/ + otg_fifo_read_to_queue(usbp->otg->FIFO[0], + usbp->epc[ep]->out_state->mode.queue.rxqueue, + cnt); + } + else { + otg_fifo_read_to_buffer(usbp->otg->FIFO[0], + usbp->epc[ep]->out_state->mode.linear.rxbuf, + cnt, + usbp->epc[ep]->out_state->rxsize - + usbp->epc[ep]->out_state->rxcnt); + usbp->epc[ep]->out_state->mode.linear.rxbuf += cnt; + } + usbp->epc[ep]->out_state->rxcnt += cnt; + break; + case GRXSTSP_OUT_GLOBAL_NAK: + case GRXSTSP_OUT_COMP: + default: + ; + } +} + +/** + * @brief Outgoing packets handler. + * + * @param[in] usbp pointer to the @p USBDriver object + * @param[in] ep endpoint number + * + * @notapi + */ +static bool_t otg_txfifo_handler(USBDriver *usbp, usbep_t ep) { + + /* The TXFIFO is filled until there is space and data to be transmitted.*/ + while (TRUE) { + uint32_t n; + + /* Transaction end condition.*/ + if (usbp->epc[ep]->in_state->txcnt >= usbp->epc[ep]->in_state->txsize) + return TRUE; + + /* Number of bytes remaining in current transaction.*/ + n = usbp->epc[ep]->in_state->txsize - usbp->epc[ep]->in_state->txcnt; + if (n > usbp->epc[ep]->in_maxsize) + n = usbp->epc[ep]->in_maxsize; + + /* Checks if in the TXFIFO there is enough space to accommodate the + next packet.*/ + if (((usbp->otg->ie[ep].DTXFSTS & DTXFSTS_INEPTFSAV_MASK) * 4) < n) + return FALSE; + +#if STM32_USB_OTGFIFO_FILL_BASEPRI + __set_BASEPRI(CORTEX_PRIORITY_MASK(STM32_USB_OTGFIFO_FILL_BASEPRI)); +#endif + /* Handles the two cases: linear buffer or queue.*/ + if (usbp->epc[ep]->in_state->txqueued) { + /* Queue associated.*/ + otg_fifo_write_from_queue(usbp->otg->FIFO[ep], + usbp->epc[ep]->in_state->mode.queue.txqueue, + n); + } + else { + /* Linear buffer associated.*/ + otg_fifo_write_from_buffer(usbp->otg->FIFO[ep], + usbp->epc[ep]->in_state->mode.linear.txbuf, + n); + usbp->epc[ep]->in_state->mode.linear.txbuf += n; + } + usbp->epc[ep]->in_state->txcnt += n; + } +#if STM32_USB_OTGFIFO_FILL_BASEPRI + __set_BASEPRI(0); +#endif +} + +/** + * @brief Generic endpoint IN handler. + * + * @param[in] usbp pointer to the @p USBDriver object + * @param[in] ep endpoint number + * + * @notapi + */ +static void otg_epin_handler(USBDriver *usbp, usbep_t ep) { + stm32_otg_t *otgp = usbp->otg; + uint32_t epint = otgp->ie[ep].DIEPINT; + + otgp->ie[ep].DIEPINT = 0xFFFFFFFF; + + if (epint & DIEPINT_TOC) { + /* Timeouts not handled yet, not sure how to handle.*/ + } + if ((epint & DIEPINT_XFRC) && (otgp->DIEPMSK & DIEPMSK_XFRCM)) { + /* Transmit transfer complete.*/ + _usb_isr_invoke_in_cb(usbp, ep); + } + if ((epint & DIEPINT_TXFE) && + (otgp->DIEPEMPMSK & DIEPEMPMSK_INEPTXFEM(ep))) { + /* The thread is made ready, it will be scheduled on ISR exit.*/ + chSysLockFromIsr(); + usbp->txpending |= (1 << ep); + otgp->DIEPEMPMSK &= ~(1 << ep); + usb_lld_wakeup_pump(usbp); + chSysUnlockFromIsr(); + } +} + +/** + * @brief Generic endpoint OUT handler. + * + * @param[in] usbp pointer to the @p USBDriver object + * @param[in] ep endpoint number + * + * @notapi + */ +static void otg_epout_handler(USBDriver *usbp, usbep_t ep) { + stm32_otg_t *otgp = usbp->otg; + uint32_t epint = otgp->oe[ep].DOEPINT; + + /* Resets all EP IRQ sources.*/ + otgp->oe[ep].DOEPINT = 0xFFFFFFFF; + + if ((epint & DOEPINT_STUP) && (otgp->DOEPMSK & DOEPMSK_STUPM)) { + /* Setup packets handling, setup packets are handled using a + specific callback.*/ + _usb_isr_invoke_setup_cb(usbp, ep); + + } + if ((epint & DOEPINT_XFRC) && (otgp->DOEPMSK & DOEPMSK_XFRCM)) { + /* Receive transfer complete.*/ + _usb_isr_invoke_out_cb(usbp, ep); + } +} + +/** + * @brief OTG shared ISR. + * + * @param[in] usbp pointer to the @p USBDriver object + * + * @notapi + */ +static void usb_lld_serve_interrupt(USBDriver *usbp) { + stm32_otg_t *otgp = usbp->otg; + uint32_t sts, src; + + sts = otgp->GINTSTS & otgp->GINTMSK; + otgp->GINTSTS = sts; + + /* Reset interrupt handling.*/ + if (sts & GINTSTS_USBRST) { + _usb_reset(usbp); + _usb_isr_invoke_event_cb(usbp, USB_EVENT_RESET); + } + + /* Enumeration done.*/ + if (sts & GINTSTS_ENUMDNE) { + (void)otgp->DSTS; + } + + /* SOF interrupt handling.*/ + if (sts & GINTSTS_SOF) { + _usb_isr_invoke_sof_cb(usbp); + } + + /* RX FIFO not empty handling.*/ + if (sts & GINTSTS_RXFLVL) { + /* The interrupt is masked while the thread has control or it would + be triggered again.*/ + chSysLockFromIsr(); + otgp->GINTMSK &= ~GINTMSK_RXFLVLM; + usb_lld_wakeup_pump(usbp); + chSysUnlockFromIsr(); + } + + /* IN/OUT endpoints event handling.*/ + src = otgp->DAINT; + if (sts & GINTSTS_IEPINT) { + if (src & (1 << 0)) + otg_epin_handler(usbp, 0); + if (src & (1 << 1)) + otg_epin_handler(usbp, 1); + if (src & (1 << 2)) + otg_epin_handler(usbp, 2); + if (src & (1 << 3)) + otg_epin_handler(usbp, 3); +#if STM32_USB_USE_OTG2 + if (src & (1 << 4)) + otg_epin_handler(usbp, 4); + if (src & (1 << 5)) + otg_epin_handler(usbp, 5); +#endif + } + if (sts & GINTSTS_OEPINT) { + if (src & (1 << 16)) + otg_epout_handler(usbp, 0); + if (src & (1 << 17)) + otg_epout_handler(usbp, 1); + if (src & (1 << 18)) + otg_epout_handler(usbp, 2); + if (src & (1 << 19)) + otg_epout_handler(usbp, 3); +#if STM32_USB_USE_OTG2 + if (src & (1 << 20)) + otg_epout_handler(usbp, 4); + if (src & (1 << 21)) + otg_epout_handler(usbp, 5); +#endif + } +} + +/*===========================================================================*/ +/* Driver interrupt handlers and threads. */ +/*===========================================================================*/ + +static msg_t usb_lld_pump(void *p) { + USBDriver *usbp = (USBDriver *)p; + stm32_otg_t *otgp = usbp->otg; + + chRegSetThreadName("usb_lld_pump"); + chSysLock(); + while (TRUE) { + usbep_t ep; + uint32_t epmask; + + /* Nothing to do, going to sleep.*/ + if ((usbp->state == USB_STOP) || + ((usbp->txpending == 0) && !(otgp->GINTSTS & GINTSTS_RXFLVL))) { + otgp->GINTMSK |= GINTMSK_RXFLVLM; + usbp->thd_wait = chThdSelf(); + chSchGoSleepS(THD_STATE_SUSPENDED); + } + chSysUnlock(); + + /* Checks if there are TXFIFOs to be filled.*/ + for (ep = 0; ep <= usbp->otgparams->num_endpoints; ep++) { + + /* Empties the RX FIFO.*/ + while (otgp->GINTSTS & GINTSTS_RXFLVL) { + otg_rxfifo_handler(usbp); + } + + epmask = (1 << ep); + if (usbp->txpending & epmask) { + bool_t done; + + chSysLock(); + /* USB interrupts are globally *suspended* because the peripheral + does not allow any interference during the TX FIFO filling + operation. + Synopsys document: DesignWare Cores USB 2.0 Hi-Speed On-The-Go (OTG) + "The application has to finish writing one complete packet before + switching to a different channel/endpoint FIFO. Violating this + rule results in an error.".*/ + otgp->GAHBCFG &= ~GAHBCFG_GINTMSK; + usbp->txpending &= ~epmask; + chSysUnlock(); + + done = otg_txfifo_handler(usbp, ep); + + chSysLock(); + otgp->GAHBCFG |= GAHBCFG_GINTMSK; + if (!done) + otgp->DIEPEMPMSK |= epmask; + chSysUnlock(); + } + } + chSysLock(); + } + chSysUnlock(); + return 0; +} + +#if STM32_USB_USE_OTG1 || defined(__DOXYGEN__) +#if !defined(STM32_OTG1_HANDLER) +#error "STM32_OTG1_HANDLER not defined" +#endif +/** + * @brief OTG1 interrupt handler. + * + * @isr + */ +CH_IRQ_HANDLER(STM32_OTG1_HANDLER) { + + CH_IRQ_PROLOGUE(); + + usb_lld_serve_interrupt(&USBD1); + + CH_IRQ_EPILOGUE(); +} +#endif + +#if STM32_USB_USE_OTG2 || defined(__DOXYGEN__) +#if !defined(STM32_OTG2_HANDLER) +#error "STM32_OTG2_HANDLER not defined" +#endif +/** + * @brief OTG2 interrupt handler. + * + * @isr + */ +CH_IRQ_HANDLER(STM32_OTG2_HANDLER) { + + CH_IRQ_PROLOGUE(); + + usb_lld_serve_interrupt(&USBD2); + + CH_IRQ_EPILOGUE(); +} +#endif + +/*===========================================================================*/ +/* Driver exported functions. */ +/*===========================================================================*/ + +/** + * @brief Low level USB driver initialization. + * + * @notapi + */ +void usb_lld_init(void) { + + /* Driver initialization.*/ +#if STM32_USB_USE_OTG1 + usbObjectInit(&USBD1); + USBD1.thd_ptr = NULL; + USBD1.thd_wait = NULL; + USBD1.otg = OTG_FS; + USBD1.otgparams = &fsparams; + + /* Filling the thread working area here because the function + @p chThdCreateI() does not do it.*/ +#if CH_DBG_FILL_THREADS + { + void *wsp = USBD1.wa_pump; + _thread_memfill((uint8_t *)wsp, + (uint8_t *)wsp + sizeof(Thread), + CH_THREAD_FILL_VALUE); + _thread_memfill((uint8_t *)wsp + sizeof(Thread), + (uint8_t *)wsp + sizeof(USBD1.wa_pump) - sizeof(Thread), + CH_STACK_FILL_VALUE); + } +#endif +#endif + +#if STM32_USB_USE_OTG2 + usbObjectInit(&USBD2); + USBD2.thd_ptr = NULL; + USBD2.thd_wait = NULL; + USBD2.otg = OTG_HS; + USBD2.otgparams = &hsparams; + + /* Filling the thread working area here because the function + @p chThdCreateI() does not do it.*/ +#if CH_DBG_FILL_THREADS + { + void *wsp = USBD2.wa_pump; + _thread_memfill((uint8_t *)wsp, + (uint8_t *)wsp + sizeof(Thread), + CH_THREAD_FILL_VALUE); + _thread_memfill((uint8_t *)wsp + sizeof(Thread), + (uint8_t *)wsp + sizeof(USBD2.wa_pump) - sizeof(Thread), + CH_STACK_FILL_VALUE); + } +#endif +#endif +} + +/** + * @brief Configures and activates the USB peripheral. + * @note Starting the OTG cell can be a slow operation carried out with + * interrupts disabled, perform it before starting time-critical + * operations. + * + * @param[in] usbp pointer to the @p USBDriver object + * + * @notapi + */ +void usb_lld_start(USBDriver *usbp) { + stm32_otg_t *otgp = usbp->otg; + + if (usbp->state == USB_STOP) { + /* Clock activation.*/ +#if STM32_USB_USE_OTG1 + if (&USBD1 == usbp) { + /* OTG FS clock enable and reset.*/ + rccEnableOTG_FS(FALSE); + rccResetOTG_FS(); + + /* Enables IRQ vector.*/ + nvicEnableVector(STM32_OTG1_NUMBER, + CORTEX_PRIORITY_MASK(STM32_USB_OTG1_IRQ_PRIORITY)); + } +#endif +#if STM32_USB_USE_OTG2 + if (&USBD2 == usbp) { + /* OTG HS clock enable and reset.*/ + rccEnableOTG_HS(FALSE); + rccResetOTG_HS(); + + /* Enables IRQ vector.*/ + nvicEnableVector(STM32_OTG2_NUMBER, + CORTEX_PRIORITY_MASK(STM32_USB_OTG2_IRQ_PRIORITY)); + } +#endif + + /* Creates the data pump threads in a suspended state. Note, it is + created only once, the first time @p usbStart() is invoked.*/ + usbp->txpending = 0; + if (usbp->thd_ptr == NULL) + usbp->thd_ptr = usbp->thd_wait = chThdCreateI(usbp->wa_pump, + sizeof usbp->wa_pump, + STM32_USB_OTG_THREAD_PRIO, + usb_lld_pump, + usbp); + + /* - Forced device mode. + - USB turn-around time = TRDT_VALUE. + - Full Speed 1.1 PHY.*/ + otgp->GUSBCFG = GUSBCFG_FDMOD | GUSBCFG_TRDT(TRDT_VALUE) | GUSBCFG_PHYSEL; + + /* 48MHz 1.1 PHY.*/ + otgp->DCFG = 0x02200000 | DCFG_DSPD_FS11; + + /* PHY enabled.*/ + otgp->PCGCCTL = 0; + + /* Internal FS PHY activation.*/ + otgp->GCCFG = GCCFG_VBUSASEN | GCCFG_VBUSBSEN | GCCFG_PWRDWN; + + /* Soft core reset.*/ + otg_core_reset(usbp); + + /* Interrupts on TXFIFOs half empty.*/ + otgp->GAHBCFG = 0; + + /* Endpoints re-initialization.*/ + otg_disable_ep(usbp); + + /* Clear all pending Device Interrupts, only the USB Reset interrupt + is required initially.*/ + otgp->DIEPMSK = 0; + otgp->DOEPMSK = 0; + otgp->DAINTMSK = 0; + if (usbp->config->sof_cb == NULL) + otgp->GINTMSK = GINTMSK_ENUMDNEM | GINTMSK_USBRSTM /*| GINTMSK_USBSUSPM | + GINTMSK_ESUSPM |*/; + else + otgp->GINTMSK = GINTMSK_ENUMDNEM | GINTMSK_USBRSTM /*| GINTMSK_USBSUSPM | + GINTMSK_ESUSPM */ | GINTMSK_SOFM; + otgp->GINTSTS = 0xFFFFFFFF; /* Clears all pending IRQs, if any. */ + + /* Global interrupts enable.*/ + otgp->GAHBCFG |= GAHBCFG_GINTMSK; + } +} + +/** + * @brief Deactivates the USB peripheral. + * + * @param[in] usbp pointer to the @p USBDriver object + * + * @notapi + */ +void usb_lld_stop(USBDriver *usbp) { + stm32_otg_t *otgp = usbp->otg; + + /* If in ready state then disables the USB clock.*/ + if (usbp->state != USB_STOP) { + + /* Disabling all endpoints in case the driver has been stopped while + active.*/ + otg_disable_ep(usbp); + + usbp->txpending = 0; + + otgp->DAINTMSK = 0; + otgp->GAHBCFG = 0; + otgp->GCCFG = 0; + +#if STM32_USB_USE_USB1 + if (&USBD1 == usbp) { + nvicDisableVector(STM32_OTG1_NUMBER); + rccDisableOTG1(FALSE); + } +#endif + +#if STM32_USB_USE_USB2 + if (&USBD2 == usbp) { + nvicDisableVector(STM32_OTG2_NUMBER); + rccDisableOTG2(FALSE); + } +#endif + } +} + +/** + * @brief USB low level reset routine. + * + * @param[in] usbp pointer to the @p USBDriver object + * + * @notapi + */ +void usb_lld_reset(USBDriver *usbp) { + unsigned i; + stm32_otg_t *otgp = usbp->otg; + + /* Flush the Tx FIFO.*/ + otg_txfifo_flush(usbp, 0); + + /* All endpoints in NAK mode, interrupts cleared.*/ + for (i = 0; i <= usbp->otgparams->num_endpoints; i++) { + otgp->ie[i].DIEPCTL = DIEPCTL_SNAK; + otgp->oe[i].DOEPCTL = DOEPCTL_SNAK; + otgp->ie[i].DIEPINT = 0xFF; + otgp->oe[i].DOEPINT = 0xFF; + } + + /* Endpoint interrupts all disabled and cleared.*/ + otgp->DAINT = 0xFFFFFFFF; + otgp->DAINTMSK = DAINTMSK_OEPM(0) | DAINTMSK_IEPM(0); + + /* Resets the FIFO memory allocator.*/ + otg_ram_reset(usbp); + + /* Receive FIFO size initialization, the address is always zero.*/ + otgp->GRXFSIZ = usbp->otgparams->rx_fifo_size; + otg_rxfifo_flush(usbp); + + /* Resets the device address to zero.*/ + otgp->DCFG = (otgp->DCFG & ~DCFG_DAD_MASK) | DCFG_DAD(0); + + /* Enables also EP-related interrupt sources.*/ + otgp->GINTMSK |= GINTMSK_RXFLVLM | GINTMSK_OEPM | GINTMSK_IEPM; + otgp->DIEPMSK = DIEPMSK_TOCM | DIEPMSK_XFRCM; + otgp->DOEPMSK = DOEPMSK_STUPM | DOEPMSK_XFRCM; + + /* EP0 initialization, it is a special case.*/ + usbp->epc[0] = &ep0config; + otgp->oe[0].DOEPTSIZ = 0; + otgp->oe[0].DOEPCTL = DOEPCTL_SD0PID | DOEPCTL_USBAEP | DOEPCTL_EPTYP_CTRL | + DOEPCTL_MPSIZ(ep0config.out_maxsize); + otgp->ie[0].DIEPTSIZ = 0; + otgp->ie[0].DIEPCTL = DIEPCTL_SD0PID | DIEPCTL_USBAEP | DIEPCTL_EPTYP_CTRL | + DIEPCTL_TXFNUM(0) | DIEPCTL_MPSIZ(ep0config.in_maxsize); + otgp->DIEPTXF0 = DIEPTXF_INEPTXFD(ep0config.in_maxsize / 4) | + DIEPTXF_INEPTXSA(otg_ram_alloc(usbp, + ep0config.in_maxsize / 4)); +} + +/** + * @brief Sets the USB address. + * + * @param[in] usbp pointer to the @p USBDriver object + * + * @notapi + */ +void usb_lld_set_address(USBDriver *usbp) { + stm32_otg_t *otgp = usbp->otg; + + otgp->DCFG = (otgp->DCFG & ~DCFG_DAD_MASK) | DCFG_DAD(usbp->address); +} + +/** + * @brief Enables an endpoint. + * + * @param[in] usbp pointer to the @p USBDriver object + * @param[in] ep endpoint number + * + * @notapi + */ +void usb_lld_init_endpoint(USBDriver *usbp, usbep_t ep) { + uint32_t ctl, fsize; + stm32_otg_t *otgp = usbp->otg; + + /* IN and OUT common parameters.*/ + switch (usbp->epc[ep]->ep_mode & USB_EP_MODE_TYPE) { + case USB_EP_MODE_TYPE_CTRL: + ctl = DIEPCTL_SD0PID | DIEPCTL_USBAEP | DIEPCTL_EPTYP_CTRL; + break; + case USB_EP_MODE_TYPE_ISOC: + ctl = DIEPCTL_SD0PID | DIEPCTL_USBAEP | DIEPCTL_EPTYP_ISO; + break; + case USB_EP_MODE_TYPE_BULK: + ctl = DIEPCTL_SD0PID | DIEPCTL_USBAEP | DIEPCTL_EPTYP_BULK; + break; + case USB_EP_MODE_TYPE_INTR: + ctl = DIEPCTL_SD0PID | DIEPCTL_USBAEP | DIEPCTL_EPTYP_INTR; + break; + default: + return; + } + + /* OUT endpoint activation or deactivation.*/ + otgp->oe[ep].DOEPTSIZ = 0; + if (usbp->epc[ep]->out_cb != NULL) { + otgp->oe[ep].DOEPCTL = ctl | DOEPCTL_MPSIZ(usbp->epc[ep]->out_maxsize); + otgp->DAINTMSK |= DAINTMSK_OEPM(ep); + } + else { + otgp->oe[ep].DOEPCTL &= ~DOEPCTL_USBAEP; + otgp->DAINTMSK &= ~DAINTMSK_OEPM(ep); + } + + /* IN endpoint activation or deactivation.*/ + otgp->ie[ep].DIEPTSIZ = 0; + if (usbp->epc[ep]->in_cb != NULL) { + /* FIFO allocation for the IN endpoint.*/ + fsize = usbp->epc[ep]->in_maxsize / 4; + if (usbp->epc[ep]->in_multiplier > 1) + fsize *= usbp->epc[ep]->in_multiplier; + otgp->DIEPTXF[ep - 1] = DIEPTXF_INEPTXFD(fsize) | + DIEPTXF_INEPTXSA(otg_ram_alloc(usbp, fsize)); + otg_txfifo_flush(usbp, ep); + + otgp->ie[ep].DIEPCTL = ctl | + DIEPCTL_TXFNUM(ep) | + DIEPCTL_MPSIZ(usbp->epc[ep]->in_maxsize); + otgp->DAINTMSK |= DAINTMSK_IEPM(ep); + } + else { + otgp->DIEPTXF[ep - 1] = 0x02000400; /* Reset value.*/ + otg_txfifo_flush(usbp, ep); + otgp->ie[ep].DIEPCTL &= ~DIEPCTL_USBAEP; + otgp->DAINTMSK &= ~DAINTMSK_IEPM(ep); + } +} + +/** + * @brief Disables all the active endpoints except the endpoint zero. + * + * @param[in] usbp pointer to the @p USBDriver object + * + * @notapi + */ +void usb_lld_disable_endpoints(USBDriver *usbp) { + + /* Resets the FIFO memory allocator.*/ + otg_ram_reset(usbp); + + /* Disabling all endpoints.*/ + otg_disable_ep(usbp); +} + +/** + * @brief Returns the status of an OUT endpoint. + * + * @param[in] usbp pointer to the @p USBDriver object + * @param[in] ep endpoint number + * @return The endpoint status. + * @retval EP_STATUS_DISABLED The endpoint is not active. + * @retval EP_STATUS_STALLED The endpoint is stalled. + * @retval EP_STATUS_ACTIVE The endpoint is active. + * + * @notapi + */ +usbepstatus_t usb_lld_get_status_out(USBDriver *usbp, usbep_t ep) { + uint32_t ctl; + + (void)usbp; + + ctl = usbp->otg->oe[ep].DOEPCTL; + if (!(ctl & DOEPCTL_USBAEP)) + return EP_STATUS_DISABLED; + if (ctl & DOEPCTL_STALL) + return EP_STATUS_STALLED; + return EP_STATUS_ACTIVE; +} + +/** + * @brief Returns the status of an IN endpoint. + * + * @param[in] usbp pointer to the @p USBDriver object + * @param[in] ep endpoint number + * @return The endpoint status. + * @retval EP_STATUS_DISABLED The endpoint is not active. + * @retval EP_STATUS_STALLED The endpoint is stalled. + * @retval EP_STATUS_ACTIVE The endpoint is active. + * + * @notapi + */ +usbepstatus_t usb_lld_get_status_in(USBDriver *usbp, usbep_t ep) { + uint32_t ctl; + + (void)usbp; + + ctl = usbp->otg->ie[ep].DIEPCTL; + if (!(ctl & DIEPCTL_USBAEP)) + return EP_STATUS_DISABLED; + if (ctl & DIEPCTL_STALL) + return EP_STATUS_STALLED; + return EP_STATUS_ACTIVE; +} + +/** + * @brief Reads a setup packet from the dedicated packet buffer. + * @details This function must be invoked in the context of the @p setup_cb + * callback in order to read the received setup packet. + * @pre In order to use this function the endpoint must have been + * initialized as a control endpoint. + * @post The endpoint is ready to accept another packet. + * + * @param[in] usbp pointer to the @p USBDriver object + * @param[in] ep endpoint number + * @param[out] buf buffer where to copy the packet data + * + * @notapi + */ +void usb_lld_read_setup(USBDriver *usbp, usbep_t ep, uint8_t *buf) { + + memcpy(buf, usbp->epc[ep]->setup_buf, 8); +} + +/** + * @brief Prepares for a receive operation. + * + * @param[in] usbp pointer to the @p USBDriver object + * @param[in] ep endpoint number + * + * @notapi + */ +void usb_lld_prepare_receive(USBDriver *usbp, usbep_t ep) { + uint32_t pcnt; + USBOutEndpointState *osp = usbp->epc[ep]->out_state; + + /* Transfer initialization.*/ + pcnt = (osp->rxsize + usbp->epc[ep]->out_maxsize - 1) / + usbp->epc[ep]->out_maxsize; + usbp->otg->oe[ep].DOEPTSIZ = DOEPTSIZ_STUPCNT(3) | DOEPTSIZ_PKTCNT(pcnt) | + DOEPTSIZ_XFRSIZ(usbp->epc[ep]->out_maxsize); + +} + +/** + * @brief Prepares for a transmit operation. + * + * @param[in] usbp pointer to the @p USBDriver object + * @param[in] ep endpoint number + * + * @notapi + */ +void usb_lld_prepare_transmit(USBDriver *usbp, usbep_t ep) { + USBInEndpointState *isp = usbp->epc[ep]->in_state; + + /* Transfer initialization.*/ + if (isp->txsize == 0) { + /* Special case, sending zero size packet.*/ + usbp->otg->ie[ep].DIEPTSIZ = DIEPTSIZ_PKTCNT(1) | DIEPTSIZ_XFRSIZ(0); + } + else { + /* Normal case.*/ + uint32_t pcnt = (isp->txsize + usbp->epc[ep]->in_maxsize - 1) / + usbp->epc[ep]->in_maxsize; + usbp->otg->ie[ep].DIEPTSIZ = DIEPTSIZ_PKTCNT(pcnt) | + DIEPTSIZ_XFRSIZ(usbp->epc[ep]->in_state->txsize); + } + +} + +/** + * @brief Starts a receive operation on an OUT endpoint. + * + * @param[in] usbp pointer to the @p USBDriver object + * @param[in] ep endpoint number + * + * @notapi + */ +void usb_lld_start_out(USBDriver *usbp, usbep_t ep) { + + usbp->otg->oe[ep].DOEPCTL |= DOEPCTL_CNAK; +} + +/** + * @brief Starts a transmit operation on an IN endpoint. + * + * @param[in] usbp pointer to the @p USBDriver object + * @param[in] ep endpoint number + * + * @notapi + */ +void usb_lld_start_in(USBDriver *usbp, usbep_t ep) { + + usbp->otg->ie[ep].DIEPCTL |= DIEPCTL_EPENA | DIEPCTL_CNAK; + usbp->otg->DIEPEMPMSK |= DIEPEMPMSK_INEPTXFEM(ep); +} + +/** + * @brief Brings an OUT endpoint in the stalled state. + * + * @param[in] usbp pointer to the @p USBDriver object + * @param[in] ep endpoint number + * + * @notapi + */ +void usb_lld_stall_out(USBDriver *usbp, usbep_t ep) { + + usbp->otg->oe[ep].DOEPCTL |= DOEPCTL_STALL; +} + +/** + * @brief Brings an IN endpoint in the stalled state. + * + * @param[in] usbp pointer to the @p USBDriver object + * @param[in] ep endpoint number + * + * @notapi + */ +void usb_lld_stall_in(USBDriver *usbp, usbep_t ep) { + + usbp->otg->ie[ep].DIEPCTL |= DIEPCTL_STALL; +} + +/** + * @brief Brings an OUT endpoint in the active state. + * + * @param[in] usbp pointer to the @p USBDriver object + * @param[in] ep endpoint number + * + * @notapi + */ +void usb_lld_clear_out(USBDriver *usbp, usbep_t ep) { + + usbp->otg->oe[ep].DOEPCTL &= ~DOEPCTL_STALL; +} + +/** + * @brief Brings an IN endpoint in the active state. + * + * @param[in] usbp pointer to the @p USBDriver object + * @param[in] ep endpoint number + * + * @notapi + */ +void usb_lld_clear_in(USBDriver *usbp, usbep_t ep) { + + usbp->otg->ie[ep].DIEPCTL &= ~DIEPCTL_STALL; +} + +#endif /* HAL_USE_USB */ + +/** @} */ diff --git a/os/hal/ports/STM32/OTGv1/usb_lld.h b/os/hal/ports/STM32/OTGv1/usb_lld.h new file mode 100644 index 000000000..570309750 --- /dev/null +++ b/os/hal/ports/STM32/OTGv1/usb_lld.h @@ -0,0 +1,534 @@ +/* + ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file STM32/OTGv1/usb_lld.h + * @brief STM32 USB subsystem low level driver header. + * + * @addtogroup USB + * @{ + */ + +#ifndef _USB_LLD_H_ +#define _USB_LLD_H_ + +#if HAL_USE_USB || defined(__DOXYGEN__) + +#include "stm32_otg.h" + +/*===========================================================================*/ +/* Driver constants. */ +/*===========================================================================*/ + +/** + * @brief Maximum endpoint address. + */ +#if !STM32_USB_USE_OTG2 || defined(__DOXYGEN__) +#define USB_MAX_ENDPOINTS 3 +#else +#define USB_MAX_ENDPOINTS 5 +#endif + +/** + * @brief The address can be changed immediately upon packet reception. + */ +#define USB_SET_ADDRESS_MODE USB_EARLY_SET_ADDRESS + +/*===========================================================================*/ +/* Driver pre-compile time settings. */ +/*===========================================================================*/ + +/** + * @brief OTG1 driver enable switch. + * @details If set to @p TRUE the support for OTG_FS is included. + * @note The default is @p TRUE. + */ +#if !defined(STM32_USB_USE_OTG1) || defined(__DOXYGEN__) +#define STM32_USB_USE_OTG1 FALSE +#endif + +/** + * @brief OTG2 driver enable switch. + * @details If set to @p TRUE the support for OTG_HS is included. + * @note The default is @p TRUE. + */ +#if !defined(STM32_USB_USE_OTG2) || defined(__DOXYGEN__) +#define STM32_USB_USE_OTG2 FALSE +#endif + +/** + * @brief OTG1 interrupt priority level setting. + */ +#if !defined(STM32_USB_OTG1_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_USB_OTG1_IRQ_PRIORITY 14 +#endif + +/** + * @brief OTG2 interrupt priority level setting. + */ +#if !defined(STM32_USB_OTG2_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_USB_OTG2_IRQ_PRIORITY 14 +#endif + +/** + * @brief OTG1 RX shared FIFO size. + * @note Must be a multiple of 4. + */ +#if !defined(STM32_USB_OTG1_RX_FIFO_SIZE) || defined(__DOXYGEN__) +#define STM32_USB_OTG1_RX_FIFO_SIZE 512 +#endif + +/** + * @brief OTG2 RX shared FIFO size. + * @note Must be a multiple of 4. + */ +#if !defined(STM32_USB_OTG2_RX_FIFO_SIZE) || defined(__DOXYGEN__) +#define STM32_USB_OTG2_RX_FIFO_SIZE 1024 +#endif + +/** + * @brief Dedicated data pump threads priority. + */ +#if !defined(STM32_USB_OTG_THREAD_PRIO) || defined(__DOXYGEN__) +#define STM32_USB_OTG_THREAD_PRIO LOWPRIO +#endif + +/** + * @brief Dedicated data pump threads stack size. + */ +#if !defined(STM32_USB_OTG_THREAD_STACK_SIZE) || defined(__DOXYGEN__) +#define STM32_USB_OTG_THREAD_STACK_SIZE 128 +#endif + +/** + * @brief Exception priority level during TXFIFOs operations. + * @note Because an undocumented silicon behavior the operation of + * copying a packet into a TXFIFO must not be interrupted by + * any other operation on the OTG peripheral. + * This parameter represents the priority mask during copy + * operations. The default value only allows to call USB + * functions from callbacks invoked from USB ISR handlers. + * If you need to invoke USB functions from other handlers + * then raise this priority mast to the same level of the + * handler you need to use. + * @note The value zero means disabled, when disabled calling USB + * functions is only safe from thread level or from USB + * callbacks. + */ +#if !defined(STM32_USB_OTGFIFO_FILL_BASEPRI) || defined(__DOXYGEN__) +#define STM32_USB_OTGFIFO_FILL_BASEPRI 0 +#endif + +/*===========================================================================*/ +/* Derived constants and error checks. */ +/*===========================================================================*/ + +#if STM32_USB_USE_OTG1 && !STM32_HAS_OTG1 +#error "OTG1 not present in the selected device" +#endif + +#if STM32_USB_USE_OTG2 && !STM32_HAS_OTG2 +#error "OTG2 not present in the selected device" +#endif + +#if !STM32_USB_USE_OTG1 && !STM32_USB_USE_OTG2 +#error "USB driver activated but no USB peripheral assigned" +#endif + +#if STM32_USB_USE_OTG1 && \ + !CORTEX_IS_VALID_KERNEL_PRIORITY(STM32_USB_OTG1_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to OTG1" +#endif + +#if STM32_USB_USE_OTG2 && \ + !CORTEX_IS_VALID_KERNEL_PRIORITY(STM32_USB_OTG2_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to OTG2" +#endif + +#if (STM32_USB_OTG1_RX_FIFO_SIZE & 3) != 0 +#error "OTG1 RX FIFO size must be a multiple of 4" +#endif + +#if (STM32_USB_OTG2_RX_FIFO_SIZE & 3) != 0 +#error "OTG2 RX FIFO size must be a multiple of 4" +#endif + +#if defined(STM32F4XX) || defined(STM32F2XX) +#define STM32_USBCLK STM32_PLL48CLK +#elif defined(STM32F10X_CL) +#define STM32_USBCLK STM32_OTGFSCLK +#else +#error "unsupported STM32 platform for OTG functionality" +#endif + +#if STM32_USBCLK != 48000000 +#error "the USB OTG driver requires a 48MHz clock" +#endif + +/*===========================================================================*/ +/* Driver data structures and types. */ +/*===========================================================================*/ + +/** + * @brief Peripheral-specific parameters block. + */ +typedef struct { + uint32_t rx_fifo_size; + uint32_t otg_ram_size; + uint32_t num_endpoints; +} stm32_otg_params_t; + +/** + * @brief Type of an IN endpoint state structure. + */ +typedef struct { + /** + * @brief Buffer mode, queue or linear. + */ + bool_t txqueued; + /** + * @brief Requested transmit transfer size. + */ + size_t txsize; + /** + * @brief Transmitted bytes so far. + */ + size_t txcnt; + union { + struct { + /** + * @brief Pointer to the transmission linear buffer. + */ + const uint8_t *txbuf; + } linear; + struct { + /** + * @brief Pointer to the output queue. + */ + OutputQueue *txqueue; + } queue; + } mode; +} USBInEndpointState; + +/** + * @brief Type of an OUT endpoint state structure. + */ +typedef struct { + /** + * @brief Buffer mode, queue or linear. + */ + bool_t rxqueued; + /** + * @brief Requested receive transfer size. + */ + size_t rxsize; + /** + * @brief Received bytes so far. + */ + size_t rxcnt; + union { + struct { + /** + * @brief Pointer to the receive linear buffer. + */ + uint8_t *rxbuf; + } linear; + struct { + /** + * @brief Pointer to the input queue. + */ + InputQueue *rxqueue; + } queue; + } mode; +} USBOutEndpointState; + +/** + * @brief Type of an USB endpoint configuration structure. + * @note Platform specific restrictions may apply to endpoints. + */ +typedef struct { + /** + * @brief Type and mode of the endpoint. + */ + uint32_t ep_mode; + /** + * @brief Setup packet notification callback. + * @details This callback is invoked when a setup packet has been + * received. + * @post The application must immediately call @p usbReadPacket() in + * order to access the received packet. + * @note This field is only valid for @p USB_EP_MODE_TYPE_CTRL + * endpoints, it should be set to @p NULL for other endpoint + * types. + */ + usbepcallback_t setup_cb; + /** + * @brief IN endpoint notification callback. + * @details This field must be set to @p NULL if the IN endpoint is not + * used. + */ + usbepcallback_t in_cb; + /** + * @brief OUT endpoint notification callback. + * @details This field must be set to @p NULL if the OUT endpoint is not + * used. + */ + usbepcallback_t out_cb; + /** + * @brief IN endpoint maximum packet size. + * @details This field must be set to zero if the IN endpoint is not + * used. + */ + uint16_t in_maxsize; + /** + * @brief OUT endpoint maximum packet size. + * @details This field must be set to zero if the OUT endpoint is not + * used. + */ + uint16_t out_maxsize; + /** + * @brief @p USBEndpointState associated to the IN endpoint. + * @details This structure maintains the state of the IN endpoint. + */ + USBInEndpointState *in_state; + /** + * @brief @p USBEndpointState associated to the OUT endpoint. + * @details This structure maintains the state of the OUT endpoint. + */ + USBOutEndpointState *out_state; + /* End of the mandatory fields.*/ + /** + * @brief Determines the space allocated for the TXFIFO as multiples of + * the packet size (@p in_maxsize). Note that zero is interpreted + * as one for simplicity and robustness. + */ + uint16_t in_multiplier; + /** + * @brief Pointer to a buffer for setup packets. + * @details Setup packets require a dedicated 8-bytes buffer, set this + * field to @p NULL for non-control endpoints. + */ + uint8_t *setup_buf; +} USBEndpointConfig; + +/** + * @brief Type of an USB driver configuration structure. + */ +typedef struct { + /** + * @brief USB events callback. + * @details This callback is invoked when an USB driver event is registered. + */ + usbeventcb_t event_cb; + /** + * @brief Device GET_DESCRIPTOR request callback. + * @note This callback is mandatory and cannot be set to @p NULL. + */ + usbgetdescriptor_t get_descriptor_cb; + /** + * @brief Requests hook callback. + * @details This hook allows to be notified of standard requests or to + * handle non standard requests. + */ + usbreqhandler_t requests_hook_cb; + /** + * @brief Start Of Frame callback. + */ + usbcallback_t sof_cb; + /* End of the mandatory fields.*/ +} USBConfig; + +/** + * @brief Structure representing an USB driver. + */ +struct USBDriver { + /** + * @brief Driver state. + */ + usbstate_t state; + /** + * @brief Current configuration data. + */ + const USBConfig *config; + /** + * @brief Bit map of the transmitting IN endpoints. + */ + uint16_t transmitting; + /** + * @brief Bit map of the receiving OUT endpoints. + */ + uint16_t receiving; + /** + * @brief Active endpoints configurations. + */ + const USBEndpointConfig *epc[USB_MAX_ENDPOINTS + 1]; + /** + * @brief Fields available to user, it can be used to associate an + * application-defined handler to an IN endpoint. + * @note The base index is one, the endpoint zero does not have a + * reserved element in this array. + */ + void *in_params[USB_MAX_ENDPOINTS]; + /** + * @brief Fields available to user, it can be used to associate an + * application-defined handler to an OUT endpoint. + * @note The base index is one, the endpoint zero does not have a + * reserved element in this array. + */ + void *out_params[USB_MAX_ENDPOINTS]; + /** + * @brief Endpoint 0 state. + */ + usbep0state_t ep0state; + /** + * @brief Next position in the buffer to be transferred through endpoint 0. + */ + uint8_t *ep0next; + /** + * @brief Number of bytes yet to be transferred through endpoint 0. + */ + size_t ep0n; + /** + * @brief Endpoint 0 end transaction callback. + */ + usbcallback_t ep0endcb; + /** + * @brief Setup packet buffer. + */ + uint8_t setup[8]; + /** + * @brief Current USB device status. + */ + uint16_t status; + /** + * @brief Assigned USB address. + */ + uint8_t address; + /** + * @brief Current USB device configuration. + */ + uint8_t configuration; +#if defined(USB_DRIVER_EXT_FIELDS) + USB_DRIVER_EXT_FIELDS +#endif + /* End of the mandatory fields.*/ + /** + * @brief Pointer to the OTG peripheral associated to this driver. + */ + stm32_otg_t *otg; + /** + * @brief Peripheral-specific parameters. + */ + const stm32_otg_params_t *otgparams; + /** + * @brief Pointer to the next address in the packet memory. + */ + uint32_t pmnext; + /** + * @brief Mask of TXFIFOs to be filled by the pump thread. + */ + uint32_t txpending; + /** + * @brief Pointer to the thread. + */ + Thread *thd_ptr; + /** + * @brief Pointer to the thread when it is sleeping or @p NULL. + */ + Thread *thd_wait; + /** + * @brief Working area for the dedicated data pump thread; + */ + WORKING_AREA(wa_pump, STM32_USB_OTG_THREAD_STACK_SIZE); +}; + +/*===========================================================================*/ +/* Driver macros. */ +/*===========================================================================*/ + +/** + * @brief Returns the exact size of a receive transaction. + * @details The received size can be different from the size specified in + * @p usbStartReceiveI() because the last packet could have a size + * different from the expected one. + * @pre The OUT endpoint must have been configured in transaction mode + * in order to use this function. + * + * @param[in] usbp pointer to the @p USBDriver object + * @param[in] ep endpoint number + * @return Received data size. + * + * @notapi + */ +#define usb_lld_get_transaction_size(usbp, ep) \ + ((usbp)->epc[ep]->out_state->rxcnt) + +/** + * @brief Connects the USB device. + * + * @api + */ +#define usb_lld_connect_bus(usbp) ((usbp)->otg->GCCFG |= GCCFG_VBUSBSEN) + +/** + * @brief Disconnect the USB device. + * + * @api + */ +#define usb_lld_disconnect_bus(usbp) ((usbp)->otg->GCCFG &= ~GCCFG_VBUSBSEN) + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +#if STM32_USB_USE_OTG1 && !defined(__DOXYGEN__) +extern USBDriver USBD1; +#endif + +#if STM32_USB_USE_OTG2 && !defined(__DOXYGEN__) +extern USBDriver USBD2; +#endif + +#ifdef __cplusplus +extern "C" { +#endif + void usb_lld_init(void); + void usb_lld_start(USBDriver *usbp); + void usb_lld_stop(USBDriver *usbp); + void usb_lld_reset(USBDriver *usbp); + void usb_lld_set_address(USBDriver *usbp); + void usb_lld_init_endpoint(USBDriver *usbp, usbep_t ep); + void usb_lld_disable_endpoints(USBDriver *usbp); + usbepstatus_t usb_lld_get_status_in(USBDriver *usbp, usbep_t ep); + usbepstatus_t usb_lld_get_status_out(USBDriver *usbp, usbep_t ep); + void usb_lld_read_setup(USBDriver *usbp, usbep_t ep, uint8_t *buf); + void usb_lld_prepare_receive(USBDriver *usbp, usbep_t ep); + void usb_lld_prepare_transmit(USBDriver *usbp, usbep_t ep); + void usb_lld_start_out(USBDriver *usbp, usbep_t ep); + void usb_lld_start_in(USBDriver *usbp, usbep_t ep); + void usb_lld_stall_out(USBDriver *usbp, usbep_t ep); + void usb_lld_stall_in(USBDriver *usbp, usbep_t ep); + void usb_lld_clear_out(USBDriver *usbp, usbep_t ep); + void usb_lld_clear_in(USBDriver *usbp, usbep_t ep); +#ifdef __cplusplus +} +#endif + +#endif /* HAL_USE_USB */ + +#endif /* _USB_LLD_H_ */ + +/** @} */ diff --git a/os/hal/ports/STM32/RTCv1/rtc_lld.c b/os/hal/ports/STM32/RTCv1/rtc_lld.c new file mode 100644 index 000000000..108d94fb6 --- /dev/null +++ b/os/hal/ports/STM32/RTCv1/rtc_lld.c @@ -0,0 +1,329 @@ +/* + ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ +/* + Concepts and parts of this file have been contributed by Uladzimir Pylinsky + aka barthess. + */ + +/** + * @file STM32/RTCv1/rtc_lld.c + * @brief STM32 RTC subsystem low level driver header. + * + * @addtogroup RTC + * @{ + */ + +#include "ch.h" +#include "hal.h" + +#if HAL_USE_RTC || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver local definitions. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver exported variables. */ +/*===========================================================================*/ + +/** + * @brief RTC driver identifier. + */ +RTCDriver RTCD1; + +/*===========================================================================*/ +/* Driver local variables and types. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local functions. */ +/*===========================================================================*/ + +/** + * @brief Wait for synchronization of RTC registers with APB1 bus. + * @details This function must be invoked before trying to read RTC registers + * in the backup domain: DIV, CNT, ALR. CR registers can always + * be read. + * + * @notapi + */ +#define rtc_lld_apb1_sync() {while ((RTC->CRL & RTC_CRL_RSF) == 0);} + +/** + * @brief Wait for for previous write operation complete. + * @details This function must be invoked before writing to any RTC registers + * + * @notapi + */ +#define rtc_lld_wait_write() {while ((RTC->CRL & RTC_CRL_RTOFF) == 0);} + +/** + * @brief Acquires write access to RTC registers. + * @details Before writing to the backup domain RTC registers the previous + * write operation must be completed. Use this function before + * writing to PRL, CNT, ALR registers. + * + * @notapi + */ +#define rtc_lld_acquire() {rtc_lld_wait_write(); RTC->CRL |= RTC_CRL_CNF;} + +/** + * @brief Releases write access to RTC registers. + * + * @notapi + */ +#define rtc_lld_release() {RTC->CRL &= ~RTC_CRL_CNF;} + +/*===========================================================================*/ +/* Driver interrupt handlers. */ +/*===========================================================================*/ + +/** + * @brief RTC interrupt handler. + * + * @isr + */ +CH_IRQ_HANDLER(RTC_IRQHandler) { + uint16_t flags; + + CH_IRQ_PROLOGUE(); + + /* This wait works only when AHB1 bus was previously powered off by any + reason (standby, reset, etc). In other cases it does nothing.*/ + rtc_lld_apb1_sync(); + + /* Mask of all enabled and pending sources.*/ + flags = RTC->CRH & RTC->CRL; + RTC->CRL &= ~(RTC_CRL_SECF | RTC_CRL_ALRF | RTC_CRL_OWF); + + if (flags & RTC_CRL_SECF) + RTCD1.callback(&RTCD1, RTC_EVENT_SECOND); + + if (flags & RTC_CRL_ALRF) + RTCD1.callback(&RTCD1, RTC_EVENT_ALARM); + + if (flags & RTC_CRL_OWF) + RTCD1.callback(&RTCD1, RTC_EVENT_OVERFLOW); + + CH_IRQ_EPILOGUE(); +} + +/*===========================================================================*/ +/* Driver exported functions. */ +/*===========================================================================*/ + +/** + * @brief Load value of RTCCLK to prescaler registers. + * @note The pre-scaler must not be set on every reset as RTC clock + * counts are lost when it is set. + * @note This function designed to be called from + * hal_lld_backup_domain_init(). Because there is only place + * where possible to detect BKP domain reset event reliably. + * + * @notapi + */ +void rtc_lld_set_prescaler(void){ + rtc_lld_acquire(); + RTC->PRLH = (uint16_t)((STM32_RTCCLK - 1) >> 16) & 0x000F; + RTC->PRLL = (uint16_t)(((STM32_RTCCLK - 1)) & 0xFFFF); + rtc_lld_release(); +} + +/** + * @brief Initialize RTC. + * + * @notapi + */ +void rtc_lld_init(void){ + + /* RSF bit must be cleared by software after an APB1 reset or an APB1 clock + stop. Otherwise its value will not be actual. */ + RTC->CRL &= ~RTC_CRL_RSF; + + /* Required because access to PRL.*/ + rtc_lld_apb1_sync(); + + /* All interrupts initially disabled.*/ + rtc_lld_wait_write(); + RTC->CRH = 0; + + /* Callback initially disabled.*/ + RTCD1.callback = NULL; + + /* IRQ vector permanently assigned to this driver.*/ + nvicEnableVector(RTC_IRQn, CORTEX_PRIORITY_MASK(STM32_RTC_IRQ_PRIORITY)); +} + +/** + * @brief Set current time. + * @note Fractional part will be silently ignored. There is no possibility + * to change it on STM32F1xx platform. + * + * @param[in] rtcp pointer to RTC driver structure + * @param[in] timespec pointer to a @p RTCTime structure + * + * @notapi + */ +void rtc_lld_set_time(RTCDriver *rtcp, const RTCTime *timespec) { + + (void)rtcp; + + rtc_lld_acquire(); + RTC->CNTH = (uint16_t)(timespec->tv_sec >> 16); + RTC->CNTL = (uint16_t)(timespec->tv_sec & 0xFFFF); + rtc_lld_release(); +} + +/** + * @brief Get current time. + * + * @param[in] rtcp pointer to RTC driver structure + * @param[in] timespec pointer to a @p RTCTime structure + * + * @notapi + */ +void rtc_lld_get_time(RTCDriver *rtcp, RTCTime *timespec) { + (void)rtcp; + + uint32_t time_frac; + + /* Required because access to CNT and DIV.*/ + rtc_lld_apb1_sync(); + + /* Loops until two consecutive read returning the same value.*/ + do { + timespec->tv_sec = ((uint32_t)(RTC->CNTH) << 16) + RTC->CNTL; + time_frac = (((uint32_t)RTC->DIVH) << 16) + (uint32_t)RTC->DIVL; + } while ((timespec->tv_sec) != (((uint32_t)(RTC->CNTH) << 16) + RTC->CNTL)); + + timespec->tv_msec = (uint16_t)(((STM32_RTCCLK - 1 - time_frac) * 1000) / + STM32_RTCCLK); +} + +/** + * @brief Set alarm time. + * + * @note Default value after BKP domain reset is 0xFFFFFFFF + * + * @param[in] rtcp pointer to RTC driver structure + * @param[in] alarm alarm identifier + * @param[in] alarmspec pointer to a @p RTCAlarm structure + * + * @notapi + */ +void rtc_lld_set_alarm(RTCDriver *rtcp, + rtcalarm_t alarm, + const RTCAlarm *alarmspec) { + + (void)rtcp; + (void)alarm; + + rtc_lld_acquire(); + if (alarmspec != NULL) { + RTC->ALRH = (uint16_t)(alarmspec->tv_sec >> 16); + RTC->ALRL = (uint16_t)(alarmspec->tv_sec & 0xFFFF); + } + else { + RTC->ALRH = 0; + RTC->ALRL = 0; + } + rtc_lld_release(); +} + +/** + * @brief Get current alarm. + * @note If an alarm has not been set then the returned alarm specification + * is not meaningful. + * + * @note Default value after BKP domain reset is 0xFFFFFFFF. + * + * @param[in] rtcp pointer to RTC driver structure + * @param[in] alarm alarm identifier + * @param[out] alarmspec pointer to a @p RTCAlarm structure + * + * @notapi + */ +void rtc_lld_get_alarm(RTCDriver *rtcp, + rtcalarm_t alarm, + RTCAlarm *alarmspec) { + + (void)rtcp; + (void)alarm; + + /* Required because access to ALR.*/ + rtc_lld_apb1_sync(); + + alarmspec->tv_sec = ((RTC->ALRH << 16) + RTC->ALRL); +} + +/** + * @brief Enables or disables RTC callbacks. + * @details This function enables or disables callbacks, use a @p NULL pointer + * in order to disable a callback. + * + * @param[in] rtcp pointer to RTC driver structure + * @param[in] callback callback function pointer or @p NULL + * + * @notapi + */ +void rtc_lld_set_callback(RTCDriver *rtcp, rtccb_t callback) { + + if (callback != NULL) { + + /* IRQ sources enabled only after setting up the callback.*/ + rtcp->callback = callback; + + rtc_lld_wait_write(); + RTC->CRL &= ~(RTC_CRL_OWF | RTC_CRL_ALRF | RTC_CRL_SECF); + RTC->CRH = RTC_CRH_OWIE | RTC_CRH_ALRIE | RTC_CRH_SECIE; + } + else { + rtc_lld_wait_write(); + RTC->CRH = 0; + + /* Callback set to NULL only after disabling the IRQ sources.*/ + rtcp->callback = NULL; + } +} + +#include "chrtclib.h" + +/** + * @brief Get current time in format suitable for usage in FatFS. + * + * @param[in] rtcp pointer to RTC driver structure + * @return FAT time value. + * + * @api + */ +uint32_t rtc_lld_get_time_fat(RTCDriver *rtcp) { + uint32_t fattime; + struct tm timp; + + rtcGetTimeTm(rtcp, &timp); + + fattime = (timp.tm_sec) >> 1; + fattime |= (timp.tm_min) << 5; + fattime |= (timp.tm_hour) << 11; + fattime |= (timp.tm_mday) << 16; + fattime |= (timp.tm_mon + 1) << 21; + fattime |= (timp.tm_year - 80) << 25; + + return fattime; +} +#endif /* HAL_USE_RTC */ + +/** @} */ diff --git a/os/hal/ports/STM32/RTCv1/rtc_lld.h b/os/hal/ports/STM32/RTCv1/rtc_lld.h new file mode 100644 index 000000000..62b74cc46 --- /dev/null +++ b/os/hal/ports/STM32/RTCv1/rtc_lld.h @@ -0,0 +1,187 @@ +/* + ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ +/* + Concepts and parts of this file have been contributed by Uladzimir Pylinsky + aka barthess. + */ + +/** + * @file STM32/RTCv1/rtc_lld.h + * @brief STM32F1xx RTC subsystem low level driver header. + * + * @addtogroup RTC + * @{ + */ + +#ifndef _RTC_LLD_H_ +#define _RTC_LLD_H_ + +#if HAL_USE_RTC || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver constants. */ +/*===========================================================================*/ + +/** + * @brief This RTC implementation supports callbacks. + */ +#define RTC_SUPPORTS_CALLBACKS TRUE + +/** + * @brief One alarm comparator available. + */ +#define RTC_ALARMS 1 + +/*===========================================================================*/ +/* Driver pre-compile time settings. */ +/*===========================================================================*/ + +/** + * @name Configuration options + * @{ + */ +/* + * RTC driver system settings. + */ +#define STM32_RTC_IRQ_PRIORITY 15 +/** @} */ + +/*===========================================================================*/ +/* Derived constants and error checks. */ +/*===========================================================================*/ + +#if HAL_USE_RTC && !STM32_HAS_RTC +#error "RTC not present in the selected device" +#endif + +#if STM32_RTCCLK == 0 +#error "RTC clock not enabled" +#endif + +/*===========================================================================*/ +/* Driver data structures and types. */ +/*===========================================================================*/ + +/** + * @brief Type of a structure representing an RTC alarm time stamp. + */ +typedef struct RTCAlarm RTCAlarm; + +/** + * @brief Type of a structure representing an RTC callbacks config. + */ +typedef struct RTCCallbackConfig RTCCallbackConfig; + +/** + * @brief Type of an RTC alarm. + * @details Meaningful on platforms with more than 1 alarm comparator. + */ +typedef uint32_t rtcalarm_t; + +/** + * @brief Type of an RTC event. + */ +typedef enum { + RTC_EVENT_SECOND = 0, /** Triggered every second. */ + RTC_EVENT_ALARM = 1, /** Triggered on alarm. */ + RTC_EVENT_OVERFLOW = 2 /** Triggered on counter overflow. */ +} rtcevent_t; + +/** + * @brief Type of a generic RTC callback. + */ +typedef void (*rtccb_t)(RTCDriver *rtcp, rtcevent_t event); + +/** + * @brief Structure representing an RTC callbacks config. + */ +struct RTCCallbackConfig{ + /** + * @brief Generic RTC callback pointer. + */ + rtccb_t callback; +}; + +/** + * @brief Structure representing an RTC time stamp. + */ +struct RTCTime { + /** + * @brief Seconds since UNIX epoch. + */ + uint32_t tv_sec; + /** + * @brief Fractional part. + */ + uint32_t tv_msec; +}; + +/** + * @brief Structure representing an RTC alarm time stamp. + */ +struct RTCAlarm { + /** + * @brief Seconds since UNIX epoch. + */ + uint32_t tv_sec; +}; + +/** + * @brief Structure representing an RTC driver. + */ +struct RTCDriver{ + /** + * @brief Callback pointer. + */ + rtccb_t callback; +}; + +/*===========================================================================*/ +/* Driver macros. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +#if !defined(__DOXYGEN__) +extern RTCDriver RTCD1; +#endif + +#ifdef __cplusplus +extern "C" { +#endif + void rtc_lld_set_prescaler(void); + void rtc_lld_init(void); + void rtc_lld_set_time(RTCDriver *rtcp, const RTCTime *timespec); + void rtc_lld_get_time(RTCDriver *rtcp, RTCTime *timespec); + void rtc_lld_set_alarm(RTCDriver *rtcp, + rtcalarm_t alarm, + const RTCAlarm *alarmspec); + void rtc_lld_get_alarm(RTCDriver *rtcp, + rtcalarm_t alarm, + RTCAlarm *alarmspec); + void rtc_lld_set_callback(RTCDriver *rtcp, rtccb_t callback); + uint32_t rtc_lld_get_time_fat(RTCDriver *rtcp); +#ifdef __cplusplus +} +#endif + +#endif /* HAL_USE_RTC */ + +#endif /* _RTC_LLD_H_ */ + +/** @} */ diff --git a/os/hal/ports/STM32/RTCv2/rtc_lld.c b/os/hal/ports/STM32/RTCv2/rtc_lld.c new file mode 100644 index 000000000..17ae46ccf --- /dev/null +++ b/os/hal/ports/STM32/RTCv2/rtc_lld.c @@ -0,0 +1,322 @@ +/* + ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ +/* + Concepts and parts of this file have been contributed by Uladzimir Pylinsky + aka barthess. + */ + +/** + * @file STM32/RTCv2/rtc_lld.c + * @brief STM32L1xx/STM32F2xx/STM32F4xx RTC low level driver. + * + * @addtogroup RTC + * @{ + */ + +#include "ch.h" +#include "hal.h" + +#if HAL_USE_RTC || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver local definitions. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver exported variables. */ +/*===========================================================================*/ + +/** + * @brief RTC driver identifier. + */ +RTCDriver RTCD1; + +/*===========================================================================*/ +/* Driver local variables and types. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local functions. */ +/*===========================================================================*/ +/** + * @brief Wait for synchronization of RTC registers with APB1 bus. + * @details This function must be invoked before trying to read RTC registers. + * + * @notapi + */ +#define rtc_lld_apb1_sync() {while ((RTCD1.id_rtc->ISR & RTC_ISR_RSF) == 0);} + +/** + * @brief Beginning of configuration procedure. + * + * @notapi + */ +#define rtc_lld_enter_init() { \ + RTCD1.id_rtc->ISR |= RTC_ISR_INIT; \ + while ((RTCD1.id_rtc->ISR & RTC_ISR_INITF) == 0) \ + ; \ +} + +/** + * @brief Finalizing of configuration procedure. + * + * @notapi + */ +#define rtc_lld_exit_init() {RTCD1.id_rtc->ISR &= ~RTC_ISR_INIT;} + +/*===========================================================================*/ +/* Driver interrupt handlers. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver exported functions. */ +/*===========================================================================*/ + +/** + * @brief Enable access to registers. + * + * @api + */ +void rtc_lld_init(void){ + RTCD1.id_rtc = RTC; + + /* Asynchronous part of preloader. Set it to maximum value. */ + uint32_t prediv_a = 0x7F; + + /* Disable write protection. */ + RTCD1.id_rtc->WPR = 0xCA; + RTCD1.id_rtc->WPR = 0x53; + + /* If calendar not init yet. */ + if (!(RTC->ISR & RTC_ISR_INITS)){ + rtc_lld_enter_init(); + + /* Prescaler register must be written in two SEPARATE writes. */ + prediv_a = (prediv_a << 16) | + (((STM32_RTCCLK / (prediv_a + 1)) - 1) & 0x7FFF); + RTCD1.id_rtc->PRER = prediv_a; + RTCD1.id_rtc->PRER = prediv_a; + rtc_lld_exit_init(); + } +} + +/** + * @brief Set current time. + * @note Fractional part will be silently ignored. There is no possibility + * to set it on STM32 platform. + * + * @param[in] rtcp pointer to RTC driver structure + * @param[in] timespec pointer to a @p RTCTime structure + * + * @api + */ +void rtc_lld_set_time(RTCDriver *rtcp, const RTCTime *timespec) { + (void)rtcp; + + rtc_lld_enter_init(); + if (timespec->h12) + RTCD1.id_rtc->CR |= RTC_CR_FMT; + else + RTCD1.id_rtc->CR &= ~RTC_CR_FMT; + RTCD1.id_rtc->TR = timespec->tv_time; + RTCD1.id_rtc->DR = timespec->tv_date; + rtc_lld_exit_init(); +} + +/** + * @brief Get current time. + * + * @param[in] rtcp pointer to RTC driver structure + * @param[out] timespec pointer to a @p RTCTime structure + * + * @api + */ +void rtc_lld_get_time(RTCDriver *rtcp, RTCTime *timespec) { + (void)rtcp; + + rtc_lld_apb1_sync(); + +#if STM32_RTC_HAS_SUBSECONDS + timespec->tv_msec = + (1000 * ((RTCD1.id_rtc->PRER & 0x7FFF) - RTCD1.id_rtc->SSR)) / + ((RTCD1.id_rtc->PRER & 0x7FFF) + 1); +#endif /* STM32_RTC_HAS_SUBSECONDS */ + timespec->tv_time = RTCD1.id_rtc->TR; + timespec->tv_date = RTCD1.id_rtc->DR; +} + +/** + * @brief Set alarm time. + * + * @note Default value after BKP domain reset for both comparators is 0. + * @note Function does not performs any checks of alarm time validity. + * + * @param[in] rtcp Pointer to RTC driver structure. + * @param[in] alarm Alarm identifier. Can be 1 or 2. + * @param[in] alarmspec Pointer to a @p RTCAlarm structure. + * + * @api + */ +void rtc_lld_set_alarm(RTCDriver *rtcp, + rtcalarm_t alarm, + const RTCAlarm *alarmspec) { + if (alarm == 1){ + if (alarmspec != NULL){ + rtcp->id_rtc->CR &= ~RTC_CR_ALRAE; + while(!(rtcp->id_rtc->ISR & RTC_ISR_ALRAWF)) + ; + rtcp->id_rtc->ALRMAR = alarmspec->tv_datetime; + rtcp->id_rtc->CR |= RTC_CR_ALRAE; + rtcp->id_rtc->CR |= RTC_CR_ALRAIE; + } + else { + rtcp->id_rtc->CR &= ~RTC_CR_ALRAIE; + rtcp->id_rtc->CR &= ~RTC_CR_ALRAE; + } + } + else{ + if (alarmspec != NULL){ + rtcp->id_rtc->CR &= ~RTC_CR_ALRBE; + while(!(rtcp->id_rtc->ISR & RTC_ISR_ALRBWF)) + ; + rtcp->id_rtc->ALRMBR = alarmspec->tv_datetime; + rtcp->id_rtc->CR |= RTC_CR_ALRBE; + rtcp->id_rtc->CR |= RTC_CR_ALRBIE; + } + else { + rtcp->id_rtc->CR &= ~RTC_CR_ALRBIE; + rtcp->id_rtc->CR &= ~RTC_CR_ALRBE; + } + } +} + +/** + * @brief Get alarm time. + * + * @param[in] rtcp pointer to RTC driver structure + * @param[in] alarm alarm identifier + * @param[out] alarmspec pointer to a @p RTCAlarm structure + * + * @api + */ +void rtc_lld_get_alarm(RTCDriver *rtcp, + rtcalarm_t alarm, + RTCAlarm *alarmspec) { + if (alarm == 1) + alarmspec->tv_datetime = rtcp->id_rtc->ALRMAR; + else + alarmspec->tv_datetime = rtcp->id_rtc->ALRMBR; +} + +/** + * @brief Sets time of periodic wakeup. + * + * @note Default value after BKP domain reset is 0x0000FFFF + * + * @param[in] rtcp pointer to RTC driver structure + * @param[in] wakeupspec pointer to a @p RTCWakeup structure + * + * @api + */ +void rtcSetPeriodicWakeup_v2(RTCDriver *rtcp, RTCWakeup *wakeupspec){ + chDbgCheck((wakeupspec->wakeup != 0x30000), + "rtc_lld_set_periodic_wakeup, forbidden combination"); + + if (wakeupspec != NULL){ + rtcp->id_rtc->CR &= ~RTC_CR_WUTE; + while(!(rtcp->id_rtc->ISR & RTC_ISR_WUTWF)) + ; + rtcp->id_rtc->WUTR = wakeupspec->wakeup & 0xFFFF; + rtcp->id_rtc->CR = (wakeupspec->wakeup >> 16) & 0x7; + rtcp->id_rtc->CR |= RTC_CR_WUTIE; + rtcp->id_rtc->CR |= RTC_CR_WUTE; + } + else { + rtcp->id_rtc->CR &= ~RTC_CR_WUTIE; + rtcp->id_rtc->CR &= ~RTC_CR_WUTE; + } +} + +/** + * @brief Gets time of periodic wakeup. + * + * @note Default value after BKP domain reset is 0x0000FFFF + * + * @param[in] rtcp pointer to RTC driver structure + * @param[out] wakeupspec pointer to a @p RTCWakeup structure + * + * @api + */ +void rtcGetPeriodicWakeup_v2(RTCDriver *rtcp, RTCWakeup *wakeupspec){ + wakeupspec->wakeup = 0; + wakeupspec->wakeup |= rtcp->id_rtc->WUTR; + wakeupspec->wakeup |= (((uint32_t)rtcp->id_rtc->CR) & 0x7) << 16; +} + +/** + * @brief Get current time in format suitable for usage in FatFS. + * + * @param[in] rtcp pointer to RTC driver structure + * @return FAT time value. + * + * @api + */ +uint32_t rtc_lld_get_time_fat(RTCDriver *rtcp) { + uint32_t fattime; + RTCTime timespec; + uint32_t tv_time; + uint32_t tv_date; + uint32_t v; + + chSysLock(); + rtcGetTimeI(rtcp, ×pec); + chSysUnlock(); + + tv_time = timespec.tv_time; + tv_date = timespec.tv_date; + + v = (tv_time & RTC_TR_SU) >> RTC_TR_SU_OFFSET; + v += ((tv_time & RTC_TR_ST) >> RTC_TR_ST_OFFSET) * 10; + fattime = v >> 1; + + v = (tv_time & RTC_TR_MNU) >> RTC_TR_MNU_OFFSET; + v += ((tv_time & RTC_TR_MNT) >> RTC_TR_MNT_OFFSET) * 10; + fattime |= v << 5; + + v = (tv_time & RTC_TR_HU) >> RTC_TR_HU_OFFSET; + v += ((tv_time & RTC_TR_HT) >> RTC_TR_HT_OFFSET) * 10; + v += 12 * ((tv_time & RTC_TR_PM) >> RTC_TR_PM_OFFSET); + fattime |= v << 11; + + v = (tv_date & RTC_DR_DU) >> RTC_DR_DU_OFFSET; + v += ((tv_date & RTC_DR_DT) >> RTC_DR_DT_OFFSET) * 10; + fattime |= v << 16; + + v = (tv_date & RTC_DR_MU) >> RTC_DR_MU_OFFSET; + v += ((tv_date & RTC_DR_MT) >> RTC_DR_MT_OFFSET) * 10; + fattime |= v << 21; + + v = (tv_date & RTC_DR_YU) >> RTC_DR_YU_OFFSET; + v += ((tv_date & RTC_DR_YT) >> RTC_DR_YT_OFFSET) * 10; + v += 2000 - 1900 - 80; + fattime |= v << 25; + + return fattime; +} + +#endif /* HAL_USE_RTC */ + +/** @} */ diff --git a/os/hal/ports/STM32/RTCv2/rtc_lld.h b/os/hal/ports/STM32/RTCv2/rtc_lld.h new file mode 100644 index 000000000..8e0ce8dd0 --- /dev/null +++ b/os/hal/ports/STM32/RTCv2/rtc_lld.h @@ -0,0 +1,206 @@ +/* + ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ +/* + Concepts and parts of this file have been contributed by Uladzimir Pylinsky + aka barthess. + */ + +/** + * @file STM32/RTCv2/rtc_lld.h + * @brief STM32L1xx/STM32F2xx/STM32F4xx RTC low level driver header. + * + * @addtogroup RTC + * @{ + */ + +#ifndef _RTC_LLD_H_ +#define _RTC_LLD_H_ + +#if HAL_USE_RTC || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver constants. */ +/*===========================================================================*/ + +/** + * @brief Two alarm comparators available on STM32F4x. + */ +#define RTC_ALARMS 2 + +/** + * @brief Data offsets in RTC date and time registers. + */ +#define RTC_TR_PM_OFFSET 22 +#define RTC_TR_HT_OFFSET 20 +#define RTC_TR_HU_OFFSET 16 +#define RTC_TR_MNT_OFFSET 12 +#define RTC_TR_MNU_OFFSET 8 +#define RTC_TR_ST_OFFSET 4 +#define RTC_TR_SU_OFFSET 0 + +#define RTC_DR_YT_OFFSET 20 +#define RTC_DR_YU_OFFSET 16 +#define RTC_DR_WDU_OFFSET 13 +#define RTC_DR_MT_OFFSET 12 +#define RTC_DR_MU_OFFSET 8 +#define RTC_DR_DT_OFFSET 4 +#define RTC_DR_DU_OFFSET 0 + +/*===========================================================================*/ +/* Driver pre-compile time settings. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Derived constants and error checks. */ +/*===========================================================================*/ + +#if HAL_USE_RTC && !STM32_HAS_RTC +#error "RTC not present in the selected device" +#endif + +#if !(STM32_RTCSEL == STM32_RTCSEL_LSE) && \ + !(STM32_RTCSEL == STM32_RTCSEL_LSI) && \ + !(STM32_RTCSEL == STM32_RTCSEL_HSEDIV) +#error "invalid source selected for RTC clock" +#endif + +#if !defined(RTC_USE_INTERRUPTS) || defined(__DOXYGEN__) +#define RTC_USE_INTERRUPTS FALSE +#endif + +#if STM32_PCLK1 < (STM32_RTCCLK * 7) +#error "STM32_PCLK1 frequency is too low to handle RTC without ugly workaround" +#endif + +/*===========================================================================*/ +/* Driver data structures and types. */ +/*===========================================================================*/ + +/** + * @brief Type of a structure representing an RTC alarm time stamp. + */ +typedef struct RTCAlarm RTCAlarm; + +/** + * @brief Type of a structure representing an RTC wakeup period. + */ +typedef struct RTCWakeup RTCWakeup; + +/** + * @brief Type of a structure representing an RTC callbacks config. + */ +typedef struct RTCCallbackConfig RTCCallbackConfig; + +/** + * @brief Type of an RTC alarm. + * @details Meaningful on platforms with more than 1 alarm comparator. + */ +typedef uint32_t rtcalarm_t; + +/** + * @brief Structure representing an RTC time stamp. + */ +struct RTCTime { + /** + * @brief RTC date register in STM32 BCD format. + */ + uint32_t tv_date; + /** + * @brief RTC time register in STM32 BCD format. + */ + uint32_t tv_time; + /** + * @brief Set this to TRUE to use 12 hour notation. + */ + bool_t h12; + /** + * @brief Fractional part of time. + */ +#if STM32_RTC_HAS_SUBSECONDS + uint32_t tv_msec; +#endif +}; + +/** + * @brief Structure representing an RTC alarm time stamp. + */ +struct RTCAlarm { + /** + * @brief Date and time of alarm in STM32 BCD. + */ + uint32_t tv_datetime; +}; + +/** + * @brief Structure representing an RTC periodic wakeup period. + */ +struct RTCWakeup { + /** + * @brief RTC WUTR register. + * @details Bits [15:0] contain value of WUTR register + * Bits [18:16] contain value of WUCKSEL bits in CR register + * + * @note ((WUTR == 0) || (WUCKSEL == 3)) is forbidden combination. + */ + uint32_t wakeup; +}; + +/** + * @brief Structure representing an RTC driver. + */ +struct RTCDriver{ + /** + * @brief Pointer to the RTC registers block. + */ + RTC_TypeDef *id_rtc; +}; + +/*===========================================================================*/ +/* Driver macros. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +#if !defined(__DOXYGEN__) +extern RTCDriver RTCD1; +#endif + +#ifdef __cplusplus +extern "C" { +#endif + void rtc_lld_init(void); + void rtc_lld_set_time(RTCDriver *rtcp, const RTCTime *timespec); + void rtc_lld_get_time(RTCDriver *rtcp, RTCTime *timespec); + void rtc_lld_set_alarm(RTCDriver *rtcp, + rtcalarm_t alarm, + const RTCAlarm *alarmspec); + void rtc_lld_get_alarm(RTCDriver *rtcp, + rtcalarm_t alarm, + RTCAlarm *alarmspec); + void rtcSetPeriodicWakeup_v2(RTCDriver *rtcp, RTCWakeup *wakeupspec); + void rtcGetPeriodicWakeup_v2(RTCDriver *rtcp, RTCWakeup *wakeupspec); + uint32_t rtc_lld_get_time_fat(RTCDriver *rtcp); +#ifdef __cplusplus +} +#endif + +#endif /* HAL_USE_RTC */ + +#endif /* _RTC_LLD_H_ */ + +/** @} */ diff --git a/os/hal/ports/STM32/SPIv1/spi_lld.c b/os/hal/ports/STM32/SPIv1/spi_lld.c new file mode 100644 index 000000000..74d21273a --- /dev/null +++ b/os/hal/ports/STM32/SPIv1/spi_lld.c @@ -0,0 +1,483 @@ +/* + ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file STM32/SPIv1/spi_lld.c + * @brief STM32 SPI subsystem low level driver source. + * + * @addtogroup SPI + * @{ + */ + +#include "ch.h" +#include "hal.h" + +#if HAL_USE_SPI || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver local definitions. */ +/*===========================================================================*/ + +#define SPI1_RX_DMA_CHANNEL \ + STM32_DMA_GETCHANNEL(STM32_SPI_SPI1_RX_DMA_STREAM, \ + STM32_SPI1_RX_DMA_CHN) + +#define SPI1_TX_DMA_CHANNEL \ + STM32_DMA_GETCHANNEL(STM32_SPI_SPI1_TX_DMA_STREAM, \ + STM32_SPI1_TX_DMA_CHN) + +#define SPI2_RX_DMA_CHANNEL \ + STM32_DMA_GETCHANNEL(STM32_SPI_SPI2_RX_DMA_STREAM, \ + STM32_SPI2_RX_DMA_CHN) + +#define SPI2_TX_DMA_CHANNEL \ + STM32_DMA_GETCHANNEL(STM32_SPI_SPI2_TX_DMA_STREAM, \ + STM32_SPI2_TX_DMA_CHN) + +#define SPI3_RX_DMA_CHANNEL \ + STM32_DMA_GETCHANNEL(STM32_SPI_SPI3_RX_DMA_STREAM, \ + STM32_SPI3_RX_DMA_CHN) + +#define SPI3_TX_DMA_CHANNEL \ + STM32_DMA_GETCHANNEL(STM32_SPI_SPI3_TX_DMA_STREAM, \ + STM32_SPI3_TX_DMA_CHN) + +/*===========================================================================*/ +/* Driver exported variables. */ +/*===========================================================================*/ + +/** @brief SPI1 driver identifier.*/ +#if STM32_SPI_USE_SPI1 || defined(__DOXYGEN__) +SPIDriver SPID1; +#endif + +/** @brief SPI2 driver identifier.*/ +#if STM32_SPI_USE_SPI2 || defined(__DOXYGEN__) +SPIDriver SPID2; +#endif + +/** @brief SPI3 driver identifier.*/ +#if STM32_SPI_USE_SPI3 || defined(__DOXYGEN__) +SPIDriver SPID3; +#endif + +/*===========================================================================*/ +/* Driver local variables and types. */ +/*===========================================================================*/ + +static uint16_t dummytx; +static uint16_t dummyrx; + +/*===========================================================================*/ +/* Driver local functions. */ +/*===========================================================================*/ + +/** + * @brief Shared end-of-rx service routine. + * + * @param[in] spip pointer to the @p SPIDriver object + * @param[in] flags pre-shifted content of the ISR register + */ +static void spi_lld_serve_rx_interrupt(SPIDriver *spip, uint32_t flags) { + + /* DMA errors handling.*/ +#if defined(STM32_SPI_DMA_ERROR_HOOK) + if ((flags & (STM32_DMA_ISR_TEIF | STM32_DMA_ISR_DMEIF)) != 0) { + STM32_SPI_DMA_ERROR_HOOK(spip); + } +#else + (void)flags; +#endif + + /* Stop everything.*/ + dmaStreamDisable(spip->dmatx); + dmaStreamDisable(spip->dmarx); + + /* Portable SPI ISR code defined in the high level driver, note, it is + a macro.*/ + _spi_isr_code(spip); +} + +/** + * @brief Shared end-of-tx service routine. + * + * @param[in] spip pointer to the @p SPIDriver object + * @param[in] flags pre-shifted content of the ISR register + */ +static void spi_lld_serve_tx_interrupt(SPIDriver *spip, uint32_t flags) { + + /* DMA errors handling.*/ +#if defined(STM32_SPI_DMA_ERROR_HOOK) + (void)spip; + if ((flags & (STM32_DMA_ISR_TEIF | STM32_DMA_ISR_DMEIF)) != 0) { + STM32_SPI_DMA_ERROR_HOOK(spip); + } +#else + (void)spip; + (void)flags; +#endif +} + +/*===========================================================================*/ +/* Driver interrupt handlers. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver exported functions. */ +/*===========================================================================*/ + +/** + * @brief Low level SPI driver initialization. + * + * @notapi + */ +void spi_lld_init(void) { + + dummytx = 0xFFFF; + +#if STM32_SPI_USE_SPI1 + spiObjectInit(&SPID1); + SPID1.spi = SPI1; + SPID1.dmarx = STM32_DMA_STREAM(STM32_SPI_SPI1_RX_DMA_STREAM); + SPID1.dmatx = STM32_DMA_STREAM(STM32_SPI_SPI1_TX_DMA_STREAM); + SPID1.rxdmamode = STM32_DMA_CR_CHSEL(SPI1_RX_DMA_CHANNEL) | + STM32_DMA_CR_PL(STM32_SPI_SPI1_DMA_PRIORITY) | + STM32_DMA_CR_DIR_P2M | + STM32_DMA_CR_TCIE | + STM32_DMA_CR_DMEIE | + STM32_DMA_CR_TEIE; + SPID1.txdmamode = STM32_DMA_CR_CHSEL(SPI1_TX_DMA_CHANNEL) | + STM32_DMA_CR_PL(STM32_SPI_SPI1_DMA_PRIORITY) | + STM32_DMA_CR_DIR_M2P | + STM32_DMA_CR_DMEIE | + STM32_DMA_CR_TEIE; +#endif + +#if STM32_SPI_USE_SPI2 + spiObjectInit(&SPID2); + SPID2.spi = SPI2; + SPID2.dmarx = STM32_DMA_STREAM(STM32_SPI_SPI2_RX_DMA_STREAM); + SPID2.dmatx = STM32_DMA_STREAM(STM32_SPI_SPI2_TX_DMA_STREAM); + SPID2.rxdmamode = STM32_DMA_CR_CHSEL(SPI2_RX_DMA_CHANNEL) | + STM32_DMA_CR_PL(STM32_SPI_SPI2_DMA_PRIORITY) | + STM32_DMA_CR_DIR_P2M | + STM32_DMA_CR_TCIE | + STM32_DMA_CR_DMEIE | + STM32_DMA_CR_TEIE; + SPID2.txdmamode = STM32_DMA_CR_CHSEL(SPI2_TX_DMA_CHANNEL) | + STM32_DMA_CR_PL(STM32_SPI_SPI2_DMA_PRIORITY) | + STM32_DMA_CR_DIR_M2P | + STM32_DMA_CR_DMEIE | + STM32_DMA_CR_TEIE; +#endif + +#if STM32_SPI_USE_SPI3 + spiObjectInit(&SPID3); + SPID3.spi = SPI3; + SPID3.dmarx = STM32_DMA_STREAM(STM32_SPI_SPI3_RX_DMA_STREAM); + SPID3.dmatx = STM32_DMA_STREAM(STM32_SPI_SPI3_TX_DMA_STREAM); + SPID3.rxdmamode = STM32_DMA_CR_CHSEL(SPI3_RX_DMA_CHANNEL) | + STM32_DMA_CR_PL(STM32_SPI_SPI3_DMA_PRIORITY) | + STM32_DMA_CR_DIR_P2M | + STM32_DMA_CR_TCIE | + STM32_DMA_CR_DMEIE | + STM32_DMA_CR_TEIE; + SPID3.txdmamode = STM32_DMA_CR_CHSEL(SPI3_TX_DMA_CHANNEL) | + STM32_DMA_CR_PL(STM32_SPI_SPI3_DMA_PRIORITY) | + STM32_DMA_CR_DIR_M2P | + STM32_DMA_CR_DMEIE | + STM32_DMA_CR_TEIE; +#endif +} + +/** + * @brief Configures and activates the SPI peripheral. + * + * @param[in] spip pointer to the @p SPIDriver object + * + * @notapi + */ +void spi_lld_start(SPIDriver *spip) { + + /* If in stopped state then enables the SPI and DMA clocks.*/ + if (spip->state == SPI_STOP) { +#if STM32_SPI_USE_SPI1 + if (&SPID1 == spip) { + bool b; + b = dmaStreamAllocate(spip->dmarx, + STM32_SPI_SPI1_IRQ_PRIORITY, + (stm32_dmaisr_t)spi_lld_serve_rx_interrupt, + (void *)spip); + osalDbgAssert(!b, "stream already allocated"); + b = dmaStreamAllocate(spip->dmatx, + STM32_SPI_SPI1_IRQ_PRIORITY, + (stm32_dmaisr_t)spi_lld_serve_tx_interrupt, + (void *)spip); + osalDbgAssert(!b, "stream already allocated"); + rccEnableSPI1(FALSE); + } +#endif +#if STM32_SPI_USE_SPI2 + if (&SPID2 == spip) { + bool b; + b = dmaStreamAllocate(spip->dmarx, + STM32_SPI_SPI2_IRQ_PRIORITY, + (stm32_dmaisr_t)spi_lld_serve_rx_interrupt, + (void *)spip); + osalDbgAssert(!b, "stream already allocated"); + b = dmaStreamAllocate(spip->dmatx, + STM32_SPI_SPI2_IRQ_PRIORITY, + (stm32_dmaisr_t)spi_lld_serve_tx_interrupt, + (void *)spip); + osalDbgAssert(!b, "stream already allocated"); + rccEnableSPI2(FALSE); + } +#endif +#if STM32_SPI_USE_SPI3 + if (&SPID3 == spip) { + bool b; + b = dmaStreamAllocate(spip->dmarx, + STM32_SPI_SPI3_IRQ_PRIORITY, + (stm32_dmaisr_t)spi_lld_serve_rx_interrupt, + (void *)spip); + osalDbgAssert(!b, "stream already allocated"); + b = dmaStreamAllocate(spip->dmatx, + STM32_SPI_SPI3_IRQ_PRIORITY, + (stm32_dmaisr_t)spi_lld_serve_tx_interrupt, + (void *)spip); + osalDbgAssert(!b, "stream already allocated"); + rccEnableSPI3(FALSE); + } +#endif + + /* DMA setup.*/ + dmaStreamSetPeripheral(spip->dmarx, &spip->spi->DR); + dmaStreamSetPeripheral(spip->dmatx, &spip->spi->DR); + } + + /* Configuration-specific DMA setup.*/ + if ((spip->config->cr1 & SPI_CR1_DFF) == 0) { + /* Frame width is 8 bits or smaller.*/ + spip->rxdmamode = (spip->rxdmamode & ~STM32_DMA_CR_SIZE_MASK) | + STM32_DMA_CR_PSIZE_BYTE | STM32_DMA_CR_MSIZE_BYTE; + spip->txdmamode = (spip->txdmamode & ~STM32_DMA_CR_SIZE_MASK) | + STM32_DMA_CR_PSIZE_BYTE | STM32_DMA_CR_MSIZE_BYTE; + } + else { + /* Frame width is larger than 8 bits.*/ + spip->rxdmamode = (spip->rxdmamode & ~STM32_DMA_CR_SIZE_MASK) | + STM32_DMA_CR_PSIZE_HWORD | STM32_DMA_CR_MSIZE_HWORD; + spip->txdmamode = (spip->txdmamode & ~STM32_DMA_CR_SIZE_MASK) | + STM32_DMA_CR_PSIZE_HWORD | STM32_DMA_CR_MSIZE_HWORD; + } + /* SPI setup and enable.*/ + spip->spi->CR1 = 0; + spip->spi->CR1 = spip->config->cr1 | SPI_CR1_MSTR | SPI_CR1_SSM | + SPI_CR1_SSI; + spip->spi->CR2 = SPI_CR2_SSOE | SPI_CR2_RXDMAEN | SPI_CR2_TXDMAEN; + spip->spi->CR1 |= SPI_CR1_SPE; +} + +/** + * @brief Deactivates the SPI peripheral. + * + * @param[in] spip pointer to the @p SPIDriver object + * + * @notapi + */ +void spi_lld_stop(SPIDriver *spip) { + + /* If in ready state then disables the SPI clock.*/ + if (spip->state == SPI_READY) { + + /* SPI disable.*/ + spip->spi->CR1 = 0; + spip->spi->CR2 = 0; + dmaStreamRelease(spip->dmarx); + dmaStreamRelease(spip->dmatx); + +#if STM32_SPI_USE_SPI1 + if (&SPID1 == spip) + rccDisableSPI1(FALSE); +#endif +#if STM32_SPI_USE_SPI2 + if (&SPID2 == spip) + rccDisableSPI2(FALSE); +#endif +#if STM32_SPI_USE_SPI3 + if (&SPID3 == spip) + rccDisableSPI3(FALSE); +#endif + } +} + +/** + * @brief Asserts the slave select signal and prepares for transfers. + * + * @param[in] spip pointer to the @p SPIDriver object + * + * @notapi + */ +void spi_lld_select(SPIDriver *spip) { + + palClearPad(spip->config->ssport, spip->config->sspad); +} + +/** + * @brief Deasserts the slave select signal. + * @details The previously selected peripheral is unselected. + * + * @param[in] spip pointer to the @p SPIDriver object + * + * @notapi + */ +void spi_lld_unselect(SPIDriver *spip) { + + palSetPad(spip->config->ssport, spip->config->sspad); +} + +/** + * @brief Ignores data on the SPI bus. + * @details This asynchronous function starts the transmission of a series of + * idle words on the SPI bus and ignores the received data. + * @post At the end of the operation the configured callback is invoked. + * + * @param[in] spip pointer to the @p SPIDriver object + * @param[in] n number of words to be ignored + * + * @notapi + */ +void spi_lld_ignore(SPIDriver *spip, size_t n) { + + dmaStreamSetMemory0(spip->dmarx, &dummyrx); + dmaStreamSetTransactionSize(spip->dmarx, n); + dmaStreamSetMode(spip->dmarx, spip->rxdmamode); + + dmaStreamSetMemory0(spip->dmatx, &dummytx); + dmaStreamSetTransactionSize(spip->dmatx, n); + dmaStreamSetMode(spip->dmatx, spip->txdmamode); + + dmaStreamEnable(spip->dmarx); + dmaStreamEnable(spip->dmatx); +} + +/** + * @brief Exchanges data on the SPI bus. + * @details This asynchronous function starts a simultaneous transmit/receive + * operation. + * @post At the end of the operation the configured callback is invoked. + * @note The buffers are organized as uint8_t arrays for data sizes below or + * equal to 8 bits else it is organized as uint16_t arrays. + * + * @param[in] spip pointer to the @p SPIDriver object + * @param[in] n number of words to be exchanged + * @param[in] txbuf the pointer to the transmit buffer + * @param[out] rxbuf the pointer to the receive buffer + * + * @notapi + */ +void spi_lld_exchange(SPIDriver *spip, size_t n, + const void *txbuf, void *rxbuf) { + + dmaStreamSetMemory0(spip->dmarx, rxbuf); + dmaStreamSetTransactionSize(spip->dmarx, n); + dmaStreamSetMode(spip->dmarx, spip->rxdmamode| STM32_DMA_CR_MINC); + + dmaStreamSetMemory0(spip->dmatx, txbuf); + dmaStreamSetTransactionSize(spip->dmatx, n); + dmaStreamSetMode(spip->dmatx, spip->txdmamode | STM32_DMA_CR_MINC); + + dmaStreamEnable(spip->dmarx); + dmaStreamEnable(spip->dmatx); +} + +/** + * @brief Sends data over the SPI bus. + * @details This asynchronous function starts a transmit operation. + * @post At the end of the operation the configured callback is invoked. + * @note The buffers are organized as uint8_t arrays for data sizes below or + * equal to 8 bits else it is organized as uint16_t arrays. + * + * @param[in] spip pointer to the @p SPIDriver object + * @param[in] n number of words to send + * @param[in] txbuf the pointer to the transmit buffer + * + * @notapi + */ +void spi_lld_send(SPIDriver *spip, size_t n, const void *txbuf) { + + dmaStreamSetMemory0(spip->dmarx, &dummyrx); + dmaStreamSetTransactionSize(spip->dmarx, n); + dmaStreamSetMode(spip->dmarx, spip->rxdmamode); + + dmaStreamSetMemory0(spip->dmatx, txbuf); + dmaStreamSetTransactionSize(spip->dmatx, n); + dmaStreamSetMode(spip->dmatx, spip->txdmamode | STM32_DMA_CR_MINC); + + dmaStreamEnable(spip->dmarx); + dmaStreamEnable(spip->dmatx); +} + +/** + * @brief Receives data from the SPI bus. + * @details This asynchronous function starts a receive operation. + * @post At the end of the operation the configured callback is invoked. + * @note The buffers are organized as uint8_t arrays for data sizes below or + * equal to 8 bits else it is organized as uint16_t arrays. + * + * @param[in] spip pointer to the @p SPIDriver object + * @param[in] n number of words to receive + * @param[out] rxbuf the pointer to the receive buffer + * + * @notapi + */ +void spi_lld_receive(SPIDriver *spip, size_t n, void *rxbuf) { + + dmaStreamSetMemory0(spip->dmarx, rxbuf); + dmaStreamSetTransactionSize(spip->dmarx, n); + dmaStreamSetMode(spip->dmarx, spip->rxdmamode | STM32_DMA_CR_MINC); + + dmaStreamSetMemory0(spip->dmatx, &dummytx); + dmaStreamSetTransactionSize(spip->dmatx, n); + dmaStreamSetMode(spip->dmatx, spip->txdmamode); + + dmaStreamEnable(spip->dmarx); + dmaStreamEnable(spip->dmatx); +} + +/** + * @brief Exchanges one frame using a polled wait. + * @details This synchronous function exchanges one frame using a polled + * synchronization method. This function is useful when exchanging + * small amount of data on high speed channels, usually in this + * situation is much more efficient just wait for completion using + * polling than suspending the thread waiting for an interrupt. + * + * @param[in] spip pointer to the @p SPIDriver object + * @param[in] frame the data frame to send over the SPI bus + * @return The received data frame from the SPI bus. + */ +uint16_t spi_lld_polled_exchange(SPIDriver *spip, uint16_t frame) { + + spip->spi->DR = frame; + while ((spip->spi->SR & SPI_SR_RXNE) == 0) + ; + return spip->spi->DR; +} + +#endif /* HAL_USE_SPI */ + +/** @} */ diff --git a/os/hal/ports/STM32/SPIv1/spi_lld.h b/os/hal/ports/STM32/SPIv1/spi_lld.h new file mode 100644 index 000000000..b0a65d7cd --- /dev/null +++ b/os/hal/ports/STM32/SPIv1/spi_lld.h @@ -0,0 +1,407 @@ +/* + ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file STM32/SPIv1/spi_lld.h + * @brief STM32 SPI subsystem low level driver header. + * + * @addtogroup SPI + * @{ + */ + +#ifndef _SPI_LLD_H_ +#define _SPI_LLD_H_ + +#if HAL_USE_SPI || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver constants. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver pre-compile time settings. */ +/*===========================================================================*/ + +/** + * @name Configuration options + * @{ + */ +/** + * @brief SPI1 driver enable switch. + * @details If set to @p TRUE the support for SPI1 is included. + * @note The default is @p TRUE. + */ +#if !defined(STM32_SPI_USE_SPI1) || defined(__DOXYGEN__) +#define STM32_SPI_USE_SPI1 FALSE +#endif + +/** + * @brief SPI2 driver enable switch. + * @details If set to @p TRUE the support for SPI2 is included. + * @note The default is @p TRUE. + */ +#if !defined(STM32_SPI_USE_SPI2) || defined(__DOXYGEN__) +#define STM32_SPI_USE_SPI2 FALSE +#endif + +/** + * @brief SPI3 driver enable switch. + * @details If set to @p TRUE the support for SPI3 is included. + * @note The default is @p TRUE. + */ +#if !defined(STM32_SPI_USE_SPI3) || defined(__DOXYGEN__) +#define STM32_SPI_USE_SPI3 FALSE +#endif + +/** + * @brief SPI1 interrupt priority level setting. + */ +#if !defined(STM32_SPI_SPI1_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_SPI_SPI1_IRQ_PRIORITY 10 +#endif + +/** + * @brief SPI2 interrupt priority level setting. + */ +#if !defined(STM32_SPI_SPI2_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_SPI_SPI2_IRQ_PRIORITY 10 +#endif + +/** + * @brief SPI3 interrupt priority level setting. + */ +#if !defined(STM32_SPI_SPI3_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_SPI_SPI3_IRQ_PRIORITY 10 +#endif + +/** + * @brief SPI1 DMA priority (0..3|lowest..highest). + * @note The priority level is used for both the TX and RX DMA streams but + * because of the streams ordering the RX stream has always priority + * over the TX stream. + */ +#if !defined(STM32_SPI_SPI1_DMA_PRIORITY) || defined(__DOXYGEN__) +#define STM32_SPI_SPI1_DMA_PRIORITY 1 +#endif + +/** + * @brief SPI2 DMA priority (0..3|lowest..highest). + * @note The priority level is used for both the TX and RX DMA streams but + * because of the streams ordering the RX stream has always priority + * over the TX stream. + */ +#if !defined(STM32_SPI_SPI2_DMA_PRIORITY) || defined(__DOXYGEN__) +#define STM32_SPI_SPI2_DMA_PRIORITY 1 +#endif + +/** + * @brief SPI3 DMA priority (0..3|lowest..highest). + * @note The priority level is used for both the TX and RX DMA streams but + * because of the streams ordering the RX stream has always priority + * over the TX stream. + */ +#if !defined(STM32_SPI_SPI3_DMA_PRIORITY) || defined(__DOXYGEN__) +#define STM32_SPI_SPI3_DMA_PRIORITY 1 +#endif + +/** + * @brief SPI DMA error hook. + */ +#if !defined(STM32_SPI_DMA_ERROR_HOOK) || defined(__DOXYGEN__) +#define STM32_SPI_DMA_ERROR_HOOK(spip) chSysHalt() +#endif + +#if STM32_ADVANCED_DMA || defined(__DOXYGEN__) + +/** + * @brief DMA stream used for SPI1 RX operations. + * @note This option is only available on platforms with enhanced DMA. + */ +#if !defined(STM32_SPI_SPI1_RX_DMA_STREAM) || defined(__DOXYGEN__) +#define STM32_SPI_SPI1_RX_DMA_STREAM STM32_DMA_STREAM_ID(2, 0) +#endif + +/** + * @brief DMA stream used for SPI1 TX operations. + * @note This option is only available on platforms with enhanced DMA. + */ +#if !defined(STM32_SPI_SPI1_TX_DMA_STREAM) || defined(__DOXYGEN__) +#define STM32_SPI_SPI1_TX_DMA_STREAM STM32_DMA_STREAM_ID(2, 3) +#endif + +/** + * @brief DMA stream used for SPI2 RX operations. + * @note This option is only available on platforms with enhanced DMA. + */ +#if !defined(STM32_SPI_SPI2_RX_DMA_STREAM) || defined(__DOXYGEN__) +#define STM32_SPI_SPI2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 3) +#endif + +/** + * @brief DMA stream used for SPI2 TX operations. + * @note This option is only available on platforms with enhanced DMA. + */ +#if !defined(STM32_SPI_SPI2_TX_DMA_STREAM) || defined(__DOXYGEN__) +#define STM32_SPI_SPI2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) +#endif + +/** + * @brief DMA stream used for SPI3 RX operations. + * @note This option is only available on platforms with enhanced DMA. + */ +#if !defined(STM32_SPI_SPI3_RX_DMA_STREAM) || defined(__DOXYGEN__) +#define STM32_SPI_SPI3_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 0) +#endif + +/** + * @brief DMA stream used for SPI3 TX operations. + * @note This option is only available on platforms with enhanced DMA. + */ +#if !defined(STM32_SPI_SPI3_TX_DMA_STREAM) || defined(__DOXYGEN__) +#define STM32_SPI_SPI3_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7) +#endif + +#else /* !STM32_ADVANCED_DMA */ + +/* Fixed streams for platforms using the old DMA peripheral, the values are + valid for both STM32F1xx and STM32L1xx.*/ +#define STM32_SPI_SPI1_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2) +#define STM32_SPI_SPI1_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 3) +#define STM32_SPI_SPI2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) +#define STM32_SPI_SPI2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 5) +#define STM32_SPI_SPI3_RX_DMA_STREAM STM32_DMA_STREAM_ID(2, 1) +#define STM32_SPI_SPI3_TX_DMA_STREAM STM32_DMA_STREAM_ID(2, 2) + +#endif /* !STM32_ADVANCED_DMA*/ +/** @} */ + +/*===========================================================================*/ +/* Derived constants and error checks. */ +/*===========================================================================*/ + +#if STM32_SPI_USE_SPI1 && !STM32_HAS_SPI1 +#error "SPI1 not present in the selected device" +#endif + +#if STM32_SPI_USE_SPI2 && !STM32_HAS_SPI2 +#error "SPI2 not present in the selected device" +#endif + +#if STM32_SPI_USE_SPI3 && !STM32_HAS_SPI3 +#error "SPI3 not present in the selected device" +#endif + +#if !STM32_SPI_USE_SPI1 && !STM32_SPI_USE_SPI2 && !STM32_SPI_USE_SPI3 +#error "SPI driver activated but no SPI peripheral assigned" +#endif + +#if STM32_SPI_USE_SPI1 && \ + !CORTEX_IS_VALID_KERNEL_PRIORITY(STM32_SPI_SPI1_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to SPI1" +#endif + +#if STM32_SPI_USE_SPI2 && \ + !CORTEX_IS_VALID_KERNEL_PRIORITY(STM32_SPI_SPI2_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to SPI2" +#endif + +#if STM32_SPI_USE_SPI3 && \ + !CORTEX_IS_VALID_KERNEL_PRIORITY(STM32_SPI_SPI3_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to SPI3" +#endif + +#if STM32_SPI_USE_SPI1 && \ + !STM32_DMA_IS_VALID_PRIORITY(STM32_SPI_SPI1_DMA_PRIORITY) +#error "Invalid DMA priority assigned to SPI1" +#endif + +#if STM32_SPI_USE_SPI2 && \ + !STM32_DMA_IS_VALID_PRIORITY(STM32_SPI_SPI2_DMA_PRIORITY) +#error "Invalid DMA priority assigned to SPI2" +#endif + +#if STM32_SPI_USE_SPI3 && \ + !STM32_DMA_IS_VALID_PRIORITY(STM32_SPI_SPI3_DMA_PRIORITY) +#error "Invalid DMA priority assigned to SPI3" +#endif + +#if STM32_SPI_USE_SPI1 && \ + !STM32_DMA_IS_VALID_ID(STM32_SPI_SPI1_RX_DMA_STREAM, STM32_SPI1_RX_DMA_MSK) +#error "invalid DMA stream associated to SPI1 RX" +#endif + +#if STM32_SPI_USE_SPI1 && \ + !STM32_DMA_IS_VALID_ID(STM32_SPI_SPI1_TX_DMA_STREAM, STM32_SPI1_TX_DMA_MSK) +#error "invalid DMA stream associated to SPI1 TX" +#endif + +#if STM32_SPI_USE_SPI2 && \ + !STM32_DMA_IS_VALID_ID(STM32_SPI_SPI2_RX_DMA_STREAM, STM32_SPI2_RX_DMA_MSK) +#error "invalid DMA stream associated to SPI2 RX" +#endif + +#if STM32_SPI_USE_SPI2 && \ + !STM32_DMA_IS_VALID_ID(STM32_SPI_SPI2_TX_DMA_STREAM, STM32_SPI2_TX_DMA_MSK) +#error "invalid DMA stream associated to SPI2 TX" +#endif + +#if STM32_SPI_USE_SPI3 && \ + !STM32_DMA_IS_VALID_ID(STM32_SPI_SPI3_RX_DMA_STREAM, STM32_SPI3_RX_DMA_MSK) +#error "invalid DMA stream associated to SPI3 RX" +#endif + +#if STM32_SPI_USE_SPI3 && \ + !STM32_DMA_IS_VALID_ID(STM32_SPI_SPI3_TX_DMA_STREAM, STM32_SPI3_TX_DMA_MSK) +#error "invalid DMA stream associated to SPI3 TX" +#endif + +#if !defined(STM32_DMA_REQUIRED) +#define STM32_DMA_REQUIRED +#endif + +/*===========================================================================*/ +/* Driver data structures and types. */ +/*===========================================================================*/ + +/** + * @brief Type of a structure representing an SPI driver. + */ +typedef struct SPIDriver SPIDriver; + +/** + * @brief SPI notification callback type. + * + * @param[in] spip pointer to the @p SPIDriver object triggering the + * callback + */ +typedef void (*spicallback_t)(SPIDriver *spip); + +/** + * @brief Driver configuration structure. + */ +typedef struct { + /** + * @brief Operation complete callback or @p NULL. + */ + spicallback_t end_cb; + /* End of the mandatory fields.*/ + /** + * @brief The chip select line port. + */ + ioportid_t ssport; + /** + * @brief The chip select line pad number. + */ + uint16_t sspad; + /** + * @brief SPI initialization data. + */ + uint16_t cr1; +} SPIConfig; + +/** + * @brief Structure representing a SPI driver. + */ +struct SPIDriver{ + /** + * @brief Driver state. + */ + spistate_t state; + /** + * @brief Current configuration data. + */ + const SPIConfig *config; +#if SPI_USE_WAIT || defined(__DOXYGEN__) + /** + * @brief Waiting thread. + */ + thread_reference_t thread; +#endif /* SPI_USE_WAIT */ +#if SPI_USE_MUTUAL_EXCLUSION || defined(__DOXYGEN__) + /** + * @brief Mutex protecting the bus. + */ + mutex_t mutex; +#endif /* SPI_USE_MUTUAL_EXCLUSION */ +#if defined(SPI_DRIVER_EXT_FIELDS) + SPI_DRIVER_EXT_FIELDS +#endif + /* End of the mandatory fields.*/ + /** + * @brief Pointer to the SPIx registers block. + */ + SPI_TypeDef *spi; + /** + * @brief Receive DMA stream. + */ + const stm32_dma_stream_t *dmarx; + /** + * @brief Transmit DMA stream. + */ + const stm32_dma_stream_t *dmatx; + /** + * @brief RX DMA mode bit mask. + */ + uint32_t rxdmamode; + /** + * @brief TX DMA mode bit mask. + */ + uint32_t txdmamode; +}; + +/*===========================================================================*/ +/* Driver macros. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +#if STM32_SPI_USE_SPI1 && !defined(__DOXYGEN__) +extern SPIDriver SPID1; +#endif + +#if STM32_SPI_USE_SPI2 && !defined(__DOXYGEN__) +extern SPIDriver SPID2; +#endif + +#if STM32_SPI_USE_SPI3 && !defined(__DOXYGEN__) +extern SPIDriver SPID3; +#endif + +#ifdef __cplusplus +extern "C" { +#endif + void spi_lld_init(void); + void spi_lld_start(SPIDriver *spip); + void spi_lld_stop(SPIDriver *spip); + void spi_lld_select(SPIDriver *spip); + void spi_lld_unselect(SPIDriver *spip); + void spi_lld_ignore(SPIDriver *spip, size_t n); + void spi_lld_exchange(SPIDriver *spip, size_t n, + const void *txbuf, void *rxbuf); + void spi_lld_send(SPIDriver *spip, size_t n, const void *txbuf); + void spi_lld_receive(SPIDriver *spip, size_t n, void *rxbuf); + uint16_t spi_lld_polled_exchange(SPIDriver *spip, uint16_t frame); +#ifdef __cplusplus +} +#endif + +#endif /* HAL_USE_SPI */ + +#endif /* _SPI_LLD_H_ */ + +/** @} */ diff --git a/os/hal/ports/STM32/SPIv2/spi_lld.c b/os/hal/ports/STM32/SPIv2/spi_lld.c new file mode 100644 index 000000000..3cbcc0fc0 --- /dev/null +++ b/os/hal/ports/STM32/SPIv2/spi_lld.c @@ -0,0 +1,501 @@ +/* + ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file STM32/SPIv2/spi_lld.c + * @brief STM32 SPI subsystem low level driver source. + * + * @addtogroup SPI + * @{ + */ + +#include "hal.h" + +#if HAL_USE_SPI || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver local definitions. */ +/*===========================================================================*/ + +#define SPI1_RX_DMA_CHANNEL \ + STM32_DMA_GETCHANNEL(STM32_SPI_SPI1_RX_DMA_STREAM, \ + STM32_SPI1_RX_DMA_CHN) + +#define SPI1_TX_DMA_CHANNEL \ + STM32_DMA_GETCHANNEL(STM32_SPI_SPI1_TX_DMA_STREAM, \ + STM32_SPI1_TX_DMA_CHN) + +#define SPI2_RX_DMA_CHANNEL \ + STM32_DMA_GETCHANNEL(STM32_SPI_SPI2_RX_DMA_STREAM, \ + STM32_SPI2_RX_DMA_CHN) + +#define SPI2_TX_DMA_CHANNEL \ + STM32_DMA_GETCHANNEL(STM32_SPI_SPI2_TX_DMA_STREAM, \ + STM32_SPI2_TX_DMA_CHN) + +#define SPI3_RX_DMA_CHANNEL \ + STM32_DMA_GETCHANNEL(STM32_SPI_SPI3_RX_DMA_STREAM, \ + STM32_SPI3_RX_DMA_CHN) + +#define SPI3_TX_DMA_CHANNEL \ + STM32_DMA_GETCHANNEL(STM32_SPI_SPI3_TX_DMA_STREAM, \ + STM32_SPI3_TX_DMA_CHN) + +/*===========================================================================*/ +/* Driver exported variables. */ +/*===========================================================================*/ + +/** @brief SPI1 driver identifier.*/ +#if STM32_SPI_USE_SPI1 || defined(__DOXYGEN__) +SPIDriver SPID1; +#endif + +/** @brief SPI2 driver identifier.*/ +#if STM32_SPI_USE_SPI2 || defined(__DOXYGEN__) +SPIDriver SPID2; +#endif + +/** @brief SPI3 driver identifier.*/ +#if STM32_SPI_USE_SPI3 || defined(__DOXYGEN__) +SPIDriver SPID3; +#endif + +/*===========================================================================*/ +/* Driver local variables and types. */ +/*===========================================================================*/ + +static uint16_t dummytx; +static uint16_t dummyrx; + +/*===========================================================================*/ +/* Driver local functions. */ +/*===========================================================================*/ + +/** + * @brief Shared end-of-rx service routine. + * + * @param[in] spip pointer to the @p SPIDriver object + * @param[in] flags pre-shifted content of the ISR register + */ +static void spi_lld_serve_rx_interrupt(SPIDriver *spip, uint32_t flags) { + + /* DMA errors handling.*/ +#if defined(STM32_SPI_DMA_ERROR_HOOK) + if ((flags & (STM32_DMA_ISR_TEIF | STM32_DMA_ISR_DMEIF)) != 0) { + STM32_SPI_DMA_ERROR_HOOK(spip); + } +#else + (void)flags; +#endif + + /* Stop everything.*/ + dmaStreamDisable(spip->dmatx); + dmaStreamDisable(spip->dmarx); + + /* Portable SPI ISR code defined in the high level driver, note, it is + a macro.*/ + _spi_isr_code(spip); +} + +/** + * @brief Shared end-of-tx service routine. + * + * @param[in] spip pointer to the @p SPIDriver object + * @param[in] flags pre-shifted content of the ISR register + */ +static void spi_lld_serve_tx_interrupt(SPIDriver *spip, uint32_t flags) { + + /* DMA errors handling.*/ +#if defined(STM32_SPI_DMA_ERROR_HOOK) + (void)spip; + if ((flags & (STM32_DMA_ISR_TEIF | STM32_DMA_ISR_DMEIF)) != 0) { + STM32_SPI_DMA_ERROR_HOOK(spip); + } +#else + (void)spip; + (void)flags; +#endif +} + +/*===========================================================================*/ +/* Driver interrupt handlers. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver exported functions. */ +/*===========================================================================*/ + +/** + * @brief Low level SPI driver initialization. + * + * @notapi + */ +void spi_lld_init(void) { + + dummytx = 0xFFFF; + +#if STM32_SPI_USE_SPI1 + spiObjectInit(&SPID1); + SPID1.spi = SPI1; + SPID1.dmarx = STM32_DMA_STREAM(STM32_SPI_SPI1_RX_DMA_STREAM); + SPID1.dmatx = STM32_DMA_STREAM(STM32_SPI_SPI1_TX_DMA_STREAM); + SPID1.rxdmamode = STM32_DMA_CR_CHSEL(SPI1_RX_DMA_CHANNEL) | + STM32_DMA_CR_PL(STM32_SPI_SPI1_DMA_PRIORITY) | + STM32_DMA_CR_DIR_P2M | + STM32_DMA_CR_TCIE | + STM32_DMA_CR_DMEIE | + STM32_DMA_CR_TEIE; + SPID1.txdmamode = STM32_DMA_CR_CHSEL(SPI1_TX_DMA_CHANNEL) | + STM32_DMA_CR_PL(STM32_SPI_SPI1_DMA_PRIORITY) | + STM32_DMA_CR_DIR_M2P | + STM32_DMA_CR_DMEIE | + STM32_DMA_CR_TEIE; +#endif + +#if STM32_SPI_USE_SPI2 + spiObjectInit(&SPID2); + SPID2.spi = SPI2; + SPID2.dmarx = STM32_DMA_STREAM(STM32_SPI_SPI2_RX_DMA_STREAM); + SPID2.dmatx = STM32_DMA_STREAM(STM32_SPI_SPI2_TX_DMA_STREAM); + SPID2.rxdmamode = STM32_DMA_CR_CHSEL(SPI2_RX_DMA_CHANNEL) | + STM32_DMA_CR_PL(STM32_SPI_SPI2_DMA_PRIORITY) | + STM32_DMA_CR_DIR_P2M | + STM32_DMA_CR_TCIE | + STM32_DMA_CR_DMEIE | + STM32_DMA_CR_TEIE; + SPID2.txdmamode = STM32_DMA_CR_CHSEL(SPI2_TX_DMA_CHANNEL) | + STM32_DMA_CR_PL(STM32_SPI_SPI2_DMA_PRIORITY) | + STM32_DMA_CR_DIR_M2P | + STM32_DMA_CR_DMEIE | + STM32_DMA_CR_TEIE; +#endif + +#if STM32_SPI_USE_SPI3 + spiObjectInit(&SPID3); + SPID3.spi = SPI3; + SPID3.dmarx = STM32_DMA_STREAM(STM32_SPI_SPI3_RX_DMA_STREAM); + SPID3.dmatx = STM32_DMA_STREAM(STM32_SPI_SPI3_TX_DMA_STREAM); + SPID3.rxdmamode = STM32_DMA_CR_CHSEL(SPI3_RX_DMA_CHANNEL) | + STM32_DMA_CR_PL(STM32_SPI_SPI3_DMA_PRIORITY) | + STM32_DMA_CR_DIR_P2M | + STM32_DMA_CR_TCIE | + STM32_DMA_CR_DMEIE | + STM32_DMA_CR_TEIE; + SPID3.txdmamode = STM32_DMA_CR_CHSEL(SPI3_TX_DMA_CHANNEL) | + STM32_DMA_CR_PL(STM32_SPI_SPI3_DMA_PRIORITY) | + STM32_DMA_CR_DIR_M2P | + STM32_DMA_CR_DMEIE | + STM32_DMA_CR_TEIE; +#endif +} + +/** + * @brief Configures and activates the SPI peripheral. + * + * @param[in] spip pointer to the @p SPIDriver object + * + * @notapi + */ +void spi_lld_start(SPIDriver *spip) { + uint32_t ds; + + /* If in stopped state then enables the SPI and DMA clocks.*/ + if (spip->state == SPI_STOP) { +#if STM32_SPI_USE_SPI1 + if (&SPID1 == spip) { + bool_t b; + b = dmaStreamAllocate(spip->dmarx, + STM32_SPI_SPI1_IRQ_PRIORITY, + (stm32_dmaisr_t)spi_lld_serve_rx_interrupt, + (void *)spip); + osalDbgAssert(!b, "stream already allocated"); + b = dmaStreamAllocate(spip->dmatx, + STM32_SPI_SPI1_IRQ_PRIORITY, + (stm32_dmaisr_t)spi_lld_serve_tx_interrupt, + (void *)spip); + osalDbgAssert(!b, "stream already allocated"); + rccEnableSPI1(FALSE); + } +#endif +#if STM32_SPI_USE_SPI2 + if (&SPID2 == spip) { + bool_t b; + b = dmaStreamAllocate(spip->dmarx, + STM32_SPI_SPI2_IRQ_PRIORITY, + (stm32_dmaisr_t)spi_lld_serve_rx_interrupt, + (void *)spip); + osalDbgAssert(!b, "stream already allocated"); + b = dmaStreamAllocate(spip->dmatx, + STM32_SPI_SPI2_IRQ_PRIORITY, + (stm32_dmaisr_t)spi_lld_serve_tx_interrupt, + (void *)spip); + osalDbgAssert(!b, "stream already allocated"); + rccEnableSPI2(FALSE); + } +#endif +#if STM32_SPI_USE_SPI3 + if (&SPID3 == spip) { + bool_t b; + b = dmaStreamAllocate(spip->dmarx, + STM32_SPI_SPI3_IRQ_PRIORITY, + (stm32_dmaisr_t)spi_lld_serve_rx_interrupt, + (void *)spip); + osalDbgAssert(!b, "stream already allocated"); + b = dmaStreamAllocate(spip->dmatx, + STM32_SPI_SPI3_IRQ_PRIORITY, + (stm32_dmaisr_t)spi_lld_serve_tx_interrupt, + (void *)spip); + osalDbgAssert(!b, "stream already allocated"); + rccEnableSPI3(FALSE); + } +#endif + + /* DMA setup.*/ + dmaStreamSetPeripheral(spip->dmarx, &spip->spi->DR); + dmaStreamSetPeripheral(spip->dmatx, &spip->spi->DR); + } + + /* Configuration-specific DMA setup.*/ + ds = spip->config->cr2 & SPI_CR2_DS; + if (!ds || (ds <= (SPI_CR2_DS_2 | SPI_CR2_DS_1 | SPI_CR2_DS_0))) { + /* Frame width is 8 bits or smaller.*/ + spip->rxdmamode = (spip->rxdmamode & ~STM32_DMA_CR_SIZE_MASK) | + STM32_DMA_CR_PSIZE_BYTE | STM32_DMA_CR_MSIZE_BYTE; + spip->txdmamode = (spip->txdmamode & ~STM32_DMA_CR_SIZE_MASK) | + STM32_DMA_CR_PSIZE_BYTE | STM32_DMA_CR_MSIZE_BYTE; + } + else { + /* Frame width is larger than 8 bits.*/ + spip->rxdmamode = (spip->rxdmamode & ~STM32_DMA_CR_SIZE_MASK) | + STM32_DMA_CR_PSIZE_HWORD | STM32_DMA_CR_MSIZE_HWORD; + spip->txdmamode = (spip->txdmamode & ~STM32_DMA_CR_SIZE_MASK) | + STM32_DMA_CR_PSIZE_HWORD | STM32_DMA_CR_MSIZE_HWORD; + } + /* SPI setup and enable.*/ + spip->spi->CR1 = 0; + spip->spi->CR1 = spip->config->cr1 | SPI_CR1_MSTR | SPI_CR1_SSM | + SPI_CR1_SSI; + spip->spi->CR2 = spip->config->cr2 | SPI_CR2_FRXTH | SPI_CR2_SSOE | + SPI_CR2_RXDMAEN | SPI_CR2_TXDMAEN; + spip->spi->CR1 |= SPI_CR1_SPE; +} + +/** + * @brief Deactivates the SPI peripheral. + * + * @param[in] spip pointer to the @p SPIDriver object + * + * @notapi + */ +void spi_lld_stop(SPIDriver *spip) { + + /* If in ready state then disables the SPI clock.*/ + if (spip->state == SPI_READY) { + + /* SPI disable.*/ + spip->spi->CR1 = 0; + spip->spi->CR2 = 0; + dmaStreamRelease(spip->dmarx); + dmaStreamRelease(spip->dmatx); + +#if STM32_SPI_USE_SPI1 + if (&SPID1 == spip) + rccDisableSPI1(FALSE); +#endif +#if STM32_SPI_USE_SPI2 + if (&SPID2 == spip) + rccDisableSPI2(FALSE); +#endif +#if STM32_SPI_USE_SPI3 + if (&SPID3 == spip) + rccDisableSPI3(FALSE); +#endif + } +} + +/** + * @brief Asserts the slave select signal and prepares for transfers. + * + * @param[in] spip pointer to the @p SPIDriver object + * + * @notapi + */ +void spi_lld_select(SPIDriver *spip) { + + palClearPad(spip->config->ssport, spip->config->sspad); +} + +/** + * @brief Deasserts the slave select signal. + * @details The previously selected peripheral is unselected. + * + * @param[in] spip pointer to the @p SPIDriver object + * + * @notapi + */ +void spi_lld_unselect(SPIDriver *spip) { + + palSetPad(spip->config->ssport, spip->config->sspad); +} + +/** + * @brief Ignores data on the SPI bus. + * @details This asynchronous function starts the transmission of a series of + * idle words on the SPI bus and ignores the received data. + * @post At the end of the operation the configured callback is invoked. + * + * @param[in] spip pointer to the @p SPIDriver object + * @param[in] n number of words to be ignored + * + * @notapi + */ +void spi_lld_ignore(SPIDriver *spip, size_t n) { + + dmaStreamSetMemory0(spip->dmarx, &dummyrx); + dmaStreamSetTransactionSize(spip->dmarx, n); + dmaStreamSetMode(spip->dmarx, spip->rxdmamode); + + dmaStreamSetMemory0(spip->dmatx, &dummytx); + dmaStreamSetTransactionSize(spip->dmatx, n); + dmaStreamSetMode(spip->dmatx, spip->txdmamode); + + dmaStreamEnable(spip->dmarx); + dmaStreamEnable(spip->dmatx); +} + +/** + * @brief Exchanges data on the SPI bus. + * @details This asynchronous function starts a simultaneous transmit/receive + * operation. + * @post At the end of the operation the configured callback is invoked. + * @note The buffers are organized as uint8_t arrays for data sizes below or + * equal to 8 bits else it is organized as uint16_t arrays. + * + * @param[in] spip pointer to the @p SPIDriver object + * @param[in] n number of words to be exchanged + * @param[in] txbuf the pointer to the transmit buffer + * @param[out] rxbuf the pointer to the receive buffer + * + * @notapi + */ +void spi_lld_exchange(SPIDriver *spip, size_t n, + const void *txbuf, void *rxbuf) { + + dmaStreamSetMemory0(spip->dmarx, rxbuf); + dmaStreamSetTransactionSize(spip->dmarx, n); + dmaStreamSetMode(spip->dmarx, spip->rxdmamode| STM32_DMA_CR_MINC); + + dmaStreamSetMemory0(spip->dmatx, txbuf); + dmaStreamSetTransactionSize(spip->dmatx, n); + dmaStreamSetMode(spip->dmatx, spip->txdmamode | STM32_DMA_CR_MINC); + + dmaStreamEnable(spip->dmarx); + dmaStreamEnable(spip->dmatx); +} + +/** + * @brief Sends data over the SPI bus. + * @details This asynchronous function starts a transmit operation. + * @post At the end of the operation the configured callback is invoked. + * @note The buffers are organized as uint8_t arrays for data sizes below or + * equal to 8 bits else it is organized as uint16_t arrays. + * + * @param[in] spip pointer to the @p SPIDriver object + * @param[in] n number of words to send + * @param[in] txbuf the pointer to the transmit buffer + * + * @notapi + */ +void spi_lld_send(SPIDriver *spip, size_t n, const void *txbuf) { + + dmaStreamSetMemory0(spip->dmarx, &dummyrx); + dmaStreamSetTransactionSize(spip->dmarx, n); + dmaStreamSetMode(spip->dmarx, spip->rxdmamode); + + dmaStreamSetMemory0(spip->dmatx, txbuf); + dmaStreamSetTransactionSize(spip->dmatx, n); + dmaStreamSetMode(spip->dmatx, spip->txdmamode | STM32_DMA_CR_MINC); + + dmaStreamEnable(spip->dmarx); + dmaStreamEnable(spip->dmatx); +} + +/** + * @brief Receives data from the SPI bus. + * @details This asynchronous function starts a receive operation. + * @post At the end of the operation the configured callback is invoked. + * @note The buffers are organized as uint8_t arrays for data sizes below or + * equal to 8 bits else it is organized as uint16_t arrays. + * + * @param[in] spip pointer to the @p SPIDriver object + * @param[in] n number of words to receive + * @param[out] rxbuf the pointer to the receive buffer + * + * @notapi + */ +void spi_lld_receive(SPIDriver *spip, size_t n, void *rxbuf) { + + dmaStreamSetMemory0(spip->dmarx, rxbuf); + dmaStreamSetTransactionSize(spip->dmarx, n); + dmaStreamSetMode(spip->dmarx, spip->rxdmamode | STM32_DMA_CR_MINC); + + dmaStreamSetMemory0(spip->dmatx, &dummytx); + dmaStreamSetTransactionSize(spip->dmatx, n); + dmaStreamSetMode(spip->dmatx, spip->txdmamode); + + dmaStreamEnable(spip->dmarx); + dmaStreamEnable(spip->dmatx); +} + +/** + * @brief Exchanges one frame using a polled wait. + * @details This synchronous function exchanges one frame using a polled + * synchronization method. This function is useful when exchanging + * small amount of data on high speed channels, usually in this + * situation is much more efficient just wait for completion using + * polling than suspending the thread waiting for an interrupt. + * + * @param[in] spip pointer to the @p SPIDriver object + * @param[in] frame the data frame to send over the SPI bus + * @return The received data frame from the SPI bus. + */ +uint16_t spi_lld_polled_exchange(SPIDriver *spip, uint16_t frame) { + + /* + * Data register must be accessed with the appropriate data size. + * Byte size access (uint8_t *) for transactions that are <= 8-bit. + * Halfword size access (uint16_t) for transactions that are <= 8-bit. + */ + if ((spip->config->cr2 & SPI_CR2_DS) <= (SPI_CR2_DS_2 | + SPI_CR2_DS_1 | + SPI_CR2_DS_0)) { + volatile uint8_t *spidr = (volatile uint8_t *)&spip->spi->DR; + *spidr = (uint8_t)frame; + while ((spip->spi->SR & SPI_SR_RXNE) == 0) + ; + return (uint16_t)*spidr; + } + else { + spip->spi->DR = frame; + while ((spip->spi->SR & SPI_SR_RXNE) == 0) + ; + return spip->spi->DR; + } +} + +#endif /* HAL_USE_SPI */ + +/** @} */ diff --git a/os/hal/ports/STM32/SPIv2/spi_lld.h b/os/hal/ports/STM32/SPIv2/spi_lld.h new file mode 100644 index 000000000..07123df12 --- /dev/null +++ b/os/hal/ports/STM32/SPIv2/spi_lld.h @@ -0,0 +1,380 @@ +/* + ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file STM32/SPIv2/spi_lld.h + * @brief STM32 SPI subsystem low level driver header. + * + * @addtogroup SPI + * @{ + */ + +#ifndef _SPI_LLD_H_ +#define _SPI_LLD_H_ + +#if HAL_USE_SPI || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver constants. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver pre-compile time settings. */ +/*===========================================================================*/ + +/** + * @name Configuration options + * @{ + */ +/** + * @brief SPI1 driver enable switch. + * @details If set to @p TRUE the support for SPI1 is included. + * @note The default is @p TRUE. + */ +#if !defined(STM32_SPI_USE_SPI1) || defined(__DOXYGEN__) +#define STM32_SPI_USE_SPI1 FALSE +#endif + +/** + * @brief SPI2 driver enable switch. + * @details If set to @p TRUE the support for SPI2 is included. + * @note The default is @p TRUE. + */ +#if !defined(STM32_SPI_USE_SPI2) || defined(__DOXYGEN__) +#define STM32_SPI_USE_SPI2 FALSE +#endif + +/** + * @brief SPI3 driver enable switch. + * @details If set to @p TRUE the support for SPI3 is included. + * @note The default is @p TRUE. + */ +#if !defined(STM32_SPI_USE_SPI3) || defined(__DOXYGEN__) +#define STM32_SPI_USE_SPI3 FALSE +#endif + +/** + * @brief SPI1 interrupt priority level setting. + */ +#if !defined(STM32_SPI_SPI1_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_SPI_SPI1_IRQ_PRIORITY 10 +#endif + +/** + * @brief SPI2 interrupt priority level setting. + */ +#if !defined(STM32_SPI_SPI2_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_SPI_SPI2_IRQ_PRIORITY 10 +#endif + +/** + * @brief SPI3 interrupt priority level setting. + */ +#if !defined(STM32_SPI_SPI3_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_SPI_SPI3_IRQ_PRIORITY 10 +#endif + +/** + * @brief SPI1 DMA priority (0..3|lowest..highest). + * @note The priority level is used for both the TX and RX DMA streams but + * because of the streams ordering the RX stream has always priority + * over the TX stream. + */ +#if !defined(STM32_SPI_SPI1_DMA_PRIORITY) || defined(__DOXYGEN__) +#define STM32_SPI_SPI1_DMA_PRIORITY 1 +#endif + +/** + * @brief SPI2 DMA priority (0..3|lowest..highest). + * @note The priority level is used for both the TX and RX DMA streams but + * because of the streams ordering the RX stream has always priority + * over the TX stream. + */ +#if !defined(STM32_SPI_SPI2_DMA_PRIORITY) || defined(__DOXYGEN__) +#define STM32_SPI_SPI2_DMA_PRIORITY 1 +#endif + +/** + * @brief SPI3 DMA priority (0..3|lowest..highest). + * @note The priority level is used for both the TX and RX DMA streams but + * because of the streams ordering the RX stream has always priority + * over the TX stream. + */ +#if !defined(STM32_SPI_SPI3_DMA_PRIORITY) || defined(__DOXYGEN__) +#define STM32_SPI_SPI3_DMA_PRIORITY 1 +#endif + +/** + * @brief SPI DMA error hook. + */ +#if !defined(STM32_SPI_DMA_ERROR_HOOK) || defined(__DOXYGEN__) +#define STM32_SPI_DMA_ERROR_HOOK(spip) osalSysHalt("DMA failure") +#endif + +/* TODO: Move the following DMA settings in the STM32F37X registry.*/ +#if defined(STM32F37X) +/* Fixed values for STM32F3xx devices.*/ +#define STM32_SPI_SPI1_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2) +#define STM32_SPI_SPI1_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 3) +#define STM32_SPI_SPI2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) +#define STM32_SPI_SPI2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 5) +#define STM32_SPI_SPI3_RX_DMA_STREAM STM32_DMA_STREAM_ID(2, 1) +#define STM32_SPI_SPI3_TX_DMA_STREAM STM32_DMA_STREAM_ID(2, 2) +#endif /* defined(STM32F30X) */ +/** @} */ + +/*===========================================================================*/ +/* Derived constants and error checks. */ +/*===========================================================================*/ + +#if STM32_SPI_USE_SPI1 && !STM32_HAS_SPI1 +#error "SPI1 not present in the selected device" +#endif + +#if STM32_SPI_USE_SPI2 && !STM32_HAS_SPI2 +#error "SPI2 not present in the selected device" +#endif + +#if STM32_SPI_USE_SPI3 && !STM32_HAS_SPI3 +#error "SPI3 not present in the selected device" +#endif + +#if !STM32_SPI_USE_SPI1 && !STM32_SPI_USE_SPI2 && !STM32_SPI_USE_SPI3 +#error "SPI driver activated but no SPI peripheral assigned" +#endif + +#if STM32_SPI_USE_SPI1 && \ + !CORTEX_IS_VALID_KERNEL_PRIORITY(STM32_SPI_SPI1_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to SPI1" +#endif + +#if STM32_SPI_USE_SPI2 && \ + !CORTEX_IS_VALID_KERNEL_PRIORITY(STM32_SPI_SPI2_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to SPI2" +#endif + +#if STM32_SPI_USE_SPI3 && \ + !CORTEX_IS_VALID_KERNEL_PRIORITY(STM32_SPI_SPI3_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to SPI3" +#endif + +#if STM32_SPI_USE_SPI1 && \ + !STM32_DMA_IS_VALID_PRIORITY(STM32_SPI_SPI1_DMA_PRIORITY) +#error "Invalid DMA priority assigned to SPI1" +#endif + +#if STM32_SPI_USE_SPI2 && \ + !STM32_DMA_IS_VALID_PRIORITY(STM32_SPI_SPI2_DMA_PRIORITY) +#error "Invalid DMA priority assigned to SPI2" +#endif + +#if STM32_SPI_USE_SPI3 && \ + !STM32_DMA_IS_VALID_PRIORITY(STM32_SPI_SPI3_DMA_PRIORITY) +#error "Invalid DMA priority assigned to SPI3" +#endif + +/* The following checks are only required when there is a DMA able to + reassign streams to different channels.*/ +#if STM32_ADVANCED_DMA +/* Check on the presence of the DMA streams settings in mcuconf.h.*/ +#if STM32_SPI_USE_SPI1 && (!defined(STM32_SPI_SPI1_RX_DMA_STREAM) || \ + !defined(STM32_SPI_SPI1_TX_DMA_STREAM)) +#error "SPI1 DMA streams not defined" +#endif + +#if STM32_SPI_USE_SPI2 && (!defined(STM32_SPI_SPI2_RX_DMA_STREAM) || \ + !defined(STM32_SPI_SPI2_TX_DMA_STREAM)) +#error "SPI2 DMA streams not defined" +#endif + +#if STM32_SPI_USE_SPI3 && (!defined(STM32_SPI_SPI3_RX_DMA_STREAM) || \ + !defined(STM32_SPI_SPI3_TX_DMA_STREAM)) +#error "SPI3 DMA streams not defined" +#endif + +/* Check on the validity of the assigned DMA channels.*/ +#if STM32_SPI_USE_SPI1 && \ + !STM32_DMA_IS_VALID_ID(STM32_SPI_SPI1_RX_DMA_STREAM, STM32_SPI1_RX_DMA_MSK) +#error "invalid DMA stream associated to SPI1 RX" +#endif + +#if STM32_SPI_USE_SPI1 && \ + !STM32_DMA_IS_VALID_ID(STM32_SPI_SPI1_TX_DMA_STREAM, STM32_SPI1_TX_DMA_MSK) +#error "invalid DMA stream associated to SPI1 TX" +#endif + +#if STM32_SPI_USE_SPI2 && \ + !STM32_DMA_IS_VALID_ID(STM32_SPI_SPI2_RX_DMA_STREAM, STM32_SPI2_RX_DMA_MSK) +#error "invalid DMA stream associated to SPI2 RX" +#endif + +#if STM32_SPI_USE_SPI2 && \ + !STM32_DMA_IS_VALID_ID(STM32_SPI_SPI2_TX_DMA_STREAM, STM32_SPI2_TX_DMA_MSK) +#error "invalid DMA stream associated to SPI2 TX" +#endif + +#if STM32_SPI_USE_SPI3 && \ + !STM32_DMA_IS_VALID_ID(STM32_SPI_SPI3_RX_DMA_STREAM, STM32_SPI3_RX_DMA_MSK) +#error "invalid DMA stream associated to SPI3 RX" +#endif + +#if STM32_SPI_USE_SPI3 && \ + !STM32_DMA_IS_VALID_ID(STM32_SPI_SPI3_TX_DMA_STREAM, STM32_SPI3_TX_DMA_MSK) +#error "invalid DMA stream associated to SPI3 TX" +#endif +#endif /* STM32_ADVANCED_DMA */ + +#if !defined(STM32_DMA_REQUIRED) +#define STM32_DMA_REQUIRED +#endif + +/*===========================================================================*/ +/* Driver data structures and types. */ +/*===========================================================================*/ + +/** + * @brief Type of a structure representing an SPI driver. + */ +typedef struct SPIDriver SPIDriver; + +/** + * @brief SPI notification callback type. + * + * @param[in] spip pointer to the @p SPIDriver object triggering the + * callback + */ +typedef void (*spicallback_t)(SPIDriver *spip); + +/** + * @brief Driver configuration structure. + */ +typedef struct { + /** + * @brief Operation complete callback or @p NULL. + */ + spicallback_t end_cb; + /* End of the mandatory fields.*/ + /** + * @brief The chip select line port. + */ + ioportid_t ssport; + /** + * @brief The chip select line pad number. + */ + uint16_t sspad; + /** + * @brief SPI CR1 register initialization data. + */ + uint16_t cr1; + /** + * @brief SPI CR2 register initialization data. + */ + uint16_t cr2; +} SPIConfig; + +/** + * @brief Structure representing a SPI driver. + */ +struct SPIDriver{ + /** + * @brief Driver state. + */ + spistate_t state; + /** + * @brief Current configuration data. + */ + const SPIConfig *config; +#if SPI_USE_WAIT || defined(__DOXYGEN__) + /** + * @brief Waiting thread. + */ + thread_reference_t thread; +#endif /* SPI_USE_WAIT */ +#if SPI_USE_MUTUAL_EXCLUSION || defined(__DOXYGEN__) + /** + * @brief Mutex protecting the peripheral. + */ + mutex_t mutex; +#endif /* SPI_USE_MUTUAL_EXCLUSION */ +#if defined(SPI_DRIVER_EXT_FIELDS) + SPI_DRIVER_EXT_FIELDS +#endif + /* End of the mandatory fields.*/ + /** + * @brief Pointer to the SPIx registers block. + */ + SPI_TypeDef *spi; + /** + * @brief Receive DMA stream. + */ + const stm32_dma_stream_t *dmarx; + /** + * @brief Transmit DMA stream. + */ + const stm32_dma_stream_t *dmatx; + /** + * @brief RX DMA mode bit mask. + */ + uint32_t rxdmamode; + /** + * @brief TX DMA mode bit mask. + */ + uint32_t txdmamode; +}; + +/*===========================================================================*/ +/* Driver macros. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +#if STM32_SPI_USE_SPI1 && !defined(__DOXYGEN__) +extern SPIDriver SPID1; +#endif + +#if STM32_SPI_USE_SPI2 && !defined(__DOXYGEN__) +extern SPIDriver SPID2; +#endif + +#if STM32_SPI_USE_SPI3 && !defined(__DOXYGEN__) +extern SPIDriver SPID3; +#endif + +#ifdef __cplusplus +extern "C" { +#endif + void spi_lld_init(void); + void spi_lld_start(SPIDriver *spip); + void spi_lld_stop(SPIDriver *spip); + void spi_lld_select(SPIDriver *spip); + void spi_lld_unselect(SPIDriver *spip); + void spi_lld_ignore(SPIDriver *spip, size_t n); + void spi_lld_exchange(SPIDriver *spip, size_t n, + const void *txbuf, void *rxbuf); + void spi_lld_send(SPIDriver *spip, size_t n, const void *txbuf); + void spi_lld_receive(SPIDriver *spip, size_t n, void *rxbuf); + uint16_t spi_lld_polled_exchange(SPIDriver *spip, uint16_t frame); +#ifdef __cplusplus +} +#endif + +#endif /* HAL_USE_SPI */ + +#endif /* _SPI_LLD_H_ */ + +/** @} */ diff --git a/os/hal/ports/STM32/TIMv1/gpt_lld.c b/os/hal/ports/STM32/TIMv1/gpt_lld.c new file mode 100644 index 000000000..f9e144417 --- /dev/null +++ b/os/hal/ports/STM32/TIMv1/gpt_lld.c @@ -0,0 +1,754 @@ +/* + ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file STM32/gpt_lld.c + * @brief STM32 GPT subsystem low level driver source. + * + * @addtogroup GPT + * @{ + */ + +#include "hal.h" + +#if HAL_USE_GPT || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver local definitions. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver exported variables. */ +/*===========================================================================*/ + +/** + * @brief GPTD1 driver identifier. + * @note The driver GPTD1 allocates the complex timer TIM1 when enabled. + */ +#if STM32_GPT_USE_TIM1 || defined(__DOXYGEN__) +GPTDriver GPTD1; +#endif + +/** + * @brief GPTD2 driver identifier. + * @note The driver GPTD2 allocates the timer TIM2 when enabled. + */ +#if STM32_GPT_USE_TIM2 || defined(__DOXYGEN__) +GPTDriver GPTD2; +#endif + +/** + * @brief GPTD3 driver identifier. + * @note The driver GPTD3 allocates the timer TIM3 when enabled. + */ +#if STM32_GPT_USE_TIM3 || defined(__DOXYGEN__) +GPTDriver GPTD3; +#endif + +/** + * @brief GPTD4 driver identifier. + * @note The driver GPTD4 allocates the timer TIM4 when enabled. + */ +#if STM32_GPT_USE_TIM4 || defined(__DOXYGEN__) +GPTDriver GPTD4; +#endif + +/** + * @brief GPTD5 driver identifier. + * @note The driver GPTD5 allocates the timer TIM5 when enabled. + */ +#if STM32_GPT_USE_TIM5 || defined(__DOXYGEN__) +GPTDriver GPTD5; +#endif + +/** + * @brief GPTD6 driver identifier. + * @note The driver GPTD6 allocates the timer TIM6 when enabled. + */ +#if STM32_GPT_USE_TIM6 || defined(__DOXYGEN__) +GPTDriver GPTD6; +#endif + +/** + * @brief GPTD7 driver identifier. + * @note The driver GPTD7 allocates the timer TIM7 when enabled. + */ +#if STM32_GPT_USE_TIM7 || defined(__DOXYGEN__) +GPTDriver GPTD7; +#endif + +/** + * @brief GPTD8 driver identifier. + * @note The driver GPTD8 allocates the timer TIM8 when enabled. + */ +#if STM32_GPT_USE_TIM8 || defined(__DOXYGEN__) +GPTDriver GPTD8; +#endif + +/** + * @brief GPTD9 driver identifier. + * @note The driver GPTD9 allocates the timer TIM9 when enabled. + */ +#if STM32_GPT_USE_TIM9 || defined(__DOXYGEN__) +GPTDriver GPTD9; +#endif + +/** + * @brief GPTD11 driver identifier. + * @note The driver GPTD11 allocates the timer TIM11 when enabled. + */ +#if STM32_GPT_USE_TIM11 || defined(__DOXYGEN__) +GPTDriver GPTD11; +#endif + +/** + * @brief GPTD12 driver identifier. + * @note The driver GPTD12 allocates the timer TIM12 when enabled. + */ +#if STM32_GPT_USE_TIM12 || defined(__DOXYGEN__) +GPTDriver GPTD12; +#endif + +/** + * @brief GPTD14 driver identifier. + * @note The driver GPTD14 allocates the timer TIM14 when enabled. + */ +#if STM32_GPT_USE_TIM14 || defined(__DOXYGEN__) +GPTDriver GPTD14; +#endif + +/*===========================================================================*/ +/* Driver local variables and types. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local functions. */ +/*===========================================================================*/ + +/** + * @brief Shared IRQ handler. + * + * @param[in] gptp pointer to a @p GPTDriver object + */ +static void gpt_lld_serve_interrupt(GPTDriver *gptp) { + + gptp->tim->SR = 0; + if (gptp->state == GPT_ONESHOT) { + gptp->state = GPT_READY; /* Back in GPT_READY state. */ + gpt_lld_stop_timer(gptp); /* Timer automatically stopped. */ + } + gptp->config->callback(gptp); +} + +/*===========================================================================*/ +/* Driver interrupt handlers. */ +/*===========================================================================*/ + +#if STM32_GPT_USE_TIM1 +#if !defined(STM32_TIM1_UP_HANDLER) +#error "STM32_TIM1_UP_HANDLER not defined" +#endif +/** + * @brief TIM2 interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(STM32_TIM1_UP_HANDLER) { + + OSAL_IRQ_PROLOGUE(); + + gpt_lld_serve_interrupt(&GPTD1); + + OSAL_IRQ_EPILOGUE(); +} +#endif /* STM32_GPT_USE_TIM1 */ + +#if STM32_GPT_USE_TIM2 +#if !defined(STM32_TIM2_HANDLER) +#error "STM32_TIM2_HANDLER not defined" +#endif +/** + * @brief TIM2 interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(STM32_TIM2_HANDLER) { + + OSAL_IRQ_PROLOGUE(); + + gpt_lld_serve_interrupt(&GPTD2); + + OSAL_IRQ_EPILOGUE(); +} +#endif /* STM32_GPT_USE_TIM2 */ + +#if STM32_GPT_USE_TIM3 +#if !defined(STM32_TIM3_HANDLER) +#error "STM32_TIM3_HANDLER not defined" +#endif +/** + * @brief TIM3 interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(STM32_TIM3_HANDLER) { + + OSAL_IRQ_PROLOGUE(); + + gpt_lld_serve_interrupt(&GPTD3); + + OSAL_IRQ_EPILOGUE(); +} +#endif /* STM32_GPT_USE_TIM3 */ + +#if STM32_GPT_USE_TIM4 +#if !defined(STM32_TIM4_HANDLER) +#error "STM32_TIM4_HANDLER not defined" +#endif +/** + * @brief TIM4 interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(STM32_TIM4_HANDLER) { + + OSAL_IRQ_PROLOGUE(); + + gpt_lld_serve_interrupt(&GPTD4); + + OSAL_IRQ_EPILOGUE(); +} +#endif /* STM32_GPT_USE_TIM4 */ + +#if STM32_GPT_USE_TIM5 +#if !defined(STM32_TIM5_HANDLER) +#error "STM32_TIM5_HANDLER not defined" +#endif +/** + * @brief TIM5 interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(STM32_TIM5_HANDLER) { + + OSAL_IRQ_PROLOGUE(); + + gpt_lld_serve_interrupt(&GPTD5); + + OSAL_IRQ_EPILOGUE(); +} +#endif /* STM32_GPT_USE_TIM5 */ + +#if STM32_GPT_USE_TIM6 +#if !defined(STM32_TIM6_HANDLER) +#error "STM32_TIM6_HANDLER not defined" +#endif +/** + * @brief TIM6 interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(STM32_TIM6_HANDLER) { + + OSAL_IRQ_PROLOGUE(); + + gpt_lld_serve_interrupt(&GPTD6); + + OSAL_IRQ_EPILOGUE(); +} +#endif /* STM32_GPT_USE_TIM6 */ + +#if STM32_GPT_USE_TIM7 +#if !defined(STM32_TIM7_HANDLER) +#error "STM32_TIM7_HANDLER not defined" +#endif +/** + * @brief TIM7 interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(STM32_TIM7_HANDLER) { + + OSAL_IRQ_PROLOGUE(); + + gpt_lld_serve_interrupt(&GPTD7); + + OSAL_IRQ_EPILOGUE(); +} +#endif /* STM32_GPT_USE_TIM7 */ + +#if STM32_GPT_USE_TIM8 +#if !defined(STM32_TIM8_UP_HANDLER) +#error "STM32_TIM8_UP_HANDLER not defined" +#endif +/** + * @brief TIM8 interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(STM32_TIM8_UP_HANDLER) { + + OSAL_IRQ_PROLOGUE(); + + gpt_lld_serve_interrupt(&GPTD8); + + OSAL_IRQ_EPILOGUE(); +} +#endif /* STM32_GPT_USE_TIM8 */ + +#if STM32_GPT_USE_TIM9 +#if !defined(STM32_TIM9_HANDLER) +#error "STM32_TIM9_HANDLER not defined" +#endif +/** + * @brief TIM9 interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(STM32_TIM9_HANDLER) { + + OSAL_IRQ_PROLOGUE(); + + gpt_lld_serve_interrupt(&GPTD9); + + OSAL_IRQ_EPILOGUE(); +} +#endif /* STM32_GPT_USE_TIM9 */ + +#if STM32_GPT_USE_TIM11 +#if !defined(STM32_TIM11_HANDLER) +#error "STM32_TIM11_HANDLER not defined" +#endif +/** + * @brief TIM11 interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(STM32_TIM11_HANDLER) { + + OSAL_IRQ_PROLOGUE(); + + gpt_lld_serve_interrupt(&GPTD11); + + OSAL_IRQ_EPILOGUE(); +} +#endif /* STM32_GPT_USE_TIM11 */ + +#if STM32_GPT_USE_TIM12 +#if !defined(STM32_TIM12_HANDLER) +#error "STM32_TIM12_HANDLER not defined" +#endif +/** + * @brief TIM12 interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(STM32_TIM12_HANDLER) { + + OSAL_IRQ_PROLOGUE(); + + gpt_lld_serve_interrupt(&GPTD12); + + OSAL_IRQ_EPILOGUE(); +} +#endif /* STM32_GPT_USE_TIM12 */ + +#if STM32_GPT_USE_TIM14 +#if !defined(STM32_TIM14_HANDLER) +#error "STM32_TIM14_HANDLER not defined" +#endif +/** + * @brief TIM14 interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(STM32_TIM14_HANDLER) { + + OSAL_IRQ_PROLOGUE(); + + gpt_lld_serve_interrupt(&GPTD14); + + OSAL_IRQ_EPILOGUE(); +} +#endif /* STM32_GPT_USE_TIM14 */ + +/*===========================================================================*/ +/* Driver exported functions. */ +/*===========================================================================*/ + +/** + * @brief Low level GPT driver initialization. + * + * @notapi + */ +void gpt_lld_init(void) { + +#if STM32_GPT_USE_TIM1 + /* Driver initialization.*/ + GPTD1.tim = STM32_TIM1; + gptObjectInit(&GPTD1); +#endif + +#if STM32_GPT_USE_TIM2 + /* Driver initialization.*/ + GPTD2.tim = STM32_TIM2; + gptObjectInit(&GPTD2); +#endif + +#if STM32_GPT_USE_TIM3 + /* Driver initialization.*/ + GPTD3.tim = STM32_TIM3; + gptObjectInit(&GPTD3); +#endif + +#if STM32_GPT_USE_TIM4 + /* Driver initialization.*/ + GPTD4.tim = STM32_TIM4; + gptObjectInit(&GPTD4); +#endif + +#if STM32_GPT_USE_TIM5 + /* Driver initialization.*/ + GPTD5.tim = STM32_TIM5; + gptObjectInit(&GPTD5); +#endif + +#if STM32_GPT_USE_TIM6 + /* Driver initialization.*/ + GPTD6.tim = STM32_TIM6; + gptObjectInit(&GPTD6); +#endif + +#if STM32_GPT_USE_TIM7 + /* Driver initialization.*/ + GPTD7.tim = STM32_TIM7; + gptObjectInit(&GPTD7); +#endif + +#if STM32_GPT_USE_TIM8 + /* Driver initialization.*/ + GPTD8.tim = STM32_TIM8; + gptObjectInit(&GPTD8); +#endif + +#if STM32_GPT_USE_TIM9 + /* Driver initialization.*/ + GPTD9.tim = STM32_TIM9; + gptObjectInit(&GPTD9); +#endif + +#if STM32_GPT_USE_TIM11 + /* Driver initialization.*/ + GPTD11.tim = STM32_TIM11; + gptObjectInit(&GPTD11); +#endif + +#if STM32_GPT_USE_TIM12 + /* Driver initialization.*/ + GPTD12.tim = STM32_TIM12; + gptObjectInit(&GPTD12); +#endif + +#if STM32_GPT_USE_TIM14 + /* Driver initialization.*/ + GPTD14.tim = STM32_TIM14; + gptObjectInit(&GPTD14); +#endif +} + +/** + * @brief Configures and activates the GPT peripheral. + * + * @param[in] gptp pointer to the @p GPTDriver object + * + * @notapi + */ +void gpt_lld_start(GPTDriver *gptp) { + uint16_t psc; + + if (gptp->state == GPT_STOP) { + /* Clock activation.*/ +#if STM32_GPT_USE_TIM1 + if (&GPTD1 == gptp) { + rccEnableTIM1(FALSE); + rccResetTIM1(); + nvicEnableVector(STM32_TIM1_UP_NUMBER, STM32_GPT_TIM1_IRQ_PRIORITY); + gptp->clock = STM32_TIMCLK2; + } +#endif +#if STM32_GPT_USE_TIM2 + if (&GPTD2 == gptp) { + rccEnableTIM2(FALSE); + rccResetTIM2(); + nvicEnableVector(STM32_TIM2_NUMBER, STM32_GPT_TIM2_IRQ_PRIORITY); + gptp->clock = STM32_TIMCLK1; + } +#endif +#if STM32_GPT_USE_TIM3 + if (&GPTD3 == gptp) { + rccEnableTIM3(FALSE); + rccResetTIM3(); + nvicEnableVector(STM32_TIM3_NUMBER, STM32_GPT_TIM3_IRQ_PRIORITY); + gptp->clock = STM32_TIMCLK1; + } +#endif +#if STM32_GPT_USE_TIM4 + if (&GPTD4 == gptp) { + rccEnableTIM4(FALSE); + rccResetTIM4(); + nvicEnableVector(STM32_TIM4_NUMBER, STM32_GPT_TIM4_IRQ_PRIORITY); + gptp->clock = STM32_TIMCLK1; + } +#endif + +#if STM32_GPT_USE_TIM5 + if (&GPTD5 == gptp) { + rccEnableTIM5(FALSE); + rccResetTIM5(); + nvicEnableVector(STM32_TIM5_NUMBER, STM32_GPT_TIM5_IRQ_PRIORITY); + gptp->clock = STM32_TIMCLK1; + } +#endif + +#if STM32_GPT_USE_TIM6 + if (&GPTD6 == gptp) { + rccEnableTIM6(FALSE); + rccResetTIM6(); + nvicEnableVector(STM32_TIM6_NUMBER, STM32_GPT_TIM6_IRQ_PRIORITY); + gptp->clock = STM32_TIMCLK1; + } +#endif + +#if STM32_GPT_USE_TIM7 + if (&GPTD7 == gptp) { + rccEnableTIM7(FALSE); + rccResetTIM7(); + nvicEnableVector(STM32_TIM7_NUMBER, STM32_GPT_TIM7_IRQ_PRIORITY); + gptp->clock = STM32_TIMCLK1; + } +#endif + +#if STM32_GPT_USE_TIM8 + if (&GPTD8 == gptp) { + rccEnableTIM8(FALSE); + rccResetTIM8(); + nvicEnableVector(STM32_TIM8_UP_NUMBER, STM32_GPT_TIM8_IRQ_PRIORITY); + gptp->clock = STM32_TIMCLK2; + } +#endif + +#if STM32_GPT_USE_TIM9 + if (&GPTD9 == gptp) { + rccEnableTIM9(FALSE); + rccResetTIM9(); + nvicEnableVector(STM32_TIM9_NUMBER, STM32_GPT_TIM9_IRQ_PRIORITY); + gptp->clock = STM32_TIMCLK2; + } +#endif + +#if STM32_GPT_USE_TIM11 + if (&GPTD11 == gptp) { + rccEnableTIM11(FALSE); + rccResetTIM11(); + nvicEnableVector(STM32_TIM11_NUMBER, STM32_GPT_TIM11_IRQ_PRIORITY); + gptp->clock = STM32_TIMCLK2; + } +#endif + +#if STM32_GPT_USE_TIM12 + if (&GPTD12 == gptp) { + rccEnableTIM12(FALSE); + rccResetTIM12(); + nvicEnableVector(STM32_TIM12_NUMBER, STM32_GPT_TIM12_IRQ_PRIORITY); + gptp->clock = STM32_TIMCLK1; + } +#endif + +#if STM32_GPT_USE_TIM14 + if (&GPTD14 == gptp) { + rccEnableTIM14(FALSE); + rccResetTIM14(); + nvicEnableVector(STM32_TIM14_NUMBER, STM32_GPT_TIM14_IRQ_PRIORITY); + gptp->clock = STM32_TIMCLK1; + } +#endif + } + + /* Prescaler value calculation.*/ + psc = (uint16_t)((gptp->clock / gptp->config->frequency) - 1); + osalDbgAssert(((uint32_t)(psc + 1) * gptp->config->frequency) == gptp->clock, + "invalid frequency"); + + /* Timer configuration.*/ + gptp->tim->CR1 = 0; /* Initially stopped. */ + gptp->tim->CR2 = STM32_TIM_CR2_CCDS; /* DMA on UE (if any). */ + gptp->tim->PSC = psc; /* Prescaler value. */ + gptp->tim->DIER = gptp->config->dier & /* DMA-related DIER bits. */ + STM32_TIM_DIER_IRQ_MASK; + gptp->tim->SR = 0; /* Clear pending IRQs. */ +} + +/** + * @brief Deactivates the GPT peripheral. + * + * @param[in] gptp pointer to the @p GPTDriver object + * + * @notapi + */ +void gpt_lld_stop(GPTDriver *gptp) { + + if (gptp->state == GPT_READY) { + gptp->tim->CR1 = 0; /* Timer disabled. */ + gptp->tim->DIER = 0; /* All IRQs disabled. */ + gptp->tim->SR = 0; /* Clear pending IRQs. */ + +#if STM32_GPT_USE_TIM1 + if (&GPTD1 == gptp) { + nvicDisableVector(STM32_TIM1_UP_NUMBER); + rccDisableTIM1(FALSE); + } +#endif +#if STM32_GPT_USE_TIM2 + if (&GPTD2 == gptp) { + nvicDisableVector(STM32_TIM2_NUMBER); + rccDisableTIM2(FALSE); + } +#endif +#if STM32_GPT_USE_TIM3 + if (&GPTD3 == gptp) { + nvicDisableVector(STM32_TIM3_NUMBER); + rccDisableTIM3(FALSE); + } +#endif +#if STM32_GPT_USE_TIM4 + if (&GPTD4 == gptp) { + nvicDisableVector(STM32_TIM4_NUMBER); + rccDisableTIM4(FALSE); + } +#endif +#if STM32_GPT_USE_TIM5 + if (&GPTD5 == gptp) { + nvicDisableVector(STM32_TIM5_NUMBER); + rccDisableTIM5(FALSE); + } +#endif +#if STM32_GPT_USE_TIM6 + if (&GPTD6 == gptp) { + nvicDisableVector(STM32_TIM6_NUMBER); + rccDisableTIM6(FALSE); + } +#endif +#if STM32_GPT_USE_TIM7 + if (&GPTD7 == gptp) { + nvicDisableVector(STM32_TIM7_NUMBER); + rccDisableTIM7(FALSE); + } +#endif +#if STM32_GPT_USE_TIM8 + if (&GPTD8 == gptp) { + nvicDisableVector(STM32_TIM8_UP_NUMBER); + rccDisableTIM8(FALSE); + } +#endif +#if STM32_GPT_USE_TIM9 + if (&GPTD9 == gptp) { + nvicDisableVector(STM32_TIM9_NUMBER); + rccDisableTIM9(FALSE); + } +#endif +#if STM32_GPT_USE_TIM11 + if (&GPTD11 == gptp) { + nvicDisableVector(STM32_TIM11_NUMBER); + rccDisableTIM11(FALSE); + } +#endif +#if STM32_GPT_USE_TIM12 + if (&GPTD12 == gptp) { + nvicDisableVector(STM32_TIM12_NUMBER); + rccDisableTIM12(FALSE); + } +#endif +#if STM32_GPT_USE_TIM14 + if (&GPTD14 == gptp) { + nvicDisableVector(STM32_TIM14_NUMBER); + rccDisableTIM14(FALSE); + } +#endif + } +} + +/** + * @brief Starts the timer in continuous mode. + * + * @param[in] gptp pointer to the @p GPTDriver object + * @param[in] interval period in ticks + * + * @notapi + */ +void gpt_lld_start_timer(GPTDriver *gptp, gptcnt_t interval) { + + gptp->tim->ARR = (uint32_t)(interval - 1); /* Time constant. */ + gptp->tim->EGR = STM32_TIM_EGR_UG; /* Update event. */ + gptp->tim->CNT = 0; /* Reset counter. */ + + /* NOTE: After generating the UG event it takes several clock cycles before + SR bit 0 goes to 1. This is because the clearing of CNT has been inserted + before the clearing of SR, to give it some time.*/ + gptp->tim->SR = 0; /* Clear pending IRQs. */ + gptp->tim->DIER |= STM32_TIM_DIER_UIE; /* Update Event IRQ enabled.*/ + gptp->tim->CR1 = STM32_TIM_CR1_URS | STM32_TIM_CR1_CEN; +} + +/** + * @brief Stops the timer. + * + * @param[in] gptp pointer to the @p GPTDriver object + * + * @notapi + */ +void gpt_lld_stop_timer(GPTDriver *gptp) { + + gptp->tim->CR1 = 0; /* Initially stopped. */ + gptp->tim->SR = 0; /* Clear pending IRQs. */ + + /* All interrupts disabled.*/ + gptp->tim->DIER &= ~STM32_TIM_DIER_IRQ_MASK; +} + +/** + * @brief Starts the timer in one shot mode and waits for completion. + * @details This function specifically polls the timer waiting for completion + * in order to not have extra delays caused by interrupt servicing, + * this function is only recommended for short delays. + * + * @param[in] gptp pointer to the @p GPTDriver object + * @param[in] interval time interval in ticks + * + * @notapi + */ +void gpt_lld_polled_delay(GPTDriver *gptp, gptcnt_t interval) { + + gptp->tim->ARR = (uint32_t)(interval - 1); /* Time constant. */ + gptp->tim->EGR = STM32_TIM_EGR_UG; /* Update event. */ + gptp->tim->SR = 0; /* Clear pending IRQs. */ + gptp->tim->CR1 = STM32_TIM_CR1_OPM | STM32_TIM_CR1_URS | STM32_TIM_CR1_CEN; + while (!(gptp->tim->SR & STM32_TIM_SR_UIF)) + ; +} + +#endif /* HAL_USE_GPT */ + +/** @} */ diff --git a/os/hal/ports/STM32/TIMv1/gpt_lld.h b/os/hal/ports/STM32/TIMv1/gpt_lld.h new file mode 100644 index 000000000..56dc04f6b --- /dev/null +++ b/os/hal/ports/STM32/TIMv1/gpt_lld.h @@ -0,0 +1,512 @@ +/* + ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file STM32/gpt_lld.h + * @brief STM32 GPT subsystem low level driver header. + * + * @addtogroup GPT + * @{ + */ + +#ifndef _GPT_LLD_H_ +#define _GPT_LLD_H_ + +#include "stm32_tim.h" + +#if HAL_USE_GPT || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver constants. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver pre-compile time settings. */ +/*===========================================================================*/ + +/** + * @name Configuration options + * @{ + */ +/** + * @brief GPTD1 driver enable switch. + * @details If set to @p TRUE the support for GPTD1 is included. + * @note The default is @p TRUE. + */ +#if !defined(STM32_GPT_USE_TIM1) || defined(__DOXYGEN__) +#define STM32_GPT_USE_TIM1 FALSE +#endif + +/** + * @brief GPTD2 driver enable switch. + * @details If set to @p TRUE the support for GPTD2 is included. + * @note The default is @p TRUE. + */ +#if !defined(STM32_GPT_USE_TIM2) || defined(__DOXYGEN__) +#define STM32_GPT_USE_TIM2 FALSE +#endif + +/** + * @brief GPTD3 driver enable switch. + * @details If set to @p TRUE the support for GPTD3 is included. + * @note The default is @p TRUE. + */ +#if !defined(STM32_GPT_USE_TIM3) || defined(__DOXYGEN__) +#define STM32_GPT_USE_TIM3 FALSE +#endif + +/** + * @brief GPTD4 driver enable switch. + * @details If set to @p TRUE the support for GPTD4 is included. + * @note The default is @p TRUE. + */ +#if !defined(STM32_GPT_USE_TIM4) || defined(__DOXYGEN__) +#define STM32_GPT_USE_TIM4 FALSE +#endif + +/** + * @brief GPTD5 driver enable switch. + * @details If set to @p TRUE the support for GPTD5 is included. + * @note The default is @p TRUE. + */ +#if !defined(STM32_GPT_USE_TIM5) || defined(__DOXYGEN__) +#define STM32_GPT_USE_TIM5 FALSE +#endif + +/** + * @brief GPTD6 driver enable switch. + * @details If set to @p TRUE the support for GPTD6 is included. + * @note The default is @p TRUE. + */ +#if !defined(STM32_GPT_USE_TIM6) || defined(__DOXYGEN__) +#define STM32_GPT_USE_TIM6 FALSE +#endif + +/** + * @brief GPTD7 driver enable switch. + * @details If set to @p TRUE the support for GPTD7 is included. + * @note The default is @p TRUE. + */ +#if !defined(STM32_GPT_USE_TIM7) || defined(__DOXYGEN__) +#define STM32_GPT_USE_TIM7 FALSE +#endif + +/** + * @brief GPTD8 driver enable switch. + * @details If set to @p TRUE the support for GPTD8 is included. + * @note The default is @p TRUE. + */ +#if !defined(STM32_GPT_USE_TIM8) || defined(__DOXYGEN__) +#define STM32_GPT_USE_TIM8 FALSE +#endif + +/** + * @brief GPTD9 driver enable switch. + * @details If set to @p TRUE the support for GPTD9 is included. + * @note The default is @p TRUE. + */ +#if !defined(STM32_GPT_USE_TIM9) || defined(__DOXYGEN__) +#define STM32_GPT_USE_TIM9 FALSE +#endif + +/** + * @brief GPTD11 driver enable switch. + * @details If set to @p TRUE the support for GPTD11 is included. + * @note The default is @p TRUE. + */ +#if !defined(STM32_GPT_USE_TIM11) || defined(__DOXYGEN__) +#define STM32_GPT_USE_TIM11 FALSE +#endif + +/** + * @brief GPTD12 driver enable switch. + * @details If set to @p TRUE the support for GPTD12 is included. + * @note The default is @p TRUE. + */ +#if !defined(STM32_GPT_USE_TIM12) || defined(__DOXYGEN__) +#define STM32_GPT_USE_TIM12 FALSE +#endif + +/** + * @brief GPTD14 driver enable switch. + * @details If set to @p TRUE the support for GPTD14 is included. + * @note The default is @p TRUE. + */ +#if !defined(STM32_GPT_USE_TIM14) || defined(__DOXYGEN__) +#define STM32_GPT_USE_TIM14 FALSE +#endif + +/** + * @brief GPTD1 interrupt priority level setting. + */ +#if !defined(STM32_GPT_TIM1_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_GPT_TIM1_IRQ_PRIORITY 7 +#endif + +/** + * @brief GPTD2 interrupt priority level setting. + */ +#if !defined(STM32_GPT_TIM2_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_GPT_TIM2_IRQ_PRIORITY 7 +#endif + +/** + * @brief GPTD3 interrupt priority level setting. + */ +#if !defined(STM32_GPT_TIM3_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_GPT_TIM3_IRQ_PRIORITY 7 +#endif + +/** + * @brief GPTD4 interrupt priority level setting. + */ +#if !defined(STM32_GPT_TIM4_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_GPT_TIM4_IRQ_PRIORITY 7 +#endif + +/** + * @brief GPTD5 interrupt priority level setting. + */ +#if !defined(STM32_GPT_TIM5_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_GPT_TIM5_IRQ_PRIORITY 7 +#endif + +/** + * @brief GPTD6 interrupt priority level setting. + */ +#if !defined(STM32_GPT_TIM6_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_GPT_TIM6_IRQ_PRIORITY 7 +#endif + +/** + * @brief GPTD7 interrupt priority level setting. + */ +#if !defined(STM32_GPT_TIM7_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_GPT_TIM7_IRQ_PRIORITY 7 +#endif + +/** + * @brief GPTD8 interrupt priority level setting. + */ +#if !defined(STM32_GPT_TIM8_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_GPT_TIM8_IRQ_PRIORITY 7 +#endif + +/** + * @brief GPTD9 interrupt priority level setting. + */ +#if !defined(STM32_GPT_TIM9_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_GPT_TIM9_IRQ_PRIORITY 7 +#endif + +/** + * @brief GPTD11 interrupt priority level setting. + */ +#if !defined(STM32_GPT_TIM11_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_GPT_TIM11_IRQ_PRIORITY 7 +#endif + +/** + * @brief GPTD12 interrupt priority level setting. + */ +#if !defined(STM32_GPT_TIM12_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_GPT_TIM12_IRQ_PRIORITY 7 +#endif + +/** + * @brief GPTD14 interrupt priority level setting. + */ +#if !defined(STM32_GPT_TIM14_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_GPT_TIM14_IRQ_PRIORITY 7 +#endif +/** @} */ + +/*===========================================================================*/ +/* Derived constants and error checks. */ +/*===========================================================================*/ + +#if STM32_GPT_USE_TIM1 && !STM32_HAS_TIM1 +#error "TIM1 not present in the selected device" +#endif + +#if STM32_GPT_USE_TIM2 && !STM32_HAS_TIM2 +#error "TIM2 not present in the selected device" +#endif + +#if STM32_GPT_USE_TIM3 && !STM32_HAS_TIM3 +#error "TIM3 not present in the selected device" +#endif + +#if STM32_GPT_USE_TIM4 && !STM32_HAS_TIM4 +#error "TIM4 not present in the selected device" +#endif + +#if STM32_GPT_USE_TIM5 && !STM32_HAS_TIM5 +#error "TIM5 not present in the selected device" +#endif + +#if STM32_GPT_USE_TIM6 && !STM32_HAS_TIM6 +#error "TIM6 not present in the selected device" +#endif + +#if STM32_GPT_USE_TIM7 && !STM32_HAS_TIM7 +#error "TIM7 not present in the selected device" +#endif + +#if STM32_GPT_USE_TIM8 && !STM32_HAS_TIM8 +#error "TIM8 not present in the selected device" +#endif + +#if STM32_GPT_USE_TIM9 && !STM32_HAS_TIM9 +#error "TIM9 not present in the selected device" +#endif + +#if STM32_GPT_USE_TIM11 && !STM32_HAS_TIM11 +#error "TIM11 not present in the selected device" +#endif + +#if STM32_GPT_USE_TIM12 && !STM32_HAS_TIM12 +#error "TIM12 not present in the selected device" +#endif + +#if STM32_GPT_USE_TIM14 && !STM32_HAS_TIM14 +#error "TIM14 not present in the selected device" +#endif + +#if !STM32_GPT_USE_TIM1 && !STM32_GPT_USE_TIM2 && \ + !STM32_GPT_USE_TIM3 && !STM32_GPT_USE_TIM4 && \ + !STM32_GPT_USE_TIM5 && !STM32_GPT_USE_TIM6 && \ + !STM32_GPT_USE_TIM7 && !STM32_GPT_USE_TIM8 && \ + !STM32_GPT_USE_TIM9 && !STM32_GPT_USE_TIM11 && \ + !STM32_GPT_USE_TIM12 && !STM32_GPT_USE_TIM14 +#error "GPT driver activated but no TIM peripheral assigned" +#endif + +#if STM32_GPT_USE_TIM1 && \ + !CORTEX_IS_VALID_KERNEL_PRIORITY(STM32_GPT_TIM1_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to TIM1" +#endif + +#if STM32_GPT_USE_TIM2 && \ + !CORTEX_IS_VALID_KERNEL_PRIORITY(STM32_GPT_TIM2_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to TIM2" +#endif + +#if STM32_GPT_USE_TIM3 && \ + !CORTEX_IS_VALID_KERNEL_PRIORITY(STM32_GPT_TIM3_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to TIM3" +#endif + +#if STM32_GPT_USE_TIM4 && \ + !CORTEX_IS_VALID_KERNEL_PRIORITY(STM32_GPT_TIM4_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to TIM4" +#endif + +#if STM32_GPT_USE_TIM5 && \ + !CORTEX_IS_VALID_KERNEL_PRIORITY(STM32_GPT_TIM5_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to TIM5" +#endif + +#if STM32_GPT_USE_TIM6 && \ + !CORTEX_IS_VALID_KERNEL_PRIORITY(STM32_GPT_TIM6_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to TIM6" +#endif + +#if STM32_GPT_USE_TIM7 && \ + !CORTEX_IS_VALID_KERNEL_PRIORITY(STM32_GPT_TIM7_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to TIM7" +#endif + +#if STM32_GPT_USE_TIM8 && \ + !CORTEX_IS_VALID_KERNEL_PRIORITY(STM32_GPT_TIM8_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to TIM8" +#endif + +#if STM32_GPT_USE_TIM9 && \ + !CORTEX_IS_VALID_KERNEL_PRIORITY(STM32_GPT_TIM9_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to TIM9" +#endif + +#if STM32_GPT_USE_TIM11 && \ + !CORTEX_IS_VALID_KERNEL_PRIORITY(STM32_GPT_TIM11_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to TIM11" +#endif + +#if STM32_GPT_USE_TIM12 && \ + !CORTEX_IS_VALID_KERNEL_PRIORITY(STM32_GPT_TIM12_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to TIM12" +#endif + +#if STM32_GPT_USE_TIM14 && \ + !CORTEX_IS_VALID_KERNEL_PRIORITY(STM32_GPT_TIM14_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to TIM14" +#endif + +/*===========================================================================*/ +/* Driver data structures and types. */ +/*===========================================================================*/ + +/** + * @brief GPT frequency type. + */ +typedef uint32_t gptfreq_t; + +/** + * @brief GPT counter type. + */ +typedef uint32_t gptcnt_t; + +/** + * @brief Driver configuration structure. + * @note It could be empty on some architectures. + */ +typedef struct { + /** + * @brief Timer clock in Hz. + * @note The low level can use assertions in order to catch invalid + * frequency specifications. + */ + gptfreq_t frequency; + /** + * @brief Timer callback pointer. + * @note This callback is invoked on GPT counter events. + */ + gptcallback_t callback; + /* End of the mandatory fields.*/ + /** + * @brief TIM DIER register initialization data. + * @note The value of this field should normally be equal to zero. + * @note Only the DMA-related bits can be specified in this field. + */ + uint32_t dier; +} GPTConfig; + +/** + * @brief Structure representing a GPT driver. + */ +struct GPTDriver { + /** + * @brief Driver state. + */ + gptstate_t state; + /** + * @brief Current configuration data. + */ + const GPTConfig *config; +#if defined(GPT_DRIVER_EXT_FIELDS) + GPT_DRIVER_EXT_FIELDS +#endif + /* End of the mandatory fields.*/ + /** + * @brief Timer base clock. + */ + uint32_t clock; + /** + * @brief Pointer to the TIMx registers block. + */ + stm32_tim_t *tim; +}; + +/*===========================================================================*/ +/* Driver macros. */ +/*===========================================================================*/ + +/** + * @brief Changes the interval of GPT peripheral. + * @details This function changes the interval of a running GPT unit. + * @pre The GPT unit must have been activated using @p gptStart(). + * @pre The GPT unit must have been running in continuous mode using + * @p gptStartContinuous(). + * @post The GPT unit interval is changed to the new value. + * @note The function has effect at the next cycle start. + * + * @param[in] gptp pointer to a @p GPTDriver object + * @param[in] interval new cycle time in timer ticks + * @notapi + */ +#define gpt_lld_change_interval(gptp, interval) \ + ((gptp)->tim->ARR = (uint32_t)((interval) - 1)) + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +#if STM32_GPT_USE_TIM1 && !defined(__DOXYGEN__) +extern GPTDriver GPTD1; +#endif + +#if STM32_GPT_USE_TIM2 && !defined(__DOXYGEN__) +extern GPTDriver GPTD2; +#endif + +#if STM32_GPT_USE_TIM3 && !defined(__DOXYGEN__) +extern GPTDriver GPTD3; +#endif + +#if STM32_GPT_USE_TIM4 && !defined(__DOXYGEN__) +extern GPTDriver GPTD4; +#endif + +#if STM32_GPT_USE_TIM5 && !defined(__DOXYGEN__) +extern GPTDriver GPTD5; +#endif + +#if STM32_GPT_USE_TIM6 && !defined(__DOXYGEN__) +extern GPTDriver GPTD6; +#endif + +#if STM32_GPT_USE_TIM7 && !defined(__DOXYGEN__) +extern GPTDriver GPTD7; +#endif + +#if STM32_GPT_USE_TIM8 && !defined(__DOXYGEN__) +extern GPTDriver GPTD8; +#endif + +#if STM32_GPT_USE_TIM9 && !defined(__DOXYGEN__) +extern GPTDriver GPTD9; +#endif + +#if STM32_GPT_USE_TIM11 && !defined(__DOXYGEN__) +extern GPTDriver GPTD11; +#endif + +#if STM32_GPT_USE_TIM12 && !defined(__DOXYGEN__) +extern GPTDriver GPTD12; +#endif + +#if STM32_GPT_USE_TIM14 && !defined(__DOXYGEN__) +extern GPTDriver GPTD14; +#endif + +#ifdef __cplusplus +extern "C" { +#endif + void gpt_lld_init(void); + void gpt_lld_start(GPTDriver *gptp); + void gpt_lld_stop(GPTDriver *gptp); + void gpt_lld_start_timer(GPTDriver *gptp, gptcnt_t period); + void gpt_lld_stop_timer(GPTDriver *gptp); + void gpt_lld_polled_delay(GPTDriver *gptp, gptcnt_t interval); +#ifdef __cplusplus +} +#endif + +#endif /* HAL_USE_GPT */ + +#endif /* _GPT_LLD_H_ */ + +/** @} */ diff --git a/os/hal/ports/STM32/TIMv1/icu_lld.c b/os/hal/ports/STM32/TIMv1/icu_lld.c new file mode 100644 index 000000000..09be838a6 --- /dev/null +++ b/os/hal/ports/STM32/TIMv1/icu_lld.c @@ -0,0 +1,634 @@ +/* + ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ +/* + Concepts and parts of this file have been contributed by Fabio Utzig and + Xo Wang. + */ + +/** + * @file STM32/icu_lld.c + * @brief STM32 ICU subsystem low level driver header. + * + * @addtogroup ICU + * @{ + */ + +#include "hal.h" + +#if HAL_USE_ICU || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver local definitions. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver exported variables. */ +/*===========================================================================*/ + +/** + * @brief ICUD1 driver identifier. + * @note The driver ICUD1 allocates the complex timer TIM1 when enabled. + */ +#if STM32_ICU_USE_TIM1 || defined(__DOXYGEN__) +ICUDriver ICUD1; +#endif + +/** + * @brief ICUD2 driver identifier. + * @note The driver ICUD1 allocates the timer TIM2 when enabled. + */ +#if STM32_ICU_USE_TIM2 || defined(__DOXYGEN__) +ICUDriver ICUD2; +#endif + +/** + * @brief ICUD3 driver identifier. + * @note The driver ICUD1 allocates the timer TIM3 when enabled. + */ +#if STM32_ICU_USE_TIM3 || defined(__DOXYGEN__) +ICUDriver ICUD3; +#endif + +/** + * @brief ICUD4 driver identifier. + * @note The driver ICUD4 allocates the timer TIM4 when enabled. + */ +#if STM32_ICU_USE_TIM4 || defined(__DOXYGEN__) +ICUDriver ICUD4; +#endif + +/** + * @brief ICUD5 driver identifier. + * @note The driver ICUD5 allocates the timer TIM5 when enabled. + */ +#if STM32_ICU_USE_TIM5 || defined(__DOXYGEN__) +ICUDriver ICUD5; +#endif + +/** + * @brief ICUD8 driver identifier. + * @note The driver ICUD8 allocates the timer TIM8 when enabled. + */ +#if STM32_ICU_USE_TIM8 || defined(__DOXYGEN__) +ICUDriver ICUD8; +#endif + +/** + * @brief ICUD9 driver identifier. + * @note The driver ICUD9 allocates the timer TIM9 when enabled. + */ +#if STM32_ICU_USE_TIM9 || defined(__DOXYGEN__) +ICUDriver ICUD9; +#endif + +/*===========================================================================*/ +/* Driver local variables and types. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local functions. */ +/*===========================================================================*/ + +/** + * @brief Shared IRQ handler. + * + * @param[in] icup pointer to the @p ICUDriver object + */ +static void icu_lld_serve_interrupt(ICUDriver *icup) { + uint16_t sr; + + sr = icup->tim->SR; + sr &= icup->tim->DIER & STM32_TIM_DIER_IRQ_MASK; + icup->tim->SR = ~sr; + if (icup->config->channel == ICU_CHANNEL_1) { + if ((sr & STM32_TIM_SR_CC1IF) != 0) + _icu_isr_invoke_period_cb(icup); + if ((sr & STM32_TIM_SR_CC2IF) != 0) + _icu_isr_invoke_width_cb(icup); + } else { + if ((sr & STM32_TIM_SR_CC1IF) != 0) + _icu_isr_invoke_width_cb(icup); + if ((sr & STM32_TIM_SR_CC2IF) != 0) + _icu_isr_invoke_period_cb(icup); + } + if ((sr & STM32_TIM_SR_UIF) != 0) + _icu_isr_invoke_overflow_cb(icup); +} + +/*===========================================================================*/ +/* Driver interrupt handlers. */ +/*===========================================================================*/ + +#if STM32_ICU_USE_TIM1 +#if !defined(STM32_TIM1_UP_HANDLER) +#error "STM32_TIM1_UP_HANDLER not defined" +#endif +/** + * @brief TIM1 compare interrupt handler. + * @note It is assumed that the various sources are only activated if the + * associated callback pointer is not equal to @p NULL in order to not + * perform an extra check in a potentially critical interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(STM32_TIM1_UP_HANDLER) { + + OSAL_IRQ_PROLOGUE(); + + icu_lld_serve_interrupt(&ICUD1); + + OSAL_IRQ_EPILOGUE(); +} + +#if !defined(STM32_TIM1_CC_HANDLER) +#error "STM32_TIM1_CC_HANDLER not defined" +#endif +/** + * @brief TIM1 compare interrupt handler. + * @note It is assumed that the various sources are only activated if the + * associated callback pointer is not equal to @p NULL in order to not + * perform an extra check in a potentially critical interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(STM32_TIM1_CC_HANDLER) { + + OSAL_IRQ_PROLOGUE(); + + icu_lld_serve_interrupt(&ICUD1); + + OSAL_IRQ_EPILOGUE(); +} +#endif /* STM32_ICU_USE_TIM1 */ + +#if STM32_ICU_USE_TIM2 +#if !defined(STM32_TIM2_HANDLER) +#error "STM32_TIM2_HANDLER not defined" +#endif +/** + * @brief TIM2 interrupt handler. + * @note It is assumed that the various sources are only activated if the + * associated callback pointer is not equal to @p NULL in order to not + * perform an extra check in a potentially critical interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(STM32_TIM2_HANDLER) { + + OSAL_IRQ_PROLOGUE(); + + icu_lld_serve_interrupt(&ICUD2); + + OSAL_IRQ_EPILOGUE(); +} +#endif /* STM32_ICU_USE_TIM2 */ + +#if STM32_ICU_USE_TIM3 +#if !defined(STM32_TIM3_HANDLER) +#error "STM32_TIM3_HANDLER not defined" +#endif +/** + * @brief TIM3 interrupt handler. + * @note It is assumed that the various sources are only activated if the + * associated callback pointer is not equal to @p NULL in order to not + * perform an extra check in a potentially critical interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(STM32_TIM3_HANDLER) { + + OSAL_IRQ_PROLOGUE(); + + icu_lld_serve_interrupt(&ICUD3); + + OSAL_IRQ_EPILOGUE(); +} +#endif /* STM32_ICU_USE_TIM3 */ + +#if STM32_ICU_USE_TIM4 +#if !defined(STM32_TIM4_HANDLER) +#error "STM32_TIM4_HANDLER not defined" +#endif +/** + * @brief TIM4 interrupt handler. + * @note It is assumed that the various sources are only activated if the + * associated callback pointer is not equal to @p NULL in order to not + * perform an extra check in a potentially critical interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(STM32_TIM4_HANDLER) { + + OSAL_IRQ_PROLOGUE(); + + icu_lld_serve_interrupt(&ICUD4); + + OSAL_IRQ_EPILOGUE(); +} +#endif /* STM32_ICU_USE_TIM4 */ + +#if STM32_ICU_USE_TIM5 +#if !defined(STM32_TIM5_HANDLER) +#error "STM32_TIM5_HANDLER not defined" +#endif +/** + * @brief TIM5 interrupt handler. + * @note It is assumed that the various sources are only activated if the + * associated callback pointer is not equal to @p NULL in order to not + * perform an extra check in a potentially critical interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(STM32_TIM5_HANDLER) { + + OSAL_IRQ_PROLOGUE(); + + icu_lld_serve_interrupt(&ICUD5); + + OSAL_IRQ_EPILOGUE(); +} +#endif /* STM32_ICU_USE_TIM5 */ + +#if STM32_ICU_USE_TIM8 +#if !defined(STM32_TIM8_UP_HANDLER) +#error "STM32_TIM8_UP_HANDLER not defined" +#endif +/** + * @brief TIM8 compare interrupt handler. + * @note It is assumed that the various sources are only activated if the + * associated callback pointer is not equal to @p NULL in order to not + * perform an extra check in a potentially critical interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(STM32_TIM8_UP_HANDLER) { + + OSAL_IRQ_PROLOGUE(); + + icu_lld_serve_interrupt(&ICUD8); + + OSAL_IRQ_EPILOGUE(); +} + +#if !defined(STM32_TIM8_CC_HANDLER) +#error "STM32_TIM8_CC_HANDLER not defined" +#endif +/** + * @brief TIM8 compare interrupt handler. + * @note It is assumed that the various sources are only activated if the + * associated callback pointer is not equal to @p NULL in order to not + * perform an extra check in a potentially critical interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(STM32_TIM8_CC_HANDLER) { + + OSAL_IRQ_PROLOGUE(); + + icu_lld_serve_interrupt(&ICUD8); + + OSAL_IRQ_EPILOGUE(); +} +#endif /* STM32_ICU_USE_TIM8 */ + +#if STM32_ICU_USE_TIM9 +#if !defined(STM32_TIM9_HANDLER) +#error "STM32_TIM9_HANDLER not defined" +#endif +/** + * @brief TIM9 interrupt handler. + * @note It is assumed that the various sources are only activated if the + * associated callback pointer is not equal to @p NULL in order to not + * perform an extra check in a potentially critical interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(STM32_TIM9_HANDLER) { + + OSAL_IRQ_PROLOGUE(); + + icu_lld_serve_interrupt(&ICUD9); + + OSAL_IRQ_EPILOGUE(); +} +#endif /* STM32_ICU_USE_TIM9 */ + +/*===========================================================================*/ +/* Driver exported functions. */ +/*===========================================================================*/ + +/** + * @brief Low level ICU driver initialization. + * + * @notapi + */ +void icu_lld_init(void) { + +#if STM32_ICU_USE_TIM1 + /* Driver initialization.*/ + icuObjectInit(&ICUD1); + ICUD1.tim = STM32_TIM1; +#endif + +#if STM32_ICU_USE_TIM2 + /* Driver initialization.*/ + icuObjectInit(&ICUD2); + ICUD2.tim = STM32_TIM2; +#endif + +#if STM32_ICU_USE_TIM3 + /* Driver initialization.*/ + icuObjectInit(&ICUD3); + ICUD3.tim = STM32_TIM3; +#endif + +#if STM32_ICU_USE_TIM4 + /* Driver initialization.*/ + icuObjectInit(&ICUD4); + ICUD4.tim = STM32_TIM4; +#endif + +#if STM32_ICU_USE_TIM5 + /* Driver initialization.*/ + icuObjectInit(&ICUD5); + ICUD5.tim = STM32_TIM5; +#endif + +#if STM32_ICU_USE_TIM8 + /* Driver initialization.*/ + icuObjectInit(&ICUD8); + ICUD8.tim = STM32_TIM8; +#endif + +#if STM32_ICU_USE_TIM9 + /* Driver initialization.*/ + icuObjectInit(&ICUD9); + ICUD9.tim = STM32_TIM9; +#endif +} + +/** + * @brief Configures and activates the ICU peripheral. + * + * @param[in] icup pointer to the @p ICUDriver object + * + * @notapi + */ +void icu_lld_start(ICUDriver *icup) { + uint32_t psc; + + osalDbgAssert((icup->config->channel == ICU_CHANNEL_1) || + (icup->config->channel == ICU_CHANNEL_2), + "invalid input"); + + if (icup->state == ICU_STOP) { + /* Clock activation and timer reset.*/ +#if STM32_ICU_USE_TIM1 + if (&ICUD1 == icup) { + rccEnableTIM1(FALSE); + rccResetTIM1(); + nvicEnableVector(STM32_TIM1_UP_NUMBER, STM32_ICU_TIM1_IRQ_PRIORITY); + nvicEnableVector(STM32_TIM1_CC_NUMBER, STM32_ICU_TIM1_IRQ_PRIORITY); + icup->clock = STM32_TIMCLK2; + } +#endif +#if STM32_ICU_USE_TIM2 + if (&ICUD2 == icup) { + rccEnableTIM2(FALSE); + rccResetTIM2(); + nvicEnableVector(STM32_TIM2_NUMBER, STM32_ICU_TIM2_IRQ_PRIORITY); + icup->clock = STM32_TIMCLK1; + } +#endif +#if STM32_ICU_USE_TIM3 + if (&ICUD3 == icup) { + rccEnableTIM3(FALSE); + rccResetTIM3(); + nvicEnableVector(STM32_TIM3_NUMBER, STM32_ICU_TIM3_IRQ_PRIORITY); + icup->clock = STM32_TIMCLK1; + } +#endif +#if STM32_ICU_USE_TIM4 + if (&ICUD4 == icup) { + rccEnableTIM4(FALSE); + rccResetTIM4(); + nvicEnableVector(STM32_TIM4_NUMBER, STM32_ICU_TIM4_IRQ_PRIORITY); + icup->clock = STM32_TIMCLK1; + } +#endif +#if STM32_ICU_USE_TIM5 + if (&ICUD5 == icup) { + rccEnableTIM5(FALSE); + rccResetTIM5(); + nvicEnableVector(STM32_TIM5_NUMBER, STM32_ICU_TIM5_IRQ_PRIORITY); + icup->clock = STM32_TIMCLK1; + } +#endif +#if STM32_ICU_USE_TIM8 + if (&ICUD8 == icup) { + rccEnableTIM8(FALSE); + rccResetTIM8(); + nvicEnableVector(STM32_TIM8_UP_NUMBER, STM32_ICU_TIM8_IRQ_PRIORITY); + nvicEnableVector(STM32_TIM8_CC_NUMBER, STM32_ICU_TIM8_IRQ_PRIORITY); + icup->clock = STM32_TIMCLK2; + } +#endif +#if STM32_ICU_USE_TIM9 + if (&ICUD9 == icup) { + rccEnableTIM9(FALSE); + rccResetTIM9(); + nvicEnableVector(STM32_TIM9_NUMBER, STM32_ICU_TIM9_IRQ_PRIORITY); + icup->clock = STM32_TIMCLK1; + } +#endif + } + else { + /* Driver re-configuration scenario, it must be stopped first.*/ + icup->tim->CR1 = 0; /* Timer disabled. */ + icup->tim->DIER = icup->config->dier &/* DMA-related DIER settings. */ + ~STM32_TIM_DIER_IRQ_MASK; + icup->tim->SR = 0; /* Clear eventual pending IRQs. */ + icup->tim->CCR[0] = 0; /* Comparator 1 disabled. */ + icup->tim->CCR[1] = 0; /* Comparator 2 disabled. */ + icup->tim->CNT = 0; /* Counter reset to zero. */ + } + + /* Timer configuration.*/ + psc = (icup->clock / icup->config->frequency) - 1; + osalDbgAssert((psc <= 0xFFFF) && + ((psc + 1) * icup->config->frequency) == icup->clock, + "invalid frequency"); + icup->tim->PSC = (uint16_t)psc; + icup->tim->ARR = 0xFFFF; + + if (icup->config->channel == ICU_CHANNEL_1) { + /* Selected input 1. + CCMR1_CC1S = 01 = CH1 Input on TI1. + CCMR1_CC2S = 10 = CH2 Input on TI1.*/ + icup->tim->CCMR1 = STM32_TIM_CCMR1_CC1S(1) | STM32_TIM_CCMR1_CC2S(2); + + /* SMCR_TS = 101, input is TI1FP1. + SMCR_SMS = 100, reset on rising edge.*/ + icup->tim->SMCR = STM32_TIM_SMCR_TS(5) | STM32_TIM_SMCR_SMS(4); + + /* The CCER settings depend on the selected trigger mode. + ICU_INPUT_ACTIVE_HIGH: Active on rising edge, idle on falling edge. + ICU_INPUT_ACTIVE_LOW: Active on falling edge, idle on rising edge.*/ + if (icup->config->mode == ICU_INPUT_ACTIVE_HIGH) + icup->tim->CCER = STM32_TIM_CCER_CC1E | + STM32_TIM_CCER_CC2E | STM32_TIM_CCER_CC2P; + else + icup->tim->CCER = STM32_TIM_CCER_CC1E | STM32_TIM_CCER_CC1P | + STM32_TIM_CCER_CC2E; + + /* Direct pointers to the capture registers in order to make reading + data faster from within callbacks.*/ + icup->wccrp = &icup->tim->CCR[1]; + icup->pccrp = &icup->tim->CCR[0]; + } else { + /* Selected input 2. + CCMR1_CC1S = 10 = CH1 Input on TI2. + CCMR1_CC2S = 01 = CH2 Input on TI2.*/ + icup->tim->CCMR1 = STM32_TIM_CCMR1_CC1S(2) | STM32_TIM_CCMR1_CC2S(1); + + /* SMCR_TS = 110, input is TI2FP2. + SMCR_SMS = 100, reset on rising edge.*/ + icup->tim->SMCR = STM32_TIM_SMCR_TS(6) | STM32_TIM_SMCR_SMS(4); + + /* The CCER settings depend on the selected trigger mode. + ICU_INPUT_ACTIVE_HIGH: Active on rising edge, idle on falling edge. + ICU_INPUT_ACTIVE_LOW: Active on falling edge, idle on rising edge.*/ + if (icup->config->mode == ICU_INPUT_ACTIVE_HIGH) + icup->tim->CCER = STM32_TIM_CCER_CC1E | STM32_TIM_CCER_CC1P | + STM32_TIM_CCER_CC2E; + else + icup->tim->CCER = STM32_TIM_CCER_CC1E | + STM32_TIM_CCER_CC2E | STM32_TIM_CCER_CC2P; + + /* Direct pointers to the capture registers in order to make reading + data faster from within callbacks.*/ + icup->wccrp = &icup->tim->CCR[0]; + icup->pccrp = &icup->tim->CCR[1]; + } +} + +/** + * @brief Deactivates the ICU peripheral. + * + * @param[in] icup pointer to the @p ICUDriver object + * + * @notapi + */ +void icu_lld_stop(ICUDriver *icup) { + + if (icup->state == ICU_READY) { + /* Clock deactivation.*/ + icup->tim->CR1 = 0; /* Timer disabled. */ + icup->tim->DIER = 0; /* All IRQs disabled. */ + icup->tim->SR = 0; /* Clear eventual pending IRQs. */ + +#if STM32_ICU_USE_TIM1 + if (&ICUD1 == icup) { + nvicDisableVector(STM32_TIM1_UP_NUMBER); + nvicDisableVector(STM32_TIM1_CC_NUMBER); + rccDisableTIM1(FALSE); + } +#endif +#if STM32_ICU_USE_TIM2 + if (&ICUD2 == icup) { + nvicDisableVector(STM32_TIM2_NUMBER); + rccDisableTIM2(FALSE); + } +#endif +#if STM32_ICU_USE_TIM3 + if (&ICUD3 == icup) { + nvicDisableVector(STM32_TIM3_NUMBER); + rccDisableTIM3(FALSE); + } +#endif +#if STM32_ICU_USE_TIM4 + if (&ICUD4 == icup) { + nvicDisableVector(STM32_TIM4_NUMBER); + rccDisableTIM4(FALSE); + } +#endif +#if STM32_ICU_USE_TIM5 + if (&ICUD5 == icup) { + nvicDisableVector(STM32_TIM5_NUMBER); + rccDisableTIM5(FALSE); + } +#endif +#if STM32_ICU_USE_TIM8 + if (&ICUD8 == icup) { + nvicDisableVector(STM32_TIM8_UP_NUMBER); + nvicDisableVector(STM32_TIM8_CC_NUMBER); + rccDisableTIM8(FALSE); + } +#endif +#if STM32_ICU_USE_TIM9 + if (&ICUD9 == icup) { + nvicDisableVector(STM32_TIM9_NUMBER); + rccDisableTIM9(FALSE); + } +#endif + } +} + +/** + * @brief Enables the input capture. + * + * @param[in] icup pointer to the @p ICUDriver object + * + * @notapi + */ +void icu_lld_enable(ICUDriver *icup) { + + icup->tim->SR = 0; /* Clear pending IRQs (if any). */ + if (icup->config->channel == ICU_CHANNEL_1) { + if (icup->config->period_cb != NULL) + icup->tim->DIER |= STM32_TIM_DIER_CC1IE; + if (icup->config->width_cb != NULL) + icup->tim->DIER |= STM32_TIM_DIER_CC2IE; + } else { + if (icup->config->width_cb != NULL) + icup->tim->DIER |= STM32_TIM_DIER_CC1IE; + if (icup->config->period_cb != NULL) + icup->tim->DIER |= STM32_TIM_DIER_CC2IE; + } + if (icup->config->overflow_cb != NULL) + icup->tim->DIER |= STM32_TIM_DIER_UIE; + icup->tim->CR1 = STM32_TIM_CR1_URS | STM32_TIM_CR1_CEN; +} + +/** + * @brief Disables the input capture. + * + * @param[in] icup pointer to the @p ICUDriver object + * + * @notapi + */ +void icu_lld_disable(ICUDriver *icup) { + + icup->tim->CR1 = 0; /* Initially stopped. */ + icup->tim->SR = 0; /* Clear pending IRQs (if any). */ + + /* All interrupts disabled.*/ + icup->tim->DIER &= ~STM32_TIM_DIER_IRQ_MASK; +} + +#endif /* HAL_USE_ICU */ + +/** @} */ diff --git a/os/hal/ports/STM32/TIMv1/icu_lld.h b/os/hal/ports/STM32/TIMv1/icu_lld.h new file mode 100644 index 000000000..f436096c3 --- /dev/null +++ b/os/hal/ports/STM32/TIMv1/icu_lld.h @@ -0,0 +1,412 @@ +/* + ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file STM32/icu_lld.h + * @brief STM32 ICU subsystem low level driver header. + * + * @addtogroup ICU + * @{ + */ + +#ifndef _ICU_LLD_H_ +#define _ICU_LLD_H_ + +#if HAL_USE_ICU || defined(__DOXYGEN__) + +#include "stm32_tim.h" + +/*===========================================================================*/ +/* Driver constants. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver pre-compile time settings. */ +/*===========================================================================*/ + +/** + * @name Configuration options + * @{ + */ +/** + * @brief ICUD1 driver enable switch. + * @details If set to @p TRUE the support for ICUD1 is included. + * @note The default is @p TRUE. + */ +#if !defined(STM32_ICU_USE_TIM1) || defined(__DOXYGEN__) +#define STM32_ICU_USE_TIM1 FALSE +#endif + +/** + * @brief ICUD2 driver enable switch. + * @details If set to @p TRUE the support for ICUD2 is included. + * @note The default is @p TRUE. + */ +#if !defined(STM32_ICU_USE_TIM2) || defined(__DOXYGEN__) +#define STM32_ICU_USE_TIM2 FALSE +#endif + +/** + * @brief ICUD3 driver enable switch. + * @details If set to @p TRUE the support for ICUD3 is included. + * @note The default is @p TRUE. + */ +#if !defined(STM32_ICU_USE_TIM3) || defined(__DOXYGEN__) +#define STM32_ICU_USE_TIM3 FALSE +#endif + +/** + * @brief ICUD4 driver enable switch. + * @details If set to @p TRUE the support for ICUD4 is included. + * @note The default is @p TRUE. + */ +#if !defined(STM32_ICU_USE_TIM4) || defined(__DOXYGEN__) +#define STM32_ICU_USE_TIM4 FALSE +#endif + +/** + * @brief ICUD5 driver enable switch. + * @details If set to @p TRUE the support for ICUD5 is included. + * @note The default is @p TRUE. + */ +#if !defined(STM32_ICU_USE_TIM5) || defined(__DOXYGEN__) +#define STM32_ICU_USE_TIM5 FALSE +#endif + +/** + * @brief ICUD8 driver enable switch. + * @details If set to @p TRUE the support for ICUD8 is included. + * @note The default is @p TRUE. + */ +#if !defined(STM32_ICU_USE_TIM8) || defined(__DOXYGEN__) +#define STM32_ICU_USE_TIM8 FALSE +#endif + +/** + * @brief ICUD9 driver enable switch. + * @details If set to @p TRUE the support for ICUD9 is included. + * @note The default is @p TRUE. + */ +#if !defined(STM32_ICU_USE_TIM9) || defined(__DOXYGEN__) +#define STM32_ICU_USE_TIM9 FALSE +#endif + +/** + * @brief ICUD1 interrupt priority level setting. + */ +#if !defined(STM32_ICU_TIM1_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_ICU_TIM1_IRQ_PRIORITY 7 +#endif + +/** + * @brief ICUD2 interrupt priority level setting. + */ +#if !defined(STM32_ICU_TIM2_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_ICU_TIM2_IRQ_PRIORITY 7 +#endif + +/** + * @brief ICUD3 interrupt priority level setting. + */ +#if !defined(STM32_ICU_TIM3_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_ICU_TIM3_IRQ_PRIORITY 7 +#endif + +/** + * @brief ICUD4 interrupt priority level setting. + */ +#if !defined(STM32_ICU_TIM4_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_ICU_TIM4_IRQ_PRIORITY 7 +#endif + +/** + * @brief ICUD5 interrupt priority level setting. + */ +#if !defined(STM32_ICU_TIM5_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_ICU_TIM5_IRQ_PRIORITY 7 +#endif + +/** + * @brief ICUD8 interrupt priority level setting. + */ +#if !defined(STM32_ICU_TIM8_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_ICU_TIM8_IRQ_PRIORITY 7 +#endif + +/** + * @brief ICUD9 interrupt priority level setting. + */ +#if !defined(STM32_ICU_TIM9_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_ICU_TIM9_IRQ_PRIORITY 7 +#endif +/** @} */ + +/*===========================================================================*/ +/* Derived constants and error checks. */ +/*===========================================================================*/ + +#if STM32_ICU_USE_TIM1 && !STM32_HAS_TIM1 +#error "TIM1 not present in the selected device" +#endif + +#if STM32_ICU_USE_TIM2 && !STM32_HAS_TIM2 +#error "TIM2 not present in the selected device" +#endif + +#if STM32_ICU_USE_TIM3 && !STM32_HAS_TIM3 +#error "TIM3 not present in the selected device" +#endif + +#if STM32_ICU_USE_TIM4 && !STM32_HAS_TIM4 +#error "TIM4 not present in the selected device" +#endif + +#if STM32_ICU_USE_TIM5 && !STM32_HAS_TIM5 +#error "TIM5 not present in the selected device" +#endif + +#if STM32_ICU_USE_TIM8 && !STM32_HAS_TIM8 +#error "TIM8 not present in the selected device" +#endif + +#if STM32_ICU_USE_TIM9 && !STM32_HAS_TIM9 +#error "TIM9 not present in the selected device" +#endif + +#if !STM32_ICU_USE_TIM1 && !STM32_ICU_USE_TIM2 && \ + !STM32_ICU_USE_TIM3 && !STM32_ICU_USE_TIM4 && \ + !STM32_ICU_USE_TIM5 && !STM32_ICU_USE_TIM8 && \ + !STM32_ICU_USE_TIM9 +#error "ICU driver activated but no TIM peripheral assigned" +#endif + +#if STM32_ICU_USE_TIM1 && \ + !CORTEX_IS_VALID_KERNEL_PRIORITY(STM32_ICU_TIM1_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to TIM1" +#endif + +#if STM32_ICU_USE_TIM2 && \ + !CORTEX_IS_VALID_KERNEL_PRIORITY(STM32_ICU_TIM2_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to TIM2" +#endif + +#if STM32_ICU_USE_TIM3 && \ + !CORTEX_IS_VALID_KERNEL_PRIORITY(STM32_ICU_TIM3_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to TIM3" +#endif + +#if STM32_ICU_USE_TIM4 && \ + !CORTEX_IS_VALID_KERNEL_PRIORITY(STM32_ICU_TIM4_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to TIM4" +#endif + +#if STM32_ICU_USE_TIM5 && \ + !CORTEX_IS_VALID_KERNEL_PRIORITY(STM32_ICU_TIM5_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to TIM5" +#endif + +#if STM32_ICU_USE_TIM8 && \ + !CORTEX_IS_VALID_KERNEL_PRIORITY(STM32_ICU_TIM8_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to TIM8" +#endif + +#if STM32_ICU_USE_TIM9 && \ + !CORTEX_IS_VALID_KERNEL_PRIORITY(STM32_ICU_TIM9_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to TIM9" +#endif + +/*===========================================================================*/ +/* Driver data structures and types. */ +/*===========================================================================*/ + +/** + * @brief ICU driver mode. + */ +typedef enum { + ICU_INPUT_ACTIVE_HIGH = 0, /**< Trigger on rising edge. */ + ICU_INPUT_ACTIVE_LOW = 1, /**< Trigger on falling edge. */ +} icumode_t; + +/** + * @brief ICU frequency type. + */ +typedef uint32_t icufreq_t; + +/** + * @brief ICU channel type. + */ +typedef enum { + ICU_CHANNEL_1 = 0, /**< Use TIMxCH1. */ + ICU_CHANNEL_2 = 1, /**< Use TIMxCH2. */ +} icuchannel_t; + +/** + * @brief ICU counter type. + */ +typedef uint16_t icucnt_t; + +/** + * @brief Driver configuration structure. + * @note It could be empty on some architectures. + */ +typedef struct { + /** + * @brief Driver mode. + */ + icumode_t mode; + /** + * @brief Timer clock in Hz. + * @note The low level can use assertions in order to catch invalid + * frequency specifications. + */ + icufreq_t frequency; + /** + * @brief Callback for pulse width measurement. + */ + icucallback_t width_cb; + /** + * @brief Callback for cycle period measurement. + */ + icucallback_t period_cb; + /** + * @brief Callback for timer overflow. + */ + icucallback_t overflow_cb; + /* End of the mandatory fields.*/ + /** + * @brief Timer input channel to be used. + * @note Only inputs TIMx 1 and 2 are supported. + */ + icuchannel_t channel; + /** + * @brief TIM DIER register initialization data. + * @note The value of this field should normally be equal to zero. + * @note Only the DMA-related bits can be specified in this field. + */ + uint32_t dier; +} ICUConfig; + +/** + * @brief Structure representing an ICU driver. + */ +struct ICUDriver { + /** + * @brief Driver state. + */ + icustate_t state; + /** + * @brief Current configuration data. + */ + const ICUConfig *config; +#if defined(ICU_DRIVER_EXT_FIELDS) + ICU_DRIVER_EXT_FIELDS +#endif + /* End of the mandatory fields.*/ + /** + * @brief Timer base clock. + */ + uint32_t clock; + /** + * @brief Pointer to the TIMx registers block. + */ + stm32_tim_t *tim; + /** + * @brief CCR register used for width capture. + */ + volatile uint32_t *wccrp; + /** + * @brief CCR register used for period capture. + */ + volatile uint32_t *pccrp; +}; + +/*===========================================================================*/ +/* Driver macros. */ +/*===========================================================================*/ + +/** + * @brief Returns the width of the latest pulse. + * @details The pulse width is defined as number of ticks between the start + * edge and the stop edge. + * + * @param[in] icup pointer to the @p ICUDriver object + * @return The number of ticks. + * + * @notapi + */ +#define icu_lld_get_width(icup) (*((icup)->wccrp) + 1) + +/** + * @brief Returns the width of the latest cycle. + * @details The cycle width is defined as number of ticks between a start + * edge and the next start edge. + * + * @param[in] icup pointer to the @p ICUDriver object + * @return The number of ticks. + * + * @notapi + */ +#define icu_lld_get_period(icup) (*((icup)->pccrp) + 1) + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +#if STM32_ICU_USE_TIM1 && !defined(__DOXYGEN__) +extern ICUDriver ICUD1; +#endif + +#if STM32_ICU_USE_TIM2 && !defined(__DOXYGEN__) +extern ICUDriver ICUD2; +#endif + +#if STM32_ICU_USE_TIM3 && !defined(__DOXYGEN__) +extern ICUDriver ICUD3; +#endif + +#if STM32_ICU_USE_TIM4 && !defined(__DOXYGEN__) +extern ICUDriver ICUD4; +#endif + +#if STM32_ICU_USE_TIM5 && !defined(__DOXYGEN__) +extern ICUDriver ICUD5; +#endif + +#if STM32_ICU_USE_TIM8 && !defined(__DOXYGEN__) +extern ICUDriver ICUD8; +#endif + +#if STM32_ICU_USE_TIM9 && !defined(__DOXYGEN__) +extern ICUDriver ICUD9; +#endif + +#ifdef __cplusplus +extern "C" { +#endif + void icu_lld_init(void); + void icu_lld_start(ICUDriver *icup); + void icu_lld_stop(ICUDriver *icup); + void icu_lld_enable(ICUDriver *icup); + void icu_lld_disable(ICUDriver *icup); +#ifdef __cplusplus +} +#endif + +#endif /* HAL_USE_ICU */ + +#endif /* _ICU_LLD_H_ */ + +/** @} */ diff --git a/os/hal/ports/STM32/TIMv1/pwm_lld.c b/os/hal/ports/STM32/TIMv1/pwm_lld.c new file mode 100644 index 000000000..12abc0c44 --- /dev/null +++ b/os/hal/ports/STM32/TIMv1/pwm_lld.c @@ -0,0 +1,695 @@ +/* + ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file STM32/pwm_lld.c + * @brief STM32 PWM subsystem low level driver header. + * + * @addtogroup PWM + * @{ + */ + +#include "hal.h" + +#if HAL_USE_PWM || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver local definitions. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver exported variables. */ +/*===========================================================================*/ + +/** + * @brief PWMD1 driver identifier. + * @note The driver PWMD1 allocates the complex timer TIM1 when enabled. + */ +#if STM32_PWM_USE_TIM1 || defined(__DOXYGEN__) +PWMDriver PWMD1; +#endif + +/** + * @brief PWMD2 driver identifier. + * @note The driver PWMD2 allocates the timer TIM2 when enabled. + */ +#if STM32_PWM_USE_TIM2 || defined(__DOXYGEN__) +PWMDriver PWMD2; +#endif + +/** + * @brief PWMD3 driver identifier. + * @note The driver PWMD3 allocates the timer TIM3 when enabled. + */ +#if STM32_PWM_USE_TIM3 || defined(__DOXYGEN__) +PWMDriver PWMD3; +#endif + +/** + * @brief PWMD4 driver identifier. + * @note The driver PWMD4 allocates the timer TIM4 when enabled. + */ +#if STM32_PWM_USE_TIM4 || defined(__DOXYGEN__) +PWMDriver PWMD4; +#endif + +/** + * @brief PWMD5 driver identifier. + * @note The driver PWMD5 allocates the timer TIM5 when enabled. + */ +#if STM32_PWM_USE_TIM5 || defined(__DOXYGEN__) +PWMDriver PWMD5; +#endif + +/** + * @brief PWMD8 driver identifier. + * @note The driver PWMD8 allocates the timer TIM8 when enabled. + */ +#if STM32_PWM_USE_TIM8 || defined(__DOXYGEN__) +PWMDriver PWMD8; +#endif + +/** + * @brief PWMD9 driver identifier. + * @note The driver PWMD9 allocates the timer TIM9 when enabled. + */ +#if STM32_PWM_USE_TIM9 || defined(__DOXYGEN__) +PWMDriver PWMD9; +#endif + +/*===========================================================================*/ +/* Driver local variables and types. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local functions. */ +/*===========================================================================*/ + +#if STM32_PWM_USE_TIM2 || STM32_PWM_USE_TIM3 || STM32_PWM_USE_TIM4 || \ + STM32_PWM_USE_TIM5 || STM32_PWM_USE_TIM9 || defined(__DOXYGEN__) +/** + * @brief Common TIM2...TIM5,TIM9 IRQ handler. + * @note It is assumed that the various sources are only activated if the + * associated callback pointer is not equal to @p NULL in order to not + * perform an extra check in a potentially critical interrupt handler. + * + * @param[in] pwmp pointer to a @p PWMDriver object + */ +static void pwm_lld_serve_interrupt(PWMDriver *pwmp) { + uint16_t sr; + + sr = pwmp->tim->SR; + sr &= pwmp->tim->DIER & STM32_TIM_DIER_IRQ_MASK; + pwmp->tim->SR = ~sr; + if ((sr & STM32_TIM_SR_CC1IF) != 0) + pwmp->config->channels[0].callback(pwmp); + if ((sr & STM32_TIM_SR_CC2IF) != 0) + pwmp->config->channels[1].callback(pwmp); + if ((sr & STM32_TIM_SR_CC3IF) != 0) + pwmp->config->channels[2].callback(pwmp); + if ((sr & STM32_TIM_SR_CC4IF) != 0) + pwmp->config->channels[3].callback(pwmp); + if ((sr & STM32_TIM_SR_UIF) != 0) + pwmp->config->callback(pwmp); +} +#endif /* STM32_PWM_USE_TIM2 || ... || STM32_PWM_USE_TIM5 */ + +/*===========================================================================*/ +/* Driver interrupt handlers. */ +/*===========================================================================*/ + +#if STM32_PWM_USE_TIM1 +#if !defined(STM32_TIM1_UP_HANDLER) +#error "STM32_TIM1_UP_HANDLER not defined" +#endif +/** + * @brief TIM1 update interrupt handler. + * @note It is assumed that this interrupt is only activated if the callback + * pointer is not equal to @p NULL in order to not perform an extra + * check in a potentially critical interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(STM32_TIM1_UP_HANDLER) { + + OSAL_IRQ_PROLOGUE(); + + STM32_TIM1->SR = ~STM32_TIM_SR_UIF; + PWMD1.config->callback(&PWMD1); + + OSAL_IRQ_EPILOGUE(); +} + +#if !defined(STM32_TIM1_CC_HANDLER) +#error "STM32_TIM1_CC_HANDLER not defined" +#endif +/** + * @brief TIM1 compare interrupt handler. + * @note It is assumed that the various sources are only activated if the + * associated callback pointer is not equal to @p NULL in order to not + * perform an extra check in a potentially critical interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(STM32_TIM1_CC_HANDLER) { + uint16_t sr; + + OSAL_IRQ_PROLOGUE(); + + sr = STM32_TIM1->SR & STM32_TIM1->DIER & STM32_TIM_DIER_IRQ_MASK; + STM32_TIM1->SR = ~sr; + if ((sr & STM32_TIM_SR_CC1IF) != 0) + PWMD1.config->channels[0].callback(&PWMD1); + if ((sr & STM32_TIM_SR_CC2IF) != 0) + PWMD1.config->channels[1].callback(&PWMD1); + if ((sr & STM32_TIM_SR_CC3IF) != 0) + PWMD1.config->channels[2].callback(&PWMD1); + if ((sr & STM32_TIM_SR_CC4IF) != 0) + PWMD1.config->channels[3].callback(&PWMD1); + + OSAL_IRQ_EPILOGUE(); +} +#endif /* STM32_PWM_USE_TIM1 */ + +#if STM32_PWM_USE_TIM2 +#if !defined(STM32_TIM2_HANDLER) +#error "STM32_TIM2_HANDLER not defined" +#endif +/** + * @brief TIM2 interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(STM32_TIM2_HANDLER) { + + OSAL_IRQ_PROLOGUE(); + + pwm_lld_serve_interrupt(&PWMD2); + + OSAL_IRQ_EPILOGUE(); +} +#endif /* STM32_PWM_USE_TIM2 */ + +#if STM32_PWM_USE_TIM3 +#if !defined(STM32_TIM3_HANDLER) +#error "STM32_TIM3_HANDLER not defined" +#endif +/** + * @brief TIM3 interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(STM32_TIM3_HANDLER) { + + OSAL_IRQ_PROLOGUE(); + + pwm_lld_serve_interrupt(&PWMD3); + + OSAL_IRQ_EPILOGUE(); +} +#endif /* STM32_PWM_USE_TIM3 */ + +#if STM32_PWM_USE_TIM4 +#if !defined(STM32_TIM4_HANDLER) +#error "STM32_TIM4_HANDLER not defined" +#endif +/** + * @brief TIM4 interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(STM32_TIM4_HANDLER) { + + OSAL_IRQ_PROLOGUE(); + + pwm_lld_serve_interrupt(&PWMD4); + + OSAL_IRQ_EPILOGUE(); +} +#endif /* STM32_PWM_USE_TIM4 */ + +#if STM32_PWM_USE_TIM5 +#if !defined(STM32_TIM5_HANDLER) +#error "STM32_TIM5_HANDLER not defined" +#endif +/** + * @brief TIM5 interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(STM32_TIM5_HANDLER) { + + OSAL_IRQ_PROLOGUE(); + + pwm_lld_serve_interrupt(&PWMD5); + + OSAL_IRQ_EPILOGUE(); +} +#endif /* STM32_PWM_USE_TIM5 */ + +#if STM32_PWM_USE_TIM8 +#if !defined(STM32_TIM8_UP_HANDLER) +#error "STM32_TIM8_UP_HANDLER not defined" +#endif +/** + * @brief TIM8 update interrupt handler. + * @note It is assumed that this interrupt is only activated if the callback + * pointer is not equal to @p NULL in order to not perform an extra + * check in a potentially critical interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(STM32_TIM8_UP_HANDLER) { + + OSAL_IRQ_PROLOGUE(); + + STM32_TIM8->SR = ~TIM_SR_UIF; + PWMD8.config->callback(&PWMD8); + + OSAL_IRQ_EPILOGUE(); +} + +#if !defined(STM32_TIM8_CC_HANDLER) +#error "STM32_TIM8_CC_HANDLER not defined" +#endif +/** + * @brief TIM8 compare interrupt handler. + * @note It is assumed that the various sources are only activated if the + * associated callback pointer is not equal to @p NULL in order to not + * perform an extra check in a potentially critical interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(STM32_TIM8_CC_HANDLER) { + uint16_t sr; + + OSAL_IRQ_PROLOGUE(); + + sr = STM32_TIM8->SR & STM32_TIM8->DIER & STM32_TIM_DIER_IRQ_MASK; + STM32_TIM8->SR = ~sr; + if ((sr & STM32_TIM_SR_CC1IF) != 0) + PWMD8.config->channels[0].callback(&PWMD8); + if ((sr & STM32_TIM_SR_CC2IF) != 0) + PWMD8.config->channels[1].callback(&PWMD8); + if ((sr & STM32_TIM_SR_CC3IF) != 0) + PWMD8.config->channels[2].callback(&PWMD8); + if ((sr & STM32_TIM_SR_CC4IF) != 0) + PWMD8.config->channels[3].callback(&PWMD8); + + OSAL_IRQ_EPILOGUE(); +} +#endif /* STM32_PWM_USE_TIM8 */ + +#if STM32_PWM_USE_TIM9 +#if !defined(STM32_TIM9_HANDLER) +#error "STM32_TIM9_HANDLER not defined" +#endif +/** + * @brief TIM9 interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(STM32_TIM9_HANDLER) { + + OSAL_IRQ_PROLOGUE(); + + pwm_lld_serve_interrupt(&PWMD9); + + OSAL_IRQ_EPILOGUE(); +} +#endif /* STM32_PWM_USE_TIM9 */ + +/*===========================================================================*/ +/* Driver exported functions. */ +/*===========================================================================*/ + +/** + * @brief Low level PWM driver initialization. + * + * @notapi + */ +void pwm_lld_init(void) { + +#if STM32_PWM_USE_TIM1 + /* Driver initialization.*/ + pwmObjectInit(&PWMD1); + PWMD1.tim = STM32_TIM1; +#endif + +#if STM32_PWM_USE_TIM2 + /* Driver initialization.*/ + pwmObjectInit(&PWMD2); + PWMD2.tim = STM32_TIM2; +#endif + +#if STM32_PWM_USE_TIM3 + /* Driver initialization.*/ + pwmObjectInit(&PWMD3); + PWMD3.tim = STM32_TIM3; +#endif + +#if STM32_PWM_USE_TIM4 + /* Driver initialization.*/ + pwmObjectInit(&PWMD4); + PWMD4.tim = STM32_TIM4; +#endif + +#if STM32_PWM_USE_TIM5 + /* Driver initialization.*/ + pwmObjectInit(&PWMD5); + PWMD5.tim = STM32_TIM5; +#endif + +#if STM32_PWM_USE_TIM8 + /* Driver initialization.*/ + pwmObjectInit(&PWMD8); + PWMD8.tim = STM32_TIM8; +#endif + +#if STM32_PWM_USE_TIM9 + /* Driver initialization.*/ + pwmObjectInit(&PWMD9); + PWMD9.tim = STM32_TIM9; +#endif +} + +/** + * @brief Configures and activates the PWM peripheral. + * @note Starting a driver that is already in the @p PWM_READY state + * disables all the active channels. + * + * @param[in] pwmp pointer to a @p PWMDriver object + * + * @notapi + */ +void pwm_lld_start(PWMDriver *pwmp) { + uint32_t psc; + uint16_t ccer; + + if (pwmp->state == PWM_STOP) { + /* Clock activation and timer reset.*/ +#if STM32_PWM_USE_TIM1 + if (&PWMD1 == pwmp) { + rccEnableTIM1(FALSE); + rccResetTIM1(); + nvicEnableVector(STM32_TIM1_UP_NUMBER, STM32_PWM_TIM1_IRQ_PRIORITY); + nvicEnableVector(STM32_TIM1_CC_NUMBER, STM32_PWM_TIM1_IRQ_PRIORITY); + pwmp->clock = STM32_TIMCLK2; + } +#endif +#if STM32_PWM_USE_TIM2 + if (&PWMD2 == pwmp) { + rccEnableTIM2(FALSE); + rccResetTIM2(); + nvicEnableVector(STM32_TIM2_NUMBER, STM32_PWM_TIM2_IRQ_PRIORITY); + pwmp->clock = STM32_TIMCLK1; + } +#endif +#if STM32_PWM_USE_TIM3 + if (&PWMD3 == pwmp) { + rccEnableTIM3(FALSE); + rccResetTIM3(); + nvicEnableVector(STM32_TIM3_NUMBER, STM32_PWM_TIM3_IRQ_PRIORITY); + pwmp->clock = STM32_TIMCLK1; + } +#endif +#if STM32_PWM_USE_TIM4 + if (&PWMD4 == pwmp) { + rccEnableTIM4(FALSE); + rccResetTIM4(); + nvicEnableVector(STM32_TIM4_NUMBER, STM32_PWM_TIM4_IRQ_PRIORITY); + pwmp->clock = STM32_TIMCLK1; + } +#endif + +#if STM32_PWM_USE_TIM5 + if (&PWMD5 == pwmp) { + rccEnableTIM5(FALSE); + rccResetTIM5(); + nvicEnableVector(STM32_TIM5_NUMBER, STM32_PWM_TIM5_IRQ_PRIORITY); + pwmp->clock = STM32_TIMCLK1; + } +#endif +#if STM32_PWM_USE_TIM8 + if (&PWMD8 == pwmp) { + rccEnableTIM8(FALSE); + rccResetTIM8(); + nvicEnableVector(STM32_TIM8_UP_NUMBER, STM32_PWM_TIM8_IRQ_PRIORITY); + nvicEnableVector(STM32_TIM8_CC_NUMBER, STM32_PWM_TIM8_IRQ_PRIORITY); + pwmp->clock = STM32_TIMCLK2; + } +#endif +#if STM32_PWM_USE_TIM9 + if (&PWMD9 == pwmp) { + rccEnableTIM9(FALSE); + rccResetTIM9(); + nvicEnableVector(STM32_TIM9_NUMBER, STM32_PWM_TIM9_IRQ_PRIORITY); + pwmp->clock = STM32_TIMCLK1; + } +#endif + + /* All channels configured in PWM1 mode with preload enabled and will + stay that way until the driver is stopped.*/ + pwmp->tim->CCMR1 = STM32_TIM_CCMR1_OC1M(6) | STM32_TIM_CCMR1_OC1PE | + STM32_TIM_CCMR1_OC2M(6) | STM32_TIM_CCMR1_OC2PE; + pwmp->tim->CCMR2 = STM32_TIM_CCMR2_OC3M(6) | STM32_TIM_CCMR2_OC3PE | + STM32_TIM_CCMR2_OC4M(6) | STM32_TIM_CCMR2_OC4PE; + } + else { + /* Driver re-configuration scenario, it must be stopped first.*/ + pwmp->tim->CR1 = 0; /* Timer disabled. */ + pwmp->tim->DIER = pwmp->config->dier &/* DMA-related DIER settings. */ + ~STM32_TIM_DIER_IRQ_MASK; + pwmp->tim->SR = 0; /* Clear eventual pending IRQs. */ + pwmp->tim->CCR[0] = 0; /* Comparator 1 disabled. */ + pwmp->tim->CCR[1] = 0; /* Comparator 2 disabled. */ + pwmp->tim->CCR[2] = 0; /* Comparator 3 disabled. */ + pwmp->tim->CCR[3] = 0; /* Comparator 4 disabled. */ + pwmp->tim->CNT = 0; /* Counter reset to zero. */ + } + + /* Timer configuration.*/ + psc = (pwmp->clock / pwmp->config->frequency) - 1; + osalDbgAssert((psc <= 0xFFFF) && + ((psc + 1) * pwmp->config->frequency) == pwmp->clock, + "invalid frequency"); + pwmp->tim->PSC = (uint16_t)psc; + pwmp->tim->ARR = (uint16_t)(pwmp->period - 1); + pwmp->tim->CR2 = pwmp->config->cr2; + + /* Output enables and polarities setup.*/ + ccer = 0; + switch (pwmp->config->channels[0].mode & PWM_OUTPUT_MASK) { + case PWM_OUTPUT_ACTIVE_LOW: + ccer |= STM32_TIM_CCER_CC1P; + case PWM_OUTPUT_ACTIVE_HIGH: + ccer |= STM32_TIM_CCER_CC1E; + default: + ; + } + switch (pwmp->config->channels[1].mode & PWM_OUTPUT_MASK) { + case PWM_OUTPUT_ACTIVE_LOW: + ccer |= STM32_TIM_CCER_CC2P; + case PWM_OUTPUT_ACTIVE_HIGH: + ccer |= STM32_TIM_CCER_CC2E; + default: + ; + } + switch (pwmp->config->channels[2].mode & PWM_OUTPUT_MASK) { + case PWM_OUTPUT_ACTIVE_LOW: + ccer |= STM32_TIM_CCER_CC3P; + case PWM_OUTPUT_ACTIVE_HIGH: + ccer |= STM32_TIM_CCER_CC3E; + default: + ; + } + switch (pwmp->config->channels[3].mode & PWM_OUTPUT_MASK) { + case PWM_OUTPUT_ACTIVE_LOW: + ccer |= STM32_TIM_CCER_CC4P; + case PWM_OUTPUT_ACTIVE_HIGH: + ccer |= STM32_TIM_CCER_CC4E; + default: + ; + } +#if STM32_PWM_USE_ADVANCED +#if STM32_PWM_USE_TIM1 && !STM32_PWM_USE_TIM8 + if (&PWMD1 == pwmp) { +#endif +#if !STM32_PWM_USE_TIM1 && STM32_PWM_USE_TIM8 + if (&PWMD8 == pwmp) { +#endif +#if STM32_PWM_USE_TIM1 && STM32_PWM_USE_TIM8 + if ((&PWMD1 == pwmp) || (&PWMD8 == pwmp)) { +#endif + switch (pwmp->config->channels[0].mode & PWM_COMPLEMENTARY_OUTPUT_MASK) { + case PWM_COMPLEMENTARY_OUTPUT_ACTIVE_LOW: + ccer |= STM32_TIM_CCER_CC1NP; + case PWM_COMPLEMENTARY_OUTPUT_ACTIVE_HIGH: + ccer |= STM32_TIM_CCER_CC1NE; + default: + ; + } + switch (pwmp->config->channels[1].mode & PWM_COMPLEMENTARY_OUTPUT_MASK) { + case PWM_COMPLEMENTARY_OUTPUT_ACTIVE_LOW: + ccer |= STM32_TIM_CCER_CC2NP; + case PWM_COMPLEMENTARY_OUTPUT_ACTIVE_HIGH: + ccer |= STM32_TIM_CCER_CC2NE; + default: + ; + } + switch (pwmp->config->channels[2].mode & PWM_COMPLEMENTARY_OUTPUT_MASK) { + case PWM_COMPLEMENTARY_OUTPUT_ACTIVE_LOW: + ccer |= STM32_TIM_CCER_CC3NP; + case PWM_COMPLEMENTARY_OUTPUT_ACTIVE_HIGH: + ccer |= STM32_TIM_CCER_CC3NE; + default: + ; + } + } +#endif /* STM32_PWM_USE_ADVANCED*/ + + pwmp->tim->CCER = ccer; + pwmp->tim->EGR = STM32_TIM_EGR_UG; /* Update event. */ + pwmp->tim->DIER |= pwmp->config->callback == NULL ? 0 : STM32_TIM_DIER_UIE; + pwmp->tim->SR = 0; /* Clear pending IRQs. */ +#if STM32_PWM_USE_TIM1 || STM32_PWM_USE_TIM8 +#if STM32_PWM_USE_ADVANCED + pwmp->tim->BDTR = pwmp->config->bdtr | STM32_TIM_BDTR_MOE; +#else + pwmp->tim->BDTR = STM32_TIM_BDTR_MOE; +#endif +#endif + /* Timer configured and started.*/ + pwmp->tim->CR1 = STM32_TIM_CR1_ARPE | STM32_TIM_CR1_URS | + STM32_TIM_CR1_CEN; +} + +/** + * @brief Deactivates the PWM peripheral. + * + * @param[in] pwmp pointer to a @p PWMDriver object + * + * @notapi + */ +void pwm_lld_stop(PWMDriver *pwmp) { + + /* If in ready state then disables the PWM clock.*/ + if (pwmp->state == PWM_READY) { + pwmp->tim->CR1 = 0; /* Timer disabled. */ + pwmp->tim->DIER = 0; /* All IRQs disabled. */ + pwmp->tim->SR = 0; /* Clear eventual pending IRQs. */ +#if STM32_PWM_USE_TIM1 || STM32_PWM_USE_TIM8 + pwmp->tim->BDTR = 0; +#endif + +#if STM32_PWM_USE_TIM1 + if (&PWMD1 == pwmp) { + nvicDisableVector(STM32_TIM1_UP_NUMBER); + nvicDisableVector(STM32_TIM1_CC_NUMBER); + rccDisableTIM1(FALSE); + } +#endif +#if STM32_PWM_USE_TIM2 + if (&PWMD2 == pwmp) { + nvicDisableVector(STM32_TIM2_NUMBER); + rccDisableTIM2(FALSE); + } +#endif +#if STM32_PWM_USE_TIM3 + if (&PWMD3 == pwmp) { + nvicDisableVector(STM32_TIM3_NUMBER); + rccDisableTIM3(FALSE); + } +#endif +#if STM32_PWM_USE_TIM4 + if (&PWMD4 == pwmp) { + nvicDisableVector(STM32_TIM4_NUMBER); + rccDisableTIM4(FALSE); + } +#endif +#if STM32_PWM_USE_TIM5 + if (&PWMD5 == pwmp) { + nvicDisableVector(STM32_TIM5_NUMBER); + rccDisableTIM5(FALSE); + } +#endif +#if STM32_PWM_USE_TIM8 + if (&PWMD8 == pwmp) { + nvicDisableVector(STM32_TIM8_UP_NUMBER); + nvicDisableVector(STM32_TIM8_CC_NUMBER); + rccDisableTIM8(FALSE); + } +#endif +#if STM32_PWM_USE_TIM9 + if (&PWMD9 == pwmp) { + nvicDisableVector(STM32_TIM9_NUMBER); + rccDisableTIM9(FALSE); + } +#endif + } +} + +/** + * @brief Enables a PWM channel. + * @pre The PWM unit must have been activated using @p pwmStart(). + * @post The channel is active using the specified configuration. + * @note The function has effect at the next cycle start. + * + * @param[in] pwmp pointer to a @p PWMDriver object + * @param[in] channel PWM channel identifier (0...PWM_CHANNELS-1) + * @param[in] width PWM pulse width as clock pulses number + * + * @notapi + */ +void pwm_lld_enable_channel(PWMDriver *pwmp, + pwmchannel_t channel, + pwmcnt_t width) { + + pwmp->tim->CCR[channel] = width; /* New duty cycle. */ + /* If there is a callback defined for the channel then the associated + interrupt must be enabled.*/ + if (pwmp->config->channels[channel].callback != NULL) { + uint32_t dier = pwmp->tim->DIER; + /* If the IRQ is not already enabled care must be taken to clear it, + it is probably already pending because the timer is running.*/ + if ((dier & (2 << channel)) == 0) { + pwmp->tim->DIER = dier | (2 << channel); + pwmp->tim->SR = ~(2 << channel); + } + } +} + +/** + * @brief Disables a PWM channel. + * @pre The PWM unit must have been activated using @p pwmStart(). + * @post The channel is disabled and its output line returned to the + * idle state. + * @note The function has effect at the next cycle start. + * + * @param[in] pwmp pointer to a @p PWMDriver object + * @param[in] channel PWM channel identifier (0...PWM_CHANNELS-1) + * + * @notapi + */ +void pwm_lld_disable_channel(PWMDriver *pwmp, pwmchannel_t channel) { + + pwmp->tim->CCR[channel] = 0; + pwmp->tim->DIER &= ~(2 << channel); +} + +#endif /* HAL_USE_PWM */ + +/** @} */ diff --git a/os/hal/ports/STM32/TIMv1/pwm_lld.h b/os/hal/ports/STM32/TIMv1/pwm_lld.h new file mode 100644 index 000000000..c77acf883 --- /dev/null +++ b/os/hal/ports/STM32/TIMv1/pwm_lld.h @@ -0,0 +1,480 @@ +/* + ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file STM32/pwm_lld.h + * @brief STM32 PWM subsystem low level driver header. + * + * @addtogroup PWM + * @{ + */ + +#ifndef _PWM_LLD_H_ +#define _PWM_LLD_H_ + +#if HAL_USE_PWM || defined(__DOXYGEN__) + +#include "stm32_tim.h" + +/*===========================================================================*/ +/* Driver constants. */ +/*===========================================================================*/ + +/** + * @brief Number of PWM channels per PWM driver. + */ +#define PWM_CHANNELS 4 + +/** + * @brief Complementary output modes mask. + * @note This is an STM32-specific setting. + */ +#define PWM_COMPLEMENTARY_OUTPUT_MASK 0xF0 + +/** + * @brief Complementary output not driven. + * @note This is an STM32-specific setting. + */ +#define PWM_COMPLEMENTARY_OUTPUT_DISABLED 0x00 + +/** + * @brief Complementary output, active is logic level one. + * @note This is an STM32-specific setting. + * @note This setting is only available if the configuration option + * @p STM32_PWM_USE_ADVANCED is set to TRUE and only for advanced + * timers TIM1 and TIM8. + */ +#define PWM_COMPLEMENTARY_OUTPUT_ACTIVE_HIGH 0x10 + +/** + * @brief Complementary output, active is logic level zero. + * @note This is an STM32-specific setting. + * @note This setting is only available if the configuration option + * @p STM32_PWM_USE_ADVANCED is set to TRUE and only for advanced + * timers TIM1 and TIM8. + */ +#define PWM_COMPLEMENTARY_OUTPUT_ACTIVE_LOW 0x20 + +/*===========================================================================*/ +/* Driver pre-compile time settings. */ +/*===========================================================================*/ + +/** + * @name Configuration options + * @{ + */ +/** + * @brief If advanced timer features switch. + * @details If set to @p TRUE the advanced features for TIM1 and TIM8 are + * enabled. + * @note The default is @p TRUE. + */ +#if !defined(STM32_PWM_USE_ADVANCED) || defined(__DOXYGEN__) +#define STM32_PWM_USE_ADVANCED FALSE +#endif + +/** + * @brief PWMD1 driver enable switch. + * @details If set to @p TRUE the support for PWMD1 is included. + * @note The default is @p TRUE. + */ +#if !defined(STM32_PWM_USE_TIM1) || defined(__DOXYGEN__) +#define STM32_PWM_USE_TIM1 FALSE +#endif + +/** + * @brief PWMD2 driver enable switch. + * @details If set to @p TRUE the support for PWMD2 is included. + * @note The default is @p TRUE. + */ +#if !defined(STM32_PWM_USE_TIM2) || defined(__DOXYGEN__) +#define STM32_PWM_USE_TIM2 FALSE +#endif + +/** + * @brief PWMD3 driver enable switch. + * @details If set to @p TRUE the support for PWMD3 is included. + * @note The default is @p TRUE. + */ +#if !defined(STM32_PWM_USE_TIM3) || defined(__DOXYGEN__) +#define STM32_PWM_USE_TIM3 FALSE +#endif + +/** + * @brief PWMD4 driver enable switch. + * @details If set to @p TRUE the support for PWMD4 is included. + * @note The default is @p TRUE. + */ +#if !defined(STM32_PWM_USE_TIM4) || defined(__DOXYGEN__) +#define STM32_PWM_USE_TIM4 FALSE +#endif + +/** + * @brief PWMD5 driver enable switch. + * @details If set to @p TRUE the support for PWMD5 is included. + * @note The default is @p TRUE. + */ +#if !defined(STM32_PWM_USE_TIM5) || defined(__DOXYGEN__) +#define STM32_PWM_USE_TIM5 FALSE +#endif + +/** + * @brief PWMD8 driver enable switch. + * @details If set to @p TRUE the support for PWMD8 is included. + * @note The default is @p TRUE. + */ +#if !defined(STM32_PWM_USE_TIM8) || defined(__DOXYGEN__) +#define STM32_PWM_USE_TIM8 FALSE +#endif + +/** + * @brief PWMD9 driver enable switch. + * @details If set to @p TRUE the support for PWMD9 is included. + * @note The default is @p TRUE. + */ +#if !defined(STM32_PWM_USE_TIM9) || defined(__DOXYGEN__) +#define STM32_PWM_USE_TIM9 FALSE +#endif + +/** + * @brief PWMD1 interrupt priority level setting. + */ +#if !defined(STM32_PWM_TIM1_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_PWM_TIM1_IRQ_PRIORITY 7 +#endif + +/** + * @brief PWMD2 interrupt priority level setting. + */ +#if !defined(STM32_PWM_TIM2_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_PWM_TIM2_IRQ_PRIORITY 7 +#endif + +/** + * @brief PWMD3 interrupt priority level setting. + */ +#if !defined(STM32_PWM_TIM3_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_PWM_TIM3_IRQ_PRIORITY 7 +#endif + +/** + * @brief PWMD4 interrupt priority level setting. + */ +#if !defined(STM32_PWM_TIM4_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_PWM_TIM4_IRQ_PRIORITY 7 +#endif + +/** + * @brief PWMD5 interrupt priority level setting. + */ +#if !defined(STM32_PWM_TIM5_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_PWM_TIM5_IRQ_PRIORITY 7 +#endif + +/** + * @brief PWMD8 interrupt priority level setting. + */ +#if !defined(STM32_PWM_TIM8_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_PWM_TIM8_IRQ_PRIORITY 7 +#endif +/** @} */ + +/** + * @brief PWMD9 interrupt priority level setting. + */ +#if !defined(STM32_PWM_TIM9_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_PWM_TIM9_IRQ_PRIORITY 7 +#endif +/** @} */ + +/*===========================================================================*/ +/* Configuration checks. */ +/*===========================================================================*/ + +#if STM32_PWM_USE_TIM1 && !STM32_HAS_TIM1 +#error "TIM1 not present in the selected device" +#endif + +#if STM32_PWM_USE_TIM2 && !STM32_HAS_TIM2 +#error "TIM2 not present in the selected device" +#endif + +#if STM32_PWM_USE_TIM3 && !STM32_HAS_TIM3 +#error "TIM3 not present in the selected device" +#endif + +#if STM32_PWM_USE_TIM4 && !STM32_HAS_TIM4 +#error "TIM4 not present in the selected device" +#endif + +#if STM32_PWM_USE_TIM5 && !STM32_HAS_TIM5 +#error "TIM5 not present in the selected device" +#endif + +#if STM32_PWM_USE_TIM8 && !STM32_HAS_TIM8 +#error "TIM8 not present in the selected device" +#endif + +#if STM32_PWM_USE_TIM9 && !STM32_HAS_TIM9 +#error "TIM9 not present in the selected device" +#endif + +#if !STM32_PWM_USE_TIM1 && !STM32_PWM_USE_TIM2 && \ + !STM32_PWM_USE_TIM3 && !STM32_PWM_USE_TIM4 && \ + !STM32_PWM_USE_TIM5 && !STM32_PWM_USE_TIM8 && \ + !STM32_PWM_USE_TIM9 +#error "PWM driver activated but no TIM peripheral assigned" +#endif + +#if STM32_PWM_USE_ADVANCED && !STM32_PWM_USE_TIM1 && !STM32_PWM_USE_TIM8 +#error "advanced mode selected but no advanced timer assigned" +#endif + +#if STM32_PWM_USE_TIM1 && \ + !CORTEX_IS_VALID_KERNEL_PRIORITY(STM32_PWM_TIM1_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to TIM1" +#endif + +#if STM32_PWM_USE_TIM2 && \ + !CORTEX_IS_VALID_KERNEL_PRIORITY(STM32_PWM_TIM2_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to TIM2" +#endif + +#if STM32_PWM_USE_TIM3 && \ + !CORTEX_IS_VALID_KERNEL_PRIORITY(STM32_PWM_TIM3_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to TIM3" +#endif + +#if STM32_PWM_USE_TIM4 && \ + !CORTEX_IS_VALID_KERNEL_PRIORITY(STM32_PWM_TIM4_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to TIM4" +#endif + +#if STM32_PWM_USE_TIM5 && \ + !CORTEX_IS_VALID_KERNEL_PRIORITY(STM32_PWM_TIM5_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to TIM5" +#endif + +#if STM32_PWM_USE_TIM8 && \ + !CORTEX_IS_VALID_KERNEL_PRIORITY(STM32_PWM_TIM8_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to TIM8" +#endif + +#if STM32_PWM_USE_TIM9 && \ + !CORTEX_IS_VALID_KERNEL_PRIORITY(STM32_PWM_TIM9_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to TIM9" +#endif + +/*===========================================================================*/ +/* Driver data structures and types. */ +/*===========================================================================*/ + +/** + * @brief PWM mode type. + */ +typedef uint32_t pwmmode_t; + +/** + * @brief PWM channel type. + */ +typedef uint8_t pwmchannel_t; + +/** + * @brief PWM counter type. + */ +typedef uint16_t pwmcnt_t; + +/** + * @brief PWM driver channel configuration structure. + */ +typedef struct { + /** + * @brief Channel active logic level. + */ + pwmmode_t mode; + /** + * @brief Channel callback pointer. + * @note This callback is invoked on the channel compare event. If set to + * @p NULL then the callback is disabled. + */ + pwmcallback_t callback; + /* End of the mandatory fields.*/ +} PWMChannelConfig; + +/** + * @brief PWM driver configuration structure. + */ +typedef struct { + /** + * @brief Timer clock in Hz. + * @note The low level can use assertions in order to catch invalid + * frequency specifications. + */ + uint32_t frequency; + /** + * @brief PWM period in ticks. + * @note The low level can use assertions in order to catch invalid + * period specifications. + */ + pwmcnt_t period; + /** + * @brief Periodic callback pointer. + * @note This callback is invoked on PWM counter reset. If set to + * @p NULL then the callback is disabled. + */ + pwmcallback_t callback; + /** + * @brief Channels configurations. + */ + PWMChannelConfig channels[PWM_CHANNELS]; + /* End of the mandatory fields.*/ + /** + * @brief TIM CR2 register initialization data. + * @note The value of this field should normally be equal to zero. + */ + uint32_t cr2; +#if STM32_PWM_USE_ADVANCED || defined(__DOXYGEN__) + /** + * @brief TIM BDTR (break & dead-time) register initialization data. + * @note The value of this field should normally be equal to zero. + */ \ + uint32_t bdtr; +#endif + /** + * @brief TIM DIER register initialization data. + * @note The value of this field should normally be equal to zero. + * @note Only the DMA-related bits can be specified in this field. + */ + uint32_t dier; +} PWMConfig; + +/** + * @brief Structure representing a PWM driver. + */ +struct PWMDriver { + /** + * @brief Driver state. + */ + pwmstate_t state; + /** + * @brief Current driver configuration data. + */ + const PWMConfig *config; + /** + * @brief Current PWM period in ticks. + */ + pwmcnt_t period; +#if defined(PWM_DRIVER_EXT_FIELDS) + PWM_DRIVER_EXT_FIELDS +#endif + /* End of the mandatory fields.*/ + /** + * @brief Timer base clock. + */ + uint32_t clock; + /** + * @brief Pointer to the TIMx registers block. + */ + stm32_tim_t *tim; +}; + +/*===========================================================================*/ +/* Driver macros. */ +/*===========================================================================*/ + +/** + * @brief Changes the period the PWM peripheral. + * @details This function changes the period of a PWM unit that has already + * been activated using @p pwmStart(). + * @pre The PWM unit must have been activated using @p pwmStart(). + * @post The PWM unit period is changed to the new value. + * @note The function has effect at the next cycle start. + * @note If a period is specified that is shorter than the pulse width + * programmed in one of the channels then the behavior is not + * guaranteed. + * + * @param[in] pwmp pointer to a @p PWMDriver object + * @param[in] period new cycle time in ticks + * + * @notapi + */ +#define pwm_lld_change_period(pwmp, period) \ + ((pwmp)->tim->ARR = (uint16_t)((period) - 1)) + +/** + * @brief Returns a PWM channel status. + * @pre The PWM unit must have been activated using @p pwmStart(). + * + * @param[in] pwmp pointer to a @p PWMDriver object + * @param[in] channel PWM channel identifier (0...PWM_CHANNELS-1) + * + * @notapi + */ +#define pwm_lld_is_channel_enabled(pwmp, channel) \ + (((pwmp)->tim->CCR[channel] != 0) || \ + (((pwmp)->tim->DIER & (2 << channel)) != 0)) + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +#if STM32_PWM_USE_TIM1 && !defined(__DOXYGEN__) +extern PWMDriver PWMD1; +#endif + +#if STM32_PWM_USE_TIM2 && !defined(__DOXYGEN__) +extern PWMDriver PWMD2; +#endif + +#if STM32_PWM_USE_TIM3 && !defined(__DOXYGEN__) +extern PWMDriver PWMD3; +#endif + +#if STM32_PWM_USE_TIM4 && !defined(__DOXYGEN__) +extern PWMDriver PWMD4; +#endif + +#if STM32_PWM_USE_TIM5 && !defined(__DOXYGEN__) +extern PWMDriver PWMD5; +#endif + +#if STM32_PWM_USE_TIM8 && !defined(__DOXYGEN__) +extern PWMDriver PWMD8; +#endif + +#if STM32_PWM_USE_TIM9 && !defined(__DOXYGEN__) +extern PWMDriver PWMD9; +#endif + +#ifdef __cplusplus +extern "C" { +#endif + void pwm_lld_init(void); + void pwm_lld_start(PWMDriver *pwmp); + void pwm_lld_stop(PWMDriver *pwmp); + void pwm_lld_enable_channel(PWMDriver *pwmp, + pwmchannel_t channel, + pwmcnt_t width); + void pwm_lld_disable_channel(PWMDriver *pwmp, pwmchannel_t channel); +#ifdef __cplusplus +} +#endif + +#endif /* HAL_USE_PWM */ + +#endif /* _PWM_LLD_H_ */ + +/** @} */ diff --git a/os/hal/ports/STM32/TIMv1/st_lld.c b/os/hal/ports/STM32/TIMv1/st_lld.c new file mode 100644 index 000000000..240328ff5 --- /dev/null +++ b/os/hal/ports/STM32/TIMv1/st_lld.c @@ -0,0 +1,161 @@ +/* + ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file STM32/st_lld.c + * @brief ST Driver subsystem low level driver code. + * + * @addtogroup ST + * @{ + */ + +#include "hal.h" + +#if (OSAL_ST_MODE != OSAL_ST_MODE_NONE) || defined(__DOXYGEN__) + +/* The following checks and settings are unusually done here because the + file st.h needs to not have external dependencies. In this case there + would be a dependency on osal.h and mcuconf.h.*/ +#if (OSAL_ST_MODE == OSAL_ST_MODE_FREERUNNING) && !STM32_HAS_TIM2 +#error "TIM2 not present in the selected device" +#endif + +#if (OSAL_ST_MODE == OSAL_ST_MODE_FREERUNNING) && !STM32_TIM2_IS_32BITS +#error "TIM2 is not a 32 bits timer" +#endif + +/** + * @name Configuration options + * @{ + */ +/** + * @brief SysTick timer IRQ priority. + */ +#if !defined(STM32_ST_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_ST_IRQ_PRIORITY 8 +#endif +/** @} */ + +/*===========================================================================*/ +/* Driver local definitions. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver exported variables. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local types. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local variables and types. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local functions. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver interrupt handlers. */ +/*===========================================================================*/ + +#if (OSAL_ST_MODE == OSAL_ST_MODE_PERIODIC) || defined(__DOXYGEN__) +/** + * @brief System Timer vector. + * @details This interrupt is used for system tick in periodic mode. + * + * @isr + */ +OSAL_IRQ_HANDLER(SysTick_Handler) { + + OSAL_IRQ_PROLOGUE(); + + osalSysLockFromISR(); + osalOsTimerHandlerI(); + osalSysUnlockFromISR(); + + OSAL_IRQ_EPILOGUE(); +} +#endif + +#if (OSAL_ST_MODE == OSAL_ST_MODE_FREERUNNING) || defined(__DOXYGEN__) +/** + * @brief TIM2 interrupt handler. + * @details This interrupt is used for system tick in free running mode. + * + * @isr + */ +OSAL_IRQ_HANDLER(STM32_TIM2_HANDLER) { + + OSAL_IRQ_PROLOGUE(); + + STM32_TIM2->SR = 0; + + osalSysLockFromISR(); + osalOsTimerHandlerI(); + osalSysUnlockFromISR(); + + OSAL_IRQ_EPILOGUE(); +} +#endif + +/*===========================================================================*/ +/* Driver exported functions. */ +/*===========================================================================*/ + +/** + * @brief Low level ST driver initialization. + * + * @notapi + */ +void st_lld_init(void) { + +#if OSAL_ST_MODE == OSAL_ST_MODE_FREERUNNING + /* Free running counter mode.*/ + rccEnableTIM2(FALSE); + + /* Initializing the counter in free running mode.*/ + STM32_TIM2->PSC = STM32_TIMCLK1 / OSAL_SYSTICK_FREQUENCY - 1; + STM32_TIM2->ARR = 0xFFFFFFFF; + STM32_TIM2->CCMR1 = 0; + STM32_TIM2->CCR[0] = 0; + STM32_TIM2->DIER = 0; + STM32_TIM2->CR2 = 0; + STM32_TIM2->EGR = TIM_EGR_UG; + STM32_TIM2->CR1 = TIM_CR1_CEN; + + /* IRQ enabled.*/ + nvicEnableVector(STM32_TIM2_NUMBER, STM32_ST_IRQ_PRIORITY); +#endif + +#if OSAL_ST_MODE == OSAL_ST_MODE_PERIODIC + /* Periodic systick mode, the Cortex-Mx internal systick timer is used + in this mode.*/ + SysTick->LOAD = STM32_HCLK / OSAL_SYSTICK_FREQUENCY - 1; + SysTick->VAL = 0; + SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk | + SysTick_CTRL_ENABLE_Msk | + SysTick_CTRL_TICKINT_Msk; + + /* IRQ enabled.*/ + nvicSetSystemHandlerPriority(SysTick_IRQn, STM32_ST_IRQ_PRIORITY); +#endif +} + +#endif /* OSAL_ST_MODE != OSAL_ST_MODE_NONE */ + +/** @} */ diff --git a/os/hal/ports/STM32/TIMv1/st_lld.h b/os/hal/ports/STM32/TIMv1/st_lld.h new file mode 100644 index 000000000..fb067f202 --- /dev/null +++ b/os/hal/ports/STM32/TIMv1/st_lld.h @@ -0,0 +1,147 @@ +/* + ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file STM32/st_lld.h + * @brief ST Driver subsystem low level driver header. + * @details This header is designed to be include-able without having to + * include other files from the HAL. + * + * @addtogroup ST + * @{ + */ + +#ifndef _ST_LLD_H_ +#define _ST_LLD_H_ + +#include "stm32_registry.h" +#include "stm32_tim.h" + +/*===========================================================================*/ +/* Driver constants. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver pre-compile time settings. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Derived constants and error checks. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver data structures and types. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver macros. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +#ifdef __cplusplus +extern "C" { +#endif + void st_lld_init(void); +#ifdef __cplusplus +} +#endif + +/*===========================================================================*/ +/* Driver inline functions. */ +/*===========================================================================*/ + +/** + * @brief Returns the time counter value. + * + * @return The counter value. + * + * @notapi + */ +static inline systime_t st_lld_get_counter(void) { + + return (systime_t)(STM32_TIM2->CNT); +} + +/** + * @brief Starts the alarm. + * @note Makes sure that no spurious alarms are triggered after + * this call. + * + * @param[in] time the time to be set for the first alarm + * + * @notapi + */ +static inline void st_lld_start_alarm(systime_t time) { + + STM32_TIM2->CCR[0] = time; + STM32_TIM2->SR = 0; + STM32_TIM2->DIER = STM32_TIM_DIER_CC1IE; +} + +/** + * @brief Stops the alarm interrupt. + * + * @notapi + */ +static inline void st_lld_stop_alarm(void) { + + STM32_TIM2->DIER = 0; +} + +/** + * @brief Sets the alarm time. + * + * @param[in] time the time to be set for the next alarm + * + * @notapi + */ +static inline void st_lld_set_alarm(systime_t time) { + + STM32_TIM2->CCR[0] = (uint32_t)time; +} + +/** + * @brief Returns the current alarm time. + * + * @return The currently set alarm time. + * + * @notapi + */ +static inline systime_t st_lld_get_alarm(void) { + + return (systime_t)STM32_TIM2->CCR[0]; +} + +/** + * @brief Determines if the alarm is active. + * + * @return The alarm status. + * @retval false if the alarm is not active. + * @retval true is the alarm is active + * + * @notapi + */ +static inline bool st_lld_is_alarm_active(void) { + + return (bool)((STM32_TIM2->DIER & STM32_TIM_DIER_CC1IE) != 0); +} + +#endif /* _ST_LLD_H_ */ + +/** @} */ diff --git a/os/hal/ports/STM32/TIMv1/stm32_tim.h b/os/hal/ports/STM32/TIMv1/stm32_tim.h new file mode 100644 index 000000000..ce0274c33 --- /dev/null +++ b/os/hal/ports/STM32/TIMv1/stm32_tim.h @@ -0,0 +1,448 @@ +/* + ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file stm32_tim.h + * @brief STM32 TIM registers layout header. + * @note This file requires definitions from the ST STM32 header file. + * + * @addtogroup STM32_TIMv1 + * @{ + */ + +#ifndef _STM32_TIM_H_ +#define _STM32_TIM_H_ + +/*===========================================================================*/ +/* Driver constants. */ +/*===========================================================================*/ + +/** + * @name TIM_CR1 register + * @{ + */ +#define STM32_TIM_CR1_CEN (1U << 0) +#define STM32_TIM_CR1_UDIS (1U << 1) +#define STM32_TIM_CR1_URS (1U << 2) +#define STM32_TIM_CR1_OPM (1U << 3) +#define STM32_TIM_CR1_DIR (1U << 4) + +#define STM32_TIM_CR1_CMS_MASK (3U << 5) +#define STM32_TIM_CR1_CMS(n) ((n) << 5) + +#define STM32_TIM_CR1_ARPE (1U << 7) + +#define STM32_TIM_CR1_CKD_MASK (3U << 8) +#define STM32_TIM_CR1_CKD(n) ((n) << 8) + +#define STM32_TIM_CR1_UIFREMAP (1U << 11) +/** @} */ + +/** + * @name TIM_CR2 register + * @{ + */ +#define STM32_TIM_CR2_CCPC (1U << 0) +#define STM32_TIM_CR2_CCUS (1U << 2) +#define STM32_TIM_CR2_CCDS (1U << 3) + +#define STM32_TIM_CR2_MMS_MASK (7U << 4) +#define STM32_TIM_CR2_MMS(n) ((n) << 4) + +#define STM32_TIM_CR2_TI1S (1U << 7) +#define STM32_TIM_CR2_OIS1 (1U << 8) +#define STM32_TIM_CR2_OIS1N (1U << 9) +#define STM32_TIM_CR2_OIS2 (1U << 10) +#define STM32_TIM_CR2_OIS2N (1U << 11) +#define STM32_TIM_CR2_OIS3 (1U << 12) +#define STM32_TIM_CR2_OIS3N (1U << 13) +#define STM32_TIM_CR2_OIS4 (1U << 14) +#define STM32_TIM_CR2_OIS5 (1U << 16) +#define STM32_TIM_CR2_OIS6 (1U << 18) + +#define STM32_TIM_CR2_MMS2_MASK (15U << 20) +#define STM32_TIM_CR2_MMS2(n) ((n) << 20) +/** @} */ + +/** + * @name TIM_SMCR register + * @{ + */ +#define STM32_TIM_SMCR_SMS_MASK ((7U << 0) | (1U << 16)) +#define STM32_TIM_SMCR_SMS(n) ((((n) & 7) << 0) | \ + (((n) >> 3) << 16)) + +#define STM32_TIM_SMCR_OCCS (1U << 3) + +#define STM32_TIM_SMCR_TS_MASK (7U << 4) +#define STM32_TIM_SMCR_TS(n) ((n) << 4) + +#define STM32_TIM_SMCR_MSM (1U << 7) + +#define STM32_TIM_SMCR_ETF_MASK (15U << 8) +#define STM32_TIM_SMCR_ETF(n) ((n) << 8) + +#define STM32_TIM_SMCR_ETPS_MASK (3U << 12) +#define STM32_TIM_SMCR_ETPS(n) ((n) << 12) + +#define STM32_TIM_SMCR_ECE (1U << 14) +#define STM32_TIM_SMCR_ETP (1U << 15) +/** @} */ + +/** + * @name TIM_DIER register + * @{ + */ +#define STM32_TIM_DIER_UIE (1U << 0) +#define STM32_TIM_DIER_CC1IE (1U << 1) +#define STM32_TIM_DIER_CC2IE (1U << 2) +#define STM32_TIM_DIER_CC3IE (1U << 3) +#define STM32_TIM_DIER_CC4IE (1U << 4) +#define STM32_TIM_DIER_COMIE (1U << 5) +#define STM32_TIM_DIER_TIE (1U << 6) +#define STM32_TIM_DIER_BIE (1U << 7) +#define STM32_TIM_DIER_UDE (1U << 8) +#define STM32_TIM_DIER_CC1DE (1U << 9) +#define STM32_TIM_DIER_CC2DE (1U << 10) +#define STM32_TIM_DIER_CC3DE (1U << 11) +#define STM32_TIM_DIER_CC4DE (1U << 12) +#define STM32_TIM_DIER_COMDE (1U << 13) +#define STM32_TIM_DIER_TDE (1U << 14) + +#define STM32_TIM_DIER_IRQ_MASK (STM32_TIM_DIER_UIE | \ + STM32_TIM_DIER_CC1IE | \ + STM32_TIM_DIER_CC2IE | \ + STM32_TIM_DIER_CC3IE | \ + STM32_TIM_DIER_CC4IE | \ + STM32_TIM_DIER_COMIE | \ + STM32_TIM_DIER_TIE | \ + STM32_TIM_DIER_BIE) + +/** @} */ + +/** + * @name TIM_SR register + * @{ + */ +#define STM32_TIM_SR_UIF (1U << 0) +#define STM32_TIM_SR_CC1IF (1U << 1) +#define STM32_TIM_SR_CC2IF (1U << 2) +#define STM32_TIM_SR_CC3IF (1U << 3) +#define STM32_TIM_SR_CC4IF (1U << 4) +#define STM32_TIM_SR_COMIF (1U << 5) +#define STM32_TIM_SR_TIF (1U << 6) +#define STM32_TIM_SR_BIF (1U << 7) +#define STM32_TIM_SR_B2IF (1U << 8) +#define STM32_TIM_SR_CC1OF (1U << 9) +#define STM32_TIM_SR_CC2OF (1U << 10) +#define STM32_TIM_SR_CC3OF (1U << 11) +#define STM32_TIM_SR_CC4OF (1U << 12) +#define STM32_TIM_SR_CC5IF (1U << 16) +#define STM32_TIM_SR_CC6IF (1U << 17) +/** @} */ + +/** + * @name TIM_EGR register + * @{ + */ +#define STM32_TIM_EGR_UG (1U << 0) +#define STM32_TIM_EGR_CC1G (1U << 1) +#define STM32_TIM_EGR_CC2G (1U << 2) +#define STM32_TIM_EGR_CC3G (1U << 3) +#define STM32_TIM_EGR_CC4G (1U << 4) +#define STM32_TIM_EGR_COMG (1U << 5) +#define STM32_TIM_EGR_TG (1U << 6) +#define STM32_TIM_EGR_BG (1U << 7) +#define STM32_TIM_EGR_B2G (1U << 8) +/** @} */ + +/** + * @name TIM_CCMR1 register (output) + * @{ + */ +#define STM32_TIM_CCMR1_CC1S_MASK (3U << 0) +#define STM32_TIM_CCMR1_CC1S(n) ((n) << 0) + +#define STM32_TIM_CCMR1_OC1FE (1U << 2) +#define STM32_TIM_CCMR1_OC1PE (1U << 3) + +#define STM32_TIM_CCMR1_OC1M_MASK ((7U << 4) | (1U << 16)) +#define STM32_TIM_CCMR1_OC1M(n) ((((n) & 7) << 4) | \ + (((n) >> 2) << 16)) + +#define STM32_TIM_CCMR1_OC1CE (1U << 7) + +#define STM32_TIM_CCMR1_CC2S_MASK (3U << 8) +#define STM32_TIM_CCMR1_CC2S(n) ((n) << 8) + +#define STM32_TIM_CCMR1_OC2FE (1U << 10) +#define STM32_TIM_CCMR1_OC2PE (1U << 11) + +#define STM32_TIM_CCMR1_OC2M_MASK ((7U << 12) | (1U << 24)) +#define STM32_TIM_CCMR1_OC2M(n) ((((n) & 7) << 12) | \ + (((n) >> 2) << 24)) + +#define STM32_TIM_CCMR1_OC2CE (1U << 15) +/** @} */ + +/** + * @name CCMR1 register (input) + * @{ + */ +#define STM32_TIM_CCMR1_IC1PSC_MASK (3U << 2) +#define STM32_TIM_CCMR1_IC1PSC(n) ((n) << 2) + +#define STM32_TIM_CCMR1_IC1F_MASK (15U << 4) +#define STM32_TIM_CCMR1_IC1F(n) ((n) << 4) + +#define STM32_TIM_CCMR1_IC2PSC_MASK (3U << 10) +#define STM32_TIM_CCMR1_IC2PSC(n) ((n) << 10) + +#define STM32_TIM_CCMR1_IC2F_MASK (15U << 12) +#define STM32_TIM_CCMR1_IC2F(n) ((n) << 12) +/** @} */ + +/** + * @name TIM_CCMR2 register (output) + * @{ + */ +#define STM32_TIM_CCMR2_CC3S_MASK (3U << 0) +#define STM32_TIM_CCMR2_CC3S(n) ((n) << 0) + +#define STM32_TIM_CCMR2_OC3FE (1U << 2) +#define STM32_TIM_CCMR2_OC3PE (1U << 3) + +#define STM32_TIM_CCMR2_OC3M_MASK ((7U << 4) | (1U << 16)) +#define STM32_TIM_CCMR2_OC3M(n) ((((n) & 7) << 4) | \ + (((n) >> 2) << 16)) + +#define STM32_TIM_CCMR2_OC3CE (1U << 7) + +#define STM32_TIM_CCMR2_CC4S_MASK (3U << 8) +#define STM32_TIM_CCMR2_CC4S(n) ((n) << 8) + +#define STM32_TIM_CCMR2_OC4FE (1U << 10) +#define STM32_TIM_CCMR2_OC4PE (1U << 11) + +#define STM32_TIM_CCMR2_OC4M_MASK ((7U << 12) | (1U << 24)) +#define STM32_TIM_CCMR2_OC4M(n) ((((n) & 7) << 12) | \ + (((n) >> 2) << 24)) + +#define STM32_TIM_CCMR2_OC4CE (1U << 15) +/** @} */ + +/** + * @name TIM_CCMR2 register (input) + * @{ + */ +#define STM32_TIM_CCMR2_IC3PSC_MASK (3U << 2) +#define STM32_TIM_CCMR2_IC3PSC(n) ((n) << 2) + +#define STM32_TIM_CCMR2_IC3F_MASK (15U << 4) +#define STM32_TIM_CCMR2_IC3F(n) ((n) << 4) + +#define STM32_TIM_CCMR2_IC4PSC_MASK (3U << 10) +#define STM32_TIM_CCMR2_IC4PSC(n) ((n) << 10) + +#define STM32_TIM_CCMR2_IC4F_MASK (15U << 12) +#define STM32_TIM_CCMR2_IC4F(n) ((n) << 12) +/** @} */ + +/** + * @name TIM_CCER register + * @{ + */ +#define STM32_TIM_CCER_CC1E (1U << 0) +#define STM32_TIM_CCER_CC1P (1U << 1) +#define STM32_TIM_CCER_CC1NE (1U << 2) +#define STM32_TIM_CCER_CC1NP (1U << 3) +#define STM32_TIM_CCER_CC2E (1U << 4) +#define STM32_TIM_CCER_CC2P (1U << 5) +#define STM32_TIM_CCER_CC2NE (1U << 6) +#define STM32_TIM_CCER_CC2NP (1U << 7) +#define STM32_TIM_CCER_CC3E (1U << 8) +#define STM32_TIM_CCER_CC3P (1U << 9) +#define STM32_TIM_CCER_CC3NE (1U << 10) +#define STM32_TIM_CCER_CC3NP (1U << 11) +#define STM32_TIM_CCER_CC4E (1U << 12) +#define STM32_TIM_CCER_CC4P (1U << 13) +#define STM32_TIM_CCER_CC4NP (1U << 15) +#define STM32_TIM_CCER_CC5E (1U << 16) +#define STM32_TIM_CCER_CC5P (1U << 17) +#define STM32_TIM_CCER_CC6E (1U << 20) +#define STM32_TIM_CCER_CC6P (1U << 21) +/** @} */ + +/** + * @name TIM_CNT register + * @{ + */ +#define STM32_TIM_CNT_UIFCPY (1U << 31) +/** @} */ + +/** + * @name TIM_BDTR register + * @{ + */ +#define STM32_TIM_BDTR_DTG_MASK (255U << 0) +#define STM32_TIM_BDTR_DTG(n) ((n) << 0) + +#define STM32_TIM_BDTR_LOCK_MASK (3U << 8) +#define STM32_TIM_BDTR_LOCK(n) ((n) << 8) + +#define STM32_TIM_BDTR_OSSI (1U << 10) +#define STM32_TIM_BDTR_OSSR (1U << 11) +#define STM32_TIM_BDTR_BKE (1U << 12) +#define STM32_TIM_BDTR_BKP (1U << 13) +#define STM32_TIM_BDTR_AOE (1U << 14) +#define STM32_TIM_BDTR_MOE (1U << 15) + +#define STM32_TIM_BDTR_BKF_MASK (15U << 16) +#define STM32_TIM_BDTR_BKF(n) ((n) << 16) +#define STM32_TIM_BDTR_BK2F_MASK (15U << 20) +#define STM32_TIM_BDTR_BK2F(n) ((n) << 20) + +#define STM32_TIM_BDTR_BK2E (1U << 24) +#define STM32_TIM_BDTR_BK2P (1U << 25) +/** @} */ + +/** + * @name TIM_DCR register + * @{ + */ +#define STM32_TIM_DCR_DBA_MASK (31U << 0) +#define STM32_TIM_DCR_DBA(n) ((n) << 0) + +#define STM32_TIM_DCR_DBL_MASK (31U << 8) +#define STM32_TIM_DCR_DBL(b) ((n) << 8) +/** @} */ + +/** + * @name TIM16_OR register + * @{ + */ +#define STM32_TIM16_OR_TI1_RMP_MASK (3U << 6) +#define STM32_TIM16_OR_TI1_RMP(n) ((n) << 6) +/** @} */ + +/** + * @name TIM_OR register + * @{ + */ +#define STM32_TIM_OR_ETR_RMP_MASK (15U << 0) +#define STM32_TIM_OR_ETR_RMP(n) ((n) << 0) +/** @} */ + +/** + * @name TIM_CCMR3 register + * @{ + */ +#define STM32_TIM_CCMR3_OC5FE (1U << 2) +#define STM32_TIM_CCMR3_OC5PE (1U << 3) + +#define STM32_TIM_CCMR3_OC5M_MASK ((7U << 4) | (1U << 16)) +#define STM32_TIM_CCMR3_OC5M(n) ((((n) & 7) << 4) | \ + (((n) >> 2) << 16)) + +#define STM32_TIM_CCMR3_OC5CE (1U << 7) + +#define STM32_TIM_CCMR3_OC6FE (1U << 10) +#define STM32_TIM_CCMR3_OC6PE (1U << 11) + +#define STM32_TIM_CCMR3_OC6M_MASK ((7U << 12) | (1U << 24)) +#define STM32_TIM_CCMR3_OC6M(n) ((((n) & 7) << 12) | \ + (((n) >> 2) << 24)) + +#define STM32_TIM_CCMR3_OC6CE (1U << 15) +/** @} */ + +/** + * @name TIM units references + * @{ + */ +#define STM32_TIM1 ((stm32_tim_t *)TIM1_BASE) +#define STM32_TIM2 ((stm32_tim_t *)TIM2_BASE) +#define STM32_TIM3 ((stm32_tim_t *)TIM3_BASE) +#define STM32_TIM4 ((stm32_tim_t *)TIM4_BASE) +#define STM32_TIM5 ((stm32_tim_t *)TIM5_BASE) +#define STM32_TIM6 ((stm32_tim_t *)TIM6_BASE) +#define STM32_TIM7 ((stm32_tim_t *)TIM7_BASE) +#define STM32_TIM8 ((stm32_tim_t *)TIM8_BASE) +#define STM32_TIM9 ((stm32_tim_t *)TIM9_BASE) +#define STM32_TIM10 ((stm32_tim_t *)TIM10_BASE) +#define STM32_TIM11 ((stm32_tim_t *)TIM11_BASE) +#define STM32_TIM12 ((stm32_tim_t *)TIM12_BASE) +#define STM32_TIM13 ((stm32_tim_t *)TIM13_BASE) +#define STM32_TIM14 ((stm32_tim_t *)TIM14_BASE) +#define STM32_TIM15 ((stm32_tim_t *)TIM15_BASE) +#define STM32_TIM16 ((stm32_tim_t *)TIM16_BASE) +#define STM32_TIM17 ((stm32_tim_t *)TIM17_BASE) +#define STM32_TIM18 ((stm32_tim_t *)TIM18_BASE) +#define STM32_TIM19 ((stm32_tim_t *)TIM19_BASE) +/** @} */ + +/*===========================================================================*/ +/* Driver pre-compile time settings. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Derived constants and error checks. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver data structures and types. */ +/*===========================================================================*/ + +/** + * @brief STM32 TIM registers block. + * @note This is the most general known form, not all timers have + * necessarily all registers and bits. + */ +typedef struct { + volatile uint32_t CR1; + volatile uint32_t CR2; + volatile uint32_t SMCR; + volatile uint32_t DIER; + volatile uint32_t SR; + volatile uint32_t EGR; + volatile uint32_t CCMR1; + volatile uint32_t CCMR2; + volatile uint32_t CCER; + volatile uint32_t CNT; + volatile uint32_t PSC; + volatile uint32_t ARR; + volatile uint32_t RCR; + volatile uint32_t CCR[4]; + volatile uint32_t BDTR; + volatile uint32_t DCR; + volatile uint32_t DMAR; + volatile uint32_t OR; + volatile uint32_t CCMR3; + volatile uint32_t CCR5; + volatile uint32_t CCR6; +} stm32_tim_t; + +/*===========================================================================*/ +/* Driver macros. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +#endif /* _STM32_TIM_H_ */ + +/** @} */ diff --git a/os/hal/ports/STM32/USARTv1/serial_lld.c b/os/hal/ports/STM32/USARTv1/serial_lld.c new file mode 100644 index 000000000..ae6042a8d --- /dev/null +++ b/os/hal/ports/STM32/USARTv1/serial_lld.c @@ -0,0 +1,524 @@ +/* + ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file STM32/USARTv1/serial_lld.c + * @brief STM32 low level serial driver code. + * + * @addtogroup SERIAL + * @{ + */ + +#include "hal.h" + +#if HAL_USE_SERIAL || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver local definitions. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver exported variables. */ +/*===========================================================================*/ + +/** @brief USART1 serial driver identifier.*/ +#if STM32_SERIAL_USE_USART1 || defined(__DOXYGEN__) +SerialDriver SD1; +#endif + +/** @brief USART2 serial driver identifier.*/ +#if STM32_SERIAL_USE_USART2 || defined(__DOXYGEN__) +SerialDriver SD2; +#endif + +/** @brief USART3 serial driver identifier.*/ +#if STM32_SERIAL_USE_USART3 || defined(__DOXYGEN__) +SerialDriver SD3; +#endif + +/** @brief UART4 serial driver identifier.*/ +#if STM32_SERIAL_USE_UART4 || defined(__DOXYGEN__) +SerialDriver SD4; +#endif + +/** @brief UART5 serial driver identifier.*/ +#if STM32_SERIAL_USE_UART5 || defined(__DOXYGEN__) +SerialDriver SD5; +#endif + +/** @brief USART6 serial driver identifier.*/ +#if STM32_SERIAL_USE_USART6 || defined(__DOXYGEN__) +SerialDriver SD6; +#endif + +/*===========================================================================*/ +/* Driver local variables and types. */ +/*===========================================================================*/ + +/** @brief Driver default configuration.*/ +static const SerialConfig default_config = +{ + SERIAL_DEFAULT_BITRATE, + 0, + USART_CR2_STOP1_BITS | USART_CR2_LINEN, + 0 +}; + +/*===========================================================================*/ +/* Driver local functions. */ +/*===========================================================================*/ + +/** + * @brief USART initialization. + * @details This function must be invoked with interrupts disabled. + * + * @param[in] sdp pointer to a @p SerialDriver object + * @param[in] config the architecture-dependent serial driver configuration + */ +static void usart_init(SerialDriver *sdp, const SerialConfig *config) { + USART_TypeDef *u = sdp->usart; + + /* Baud rate setting.*/ +#if STM32_HAS_USART6 + if ((sdp->usart == USART1) || (sdp->usart == USART6)) +#else + if (sdp->usart == USART1) +#endif + u->BRR = STM32_PCLK2 / config->speed; + else + u->BRR = STM32_PCLK1 / config->speed; + + /* Note that some bits are enforced.*/ + u->CR2 = config->cr2 | USART_CR2_LBDIE; + u->CR3 = config->cr3 | USART_CR3_EIE; + u->CR1 = config->cr1 | USART_CR1_UE | USART_CR1_PEIE | + USART_CR1_RXNEIE | USART_CR1_TE | + USART_CR1_RE; + u->SR = 0; + (void)u->SR; /* SR reset step 1.*/ + (void)u->DR; /* SR reset step 2.*/ +} + +/** + * @brief USART de-initialization. + * @details This function must be invoked with interrupts disabled. + * + * @param[in] u pointer to an USART I/O block + */ +static void usart_deinit(USART_TypeDef *u) { + + u->CR1 = 0; + u->CR2 = 0; + u->CR3 = 0; +} + +/** + * @brief Error handling routine. + * + * @param[in] sdp pointer to a @p SerialDriver object + * @param[in] sr USART SR register value + */ +static void set_error(SerialDriver *sdp, uint16_t sr) { + eventflags_t sts = 0; + + if (sr & USART_SR_ORE) + sts |= SD_OVERRUN_ERROR; + if (sr & USART_SR_PE) + sts |= SD_PARITY_ERROR; + if (sr & USART_SR_FE) + sts |= SD_FRAMING_ERROR; + if (sr & USART_SR_NE) + sts |= SD_NOISE_ERROR; + osalSysLockFromISR(); + chnAddFlagsI(sdp, sts); + osalSysUnlockFromISR(); +} + +/** + * @brief Common IRQ handler. + * + * @param[in] sdp communication channel associated to the USART + */ +static void serve_interrupt(SerialDriver *sdp) { + USART_TypeDef *u = sdp->usart; + uint16_t cr1 = u->CR1; + uint16_t sr = u->SR; /* SR reset step 1.*/ + uint16_t dr = u->DR; /* SR reset step 2.*/ + + /* Error condition detection.*/ + if (sr & (USART_SR_ORE | USART_SR_NE | USART_SR_FE | USART_SR_PE)) + set_error(sdp, sr); + /* Special case, LIN break detection.*/ + if (sr & USART_SR_LBD) { + osalSysLockFromISR(); + chnAddFlagsI(sdp, SD_BREAK_DETECTED); + osalSysUnlockFromISR(); + u->SR &= ~USART_SR_LBD; + } + /* Data available.*/ + if (sr & USART_SR_RXNE) { + osalSysLockFromISR(); + sdIncomingDataI(sdp, (uint8_t)dr); + osalSysUnlockFromISR(); + } + /* Transmission buffer empty.*/ + if ((cr1 & USART_CR1_TXEIE) && (sr & USART_SR_TXE)) { + msg_t b; + osalSysLockFromISR(); + b = oqGetI(&sdp->oqueue); + if (b < Q_OK) { + chnAddFlagsI(sdp, CHN_OUTPUT_EMPTY); + u->CR1 = (cr1 & ~USART_CR1_TXEIE) | USART_CR1_TCIE; + } + else + u->DR = b; + osalSysUnlockFromISR(); + } + /* Physical transmission end.*/ + if (sr & USART_SR_TC) { + osalSysLockFromISR(); + chnAddFlagsI(sdp, CHN_TRANSMISSION_END); + osalSysUnlockFromISR(); + u->CR1 = cr1 & ~USART_CR1_TCIE; + u->SR &= ~USART_SR_TC; + } +} + +#if STM32_SERIAL_USE_USART1 || defined(__DOXYGEN__) +static void notify1(io_queue_t *qp) { + + (void)qp; + USART1->CR1 |= USART_CR1_TXEIE; +} +#endif + +#if STM32_SERIAL_USE_USART2 || defined(__DOXYGEN__) +static void notify2(io_queue_t *qp) { + + (void)qp; + USART2->CR1 |= USART_CR1_TXEIE; +} +#endif + +#if STM32_SERIAL_USE_USART3 || defined(__DOXYGEN__) +static void notify3(io_queue_t *qp) { + + (void)qp; + USART3->CR1 |= USART_CR1_TXEIE; +} +#endif + +#if STM32_SERIAL_USE_UART4 || defined(__DOXYGEN__) +static void notify4(io_queue_t *qp) { + + (void)qp; + UART4->CR1 |= USART_CR1_TXEIE; +} +#endif + +#if STM32_SERIAL_USE_UART5 || defined(__DOXYGEN__) +static void notify5(io_queue_t *qp) { + + (void)qp; + UART5->CR1 |= USART_CR1_TXEIE; +} +#endif + +#if STM32_SERIAL_USE_USART6 || defined(__DOXYGEN__) +static void notify6(io_queue_t *qp) { + + (void)qp; + USART6->CR1 |= USART_CR1_TXEIE; +} +#endif + +/*===========================================================================*/ +/* Driver interrupt handlers. */ +/*===========================================================================*/ + +#if STM32_SERIAL_USE_USART1 || defined(__DOXYGEN__) +#if !defined(STM32_USART1_HANDLER) +#error "STM32_USART1_HANDLER not defined" +#endif +/** + * @brief USART1 interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(STM32_USART1_HANDLER) { + + OSAL_IRQ_PROLOGUE(); + + serve_interrupt(&SD1); + + OSAL_IRQ_EPILOGUE(); +} +#endif + +#if STM32_SERIAL_USE_USART2 || defined(__DOXYGEN__) +#if !defined(STM32_USART2_HANDLER) +#error "STM32_USART2_HANDLER not defined" +#endif +/** + * @brief USART2 interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(STM32_USART2_HANDLER) { + + OSAL_IRQ_PROLOGUE(); + + serve_interrupt(&SD2); + + OSAL_IRQ_EPILOGUE(); +} +#endif + +#if STM32_SERIAL_USE_USART3 || defined(__DOXYGEN__) +#if !defined(STM32_USART3_HANDLER) +#error "STM32_USART3_HANDLER not defined" +#endif +/** + * @brief USART3 interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(STM32_USART3_HANDLER) { + + OSAL_IRQ_PROLOGUE(); + + serve_interrupt(&SD3); + + OSAL_IRQ_EPILOGUE(); +} +#endif + +#if STM32_SERIAL_USE_UART4 || defined(__DOXYGEN__) +#if !defined(STM32_UART4_HANDLER) +#error "STM32_UART4_HANDLER not defined" +#endif +/** + * @brief UART4 interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(STM32_UART4_HANDLER) { + + OSAL_IRQ_PROLOGUE(); + + serve_interrupt(&SD4); + + OSAL_IRQ_EPILOGUE(); +} +#endif + +#if STM32_SERIAL_USE_UART5 || defined(__DOXYGEN__) +#if !defined(STM32_UART5_HANDLER) +#error "STM32_UART5_HANDLER not defined" +#endif +/** + * @brief UART5 interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(STM32_UART5_HANDLER) { + + OSAL_IRQ_PROLOGUE(); + + serve_interrupt(&SD5); + + OSAL_IRQ_EPILOGUE(); +} +#endif + +#if STM32_SERIAL_USE_USART6 || defined(__DOXYGEN__) +#if !defined(STM32_USART6_HANDLER) +#error "STM32_USART6_HANDLER not defined" +#endif +/** + * @brief USART1 interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(STM32_USART6_HANDLER) { + + OSAL_IRQ_PROLOGUE(); + + serve_interrupt(&SD6); + + OSAL_IRQ_EPILOGUE(); +} +#endif + +/*===========================================================================*/ +/* Driver exported functions. */ +/*===========================================================================*/ + +/** + * @brief Low level serial driver initialization. + * + * @notapi + */ +void sd_lld_init(void) { + +#if STM32_SERIAL_USE_USART1 + sdObjectInit(&SD1, NULL, notify1); + SD1.usart = USART1; +#endif + +#if STM32_SERIAL_USE_USART2 + sdObjectInit(&SD2, NULL, notify2); + SD2.usart = USART2; +#endif + +#if STM32_SERIAL_USE_USART3 + sdObjectInit(&SD3, NULL, notify3); + SD3.usart = USART3; +#endif + +#if STM32_SERIAL_USE_UART4 + sdObjectInit(&SD4, NULL, notify4); + SD4.usart = UART4; +#endif + +#if STM32_SERIAL_USE_UART5 + sdObjectInit(&SD5, NULL, notify5); + SD5.usart = UART5; +#endif + +#if STM32_SERIAL_USE_USART6 + sdObjectInit(&SD6, NULL, notify6); + SD6.usart = USART6; +#endif +} + +/** + * @brief Low level serial driver configuration and (re)start. + * + * @param[in] sdp pointer to a @p SerialDriver object + * @param[in] config the architecture-dependent serial driver configuration. + * If this parameter is set to @p NULL then a default + * configuration is used. + * + * @notapi + */ +void sd_lld_start(SerialDriver *sdp, const SerialConfig *config) { + + if (config == NULL) + config = &default_config; + + if (sdp->state == SD_STOP) { +#if STM32_SERIAL_USE_USART1 + if (&SD1 == sdp) { + rccEnableUSART1(FALSE); + nvicEnableVector(STM32_USART1_NUMBER, STM32_SERIAL_USART1_PRIORITY); + } +#endif +#if STM32_SERIAL_USE_USART2 + if (&SD2 == sdp) { + rccEnableUSART2(FALSE); + nvicEnableVector(STM32_USART2_NUMBER, STM32_SERIAL_USART2_PRIORITY); + } +#endif +#if STM32_SERIAL_USE_USART3 + if (&SD3 == sdp) { + rccEnableUSART3(FALSE); + nvicEnableVector(STM32_USART3_NUMBER, STM32_SERIAL_USART3_PRIORITY); + } +#endif +#if STM32_SERIAL_USE_UART4 + if (&SD4 == sdp) { + rccEnableUART4(FALSE); + nvicEnableVector(STM32_UART4_NUMBER, STM32_SERIAL_UART4_PRIORITY); + } +#endif +#if STM32_SERIAL_USE_UART5 + if (&SD5 == sdp) { + rccEnableUART5(FALSE); + nvicEnableVector(STM32_UART5_NUMBER, STM32_SERIAL_UART5_PRIORITY); + } +#endif +#if STM32_SERIAL_USE_USART6 + if (&SD6 == sdp) { + rccEnableUSART6(FALSE); + nvicEnableVector(STM32_USART6_NUMBER, STM32_SERIAL_USART6_PRIORITY); + } +#endif + } + usart_init(sdp, config); +} + +/** + * @brief Low level serial driver stop. + * @details De-initializes the USART, stops the associated clock, resets the + * interrupt vector. + * + * @param[in] sdp pointer to a @p SerialDriver object + * + * @notapi + */ +void sd_lld_stop(SerialDriver *sdp) { + + if (sdp->state == SD_READY) { + usart_deinit(sdp->usart); +#if STM32_SERIAL_USE_USART1 + if (&SD1 == sdp) { + rccDisableUSART1(FALSE); + nvicDisableVector(STM32_USART1_NUMBER); + return; + } +#endif +#if STM32_SERIAL_USE_USART2 + if (&SD2 == sdp) { + rccDisableUSART2(FALSE); + nvicDisableVector(STM32_USART2_NUMBER); + return; + } +#endif +#if STM32_SERIAL_USE_USART3 + if (&SD3 == sdp) { + rccDisableUSART3(FALSE); + nvicDisableVector(STM32_USART3_NUMBER); + return; + } +#endif +#if STM32_SERIAL_USE_UART4 + if (&SD4 == sdp) { + rccDisableUART4(FALSE); + nvicDisableVector(STM32_UART4_NUMBER); + return; + } +#endif +#if STM32_SERIAL_USE_UART5 + if (&SD5 == sdp) { + rccDisableUART5(FALSE); + nvicDisableVector(STM32_UART5_NUMBER); + return; + } +#endif +#if STM32_SERIAL_USE_USART6 + if (&SD6 == sdp) { + rccDisableUSART6(FALSE); + nvicDisableVector(STM32_USART6_NUMBER); + return; + } +#endif + } +} + +#endif /* HAL_USE_SERIAL */ + +/** @} */ diff --git a/os/hal/ports/STM32/USARTv1/serial_lld.h b/os/hal/ports/STM32/USARTv1/serial_lld.h new file mode 100644 index 000000000..bdf8e9bdb --- /dev/null +++ b/os/hal/ports/STM32/USARTv1/serial_lld.h @@ -0,0 +1,303 @@ +/* + ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file STM32/USARTv1/serial_lld.h + * @brief STM32 low level serial driver header. + * + * @addtogroup SERIAL + * @{ + */ + +#ifndef _SERIAL_LLD_H_ +#define _SERIAL_LLD_H_ + +#if HAL_USE_SERIAL || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver constants. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver pre-compile time settings. */ +/*===========================================================================*/ + +/** + * @name Configuration options + * @{ + */ +/** + * @brief USART1 driver enable switch. + * @details If set to @p TRUE the support for USART1 is included. + * @note The default is @p TRUE. + */ +#if !defined(STM32_SERIAL_USE_USART1) || defined(__DOXYGEN__) +#define STM32_SERIAL_USE_USART1 FALSE +#endif + +/** + * @brief USART2 driver enable switch. + * @details If set to @p TRUE the support for USART2 is included. + * @note The default is @p TRUE. + */ +#if !defined(STM32_SERIAL_USE_USART2) || defined(__DOXYGEN__) +#define STM32_SERIAL_USE_USART2 FALSE +#endif + +/** + * @brief USART3 driver enable switch. + * @details If set to @p TRUE the support for USART3 is included. + * @note The default is @p TRUE. + */ +#if !defined(STM32_SERIAL_USE_USART3) || defined(__DOXYGEN__) +#define STM32_SERIAL_USE_USART3 FALSE +#endif + +/** + * @brief UART4 driver enable switch. + * @details If set to @p TRUE the support for UART4 is included. + * @note The default is @p TRUE. + */ +#if !defined(STM32_SERIAL_USE_UART4) || defined(__DOXYGEN__) +#define STM32_SERIAL_USE_UART4 FALSE +#endif + +/** + * @brief UART5 driver enable switch. + * @details If set to @p TRUE the support for UART5 is included. + * @note The default is @p TRUE. + */ +#if !defined(STM32_SERIAL_USE_UART5) || defined(__DOXYGEN__) +#define STM32_SERIAL_USE_UART5 FALSE +#endif + +/** + * @brief USART6 driver enable switch. + * @details If set to @p TRUE the support for USART6 is included. + * @note The default is @p TRUE. + */ +#if !defined(STM32_SERIAL_USE_USART6) || defined(__DOXYGEN__) +#define STM32_SERIAL_USE_USART6 FALSE +#endif + +/** + * @brief USART1 interrupt priority level setting. + */ +#if !defined(STM32_SERIAL_USART1_PRIORITY) || defined(__DOXYGEN__) +#define STM32_SERIAL_USART1_PRIORITY 12 +#endif + +/** + * @brief USART2 interrupt priority level setting. + */ +#if !defined(STM32_SERIAL_USART2_PRIORITY) || defined(__DOXYGEN__) +#define STM32_SERIAL_USART2_PRIORITY 12 +#endif + +/** + * @brief USART3 interrupt priority level setting. + */ +#if !defined(STM32_SERIAL_USART3_PRIORITY) || defined(__DOXYGEN__) +#define STM32_SERIAL_USART3_PRIORITY 12 +#endif + +/** + * @brief UART4 interrupt priority level setting. + */ +#if !defined(STM32_SERIAL_UART4_PRIORITY) || defined(__DOXYGEN__) +#define STM32_SERIAL_UART4_PRIORITY 12 +#endif + +/** + * @brief UART5 interrupt priority level setting. + */ +#if !defined(STM32_SERIAL_UART5_PRIORITY) || defined(__DOXYGEN__) +#define STM32_SERIAL_UART5_PRIORITY 12 +#endif + +/** + * @brief USART6 interrupt priority level setting. + */ +#if !defined(STM32_SERIAL_USART6_PRIORITY) || defined(__DOXYGEN__) +#define STM32_SERIAL_USART6_PRIORITY 12 +#endif +/** @} */ + +/*===========================================================================*/ +/* Derived constants and error checks. */ +/*===========================================================================*/ + +#if STM32_SERIAL_USE_USART1 && !STM32_HAS_USART1 +#error "USART1 not present in the selected device" +#endif + +#if STM32_SERIAL_USE_USART2 && !STM32_HAS_USART2 +#error "USART2 not present in the selected device" +#endif + +#if STM32_SERIAL_USE_USART3 && !STM32_HAS_USART3 +#error "USART3 not present in the selected device" +#endif + +#if STM32_SERIAL_USE_UART4 && !STM32_HAS_UART4 +#error "UART4 not present in the selected device" +#endif + +#if STM32_SERIAL_USE_UART5 && !STM32_HAS_UART5 +#error "UART5 not present in the selected device" +#endif + +#if STM32_SERIAL_USE_USART6 && !STM32_HAS_USART6 +#error "USART6 not present in the selected device" +#endif + +#if !STM32_SERIAL_USE_USART1 && !STM32_SERIAL_USE_USART2 && \ + !STM32_SERIAL_USE_USART3 && !STM32_SERIAL_USE_UART4 && \ + !STM32_SERIAL_USE_UART5 && !STM32_SERIAL_USE_USART6 +#error "SERIAL driver activated but no USART/UART peripheral assigned" +#endif + +#if STM32_SERIAL_USE_USART1 && \ + !CORTEX_IS_VALID_KERNEL_PRIORITY(STM32_SERIAL_USART1_PRIORITY) +#error "Invalid IRQ priority assigned to USART1" +#endif + +#if STM32_SERIAL_USE_USART2 && \ + !CORTEX_IS_VALID_KERNEL_PRIORITY(STM32_SERIAL_USART2_PRIORITY) +#error "Invalid IRQ priority assigned to USART2" +#endif + +#if STM32_SERIAL_USE_USART3 && \ + !CORTEX_IS_VALID_KERNEL_PRIORITY(STM32_SERIAL_USART3_PRIORITY) +#error "Invalid IRQ priority assigned to USART3" +#endif + +#if STM32_SERIAL_USE_UART4 && \ + !CORTEX_IS_VALID_KERNEL_PRIORITY(STM32_SERIAL_UART4_PRIORITY) +#error "Invalid IRQ priority assigned to UART4" +#endif + +#if STM32_SERIAL_USE_UART5 && \ + !CORTEX_IS_VALID_KERNEL_PRIORITY(STM32_SERIAL_UART5_PRIORITY) +#error "Invalid IRQ priority assigned to UART5" +#endif + +#if STM32_SERIAL_USE_USART6 && \ + !CORTEX_IS_VALID_KERNEL_PRIORITY(STM32_SERIAL_USART6_PRIORITY) +#error "Invalid IRQ priority assigned to USART6" +#endif + +/*===========================================================================*/ +/* Driver data structures and types. */ +/*===========================================================================*/ + +/** + * @brief STM32 Serial Driver configuration structure. + * @details An instance of this structure must be passed to @p sdStart() + * in order to configure and start a serial driver operations. + * @note This structure content is architecture dependent, each driver + * implementation defines its own version and the custom static + * initializers. + */ +typedef struct { + /** + * @brief Bit rate. + */ + uint32_t speed; + /* End of the mandatory fields.*/ + /** + * @brief Initialization value for the CR1 register. + */ + uint16_t cr1; + /** + * @brief Initialization value for the CR2 register. + */ + uint16_t cr2; + /** + * @brief Initialization value for the CR3 register. + */ + uint16_t cr3; +} SerialConfig; + +/** + * @brief @p SerialDriver specific data. + */ +#define _serial_driver_data \ + _base_asynchronous_channel_data \ + /* Driver state.*/ \ + sdstate_t state; \ + /* Input queue.*/ \ + input_queue_t iqueue; \ + /* Output queue.*/ \ + output_queue_t oqueue; \ + /* Input circular buffer.*/ \ + uint8_t ib[SERIAL_BUFFERS_SIZE]; \ + /* Output circular buffer.*/ \ + uint8_t ob[SERIAL_BUFFERS_SIZE]; \ + /* End of the mandatory fields.*/ \ + /* Pointer to the USART registers block.*/ \ + USART_TypeDef *usart; + +/*===========================================================================*/ +/* Driver macros. */ +/*===========================================================================*/ + +/* + * Extra USARTs definitions here (missing from the ST header file). + */ +#define USART_CR2_STOP1_BITS (0 << 12) /**< @brief CR2 1 stop bit value.*/ +#define USART_CR2_STOP0P5_BITS (1 << 12) /**< @brief CR2 0.5 stop bit value.*/ +#define USART_CR2_STOP2_BITS (2 << 12) /**< @brief CR2 2 stop bit value.*/ +#define USART_CR2_STOP1P5_BITS (3 << 12) /**< @brief CR2 1.5 stop bit value.*/ + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +#if STM32_SERIAL_USE_USART1 && !defined(__DOXYGEN__) +extern SerialDriver SD1; +#endif +#if STM32_SERIAL_USE_USART2 && !defined(__DOXYGEN__) +extern SerialDriver SD2; +#endif +#if STM32_SERIAL_USE_USART3 && !defined(__DOXYGEN__) +extern SerialDriver SD3; +#endif +#if STM32_SERIAL_USE_UART4 && !defined(__DOXYGEN__) +extern SerialDriver SD4; +#endif +#if STM32_SERIAL_USE_UART5 && !defined(__DOXYGEN__) +extern SerialDriver SD5; +#endif +#if STM32_SERIAL_USE_USART6 && !defined(__DOXYGEN__) +extern SerialDriver SD6; +#endif + +#ifdef __cplusplus +extern "C" { +#endif + void sd_lld_init(void); + void sd_lld_start(SerialDriver *sdp, const SerialConfig *config); + void sd_lld_stop(SerialDriver *sdp); +#ifdef __cplusplus +} +#endif + +#endif /* HAL_USE_SERIAL */ + +#endif /* _SERIAL_LLD_H_ */ + +/** @} */ diff --git a/os/hal/ports/STM32/USARTv1/uart_lld.c b/os/hal/ports/STM32/USARTv1/uart_lld.c new file mode 100644 index 000000000..d77d9bd98 --- /dev/null +++ b/os/hal/ports/STM32/USARTv1/uart_lld.c @@ -0,0 +1,794 @@ +/* + ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file STM32/USARTv1/uart_lld.c + * @brief STM32 low level UART driver code. + * + * @addtogroup UART + * @{ + */ + +#include "ch.h" +#include "hal.h" + +#if HAL_USE_UART || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver local definitions. */ +/*===========================================================================*/ + +#define USART1_RX_DMA_CHANNEL \ + STM32_DMA_GETCHANNEL(STM32_UART_USART1_RX_DMA_STREAM, \ + STM32_USART1_RX_DMA_CHN) + +#define USART1_TX_DMA_CHANNEL \ + STM32_DMA_GETCHANNEL(STM32_UART_USART1_TX_DMA_STREAM, \ + STM32_USART1_TX_DMA_CHN) + +#define USART2_RX_DMA_CHANNEL \ + STM32_DMA_GETCHANNEL(STM32_UART_USART2_RX_DMA_STREAM, \ + STM32_USART2_RX_DMA_CHN) + +#define USART2_TX_DMA_CHANNEL \ + STM32_DMA_GETCHANNEL(STM32_UART_USART2_TX_DMA_STREAM, \ + STM32_USART2_TX_DMA_CHN) + +#define USART3_RX_DMA_CHANNEL \ + STM32_DMA_GETCHANNEL(STM32_UART_USART3_RX_DMA_STREAM, \ + STM32_USART3_RX_DMA_CHN) + +#define USART3_TX_DMA_CHANNEL \ + STM32_DMA_GETCHANNEL(STM32_UART_USART3_TX_DMA_STREAM, \ + STM32_USART3_TX_DMA_CHN) + +#define UART4_RX_DMA_CHANNEL \ + STM32_DMA_GETCHANNEL(STM32_UART_UART4_RX_DMA_STREAM, \ + STM32_UART4_RX_DMA_CHN) + +#define UART4_TX_DMA_CHANNEL \ + STM32_DMA_GETCHANNEL(STM32_UART_UART4_TX_DMA_STREAM, \ + STM32_UART4_TX_DMA_CHN) + +#define UART5_RX_DMA_CHANNEL \ + STM32_DMA_GETCHANNEL(STM32_UART_UART5_RX_DMA_STREAM, \ + STM32_UART5_RX_DMA_CHN) + +#define UART5_TX_DMA_CHANNEL \ + STM32_DMA_GETCHANNEL(STM32_UART_UART5_TX_DMA_STREAM, \ + STM32_UART5_TX_DMA_CHN) + +#define USART6_RX_DMA_CHANNEL \ + STM32_DMA_GETCHANNEL(STM32_UART_USART6_RX_DMA_STREAM, \ + STM32_USART6_RX_DMA_CHN) + +#define USART6_TX_DMA_CHANNEL \ + STM32_DMA_GETCHANNEL(STM32_UART_USART6_TX_DMA_STREAM, \ + STM32_USART6_TX_DMA_CHN) + +/*===========================================================================*/ +/* Driver exported variables. */ +/*===========================================================================*/ + +/** @brief USART1 UART driver identifier.*/ +#if STM32_UART_USE_USART1 || defined(__DOXYGEN__) +UARTDriver UARTD1; +#endif + +/** @brief USART2 UART driver identifier.*/ +#if STM32_UART_USE_USART2 || defined(__DOXYGEN__) +UARTDriver UARTD2; +#endif + +/** @brief USART3 UART driver identifier.*/ +#if STM32_UART_USE_USART3 || defined(__DOXYGEN__) +UARTDriver UARTD3; +#endif + +/** @brief UART4 UART driver identifier.*/ +#if STM32_UART_USE_UART4 || defined(__DOXYGEN__) +UARTDriver UARTD4; +#endif + +/** @brief UART5 UART driver identifier.*/ +#if STM32_UART_USE_UART5 || defined(__DOXYGEN__) +UARTDriver UARTD5; +#endif + +/** @brief USART6 UART driver identifier.*/ +#if STM32_UART_USE_USART6 || defined(__DOXYGEN__) +UARTDriver UARTD6; +#endif + +/*===========================================================================*/ +/* Driver local variables and types. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local functions. */ +/*===========================================================================*/ + +/** + * @brief Status bits translation. + * + * @param[in] sr USART SR register value + * + * @return The error flags. + */ +static uartflags_t translate_errors(uint16_t sr) { + uartflags_t sts = 0; + + if (sr & USART_SR_ORE) + sts |= UART_OVERRUN_ERROR; + if (sr & USART_SR_PE) + sts |= UART_PARITY_ERROR; + if (sr & USART_SR_FE) + sts |= UART_FRAMING_ERROR; + if (sr & USART_SR_NE) + sts |= UART_NOISE_ERROR; + if (sr & USART_SR_LBD) + sts |= UART_BREAK_DETECTED; + return sts; +} + +/** + * @brief Puts the receiver in the UART_RX_IDLE state. + * + * @param[in] uartp pointer to the @p UARTDriver object + */ +static void set_rx_idle_loop(UARTDriver *uartp) { + uint32_t mode; + + /* RX DMA channel preparation, if the char callback is defined then the + TCIE interrupt is enabled too.*/ + if (uartp->config->rxchar_cb == NULL) + mode = STM32_DMA_CR_DIR_P2M | STM32_DMA_CR_CIRC; + else + mode = STM32_DMA_CR_DIR_P2M | STM32_DMA_CR_CIRC | STM32_DMA_CR_TCIE; + dmaStreamSetMemory0(uartp->dmarx, &uartp->rxbuf); + dmaStreamSetTransactionSize(uartp->dmarx, 1); + dmaStreamSetMode(uartp->dmarx, uartp->dmamode | mode); + dmaStreamEnable(uartp->dmarx); +} + +/** + * @brief USART de-initialization. + * @details This function must be invoked with interrupts disabled. + * + * @param[in] uartp pointer to the @p UARTDriver object + */ +static void usart_stop(UARTDriver *uartp) { + + /* Stops RX and TX DMA channels.*/ + dmaStreamDisable(uartp->dmarx); + dmaStreamDisable(uartp->dmatx); + + /* Stops USART operations.*/ + uartp->usart->CR1 = 0; + uartp->usart->CR2 = 0; + uartp->usart->CR3 = 0; +} + +/** + * @brief USART initialization. + * @details This function must be invoked with interrupts disabled. + * + * @param[in] uartp pointer to the @p UARTDriver object + */ +static void usart_start(UARTDriver *uartp) { + uint16_t cr1; + USART_TypeDef *u = uartp->usart; + + /* Defensive programming, starting from a clean state.*/ + usart_stop(uartp); + + /* Baud rate setting.*/ +#if STM32_HAS_USART6 + if ((uartp->usart == USART1) || (uartp->usart == USART6)) +#else + if (uartp->usart == USART1) +#endif + u->BRR = STM32_PCLK2 / uartp->config->speed; + else + u->BRR = STM32_PCLK1 / uartp->config->speed; + + /* Resetting eventual pending status flags.*/ + (void)u->SR; /* SR reset step 1.*/ + (void)u->DR; /* SR reset step 2.*/ + u->SR = 0; + + /* Note that some bits are enforced because required for correct driver + operations.*/ + u->CR2 = uartp->config->cr2 | USART_CR2_LBDIE; + u->CR3 = uartp->config->cr3 | USART_CR3_DMAT | USART_CR3_DMAR | + USART_CR3_EIE; + if (uartp->config->txend2_cb == NULL) + cr1 = USART_CR1_UE | USART_CR1_PEIE | USART_CR1_TE | USART_CR1_RE; + else + cr1 = USART_CR1_UE | USART_CR1_PEIE | USART_CR1_TE | USART_CR1_RE | + USART_CR1_TCIE; + u->CR1 = uartp->config->cr1 | cr1; + + /* Starting the receiver idle loop.*/ + set_rx_idle_loop(uartp); +} + +/** + * @brief RX DMA common service routine. + * + * @param[in] uartp pointer to the @p UARTDriver object + * @param[in] flags pre-shifted content of the ISR register + */ +static void uart_lld_serve_rx_end_irq(UARTDriver *uartp, uint32_t flags) { + + /* DMA errors handling.*/ +#if defined(STM32_UART_DMA_ERROR_HOOK) + if ((flags & (STM32_DMA_ISR_TEIF | STM32_DMA_ISR_DMEIF)) != 0) { + STM32_UART_DMA_ERROR_HOOK(uartp); + } +#else + (void)flags; +#endif + + if (uartp->rxstate == UART_RX_IDLE) { + /* Receiver in idle state, a callback is generated, if enabled, for each + received character and then the driver stays in the same state.*/ + if (uartp->config->rxchar_cb != NULL) + uartp->config->rxchar_cb(uartp, uartp->rxbuf); + } + else { + /* Receiver in active state, a callback is generated, if enabled, after + a completed transfer.*/ + dmaStreamDisable(uartp->dmarx); + uartp->rxstate = UART_RX_COMPLETE; + if (uartp->config->rxend_cb != NULL) + uartp->config->rxend_cb(uartp); + + /* If the callback didn't explicitly change state then the receiver + automatically returns to the idle state.*/ + if (uartp->rxstate == UART_RX_COMPLETE) { + uartp->rxstate = UART_RX_IDLE; + set_rx_idle_loop(uartp); + } + } +} + +/** + * @brief TX DMA common service routine. + * + * @param[in] uartp pointer to the @p UARTDriver object + * @param[in] flags pre-shifted content of the ISR register + */ +static void uart_lld_serve_tx_end_irq(UARTDriver *uartp, uint32_t flags) { + + /* DMA errors handling.*/ +#if defined(STM32_UART_DMA_ERROR_HOOK) + if ((flags & (STM32_DMA_ISR_TEIF | STM32_DMA_ISR_DMEIF)) != 0) { + STM32_UART_DMA_ERROR_HOOK(uartp); + } +#else + (void)flags; +#endif + + dmaStreamDisable(uartp->dmatx); + + /* A callback is generated, if enabled, after a completed transfer.*/ + uartp->txstate = UART_TX_COMPLETE; + if (uartp->config->txend1_cb != NULL) + uartp->config->txend1_cb(uartp); + + /* If the callback didn't explicitly change state then the transmitter + automatically returns to the idle state.*/ + if (uartp->txstate == UART_TX_COMPLETE) + uartp->txstate = UART_TX_IDLE; +} + +/** + * @brief USART common service routine. + * + * @param[in] uartp pointer to the @p UARTDriver object + */ +static void serve_usart_irq(UARTDriver *uartp) { + uint16_t sr; + USART_TypeDef *u = uartp->usart; + + sr = u->SR; /* SR reset step 1.*/ + (void)u->DR; /* SR reset step 2.*/ + if (sr & (USART_SR_LBD | USART_SR_ORE | USART_SR_NE | + USART_SR_FE | USART_SR_PE)) { + u->SR = ~USART_SR_LBD; + if (uartp->config->rxerr_cb != NULL) + uartp->config->rxerr_cb(uartp, translate_errors(sr)); + } + if (sr & USART_SR_TC) { + u->SR = ~USART_SR_TC; + + /* End of transmission, a callback is generated.*/ + if (uartp->config->txend2_cb != NULL) + uartp->config->txend2_cb(uartp); + } +} + +/*===========================================================================*/ +/* Driver interrupt handlers. */ +/*===========================================================================*/ + +#if STM32_UART_USE_USART1 || defined(__DOXYGEN__) +#if !defined(STM32_USART1_HANDLER) +#error "STM32_USART1_HANDLER not defined" +#endif +/** + * @brief USART1 IRQ handler. + * + * @isr + */ +CH_IRQ_HANDLER(STM32_USART1_HANDLER) { + + CH_IRQ_PROLOGUE(); + + serve_usart_irq(&UARTD1); + + CH_IRQ_EPILOGUE(); +} +#endif /* STM32_UART_USE_USART1 */ + +#if STM32_UART_USE_USART2 || defined(__DOXYGEN__) +#if !defined(STM32_USART2_HANDLER) +#error "STM32_USART2_HANDLER not defined" +#endif +/** + * @brief USART2 IRQ handler. + * + * @isr + */ +CH_IRQ_HANDLER(STM32_USART2_HANDLER) { + + CH_IRQ_PROLOGUE(); + + serve_usart_irq(&UARTD2); + + CH_IRQ_EPILOGUE(); +} +#endif /* STM32_UART_USE_USART2 */ + +#if STM32_UART_USE_USART3 || defined(__DOXYGEN__) +#if !defined(STM32_USART3_HANDLER) +#error "STM32_USART3_HANDLER not defined" +#endif +/** + * @brief USART3 IRQ handler. + * + * @isr + */ +CH_IRQ_HANDLER(STM32_USART3_HANDLER) { + + CH_IRQ_PROLOGUE(); + + serve_usart_irq(&UARTD3); + + CH_IRQ_EPILOGUE(); +} +#endif /* STM32_UART_USE_USART3 */ + +#if STM32_UART_USE_UART4 || defined(__DOXYGEN__) +#if !defined(STM32_UART4_HANDLER) +#error "STM32_UART4_HANDLER not defined" +#endif +/** + * @brief UART4 IRQ handler. + * + * @isr + */ +CH_IRQ_HANDLER(STM32_UART4_HANDLER) { + + CH_IRQ_PROLOGUE(); + + serve_usart_irq(&UARTD4); + + CH_IRQ_EPILOGUE(); +} +#endif /* STM32_UART_USE_UART4 */ + +#if STM32_UART_USE_UART5 || defined(__DOXYGEN__) +#if !defined(STM32_UART5_HANDLER) +#error "STM32_UART5_HANDLER not defined" +#endif +/** + * @brief UART5 IRQ handler. + * + * @isr + */ +CH_IRQ_HANDLER(STM32_UART5_HANDLER) { + + CH_IRQ_PROLOGUE(); + + serve_usart_irq(&UARTD5); + + CH_IRQ_EPILOGUE(); +} +#endif /* STM32_UART_USE_UART5 */ + +#if STM32_UART_USE_USART6 || defined(__DOXYGEN__) +#if !defined(STM32_USART6_HANDLER) +#error "STM32_USART6_HANDLER not defined" +#endif +/** + * @brief USART6 IRQ handler. + * + * @isr + */ +CH_IRQ_HANDLER(STM32_USART6_HANDLER) { + + CH_IRQ_PROLOGUE(); + + serve_usart_irq(&UARTD6); + + CH_IRQ_EPILOGUE(); +} +#endif /* STM32_UART_USE_USART6 */ + +/*===========================================================================*/ +/* Driver exported functions. */ +/*===========================================================================*/ + +/** + * @brief Low level UART driver initialization. + * + * @notapi + */ +void uart_lld_init(void) { + +#if STM32_UART_USE_USART1 + uartObjectInit(&UARTD1); + UARTD1.usart = USART1; + UARTD1.dmamode = STM32_DMA_CR_DMEIE | STM32_DMA_CR_TEIE; + UARTD1.dmarx = STM32_DMA_STREAM(STM32_UART_USART1_RX_DMA_STREAM); + UARTD1.dmatx = STM32_DMA_STREAM(STM32_UART_USART1_TX_DMA_STREAM); +#endif + +#if STM32_UART_USE_USART2 + uartObjectInit(&UARTD2); + UARTD2.usart = USART2; + UARTD2.dmamode = STM32_DMA_CR_DMEIE | STM32_DMA_CR_TEIE; + UARTD2.dmarx = STM32_DMA_STREAM(STM32_UART_USART2_RX_DMA_STREAM); + UARTD2.dmatx = STM32_DMA_STREAM(STM32_UART_USART2_TX_DMA_STREAM); +#endif + +#if STM32_UART_USE_USART3 + uartObjectInit(&UARTD3); + UARTD3.usart = USART3; + UARTD3.dmamode = STM32_DMA_CR_DMEIE | STM32_DMA_CR_TEIE; + UARTD3.dmarx = STM32_DMA_STREAM(STM32_UART_USART3_RX_DMA_STREAM); + UARTD3.dmatx = STM32_DMA_STREAM(STM32_UART_USART3_TX_DMA_STREAM); +#endif + +#if STM32_UART_USE_UART4 + uartObjectInit(&UARTD4); + UARTD4.usart = UART4; + UARTD4.dmamode = STM32_DMA_CR_DMEIE | STM32_DMA_CR_TEIE; + UARTD4.dmarx = STM32_DMA_STREAM(STM32_UART_UART4_RX_DMA_STREAM); + UARTD4.dmatx = STM32_DMA_STREAM(STM32_UART_UART4_TX_DMA_STREAM); +#endif + +#if STM32_UART_USE_UART5 + uartObjectInit(&UARTD5); + UARTD5.usart = UART5; + UARTD5.dmamode = STM32_DMA_CR_DMEIE | STM32_DMA_CR_TEIE; + UARTD5.dmarx = STM32_DMA_STREAM(STM32_UART_UART5_RX_DMA_STREAM); + UARTD5.dmatx = STM32_DMA_STREAM(STM32_UART_UART5_TX_DMA_STREAM); +#endif + +#if STM32_UART_USE_USART6 + uartObjectInit(&UARTD6); + UARTD6.usart = USART6; + UARTD6.dmarx = STM32_DMA_STREAM(STM32_UART_USART6_RX_DMA_STREAM); + UARTD6.dmatx = STM32_DMA_STREAM(STM32_UART_USART6_TX_DMA_STREAM); +#endif +} + +/** + * @brief Configures and activates the UART peripheral. + * + * @param[in] uartp pointer to the @p UARTDriver object + * + * @notapi + */ +void uart_lld_start(UARTDriver *uartp) { + + if (uartp->state == UART_STOP) { +#if STM32_UART_USE_USART1 + if (&UARTD1 == uartp) { + bool b; + b = dmaStreamAllocate(uartp->dmarx, + STM32_UART_USART1_IRQ_PRIORITY, + (stm32_dmaisr_t)uart_lld_serve_rx_end_irq, + (void *)uartp); + osalDbgAssert(!b, "stream already allocated"); + b = dmaStreamAllocate(uartp->dmatx, + STM32_UART_USART1_IRQ_PRIORITY, + (stm32_dmaisr_t)uart_lld_serve_tx_end_irq, + (void *)uartp); + osalDbgAssert(!b, "stream already allocated"); + rccEnableUSART1(FALSE); + nvicEnableVector(STM32_USART1_NUMBER, STM32_UART_USART1_IRQ_PRIORITY); + uartp->dmamode |= STM32_DMA_CR_CHSEL(USART1_RX_DMA_CHANNEL) | + STM32_DMA_CR_PL(STM32_UART_USART1_DMA_PRIORITY); + } +#endif + +#if STM32_UART_USE_USART2 + if (&UARTD2 == uartp) { + bool b; + b = dmaStreamAllocate(uartp->dmarx, + STM32_UART_USART2_IRQ_PRIORITY, + (stm32_dmaisr_t)uart_lld_serve_rx_end_irq, + (void *)uartp); + osalDbgAssert(!b, "stream already allocated"); + b = dmaStreamAllocate(uartp->dmatx, + STM32_UART_USART2_IRQ_PRIORITY, + (stm32_dmaisr_t)uart_lld_serve_tx_end_irq, + (void *)uartp); + osalDbgAssert(!b, "stream already allocated"); + rccEnableUSART2(FALSE); + nvicEnableVector(STM32_USART2_NUMBER, STM32_UART_USART2_IRQ_PRIORITY); + uartp->dmamode |= STM32_DMA_CR_CHSEL(USART2_RX_DMA_CHANNEL) | + STM32_DMA_CR_PL(STM32_UART_USART2_DMA_PRIORITY); + } +#endif + +#if STM32_UART_USE_USART3 + if (&UARTD3 == uartp) { + bool b; + b = dmaStreamAllocate(uartp->dmarx, + STM32_UART_USART3_IRQ_PRIORITY, + (stm32_dmaisr_t)uart_lld_serve_rx_end_irq, + (void *)uartp); + osalDbgAssert(!b, "stream already allocated"); + b = dmaStreamAllocate(uartp->dmatx, + STM32_UART_USART3_IRQ_PRIORITY, + (stm32_dmaisr_t)uart_lld_serve_tx_end_irq, + (void *)uartp); + osalDbgAssert(!b, "stream already allocated"); + rccEnableUSART3(FALSE); + nvicEnableVector(STM32_USART3_NUMBER, STM32_UART_USART3_IRQ_PRIORITY); + uartp->dmamode |= STM32_DMA_CR_CHSEL(USART3_RX_DMA_CHANNEL) | + STM32_DMA_CR_PL(STM32_UART_USART3_DMA_PRIORITY); + } +#endif + +#if STM32_UART_USE_UART4 + if (&UARTD4 == uartp) { + bool b; + b = dmaStreamAllocate(uartp->dmarx, + STM32_UART_UART4_IRQ_PRIORITY, + (stm32_dmaisr_t)uart_lld_serve_rx_end_irq, + (void *)uartp); + osalDbgAssert(!b, "stream already allocated"); + b = dmaStreamAllocate(uartp->dmatx, + STM32_UART_UART4_IRQ_PRIORITY, + (stm32_dmaisr_t)uart_lld_serve_tx_end_irq, + (void *)uartp); + osalDbgAssert(!b, "stream already allocated"); + rccEnableUART4(FALSE); + nvicEnableVector(STM32_UART4_NUMBER, STM32_UART_UART4_IRQ_PRIORITY); + uartp->dmamode |= STM32_DMA_CR_CHSEL(UART4_RX_DMA_CHANNEL) | + STM32_DMA_CR_PL(STM32_UART_UART4_DMA_PRIORITY); + } +#endif + +#if STM32_UART_USE_UART5 + if (&UARTD5 == uartp) { + bool b; + b = dmaStreamAllocate(uartp->dmarx, + STM32_UART_UART5_IRQ_PRIORITY, + (stm32_dmaisr_t)uart_lld_serve_rx_end_irq, + (void *)uartp); + osalDbgAssert(!b, "stream already allocated"); + b = dmaStreamAllocate(uartp->dmatx, + STM32_UART_UART5_IRQ_PRIORITY, + (stm32_dmaisr_t)uart_lld_serve_tx_end_irq, + (void *)uartp); + osalDbgAssert(!b, "stream already allocated"); + rccEnableUART5(FALSE); + nvicEnableVector(STM32_UART5_NUMBER, STM32_UART_UART5_IRQ_PRIORITY); + uartp->dmamode |= STM32_DMA_CR_CHSEL(UART5_RX_DMA_CHANNEL) | + STM32_DMA_CR_PL(STM32_UART_UART5_DMA_PRIORITY); + } +#endif + +#if STM32_UART_USE_USART6 + if (&UARTD6 == uartp) { + bool b; + b = dmaStreamAllocate(uartp->dmarx, + STM32_UART_USART6_IRQ_PRIORITY, + (stm32_dmaisr_t)uart_lld_serve_rx_end_irq, + (void *)uartp); + osalDbgAssert(!b, "stream already allocated"); + b = dmaStreamAllocate(uartp->dmatx, + STM32_UART_USART6_IRQ_PRIORITY, + (stm32_dmaisr_t)uart_lld_serve_tx_end_irq, + (void *)uartp); + osalDbgAssert(!b, "stream already allocated"); + rccEnableUSART6(FALSE); + nvicEnableVector(STM32_USART6_NUMBER, STM32_UART_USART6_IRQ_PRIORITY); + uartp->dmamode |= STM32_DMA_CR_CHSEL(USART6_RX_DMA_CHANNEL) | + STM32_DMA_CR_PL(STM32_UART_USART6_DMA_PRIORITY); + } +#endif + + /* Static DMA setup, the transfer size depends on the USART settings, + it is 16 bits if M=1 and PCE=0 else it is 8 bits.*/ + if ((uartp->config->cr1 & (USART_CR1_M | USART_CR1_PCE)) == USART_CR1_M) + uartp->dmamode |= STM32_DMA_CR_PSIZE_HWORD | STM32_DMA_CR_MSIZE_HWORD; + dmaStreamSetPeripheral(uartp->dmarx, &uartp->usart->DR); + dmaStreamSetPeripheral(uartp->dmatx, &uartp->usart->DR); + uartp->rxbuf = 0; + } + + uartp->rxstate = UART_RX_IDLE; + uartp->txstate = UART_TX_IDLE; + usart_start(uartp); +} + +/** + * @brief Deactivates the UART peripheral. + * + * @param[in] uartp pointer to the @p UARTDriver object + * + * @notapi + */ +void uart_lld_stop(UARTDriver *uartp) { + + if (uartp->state == UART_READY) { + usart_stop(uartp); + dmaStreamRelease(uartp->dmarx); + dmaStreamRelease(uartp->dmatx); + +#if STM32_UART_USE_USART1 + if (&UARTD1 == uartp) { + nvicDisableVector(STM32_USART1_NUMBER); + rccDisableUSART1(FALSE); + return; + } +#endif + +#if STM32_UART_USE_USART2 + if (&UARTD2 == uartp) { + nvicDisableVector(STM32_USART2_NUMBER); + rccDisableUSART2(FALSE); + return; + } +#endif + +#if STM32_UART_USE_USART3 + if (&UARTD3 == uartp) { + nvicDisableVector(STM32_USART3_NUMBER); + rccDisableUSART3(FALSE); + return; + } +#endif + +#if STM32_UART_USE_UART4 + if (&UARTD4 == uartp) { + nvicDisableVector(STM32_UART4_NUMBER); + rccDisableUART4(FALSE); + return; + } +#endif + +#if STM32_UART_USE_UART5 + if (&UARTD5 == uartp) { + nvicDisableVector(STM32_UART5_NUMBER); + rccDisableUART5(FALSE); + return; + } +#endif + +#if STM32_UART_USE_USART6 + if (&UARTD6 == uartp) { + nvicDisableVector(STM32_USART6_NUMBER); + rccDisableUSART6(FALSE); + return; + } +#endif + } +} + +/** + * @brief Starts a transmission on the UART peripheral. + * @note The buffers are organized as uint8_t arrays for data sizes below + * or equal to 8 bits else it is organized as uint16_t arrays. + * + * @param[in] uartp pointer to the @p UARTDriver object + * @param[in] n number of data frames to send + * @param[in] txbuf the pointer to the transmit buffer + * + * @notapi + */ +void uart_lld_start_send(UARTDriver *uartp, size_t n, const void *txbuf) { + + /* TX DMA channel preparation and start.*/ + dmaStreamSetMemory0(uartp->dmatx, txbuf); + dmaStreamSetTransactionSize(uartp->dmatx, n); + dmaStreamSetMode(uartp->dmatx, uartp->dmamode | STM32_DMA_CR_DIR_M2P | + STM32_DMA_CR_MINC | STM32_DMA_CR_TCIE); + dmaStreamEnable(uartp->dmatx); +} + +/** + * @brief Stops any ongoing transmission. + * @note Stopping a transmission also suppresses the transmission callbacks. + * + * @param[in] uartp pointer to the @p UARTDriver object + * + * @return The number of data frames not transmitted by the + * stopped transmit operation. + * + * @notapi + */ +size_t uart_lld_stop_send(UARTDriver *uartp) { + + dmaStreamDisable(uartp->dmatx); + return dmaStreamGetTransactionSize(uartp->dmatx); +} + +/** + * @brief Starts a receive operation on the UART peripheral. + * @note The buffers are organized as uint8_t arrays for data sizes below + * or equal to 8 bits else it is organized as uint16_t arrays. + * + * @param[in] uartp pointer to the @p UARTDriver object + * @param[in] n number of data frames to send + * @param[out] rxbuf the pointer to the receive buffer + * + * @notapi + */ +void uart_lld_start_receive(UARTDriver *uartp, size_t n, void *rxbuf) { + + /* Stopping previous activity (idle state).*/ + dmaStreamDisable(uartp->dmarx); + + /* RX DMA channel preparation and start.*/ + dmaStreamSetMemory0(uartp->dmarx, rxbuf); + dmaStreamSetTransactionSize(uartp->dmarx, n); + dmaStreamSetMode(uartp->dmarx, uartp->dmamode | STM32_DMA_CR_DIR_P2M | + STM32_DMA_CR_MINC | STM32_DMA_CR_TCIE); + dmaStreamEnable(uartp->dmarx); +} + +/** + * @brief Stops any ongoing receive operation. + * @note Stopping a receive operation also suppresses the receive callbacks. + * + * @param[in] uartp pointer to the @p UARTDriver object + * + * @return The number of data frames not received by the + * stopped receive operation. + * + * @notapi + */ +size_t uart_lld_stop_receive(UARTDriver *uartp) { + size_t n; + + dmaStreamDisable(uartp->dmarx); + n = dmaStreamGetTransactionSize(uartp->dmarx); + set_rx_idle_loop(uartp); + return n; +} + +#endif /* HAL_USE_UART */ + +/** @} */ diff --git a/os/hal/ports/STM32/USARTv1/uart_lld.h b/os/hal/ports/STM32/USARTv1/uart_lld.h new file mode 100644 index 000000000..6c7df15e0 --- /dev/null +++ b/os/hal/ports/STM32/USARTv1/uart_lld.h @@ -0,0 +1,680 @@ +/* + ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file STM32/USARTv1/uart_lld.h + * @brief STM32 low level UART driver header. + * + * @addtogroup UART + * @{ + */ + +#ifndef _UART_LLD_H_ +#define _UART_LLD_H_ + +#if HAL_USE_UART || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver constants. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver pre-compile time settings. */ +/*===========================================================================*/ + +/** + * @name Configuration options + * @{ + */ +/** + * @brief UART driver on USART1 enable switch. + * @details If set to @p TRUE the support for USART1 is included. + * @note The default is @p FALSE. + */ +#if !defined(STM32_UART_USE_USART1) || defined(__DOXYGEN__) +#define STM32_UART_USE_USART1 FALSE +#endif + +/** + * @brief UART driver on USART2 enable switch. + * @details If set to @p TRUE the support for USART2 is included. + * @note The default is @p FALSE. + */ +#if !defined(STM32_UART_USE_USART2) || defined(__DOXYGEN__) +#define STM32_UART_USE_USART2 FALSE +#endif + +/** + * @brief UART driver on USART3 enable switch. + * @details If set to @p TRUE the support for USART3 is included. + * @note The default is @p FALSE. + */ +#if !defined(STM32_UART_USE_USART3) || defined(__DOXYGEN__) +#define STM32_UART_USE_USART3 FALSE +#endif + +/** + * @brief UART driver on UART4 enable switch. + * @details If set to @p TRUE the support for UART4 is included. + * @note The default is @p FALSE. + */ +#if !defined(STM32_UART_USE_UART4) || defined(__DOXYGEN__) +#define STM32_UART_USE_UART4 FALSE +#endif + +/** + * @brief UART driver on UART5 enable switch. + * @details If set to @p TRUE the support for UART5 is included. + * @note The default is @p FALSE. + */ +#if !defined(STM32_UART_USE_UART4) || defined(__DOXYGEN__) +#define STM32_UART_USE_UART5 FALSE +#endif + +/** + * @brief UART driver on USART6 enable switch. + * @details If set to @p TRUE the support for USART6 is included. + * @note The default is @p FALSE. + */ +#if !defined(STM32_UART_USE_USART6) || defined(__DOXYGEN__) +#define STM32_UART_USE_USART6 FALSE +#endif + +/** + * @brief USART1 interrupt priority level setting. + */ +#if !defined(STM32_UART_USART1_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_UART_USART1_IRQ_PRIORITY 12 +#endif + +/** + * @brief USART2 interrupt priority level setting. + */ +#if !defined(STM32_UART_USART2_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_UART_USART2_IRQ_PRIORITY 12 +#endif + +/** + * @brief USART3 interrupt priority level setting. + */ +#if !defined(STM32_UART_USART3_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_UART_USART3_IRQ_PRIORITY 12 +#endif + +/** + * @brief UART4 interrupt priority level setting. + */ +#if !defined(STM32_UART_UART4_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_UART_UART4_IRQ_PRIORITY 12 +#endif + +/** + * @brief UART5 interrupt priority level setting. + */ +#if !defined(STM32_UART_UART5_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_UART_UART5_IRQ_PRIORITY 12 +#endif + +/** + * @brief USART6 interrupt priority level setting. + */ +#if !defined(STM32_UART_USART6_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_UART_USART6_IRQ_PRIORITY 12 +#endif + +/** + * @brief USART1 DMA priority (0..3|lowest..highest). + * @note The priority level is used for both the TX and RX DMA channels but + * because of the channels ordering the RX channel has always priority + * over the TX channel. + */ +#if !defined(STM32_UART_USART1_DMA_PRIORITY) || defined(__DOXYGEN__) +#define STM32_UART_USART1_DMA_PRIORITY 0 +#endif + +/** + * @brief USART2 DMA priority (0..3|lowest..highest). + * @note The priority level is used for both the TX and RX DMA channels but + * because of the channels ordering the RX channel has always priority + * over the TX channel. + */ +#if !defined(STM32_UART_USART2_DMA_PRIORITY) || defined(__DOXYGEN__) +#define STM32_UART_USART2_DMA_PRIORITY 0 +#endif + +/** + * @brief USART3 DMA priority (0..3|lowest..highest). + * @note The priority level is used for both the TX and RX DMA channels but + * because of the channels ordering the RX channel has always priority + * over the TX channel. + */ +#if !defined(STM32_UART_USART3_DMA_PRIORITY) || defined(__DOXYGEN__) +#define STM32_UART_USART3_DMA_PRIORITY 0 +#endif + +/** + * @brief UART4 DMA priority (0..3|lowest..highest). + * @note The priority level is used for both the TX and RX DMA channels but + * because of the channels ordering the RX channel has always priority + * over the TX channel. + */ +#if !defined(STM32_UART_UART4_DMA_PRIORITY) || defined(__DOXYGEN__) +#define STM32_UART_UART4_DMA_PRIORITY 0 +#endif + +/** + * @brief UART5 DMA priority (0..3|lowest..highest). + * @note The priority level is used for both the TX and RX DMA channels but + * because of the channels ordering the RX channel has always priority + * over the TX channel. + */ +#if !defined(STM32_UART_UART5_DMA_PRIORITY) || defined(__DOXYGEN__) +#define STM32_UART_UART5_DMA_PRIORITY 0 +#endif + +/** + * @brief USART6 DMA priority (0..3|lowest..highest). + * @note The priority level is used for both the TX and RX DMA channels but + * because of the channels ordering the RX channel has always priority + * over the TX channel. + */ +#if !defined(STM32_UART_USART6_DMA_PRIORITY) || defined(__DOXYGEN__) +#define STM32_UART_USART6_DMA_PRIORITY 0 +#endif + +/** + * @brief USART DMA error hook. + * @note The default action for DMA errors is a system halt because DMA + * error can only happen because programming errors. + */ +#if !defined(STM32_UART_DMA_ERROR_HOOK) || defined(__DOXYGEN__) +#define STM32_UART_DMA_ERROR_HOOK(uartp) chSysHalt() +#endif + +#if STM32_ADVANCED_DMA || defined(__DOXYGEN__) + +/** + * @brief DMA stream used for USART1 RX operations. + * @note This option is only available on platforms with enhanced DMA. + */ +#if !defined(STM32_UART_USART1_RX_DMA_STREAM) || defined(__DOXYGEN__) +#define STM32_UART_USART1_RX_DMA_STREAM STM32_DMA_STREAM_ID(2, 5) +#endif + +/** + * @brief DMA stream used for USART1 TX operations. + * @note This option is only available on platforms with enhanced DMA. + */ +#if !defined(STM32_UART_USART1_TX_DMA_STREAM) || defined(__DOXYGEN__) +#define STM32_UART_USART1_TX_DMA_STREAM STM32_DMA_STREAM_ID(2, 7) +#endif + +/** + * @brief DMA stream used for USART2 RX operations. + * @note This option is only available on platforms with enhanced DMA. + */ +#if !defined(STM32_UART_USART2_RX_DMA_STREAM) || defined(__DOXYGEN__) +#define STM32_UART_USART2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 5) +#endif + +/** + * @brief DMA stream used for USART2 TX operations. + * @note This option is only available on platforms with enhanced DMA. + */ +#if !defined(STM32_UART_USART2_TX_DMA_STREAM) || defined(__DOXYGEN__) +#define STM32_UART_USART2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 6) +#endif + +/** + * @brief DMA stream used for USART3 RX operations. + * @note This option is only available on platforms with enhanced DMA. + */ +#if !defined(STM32_UART_USART3_RX_DMA_STREAM) || defined(__DOXYGEN__) +#define STM32_UART_USART3_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 1) +#endif + +/** + * @brief DMA stream used for USART3 TX operations. + * @note This option is only available on platforms with enhanced DMA. + */ +#if !defined(STM32_UART_USART3_TX_DMA_STREAM) || defined(__DOXYGEN__) +#define STM32_UART_USART3_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 3) +#endif + +/** + * @brief DMA stream used for UART4 RX operations. + * @note This option is only available on platforms with enhanced DMA. + */ +#if !defined(STM32_UART_UART4_RX_DMA_STREAM) || defined(__DOXYGEN__) +#define STM32_UART_UART4_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2) +#endif + +/** + * @brief DMA stream used for UART4 TX operations. + * @note This option is only available on platforms with enhanced DMA. + */ +#if !defined(STM32_UART_UART4_TX_DMA_STREAM) || defined(__DOXYGEN__) +#define STM32_UART_UART4_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) +#endif + +/** + * @brief DMA stream used for UART5 RX operations. + * @note This option is only available on platforms with enhanced DMA. + */ +#if !defined(STM32_UART_UART5_RX_DMA_STREAM) || defined(__DOXYGEN__) +#define STM32_UART_UART5_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 0) +#endif + +/** + * @brief DMA stream used for UART5 TX operations. + * @note This option is only available on platforms with enhanced DMA. + */ +#if !defined(STM32_UART_UART5_TX_DMA_STREAM) || defined(__DOXYGEN__) +#define STM32_UART_UART5_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7) +#endif + +/** + * @brief DMA stream used for USART6 RX operations. + * @note This option is only available on platforms with enhanced DMA. + */ +#if !defined(STM32_UART_USART6_RX_DMA_STREAM) || defined(__DOXYGEN__) +#define STM32_UART_USART6_RX_DMA_STREAM STM32_DMA_STREAM_ID(2, 2) +#endif + +/** + * @brief DMA stream used for USART6 TX operations. + * @note This option is only available on platforms with enhanced DMA. + */ +#if !defined(STM32_UART_USART6_TX_DMA_STREAM) || defined(__DOXYGEN__) +#define STM32_UART_USART6_TX_DMA_STREAM STM32_DMA_STREAM_ID(2, 7) +#endif + +#else /* !STM32_ADVANCED_DMA */ + +/* Fixed streams for platforms using the old DMA peripheral, the values are + valid for both STM32F1xx and STM32L1xx.*/ +#define STM32_UART_USART1_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 5) +#define STM32_UART_USART1_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) +#define STM32_UART_USART2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 6) +#define STM32_UART_USART2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7) +#define STM32_UART_USART3_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 3) +#define STM32_UART_USART3_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2) +#define STM32_UART_UART4_RX_DMA_STREAM STM32_DMA_STREAM_ID(2, 3) +#define STM32_UART_UART4_TX_DMA_STREAM STM32_DMA_STREAM_ID(2, 5) + +#endif /* !STM32_ADVANCED_DMA*/ +/** @} */ + +/*===========================================================================*/ +/* Derived constants and error checks. */ +/*===========================================================================*/ + +#if STM32_UART_USE_USART1 && !STM32_HAS_USART1 +#error "USART1 not present in the selected device" +#endif + +#if STM32_UART_USE_USART2 && !STM32_HAS_USART2 +#error "USART2 not present in the selected device" +#endif + +#if STM32_UART_USE_USART3 && !STM32_HAS_USART3 +#error "USART3 not present in the selected device" +#endif + +#if STM32_UART_USE_UART4 + #if !STM32_HAS_UART4 + #error "UART4 not present in the selected device" + #endif + + #if !defined(STM32F4XX) || !defined(STM32F4XX) + #error "UART4 DMA access not supported in this platform" + #endif +#endif + +#if STM32_UART_USE_UART5 + #if !STM32_HAS_UART5 + #error "UART5 not present in the selected device" + #endif + + #if !defined(STM32F4XX) || !defined(STM32F4XX) + #error "UART5 DMA access not supported in this platform" + #endif +#endif + +#if STM32_UART_USE_USART6 && !STM32_HAS_USART6 +#error "USART6 not present in the selected device" +#endif + +#if !STM32_UART_USE_USART1 && !STM32_UART_USE_USART2 && \ + !STM32_UART_USE_USART3 && !STM32_UART_USE_UART4 && \ + !STM32_UART_USE_UART5 && !STM32_UART_USE_USART6 +#error "UART driver activated but no USART/UART peripheral assigned" +#endif + +#if STM32_UART_USE_USART1 && \ + !CORTEX_IS_VALID_KERNEL_PRIORITY(STM32_UART_USART1_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to USART1" +#endif + +#if STM32_UART_USE_USART2 && \ + !CORTEX_IS_VALID_KERNEL_PRIORITY(STM32_UART_USART2_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to USART2" +#endif + +#if STM32_UART_USE_USART3 && \ + !CORTEX_IS_VALID_KERNEL_PRIORITY(STM32_UART_USART3_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to USART3" +#endif + +#if STM32_UART_USE_UART4 && \ + !CORTEX_IS_VALID_KERNEL_PRIORITY(STM32_UART_UART4_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to UART4" +#endif + +#if STM32_UART_USE_UART5 && \ + !CORTEX_IS_VALID_KERNEL_PRIORITY(STM32_UART_UART5_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to UART5" +#endif + +#if STM32_UART_USE_USART6 && \ + !CORTEX_IS_VALID_KERNEL_PRIORITY(STM32_UART_USART6_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to USART6" +#endif + +#if STM32_UART_USE_USART1 && \ + !STM32_DMA_IS_VALID_PRIORITY(STM32_UART_USART1_DMA_PRIORITY) +#error "Invalid DMA priority assigned to USART1" +#endif + +#if STM32_UART_USE_USART2 && \ + !STM32_DMA_IS_VALID_PRIORITY(STM32_UART_USART2_DMA_PRIORITY) +#error "Invalid DMA priority assigned to USART2" +#endif + +#if STM32_UART_USE_USART3 && \ + !STM32_DMA_IS_VALID_PRIORITY(STM32_UART_USART3_DMA_PRIORITY) +#error "Invalid DMA priority assigned to USART3" +#endif + +#if STM32_UART_USE_UART4 && \ + !STM32_DMA_IS_VALID_PRIORITY(STM32_UART_UART4_DMA_PRIORITY) +#error "Invalid DMA priority assigned to UART4" +#endif + +#if STM32_UART_USE_UART5 && \ + !STM32_DMA_IS_VALID_PRIORITY(STM32_UART_UART5_DMA_PRIORITY) +#error "Invalid DMA priority assigned to UART5" +#endif + +#if STM32_UART_USE_USART6 && \ + !STM32_DMA_IS_VALID_PRIORITY(STM32_UART_USART6_DMA_PRIORITY) +#error "Invalid DMA priority assigned to USART6" +#endif + +#if STM32_UART_USE_USART1 && \ + !STM32_DMA_IS_VALID_ID(STM32_UART_USART1_RX_DMA_STREAM, \ + STM32_USART1_RX_DMA_MSK) +#error "invalid DMA stream associated to USART1 RX" +#endif + +#if STM32_UART_USE_USART1 && \ + !STM32_DMA_IS_VALID_ID(STM32_UART_USART1_TX_DMA_STREAM, \ + STM32_USART1_TX_DMA_MSK) +#error "invalid DMA stream associated to USART1 TX" +#endif + +#if STM32_UART_USE_USART2 && \ + !STM32_DMA_IS_VALID_ID(STM32_UART_USART2_RX_DMA_STREAM, \ + STM32_USART2_RX_DMA_MSK) +#error "invalid DMA stream associated to USART2 RX" +#endif + +#if STM32_UART_USE_USART2 && \ + !STM32_DMA_IS_VALID_ID(STM32_UART_USART2_TX_DMA_STREAM, \ + STM32_USART2_TX_DMA_MSK) +#error "invalid DMA stream associated to USART2 TX" +#endif + +#if STM32_UART_USE_USART3 && \ + !STM32_DMA_IS_VALID_ID(STM32_UART_USART3_RX_DMA_STREAM, \ + STM32_USART3_RX_DMA_MSK) +#error "invalid DMA stream associated to USART3 RX" +#endif + +#if STM32_UART_USE_USART3 && \ + !STM32_DMA_IS_VALID_ID(STM32_UART_USART3_TX_DMA_STREAM, \ + STM32_USART3_TX_DMA_MSK) +#error "invalid DMA stream associated to USART3 TX" +#endif + +#if STM32_UART_USE_UART4 && \ + !STM32_DMA_IS_VALID_ID(STM32_UART_UART4_RX_DMA_STREAM, \ + STM32_UART4_RX_DMA_MSK) +#error "invalid DMA stream associated to UART4 RX" +#endif + +#if STM32_UART_USE_UART4 && \ + !STM32_DMA_IS_VALID_ID(STM32_UART_UART4_TX_DMA_STREAM, \ + STM32_UART4_TX_DMA_MSK) +#error "invalid DMA stream associated to UART4 TX" +#endif + +#if STM32_UART_USE_UART5 && \ + !STM32_DMA_IS_VALID_ID(STM32_UART_UART5_RX_DMA_STREAM, \ + STM32_UART5_RX_DMA_MSK) +#error "invalid DMA stream associated to UART5 RX" +#endif + +#if STM32_UART_USE_UART5 && \ + !STM32_DMA_IS_VALID_ID(STM32_UART_UART5_TX_DMA_STREAM, \ + STM32_UART5_TX_DMA_MSK) +#error "invalid DMA stream associated to UART5 TX" +#endif + +#if STM32_UART_USE_USART6 && \ + !STM32_DMA_IS_VALID_ID(STM32_UART_USART6_RX_DMA_STREAM, \ + STM32_USART6_RX_DMA_MSK) +#error "invalid DMA stream associated to USART6 RX" +#endif + +#if STM32_UART_USE_USART6 && \ + !STM32_DMA_IS_VALID_ID(STM32_UART_USART6_TX_DMA_STREAM, \ + STM32_USART6_TX_DMA_MSK) +#error "invalid DMA stream associated to USART6 TX" +#endif + +#if !defined(STM32_DMA_REQUIRED) +#define STM32_DMA_REQUIRED +#endif + +/*===========================================================================*/ +/* Driver data structures and types. */ +/*===========================================================================*/ + +/** + * @brief UART driver condition flags type. + */ +typedef uint32_t uartflags_t; + +/** + * @brief Structure representing an UART driver. + */ +typedef struct UARTDriver UARTDriver; + +/** + * @brief Generic UART notification callback type. + * + * @param[in] uartp pointer to the @p UARTDriver object + */ +typedef void (*uartcb_t)(UARTDriver *uartp); + +/** + * @brief Character received UART notification callback type. + * + * @param[in] uartp pointer to the @p UARTDriver object + * @param[in] c received character + */ +typedef void (*uartccb_t)(UARTDriver *uartp, uint16_t c); + +/** + * @brief Receive error UART notification callback type. + * + * @param[in] uartp pointer to the @p UARTDriver object + * @param[in] e receive error mask + */ +typedef void (*uartecb_t)(UARTDriver *uartp, uartflags_t e); + +/** + * @brief Driver configuration structure. + * @note It could be empty on some architectures. + */ +typedef struct { + /** + * @brief End of transmission buffer callback. + */ + uartcb_t txend1_cb; + /** + * @brief Physical end of transmission callback. + */ + uartcb_t txend2_cb; + /** + * @brief Receive buffer filled callback. + */ + uartcb_t rxend_cb; + /** + * @brief Character received while out if the @p UART_RECEIVE state. + */ + uartccb_t rxchar_cb; + /** + * @brief Receive error callback. + */ + uartecb_t rxerr_cb; + /* End of the mandatory fields.*/ + /** + * @brief Bit rate. + */ + uint32_t speed; + /** + * @brief Initialization value for the CR1 register. + */ + uint16_t cr1; + /** + * @brief Initialization value for the CR2 register. + */ + uint16_t cr2; + /** + * @brief Initialization value for the CR3 register. + */ + uint16_t cr3; +} UARTConfig; + +/** + * @brief Structure representing an UART driver. + */ +struct UARTDriver { + /** + * @brief Driver state. + */ + uartstate_t state; + /** + * @brief Transmitter state. + */ + uarttxstate_t txstate; + /** + * @brief Receiver state. + */ + uartrxstate_t rxstate; + /** + * @brief Current configuration data. + */ + const UARTConfig *config; +#if defined(UART_DRIVER_EXT_FIELDS) + UART_DRIVER_EXT_FIELDS +#endif + /* End of the mandatory fields.*/ + /** + * @brief Pointer to the USART registers block. + */ + USART_TypeDef *usart; + /** + * @brief DMA mode bit mask. + */ + uint32_t dmamode; + /** + * @brief Receive DMA channel. + */ + const stm32_dma_stream_t *dmarx; + /** + * @brief Transmit DMA channel. + */ + const stm32_dma_stream_t *dmatx; + /** + * @brief Default receive buffer while into @p UART_RX_IDLE state. + */ + volatile uint16_t rxbuf; +}; + +/*===========================================================================*/ +/* Driver macros. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +#if STM32_UART_USE_USART1 && !defined(__DOXYGEN__) +extern UARTDriver UARTD1; +#endif + +#if STM32_UART_USE_USART2 && !defined(__DOXYGEN__) +extern UARTDriver UARTD2; +#endif + +#if STM32_UART_USE_USART3 && !defined(__DOXYGEN__) +extern UARTDriver UARTD3; +#endif + +#if STM32_UART_USE_UART4 && !defined(__DOXYGEN__) +extern UARTDriver UARTD4; +#endif + +#if STM32_UART_USE_UART5 && !defined(__DOXYGEN__) +extern UARTDriver UARTD5; +#endif + +#if STM32_UART_USE_USART6 && !defined(__DOXYGEN__) +extern UARTDriver UARTD6; +#endif + +#ifdef __cplusplus +extern "C" { +#endif + void uart_lld_init(void); + void uart_lld_start(UARTDriver *uartp); + void uart_lld_stop(UARTDriver *uartp); + void uart_lld_start_send(UARTDriver *uartp, size_t n, const void *txbuf); + size_t uart_lld_stop_send(UARTDriver *uartp); + void uart_lld_start_receive(UARTDriver *uartp, size_t n, void *rxbuf); + size_t uart_lld_stop_receive(UARTDriver *uartp); +#ifdef __cplusplus +} +#endif + +#endif /* HAL_USE_UART */ + +#endif /* _UART_LLD_H_ */ + +/** @} */ diff --git a/os/hal/ports/STM32/USARTv2/serial_lld.c b/os/hal/ports/STM32/USARTv2/serial_lld.c new file mode 100644 index 000000000..38042003e --- /dev/null +++ b/os/hal/ports/STM32/USARTv2/serial_lld.c @@ -0,0 +1,522 @@ +/* + ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file STM32/USARTv2/serial_lld.c + * @brief STM32 low level serial driver code. + * + * @addtogroup SERIAL + * @{ + */ + +#include "hal.h" + +#if HAL_USE_SERIAL || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver local definitions. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver exported variables. */ +/*===========================================================================*/ + +/** @brief USART1 serial driver identifier.*/ +#if STM32_SERIAL_USE_USART1 || defined(__DOXYGEN__) +SerialDriver SD1; +#endif + +/** @brief USART2 serial driver identifier.*/ +#if STM32_SERIAL_USE_USART2 || defined(__DOXYGEN__) +SerialDriver SD2; +#endif + +/** @brief USART3 serial driver identifier.*/ +#if STM32_SERIAL_USE_USART3 || defined(__DOXYGEN__) +SerialDriver SD3; +#endif + +/** @brief UART4 serial driver identifier.*/ +#if STM32_SERIAL_USE_UART4 || defined(__DOXYGEN__) +SerialDriver SD4; +#endif + +/** @brief UART5 serial driver identifier.*/ +#if STM32_SERIAL_USE_UART5 || defined(__DOXYGEN__) +SerialDriver SD5; +#endif + +/** @brief USART6 serial driver identifier.*/ +#if STM32_SERIAL_USE_USART6 || defined(__DOXYGEN__) +SerialDriver SD6; +#endif + +/*===========================================================================*/ +/* Driver local variables and types. */ +/*===========================================================================*/ + +/** @brief Driver default configuration.*/ +static const SerialConfig default_config = +{ + SERIAL_DEFAULT_BITRATE, + 0, + USART_CR2_STOP1_BITS | USART_CR2_LINEN, + 0 +}; + +/*===========================================================================*/ +/* Driver local functions. */ +/*===========================================================================*/ + +/** + * @brief USART initialization. + * @details This function must be invoked with interrupts disabled. + * + * @param[in] sdp pointer to a @p SerialDriver object + * @param[in] config the architecture-dependent serial driver configuration + */ +static void usart_init(SerialDriver *sdp, const SerialConfig *config) { + USART_TypeDef *u = sdp->usart; + + /* Baud rate setting.*/ + u->BRR = (uint16_t)(sdp->clock / config->speed); + + /* Note that some bits are enforced.*/ + u->CR2 = config->cr2 | USART_CR2_LBDIE; + u->CR3 = config->cr3 | USART_CR3_EIE; + u->CR1 = config->cr1 | USART_CR1_UE | USART_CR1_PEIE | + USART_CR1_RXNEIE | USART_CR1_TE | + USART_CR1_RE; + u->ICR = 0xFFFFFFFF; +} + +/** + * @brief USART de-initialization. + * @details This function must be invoked with interrupts disabled. + * + * @param[in] u pointer to an USART I/O block + */ +static void usart_deinit(USART_TypeDef *u) { + + u->CR1 = 0; + u->CR2 = 0; + u->CR3 = 0; +} + +/** + * @brief Error handling routine. + * + * @param[in] sdp pointer to a @p SerialDriver object + * @param[in] isr USART ISR register value + */ +static void set_error(SerialDriver *sdp, uint32_t isr) { + eventflags_t sts = 0; + + if (isr & USART_ISR_ORE) + sts |= SD_OVERRUN_ERROR; + if (isr & USART_ISR_PE) + sts |= SD_PARITY_ERROR; + if (isr & USART_ISR_FE) + sts |= SD_FRAMING_ERROR; + if (isr & USART_ISR_NE) + sts |= SD_NOISE_ERROR; + osalSysLockFromISR(); + chnAddFlagsI(sdp, sts); + osalSysUnlockFromISR(); +} + +/** + * @brief Common IRQ handler. + * + * @param[in] sdp communication channel associated to the USART + */ +static void serve_interrupt(SerialDriver *sdp) { + USART_TypeDef *u = sdp->usart; + uint32_t cr1 = u->CR1; + uint32_t isr; + + /* Reading and clearing status.*/ + isr = u->ISR; + u->ICR = isr; + + /* Error condition detection.*/ + if (isr & (USART_ISR_ORE | USART_ISR_NE | USART_ISR_FE | USART_ISR_PE)) + set_error(sdp, isr); + /* Special case, LIN break detection.*/ + if (isr & USART_ISR_LBD) { + osalSysLockFromISR(); + chnAddFlagsI(sdp, SD_BREAK_DETECTED); + osalSysUnlockFromISR(); + } + /* Data available.*/ + if (isr & USART_ISR_RXNE) { + osalSysLockFromISR(); + sdIncomingDataI(sdp, (uint8_t)u->RDR); + osalSysUnlockFromISR(); + } + /* Transmission buffer empty.*/ + if ((cr1 & USART_CR1_TXEIE) && (isr & USART_ISR_TXE)) { + msg_t b; + osalSysLockFromISR(); + b = oqGetI(&sdp->oqueue); + if (b < Q_OK) { + chnAddFlagsI(sdp, CHN_OUTPUT_EMPTY); + u->CR1 = (cr1 & ~USART_CR1_TXEIE) | USART_CR1_TCIE; + } + else + u->TDR = b; + osalSysUnlockFromISR(); + } + /* Physical transmission end.*/ + if (isr & USART_ISR_TC) { + osalSysLockFromISR(); + chnAddFlagsI(sdp, CHN_TRANSMISSION_END); + osalSysUnlockFromISR(); + u->CR1 = cr1 & ~USART_CR1_TCIE; + } +} + +#if STM32_SERIAL_USE_USART1 || defined(__DOXYGEN__) +static void notify1(io_queue_t *qp) { + + (void)qp; + USART1->CR1 |= USART_CR1_TXEIE; +} +#endif + +#if STM32_SERIAL_USE_USART2 || defined(__DOXYGEN__) +static void notify2(io_queue_t *qp) { + + (void)qp; + USART2->CR1 |= USART_CR1_TXEIE; +} +#endif + +#if STM32_SERIAL_USE_USART3 || defined(__DOXYGEN__) +static void notify3(io_queue_t *qp) { + + (void)qp; + USART3->CR1 |= USART_CR1_TXEIE; +} +#endif + +#if STM32_SERIAL_USE_UART4 || defined(__DOXYGEN__) +static void notify4(io_queue_t *qp) { + + (void)qp; + UART4->CR1 |= USART_CR1_TXEIE; +} +#endif + +#if STM32_SERIAL_USE_UART5 || defined(__DOXYGEN__) +static void notify5(io_queue_t *qp) { + + (void)qp; + UART5->CR1 |= USART_CR1_TXEIE; +} +#endif + +#if STM32_SERIAL_USE_USART6 || defined(__DOXYGEN__) +static void notify6(io_queue_t *qp) { + + (void)qp; + USART6->CR1 |= USART_CR1_TXEIE; +} +#endif + +/*===========================================================================*/ +/* Driver interrupt handlers. */ +/*===========================================================================*/ + +#if STM32_SERIAL_USE_USART1 || defined(__DOXYGEN__) +#if !defined(STM32_USART1_HANDLER) +#error "STM32_USART1_HANDLER not defined" +#endif +/** + * @brief USART1 interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(STM32_USART1_HANDLER) { + + OSAL_IRQ_PROLOGUE(); + + serve_interrupt(&SD1); + + OSAL_IRQ_EPILOGUE(); +} +#endif + +#if STM32_SERIAL_USE_USART2 || defined(__DOXYGEN__) +#if !defined(STM32_USART2_HANDLER) +#error "STM32_USART2_HANDLER not defined" +#endif +/** + * @brief USART2 interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(STM32_USART2_HANDLER) { + + OSAL_IRQ_PROLOGUE(); + + serve_interrupt(&SD2); + + OSAL_IRQ_EPILOGUE(); +} +#endif + +#if STM32_SERIAL_USE_USART3 || defined(__DOXYGEN__) +#if !defined(STM32_USART3_HANDLER) +#error "STM32_USART3_HANDLER not defined" +#endif +/** + * @brief USART3 interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(STM32_USART3_HANDLER) { + + OSAL_IRQ_PROLOGUE(); + + serve_interrupt(&SD3); + + OSAL_IRQ_EPILOGUE(); +} +#endif + +#if STM32_SERIAL_USE_UART4 || defined(__DOXYGEN__) +#if !defined(STM32_UART4_HANDLER) +#error "STM32_UART4_HANDLER not defined" +#endif +/** + * @brief UART4 interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(STM32_UART4_HANDLER) { + + OSAL_IRQ_PROLOGUE(); + + serve_interrupt(&SD4); + + OSAL_IRQ_EPILOGUE(); +} +#endif + +#if STM32_SERIAL_USE_UART5 || defined(__DOXYGEN__) +#if !defined(STM32_UART5_HANDLER) +#error "STM32_UART5_HANDLER not defined" +#endif +/** + * @brief UART5 interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(STM32_UART5_HANDLER) { + + OSAL_IRQ_PROLOGUE(); + + serve_interrupt(&SD5); + + OSAL_IRQ_EPILOGUE(); +} +#endif + +#if STM32_SERIAL_USE_USART6 || defined(__DOXYGEN__) +#if !defined(STM32_USART6_HANDLER) +#error "STM32_USART6_HANDLER not defined" +#endif +/** + * @brief USART1 interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(STM32_USART6_HANDLER) { + + OSAL_IRQ_PROLOGUE(); + + serve_interrupt(&SD6); + + OSAL_IRQ_EPILOGUE(); +} +#endif + +/*===========================================================================*/ +/* Driver exported functions. */ +/*===========================================================================*/ + +/** + * @brief Low level serial driver initialization. + * + * @notapi + */ +void sd_lld_init(void) { + +#if STM32_SERIAL_USE_USART1 + sdObjectInit(&SD1, NULL, notify1); + SD1.usart = USART1; + SD1.clock = STM32_USART1CLK; +#endif + +#if STM32_SERIAL_USE_USART2 + sdObjectInit(&SD2, NULL, notify2); + SD2.usart = USART2; + SD2.clock = STM32_USART2CLK; +#endif + +#if STM32_SERIAL_USE_USART3 + sdObjectInit(&SD3, NULL, notify3); + SD3.usart = USART3; + SD3.clock = STM32_USART3CLK; +#endif + +#if STM32_SERIAL_USE_UART4 + sdObjectInit(&SD4, NULL, notify4); + SD4.usart = UART4; + SD4.clock = STM32_UART4CLK; +#endif + +#if STM32_SERIAL_USE_UART5 + sdObjectInit(&SD5, NULL, notify5); + SD5.usart = UART5; + SD5.clock = STM32_UART5CLK; +#endif + +#if STM32_SERIAL_USE_USART6 + sdObjectInit(&SD6, NULL, notify6); + SD6.usart = USART6; + SD6.clock = STM32_USART6CLK; +#endif +} + +/** + * @brief Low level serial driver configuration and (re)start. + * + * @param[in] sdp pointer to a @p SerialDriver object + * @param[in] config the architecture-dependent serial driver configuration. + * If this parameter is set to @p NULL then a default + * configuration is used. + * + * @notapi + */ +void sd_lld_start(SerialDriver *sdp, const SerialConfig *config) { + + if (config == NULL) + config = &default_config; + + if (sdp->state == SD_STOP) { +#if STM32_SERIAL_USE_USART1 + if (&SD1 == sdp) { + rccEnableUSART1(FALSE); + nvicEnableVector(STM32_USART1_NUMBER, STM32_SERIAL_USART1_PRIORITY); + } +#endif +#if STM32_SERIAL_USE_USART2 + if (&SD2 == sdp) { + rccEnableUSART2(FALSE); + nvicEnableVector(STM32_USART2_NUMBER, STM32_SERIAL_USART2_PRIORITY); + } +#endif +#if STM32_SERIAL_USE_USART3 + if (&SD3 == sdp) { + rccEnableUSART3(FALSE); + nvicEnableVector(STM32_USART3_NUMBER, STM32_SERIAL_USART3_PRIORITY); + } +#endif +#if STM32_SERIAL_USE_UART4 + if (&SD4 == sdp) { + rccEnableUART4(FALSE); + nvicEnableVector(STM32_UART4_NUMBER, STM32_SERIAL_UART4_PRIORITY); + } +#endif +#if STM32_SERIAL_USE_UART5 + if (&SD5 == sdp) { + rccEnableUART5(FALSE); + nvicEnableVector(STM32_UART5_NUMBER, STM32_SERIAL_UART5_PRIORITY); + } +#endif +#if STM32_SERIAL_USE_USART6 + if (&SD6 == sdp) { + rccEnableUSART6(FALSE); + nvicEnableVector(STM32_USART6_NUMBER, STM32_SERIAL_USART6_PRIORITY); + } +#endif + } + usart_init(sdp, config); +} + +/** + * @brief Low level serial driver stop. + * @details De-initializes the USART, stops the associated clock, resets the + * interrupt vector. + * + * @param[in] sdp pointer to a @p SerialDriver object + * + * @notapi + */ +void sd_lld_stop(SerialDriver *sdp) { + + if (sdp->state == SD_READY) { + usart_deinit(sdp->usart); +#if STM32_SERIAL_USE_USART1 + if (&SD1 == sdp) { + rccDisableUSART1(FALSE); + nvicDisableVector(STM32_USART1_NUMBER); + return; + } +#endif +#if STM32_SERIAL_USE_USART2 + if (&SD2 == sdp) { + rccDisableUSART2(FALSE); + nvicDisableVector(STM32_USART2_NUMBER); + return; + } +#endif +#if STM32_SERIAL_USE_USART3 + if (&SD3 == sdp) { + rccDisableUSART3(FALSE); + nvicDisableVector(STM32_USART3_NUMBER); + return; + } +#endif +#if STM32_SERIAL_USE_UART4 + if (&SD4 == sdp) { + rccDisableUART4(FALSE); + nvicDisableVector(STM32_UART4_NUMBER); + return; + } +#endif +#if STM32_SERIAL_USE_UART5 + if (&SD5 == sdp) { + rccDisableUART5(FALSE); + nvicDisableVector(STM32_UART5_NUMBER); + return; + } +#endif +#if STM32_SERIAL_USE_USART6 + if (&SD6 == sdp) { + rccDisableUSART6(FALSE); + nvicDisableVector(STM32_USART6_NUMBER); + return; + } +#endif + } +} + +#endif /* HAL_USE_SERIAL */ + +/** @} */ diff --git a/os/hal/ports/STM32/USARTv2/serial_lld.h b/os/hal/ports/STM32/USARTv2/serial_lld.h new file mode 100644 index 000000000..ac7415895 --- /dev/null +++ b/os/hal/ports/STM32/USARTv2/serial_lld.h @@ -0,0 +1,305 @@ +/* + ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file STM32/USARTv2/serial_lld.h + * @brief STM32 low level serial driver header. + * + * @addtogroup SERIAL + * @{ + */ + +#ifndef _SERIAL_LLD_H_ +#define _SERIAL_LLD_H_ + +#if HAL_USE_SERIAL || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver constants. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver pre-compile time settings. */ +/*===========================================================================*/ + +/** + * @name Configuration options + * @{ + */ +/** + * @brief USART1 driver enable switch. + * @details If set to @p TRUE the support for USART1 is included. + * @note The default is @p TRUE. + */ +#if !defined(STM32_SERIAL_USE_USART1) || defined(__DOXYGEN__) +#define STM32_SERIAL_USE_USART1 FALSE +#endif + +/** + * @brief USART2 driver enable switch. + * @details If set to @p TRUE the support for USART2 is included. + * @note The default is @p TRUE. + */ +#if !defined(STM32_SERIAL_USE_USART2) || defined(__DOXYGEN__) +#define STM32_SERIAL_USE_USART2 FALSE +#endif + +/** + * @brief USART3 driver enable switch. + * @details If set to @p TRUE the support for USART3 is included. + * @note The default is @p TRUE. + */ +#if !defined(STM32_SERIAL_USE_USART3) || defined(__DOXYGEN__) +#define STM32_SERIAL_USE_USART3 FALSE +#endif + +/** + * @brief UART4 driver enable switch. + * @details If set to @p TRUE the support for UART4 is included. + * @note The default is @p TRUE. + */ +#if !defined(STM32_SERIAL_USE_UART4) || defined(__DOXYGEN__) +#define STM32_SERIAL_USE_UART4 FALSE +#endif + +/** + * @brief UART5 driver enable switch. + * @details If set to @p TRUE the support for UART5 is included. + * @note The default is @p TRUE. + */ +#if !defined(STM32_SERIAL_USE_UART5) || defined(__DOXYGEN__) +#define STM32_SERIAL_USE_UART5 FALSE +#endif + +/** + * @brief USART6 driver enable switch. + * @details If set to @p TRUE the support for USART6 is included. + * @note The default is @p TRUE. + */ +#if !defined(STM32_SERIAL_USE_USART6) || defined(__DOXYGEN__) +#define STM32_SERIAL_USE_USART6 FALSE +#endif + +/** + * @brief USART1 interrupt priority level setting. + */ +#if !defined(STM32_SERIAL_USART1_PRIORITY) || defined(__DOXYGEN__) +#define STM32_SERIAL_USART1_PRIORITY 12 +#endif + +/** + * @brief USART2 interrupt priority level setting. + */ +#if !defined(STM32_SERIAL_USART2_PRIORITY) || defined(__DOXYGEN__) +#define STM32_SERIAL_USART2_PRIORITY 12 +#endif + +/** + * @brief USART3 interrupt priority level setting. + */ +#if !defined(STM32_SERIAL_USART3_PRIORITY) || defined(__DOXYGEN__) +#define STM32_SERIAL_USART3_PRIORITY 12 +#endif + +/** + * @brief UART4 interrupt priority level setting. + */ +#if !defined(STM32_SERIAL_UART4_PRIORITY) || defined(__DOXYGEN__) +#define STM32_SERIAL_UART4_PRIORITY 12 +#endif + +/** + * @brief UART5 interrupt priority level setting. + */ +#if !defined(STM32_SERIAL_UART5_PRIORITY) || defined(__DOXYGEN__) +#define STM32_SERIAL_UART5_PRIORITY 12 +#endif + +/** + * @brief USART6 interrupt priority level setting. + */ +#if !defined(STM32_SERIAL_USART6_PRIORITY) || defined(__DOXYGEN__) +#define STM32_SERIAL_USART6_PRIORITY 12 +#endif +/** @} */ + +/*===========================================================================*/ +/* Derived constants and error checks. */ +/*===========================================================================*/ + +#if STM32_SERIAL_USE_USART1 && !STM32_HAS_USART1 +#error "USART1 not present in the selected device" +#endif + +#if STM32_SERIAL_USE_USART2 && !STM32_HAS_USART2 +#error "USART2 not present in the selected device" +#endif + +#if STM32_SERIAL_USE_USART3 && !STM32_HAS_USART3 +#error "USART3 not present in the selected device" +#endif + +#if STM32_SERIAL_USE_UART4 && !STM32_HAS_UART4 +#error "UART4 not present in the selected device" +#endif + +#if STM32_SERIAL_USE_UART5 && !STM32_HAS_UART5 +#error "UART5 not present in the selected device" +#endif + +#if STM32_SERIAL_USE_USART6 && !STM32_HAS_USART6 +#error "USART6 not present in the selected device" +#endif + +#if !STM32_SERIAL_USE_USART1 && !STM32_SERIAL_USE_USART2 && \ + !STM32_SERIAL_USE_USART3 && !STM32_SERIAL_USE_UART4 && \ + !STM32_SERIAL_USE_UART5 && !STM32_SERIAL_USE_USART6 +#error "SERIAL driver activated but no USART/UART peripheral assigned" +#endif + +#if STM32_SERIAL_USE_USART1 && \ + !CORTEX_IS_VALID_KERNEL_PRIORITY(STM32_SERIAL_USART1_PRIORITY) +#error "Invalid IRQ priority assigned to USART1" +#endif + +#if STM32_SERIAL_USE_USART2 && \ + !CORTEX_IS_VALID_KERNEL_PRIORITY(STM32_SERIAL_USART2_PRIORITY) +#error "Invalid IRQ priority assigned to USART2" +#endif + +#if STM32_SERIAL_USE_USART3 && \ + !CORTEX_IS_VALID_KERNEL_PRIORITY(STM32_SERIAL_USART3_PRIORITY) +#error "Invalid IRQ priority assigned to USART3" +#endif + +#if STM32_SERIAL_USE_UART4 && \ + !CORTEX_IS_VALID_KERNEL_PRIORITY(STM32_SERIAL_UART4_PRIORITY) +#error "Invalid IRQ priority assigned to UART4" +#endif + +#if STM32_SERIAL_USE_UART5 && \ + !CORTEX_IS_VALID_KERNEL_PRIORITY(STM32_SERIAL_UART5_PRIORITY) +#error "Invalid IRQ priority assigned to UART5" +#endif + +#if STM32_SERIAL_USE_USART6 && \ + !CORTEX_IS_VALID_KERNEL_PRIORITY(STM32_SERIAL_USART6_PRIORITY) +#error "Invalid IRQ priority assigned to USART6" +#endif + +/*===========================================================================*/ +/* Driver data structures and types. */ +/*===========================================================================*/ + +/** + * @brief STM32 Serial Driver configuration structure. + * @details An instance of this structure must be passed to @p sdStart() + * in order to configure and start a serial driver operations. + * @note This structure content is architecture dependent, each driver + * implementation defines its own version and the custom static + * initializers. + */ +typedef struct { + /** + * @brief Bit rate. + */ + uint32_t speed; + /* End of the mandatory fields.*/ + /** + * @brief Initialization value for the CR1 register. + */ + uint32_t cr1; + /** + * @brief Initialization value for the CR2 register. + */ + uint32_t cr2; + /** + * @brief Initialization value for the CR3 register. + */ + uint32_t cr3; +} SerialConfig; + +/** + * @brief @p SerialDriver specific data. + */ +#define _serial_driver_data \ + _base_asynchronous_channel_data \ + /* Driver state.*/ \ + sdstate_t state; \ + /* Input queue.*/ \ + input_queue_t iqueue; \ + /* Output queue.*/ \ + output_queue_t oqueue; \ + /* Input circular buffer.*/ \ + uint8_t ib[SERIAL_BUFFERS_SIZE]; \ + /* Output circular buffer.*/ \ + uint8_t ob[SERIAL_BUFFERS_SIZE]; \ + /* End of the mandatory fields.*/ \ + /* Pointer to the USART registers block.*/ \ + USART_TypeDef *usart; \ + /* Clock frequency for the associated USART/UART.*/ \ + uint32_t clock; + +/*===========================================================================*/ +/* Driver macros. */ +/*===========================================================================*/ + +/* + * Extra USARTs definitions here (missing from the ST header file). + */ +#define USART_CR2_STOP1_BITS (0 << 12) /**< @brief CR2 1 stop bit value.*/ +#define USART_CR2_STOP0P5_BITS (1 << 12) /**< @brief CR2 0.5 stop bit value.*/ +#define USART_CR2_STOP2_BITS (2 << 12) /**< @brief CR2 2 stop bit value.*/ +#define USART_CR2_STOP1P5_BITS (3 << 12) /**< @brief CR2 1.5 stop bit value.*/ + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +#if STM32_SERIAL_USE_USART1 && !defined(__DOXYGEN__) +extern SerialDriver SD1; +#endif +#if STM32_SERIAL_USE_USART2 && !defined(__DOXYGEN__) +extern SerialDriver SD2; +#endif +#if STM32_SERIAL_USE_USART3 && !defined(__DOXYGEN__) +extern SerialDriver SD3; +#endif +#if STM32_SERIAL_USE_UART4 && !defined(__DOXYGEN__) +extern SerialDriver SD4; +#endif +#if STM32_SERIAL_USE_UART5 && !defined(__DOXYGEN__) +extern SerialDriver SD5; +#endif +#if STM32_SERIAL_USE_USART6 && !defined(__DOXYGEN__) +extern SerialDriver SD6; +#endif + +#ifdef __cplusplus +extern "C" { +#endif + void sd_lld_init(void); + void sd_lld_start(SerialDriver *sdp, const SerialConfig *config); + void sd_lld_stop(SerialDriver *sdp); +#ifdef __cplusplus +} +#endif + +#endif /* HAL_USE_SERIAL */ + +#endif /* _SERIAL_LLD_H_ */ + +/** @} */ diff --git a/os/hal/ports/STM32/USARTv2/uart_lld.c b/os/hal/ports/STM32/USARTv2/uart_lld.c new file mode 100644 index 000000000..0b85a294c --- /dev/null +++ b/os/hal/ports/STM32/USARTv2/uart_lld.c @@ -0,0 +1,590 @@ +/* + ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file STM32/USARTv2/uart_lld.c + * @brief STM32 low level UART driver code. + * + * @addtogroup UART + * @{ + */ + +#include "hal.h" + +#if HAL_USE_UART || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver local definitions. */ +/*===========================================================================*/ + +#define USART1_RX_DMA_CHANNEL \ + STM32_DMA_GETCHANNEL(STM32_UART_USART1_RX_DMA_STREAM, \ + STM32_USART1_RX_DMA_CHN) + +#define USART1_TX_DMA_CHANNEL \ + STM32_DMA_GETCHANNEL(STM32_UART_USART1_TX_DMA_STREAM, \ + STM32_USART1_TX_DMA_CHN) + +#define USART2_RX_DMA_CHANNEL \ + STM32_DMA_GETCHANNEL(STM32_UART_USART2_RX_DMA_STREAM, \ + STM32_USART2_RX_DMA_CHN) + +#define USART2_TX_DMA_CHANNEL \ + STM32_DMA_GETCHANNEL(STM32_UART_USART2_TX_DMA_STREAM, \ + STM32_USART2_TX_DMA_CHN) + +#define USART3_RX_DMA_CHANNEL \ + STM32_DMA_GETCHANNEL(STM32_UART_USART3_RX_DMA_STREAM, \ + STM32_USART3_RX_DMA_CHN) + +#define USART3_TX_DMA_CHANNEL \ + STM32_DMA_GETCHANNEL(STM32_UART_USART3_TX_DMA_STREAM, \ + STM32_USART3_TX_DMA_CHN) + +/*===========================================================================*/ +/* Driver exported variables. */ +/*===========================================================================*/ + +/** @brief USART1 UART driver identifier.*/ +#if STM32_UART_USE_USART1 || defined(__DOXYGEN__) +UARTDriver UARTD1; +#endif + +/** @brief USART2 UART driver identifier.*/ +#if STM32_UART_USE_USART2 || defined(__DOXYGEN__) +UARTDriver UARTD2; +#endif + +/** @brief USART3 UART driver identifier.*/ +#if STM32_UART_USE_USART3 || defined(__DOXYGEN__) +UARTDriver UARTD3; +#endif + +/*===========================================================================*/ +/* Driver local variables and types. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local functions. */ +/*===========================================================================*/ + +/** + * @brief Status bits translation. + * + * @param[in] sr USART SR register value + * + * @return The error flags. + */ +static uartflags_t translate_errors(uint32_t isr) { + uartflags_t sts = 0; + + if (isr & USART_ISR_ORE) + sts |= UART_OVERRUN_ERROR; + if (isr & USART_ISR_PE) + sts |= UART_PARITY_ERROR; + if (isr & USART_ISR_FE) + sts |= UART_FRAMING_ERROR; + if (isr & USART_ISR_NE) + sts |= UART_NOISE_ERROR; + if (isr & USART_ISR_LBD) + sts |= UART_BREAK_DETECTED; + return sts; +} + +/** + * @brief Puts the receiver in the UART_RX_IDLE state. + * + * @param[in] uartp pointer to the @p UARTDriver object + */ +static void set_rx_idle_loop(UARTDriver *uartp) { + uint32_t mode; + + /* RX DMA channel preparation, if the char callback is defined then the + TCIE interrupt is enabled too.*/ + if (uartp->config->rxchar_cb == NULL) + mode = STM32_DMA_CR_DIR_P2M | STM32_DMA_CR_CIRC; + else + mode = STM32_DMA_CR_DIR_P2M | STM32_DMA_CR_CIRC | STM32_DMA_CR_TCIE; + dmaStreamSetMemory0(uartp->dmarx, &uartp->rxbuf); + dmaStreamSetTransactionSize(uartp->dmarx, 1); + dmaStreamSetMode(uartp->dmarx, uartp->dmamode | mode); + dmaStreamEnable(uartp->dmarx); +} + +/** + * @brief USART de-initialization. + * @details This function must be invoked with interrupts disabled. + * + * @param[in] uartp pointer to the @p UARTDriver object + */ +static void usart_stop(UARTDriver *uartp) { + + /* Stops RX and TX DMA channels.*/ + dmaStreamDisable(uartp->dmarx); + dmaStreamDisable(uartp->dmatx); + + /* Stops USART operations.*/ + uartp->usart->CR1 = 0; + uartp->usart->CR2 = 0; + uartp->usart->CR3 = 0; +} + +/** + * @brief USART initialization. + * @details This function must be invoked with interrupts disabled. + * + * @param[in] uartp pointer to the @p UARTDriver object + */ +static void usart_start(UARTDriver *uartp) { + uint32_t cr1; + USART_TypeDef *u = uartp->usart; + + /* Defensive programming, starting from a clean state.*/ + usart_stop(uartp); + + /* Baud rate setting.*/ +#if defined(STM32F0XX) + if (uartp->usart == USART1) + u->BRR = STM32_USART1CLK / uartp->config->speed; + else + u->BRR = STM32_PCLK / uartp->config->speed; +#else /* !defined(STM32F0XX) */ + if (uartp->usart == USART1) + u->BRR = STM32_PCLK2 / uartp->config->speed; + else + u->BRR = STM32_PCLK1 / uartp->config->speed; +#endif /* !defined(STM32F0XX) */ + + /* Resetting eventual pending status flags.*/ + u->ICR = 0xFFFFFFFF; + + /* Note that some bits are enforced because required for correct driver + operations.*/ + u->CR2 = uartp->config->cr2 | USART_CR2_LBDIE; + u->CR3 = uartp->config->cr3 | USART_CR3_DMAT | USART_CR3_DMAR | + USART_CR3_EIE; + if (uartp->config->txend2_cb == NULL) + cr1 = USART_CR1_UE | USART_CR1_PEIE | USART_CR1_TE | USART_CR1_RE; + else + cr1 = USART_CR1_UE | USART_CR1_PEIE | USART_CR1_TE | USART_CR1_RE | + USART_CR1_TCIE; + u->CR1 = uartp->config->cr1 | cr1; + + /* Starting the receiver idle loop.*/ + set_rx_idle_loop(uartp); +} + +/** + * @brief RX DMA common service routine. + * + * @param[in] uartp pointer to the @p UARTDriver object + * @param[in] flags pre-shifted content of the ISR register + */ +static void uart_lld_serve_rx_end_irq(UARTDriver *uartp, uint32_t flags) { + + /* DMA errors handling.*/ +#if defined(STM32_UART_DMA_ERROR_HOOK) + if ((flags & (STM32_DMA_ISR_TEIF | STM32_DMA_ISR_DMEIF)) != 0) { + STM32_UART_DMA_ERROR_HOOK(uartp); + } +#else + (void)flags; +#endif + + if (uartp->rxstate == UART_RX_IDLE) { + /* Receiver in idle state, a callback is generated, if enabled, for each + received character and then the driver stays in the same state.*/ + if (uartp->config->rxchar_cb != NULL) + uartp->config->rxchar_cb(uartp, uartp->rxbuf); + } + else { + /* Receiver in active state, a callback is generated, if enabled, after + a completed transfer.*/ + dmaStreamDisable(uartp->dmarx); + uartp->rxstate = UART_RX_COMPLETE; + if (uartp->config->rxend_cb != NULL) + uartp->config->rxend_cb(uartp); + + /* If the callback didn't explicitly change state then the receiver + automatically returns to the idle state.*/ + if (uartp->rxstate == UART_RX_COMPLETE) { + uartp->rxstate = UART_RX_IDLE; + set_rx_idle_loop(uartp); + } + } +} + +/** + * @brief TX DMA common service routine. + * + * @param[in] uartp pointer to the @p UARTDriver object + * @param[in] flags pre-shifted content of the ISR register + */ +static void uart_lld_serve_tx_end_irq(UARTDriver *uartp, uint32_t flags) { + + /* DMA errors handling.*/ +#if defined(STM32_UART_DMA_ERROR_HOOK) + if ((flags & (STM32_DMA_ISR_TEIF | STM32_DMA_ISR_DMEIF)) != 0) { + STM32_UART_DMA_ERROR_HOOK(uartp); + } +#else + (void)flags; +#endif + + dmaStreamDisable(uartp->dmatx); + + /* A callback is generated, if enabled, after a completed transfer.*/ + uartp->txstate = UART_TX_COMPLETE; + if (uartp->config->txend1_cb != NULL) + uartp->config->txend1_cb(uartp); + + /* If the callback didn't explicitly change state then the transmitter + automatically returns to the idle state.*/ + if (uartp->txstate == UART_TX_COMPLETE) + uartp->txstate = UART_TX_IDLE; +} + +/** + * @brief USART common service routine. + * + * @param[in] uartp pointer to the @p UARTDriver object + */ +static void serve_usart_irq(UARTDriver *uartp) { + uint32_t isr; + USART_TypeDef *u = uartp->usart; + + /* Reading and clearing status.*/ + isr = u->ISR; + u->ICR = isr; + + if (isr & (USART_ISR_LBD | USART_ISR_ORE | USART_ISR_NE | + USART_ISR_FE | USART_ISR_PE)) { + if (uartp->config->rxerr_cb != NULL) + uartp->config->rxerr_cb(uartp, translate_errors(isr)); + } + if (isr & USART_ISR_TC) { + /* End of transmission, a callback is generated.*/ + if (uartp->config->txend2_cb != NULL) + uartp->config->txend2_cb(uartp); + } +} + +/*===========================================================================*/ +/* Driver interrupt handlers. */ +/*===========================================================================*/ + +#if STM32_UART_USE_USART1 || defined(__DOXYGEN__) +#if !defined(STM32_USART1_HANDLER) +#error "STM32_USART1_HANDLER not defined" +#endif +/** + * @brief USART1 IRQ handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(STM32_USART1_HANDLER) { + + OSAL_IRQ_PROLOGUE(); + + serve_usart_irq(&UARTD1); + + OSAL_IRQ_EPILOGUE(); +} +#endif /* STM32_UART_USE_USART1 */ + +#if STM32_UART_USE_USART2 || defined(__DOXYGEN__) +#if !defined(STM32_USART2_HANDLER) +#error "STM32_USART2_HANDLER not defined" +#endif +/** + * @brief USART2 IRQ handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(STM32_USART2_HANDLER) { + + OSAL_IRQ_PROLOGUE(); + + serve_usart_irq(&UARTD2); + + OSAL_IRQ_EPILOGUE(); +} +#endif /* STM32_UART_USE_USART2 */ + +#if STM32_UART_USE_USART3 || defined(__DOXYGEN__) +#if !defined(STM32_USART3_HANDLER) +#error "STM32_USART3_HANDLER not defined" +#endif +/** + * @brief USART3 IRQ handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(STM32_USART3_HANDLER) { + + OSAL_IRQ_PROLOGUE(); + + serve_usart_irq(&UARTD3); + + OSAL_IRQ_EPILOGUE(); +} +#endif /* STM32_UART_USE_USART3 */ + +/*===========================================================================*/ +/* Driver exported functions. */ +/*===========================================================================*/ + +/** + * @brief Low level UART driver initialization. + * + * @notapi + */ +void uart_lld_init(void) { + +#if STM32_UART_USE_USART1 + uartObjectInit(&UARTD1); + UARTD1.usart = USART1; + UARTD1.dmamode = STM32_DMA_CR_DMEIE | STM32_DMA_CR_TEIE; + UARTD1.dmarx = STM32_DMA_STREAM(STM32_UART_USART1_RX_DMA_STREAM); + UARTD1.dmatx = STM32_DMA_STREAM(STM32_UART_USART1_TX_DMA_STREAM); +#endif + +#if STM32_UART_USE_USART2 + uartObjectInit(&UARTD2); + UARTD2.usart = USART2; + UARTD2.dmamode = STM32_DMA_CR_DMEIE | STM32_DMA_CR_TEIE; + UARTD2.dmarx = STM32_DMA_STREAM(STM32_UART_USART2_RX_DMA_STREAM); + UARTD2.dmatx = STM32_DMA_STREAM(STM32_UART_USART2_TX_DMA_STREAM); +#endif + +#if STM32_UART_USE_USART3 + uartObjectInit(&UARTD3); + UARTD3.usart = USART3; + UARTD3.dmamode = STM32_DMA_CR_DMEIE | STM32_DMA_CR_TEIE; + UARTD3.dmarx = STM32_DMA_STREAM(STM32_UART_USART3_RX_DMA_STREAM); + UARTD3.dmatx = STM32_DMA_STREAM(STM32_UART_USART3_TX_DMA_STREAM); +#endif +} + +/** + * @brief Configures and activates the UART peripheral. + * + * @param[in] uartp pointer to the @p UARTDriver object + * + * @notapi + */ +void uart_lld_start(UARTDriver *uartp) { + + if (uartp->state == UART_STOP) { +#if STM32_UART_USE_USART1 + if (&UARTD1 == uartp) { + bool_t b; + b = dmaStreamAllocate(uartp->dmarx, + STM32_UART_USART1_IRQ_PRIORITY, + (stm32_dmaisr_t)uart_lld_serve_rx_end_irq, + (void *)uartp); + osalDbgAssert(!b, "stream already allocated"); + b = dmaStreamAllocate(uartp->dmatx, + STM32_UART_USART1_IRQ_PRIORITY, + (stm32_dmaisr_t)uart_lld_serve_tx_end_irq, + (void *)uartp); + osalDbgAssert(!b, "stream already allocated"); + rccEnableUSART1(FALSE); + nvicEnableVector(STM32_USART1_NUMBER, STM32_UART_USART1_IRQ_PRIORITY); + uartp->dmamode |= STM32_DMA_CR_CHSEL(USART1_RX_DMA_CHANNEL) | + STM32_DMA_CR_PL(STM32_UART_USART1_DMA_PRIORITY); + } +#endif + +#if STM32_UART_USE_USART2 + if (&UARTD2 == uartp) { + bool_t b; + b = dmaStreamAllocate(uartp->dmarx, + STM32_UART_USART2_IRQ_PRIORITY, + (stm32_dmaisr_t)uart_lld_serve_rx_end_irq, + (void *)uartp); + osalDbgAssert(!b, "stream already allocated"); + b = dmaStreamAllocate(uartp->dmatx, + STM32_UART_USART2_IRQ_PRIORITY, + (stm32_dmaisr_t)uart_lld_serve_tx_end_irq, + (void *)uartp); + osalDbgAssert(!b, "stream already allocated"); + rccEnableUSART2(FALSE); + nvicEnableVector(STM32_USART2_NUMBER, STM32_UART_USART2_IRQ_PRIORITY); + uartp->dmamode |= STM32_DMA_CR_CHSEL(USART2_RX_DMA_CHANNEL) | + STM32_DMA_CR_PL(STM32_UART_USART2_DMA_PRIORITY); + } +#endif + +#if STM32_UART_USE_USART3 + if (&UARTD3 == uartp) { + bool_t b; + b = dmaStreamAllocate(uartp->dmarx, + STM32_UART_USART3_IRQ_PRIORITY, + (stm32_dmaisr_t)uart_lld_serve_rx_end_irq, + (void *)uartp); + osalDbgAssert(!b, "stream already allocated"); + b = dmaStreamAllocate(uartp->dmatx, + STM32_UART_USART3_IRQ_PRIORITY, + (stm32_dmaisr_t)uart_lld_serve_tx_end_irq, + (void *)uartp); + osalDbgAssert(!b, "stream already allocated"); + rccEnableUSART3(FALSE); + nvicEnableVector(STM32_USART3_NUMBER, STM32_UART_USART3_IRQ_PRIORITY); + uartp->dmamode |= STM32_DMA_CR_CHSEL(USART3_RX_DMA_CHANNEL) | + STM32_DMA_CR_PL(STM32_UART_USART3_DMA_PRIORITY); + } +#endif + + /* Static DMA setup, the transfer size depends on the USART settings, + it is 16 bits if M=1 and PCE=0 else it is 8 bits.*/ + if ((uartp->config->cr1 & (USART_CR1_M | USART_CR1_PCE)) == USART_CR1_M) + uartp->dmamode |= STM32_DMA_CR_PSIZE_HWORD | STM32_DMA_CR_MSIZE_HWORD; + dmaStreamSetPeripheral(uartp->dmarx, &uartp->usart->RDR); + dmaStreamSetPeripheral(uartp->dmatx, &uartp->usart->TDR); + uartp->rxbuf = 0; + } + + uartp->rxstate = UART_RX_IDLE; + uartp->txstate = UART_TX_IDLE; + usart_start(uartp); +} + +/** + * @brief Deactivates the UART peripheral. + * + * @param[in] uartp pointer to the @p UARTDriver object + * + * @notapi + */ +void uart_lld_stop(UARTDriver *uartp) { + + if (uartp->state == UART_READY) { + usart_stop(uartp); + dmaStreamRelease(uartp->dmarx); + dmaStreamRelease(uartp->dmatx); + +#if STM32_UART_USE_USART1 + if (&UARTD1 == uartp) { + nvicDisableVector(STM32_USART1_NUMBER); + rccDisableUSART1(FALSE); + return; + } +#endif + +#if STM32_UART_USE_USART2 + if (&UARTD2 == uartp) { + nvicDisableVector(STM32_USART2_NUMBER); + rccDisableUSART2(FALSE); + return; + } +#endif + +#if STM32_UART_USE_USART3 + if (&UARTD3 == uartp) { + nvicDisableVector(STM32_USART3_NUMBER); + rccDisableUSART3(FALSE); + return; + } +#endif + } +} + +/** + * @brief Starts a transmission on the UART peripheral. + * @note The buffers are organized as uint8_t arrays for data sizes below + * or equal to 8 bits else it is organized as uint16_t arrays. + * + * @param[in] uartp pointer to the @p UARTDriver object + * @param[in] n number of data frames to send + * @param[in] txbuf the pointer to the transmit buffer + * + * @notapi + */ +void uart_lld_start_send(UARTDriver *uartp, size_t n, const void *txbuf) { + + /* TX DMA channel preparation and start.*/ + dmaStreamSetMemory0(uartp->dmatx, txbuf); + dmaStreamSetTransactionSize(uartp->dmatx, n); + dmaStreamSetMode(uartp->dmatx, uartp->dmamode | STM32_DMA_CR_DIR_M2P | + STM32_DMA_CR_MINC | STM32_DMA_CR_TCIE); + dmaStreamEnable(uartp->dmatx); +} + +/** + * @brief Stops any ongoing transmission. + * @note Stopping a transmission also suppresses the transmission callbacks. + * + * @param[in] uartp pointer to the @p UARTDriver object + * + * @return The number of data frames not transmitted by the + * stopped transmit operation. + * + * @notapi + */ +size_t uart_lld_stop_send(UARTDriver *uartp) { + + dmaStreamDisable(uartp->dmatx); + return dmaStreamGetTransactionSize(uartp->dmatx); +} + +/** + * @brief Starts a receive operation on the UART peripheral. + * @note The buffers are organized as uint8_t arrays for data sizes below + * or equal to 8 bits else it is organized as uint16_t arrays. + * + * @param[in] uartp pointer to the @p UARTDriver object + * @param[in] n number of data frames to send + * @param[out] rxbuf the pointer to the receive buffer + * + * @notapi + */ +void uart_lld_start_receive(UARTDriver *uartp, size_t n, void *rxbuf) { + + /* Stopping previous activity (idle state).*/ + dmaStreamDisable(uartp->dmarx); + + /* RX DMA channel preparation and start.*/ + dmaStreamSetMemory0(uartp->dmarx, rxbuf); + dmaStreamSetTransactionSize(uartp->dmarx, n); + dmaStreamSetMode(uartp->dmarx, uartp->dmamode | STM32_DMA_CR_DIR_P2M | + STM32_DMA_CR_MINC | STM32_DMA_CR_TCIE); + dmaStreamEnable(uartp->dmarx); +} + +/** + * @brief Stops any ongoing receive operation. + * @note Stopping a receive operation also suppresses the receive callbacks. + * + * @param[in] uartp pointer to the @p UARTDriver object + * + * @return The number of data frames not received by the + * stopped receive operation. + * + * @notapi + */ +size_t uart_lld_stop_receive(UARTDriver *uartp) { + size_t n; + + dmaStreamDisable(uartp->dmarx); + n = dmaStreamGetTransactionSize(uartp->dmarx); + set_rx_idle_loop(uartp); + return n; +} + +#endif /* HAL_USE_UART */ + +/** @} */ diff --git a/os/hal/ports/STM32/USARTv2/uart_lld.h b/os/hal/ports/STM32/USARTv2/uart_lld.h new file mode 100644 index 000000000..32b1f6e47 --- /dev/null +++ b/os/hal/ports/STM32/USARTv2/uart_lld.h @@ -0,0 +1,417 @@ +/* + ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file STM32/USARTv2/uart_lld.h + * @brief STM32 low level UART driver header. + * + * @addtogroup UART + * @{ + */ + +#ifndef _UART_LLD_H_ +#define _UART_LLD_H_ + +#if HAL_USE_UART || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver constants. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver pre-compile time settings. */ +/*===========================================================================*/ + +/** + * @name Configuration options + * @{ + */ +/** + * @brief UART driver on USART1 enable switch. + * @details If set to @p TRUE the support for USART1 is included. + * @note The default is @p FALSE. + */ +#if !defined(STM32_UART_USE_USART1) || defined(__DOXYGEN__) +#define STM32_UART_USE_USART1 FALSE +#endif + +/** + * @brief UART driver on USART2 enable switch. + * @details If set to @p TRUE the support for USART2 is included. + * @note The default is @p FALSE. + */ +#if !defined(STM32_UART_USE_USART2) || defined(__DOXYGEN__) +#define STM32_UART_USE_USART2 FALSE +#endif + +/** + * @brief UART driver on USART3 enable switch. + * @details If set to @p TRUE the support for USART3 is included. + * @note The default is @p FALSE. + */ +#if !defined(STM32_UART_USE_USART3) || defined(__DOXYGEN__) +#define STM32_UART_USE_USART3 FALSE +#endif + +/** + * @brief USART1 interrupt priority level setting. + */ +#if !defined(STM32_UART_USART1_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_UART_USART1_IRQ_PRIORITY 12 +#endif + +/** + * @brief USART2 interrupt priority level setting. + */ +#if !defined(STM32_UART_USART2_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_UART_USART2_IRQ_PRIORITY 12 +#endif + +/** + * @brief USART3 interrupt priority level setting. + */ +#if !defined(STM32_UART_USART3_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_UART_USART3_IRQ_PRIORITY 12 +#endif + +/** + * @brief USART1 DMA priority (0..3|lowest..highest). + * @note The priority level is used for both the TX and RX DMA channels but + * because of the channels ordering the RX channel has always priority + * over the TX channel. + */ +#if !defined(STM32_UART_USART1_DMA_PRIORITY) || defined(__DOXYGEN__) +#define STM32_UART_USART1_DMA_PRIORITY 0 +#endif + +/** + * @brief USART2 DMA priority (0..3|lowest..highest). + * @note The priority level is used for both the TX and RX DMA channels but + * because of the channels ordering the RX channel has always priority + * over the TX channel. + */ +#if !defined(STM32_UART_USART2_DMA_PRIORITY) || defined(__DOXYGEN__) +#define STM32_UART_USART2_DMA_PRIORITY 0 +#endif + +/** + * @brief USART3 DMA priority (0..3|lowest..highest). + * @note The priority level is used for both the TX and RX DMA channels but + * because of the channels ordering the RX channel has always priority + * over the TX channel. + */ +#if !defined(STM32_UART_USART3_DMA_PRIORITY) || defined(__DOXYGEN__) +#define STM32_UART_USART3_DMA_PRIORITY 0 +#endif + +/** + * @brief USART1 DMA error hook. + * @note The default action for DMA errors is a system halt because DMA + * error can only happen because programming errors. + */ +#if !defined(STM32_UART_DMA_ERROR_HOOK) || defined(__DOXYGEN__) +#define STM32_UART_DMA_ERROR_HOOK(uartp) osalSysHalt("DMA failure") +#endif + +#if defined(STM32F37X) +/* Fixed values for STM32F3xx devices.*/ +#define STM32_UART_USART1_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 5) +#define STM32_UART_USART1_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) +#define STM32_UART_USART2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 6) +#define STM32_UART_USART2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7) +#define STM32_UART_USART3_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 3) +#define STM32_UART_USART3_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2) +#endif /* defined(STM32F30X) */ +/** @} */ + +/*===========================================================================*/ +/* Derived constants and error checks. */ +/*===========================================================================*/ + +#if STM32_UART_USE_USART1 && !STM32_HAS_USART1 +#error "USART1 not present in the selected device" +#endif + +#if STM32_UART_USE_USART2 && !STM32_HAS_USART2 +#error "USART2 not present in the selected device" +#endif + +#if STM32_UART_USE_USART3 && !STM32_HAS_USART3 +#error "USART3 not present in the selected device" +#endif + +#if !STM32_UART_USE_USART1 && !STM32_UART_USE_USART2 && \ + !STM32_UART_USE_USART3 +#error "UART driver activated but no USART/UART peripheral assigned" +#endif + +#if STM32_UART_USE_USART1 && \ + !CORTEX_IS_VALID_KERNEL_PRIORITY(STM32_UART_USART1_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to USART1" +#endif + +#if STM32_UART_USE_USART2 && \ + !CORTEX_IS_VALID_KERNEL_PRIORITY(STM32_UART_USART2_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to USART2" +#endif + +#if STM32_UART_USE_USART3 && \ + !CORTEX_IS_VALID_KERNEL_PRIORITY(STM32_UART_USART3_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to USART3" +#endif + +#if STM32_UART_USE_USART1 && \ + !STM32_DMA_IS_VALID_PRIORITY(STM32_UART_USART1_DMA_PRIORITY) +#error "Invalid DMA priority assigned to USART1" +#endif + +#if STM32_UART_USE_USART2 && \ + !STM32_DMA_IS_VALID_PRIORITY(STM32_UART_USART2_DMA_PRIORITY) +#error "Invalid DMA priority assigned to USART2" +#endif + +#if STM32_UART_USE_USART3 && \ + !STM32_DMA_IS_VALID_PRIORITY(STM32_UART_USART3_DMA_PRIORITY) +#error "Invalid DMA priority assigned to USART3" +#endif + +/* The following checks are only required when there is a DMA able to + reassign streams to different channels.*/ +#if STM32_ADVANCED_DMA +/* Check on the presence of the DMA streams settings in mcuconf.h.*/ +#if STM32_UART_USE_USART1 && (!defined(STM32_UART_USART1_RX_DMA_STREAM) || \ + !defined(STM32_UART_USART1_TX_DMA_STREAM)) +#error "USART1 DMA streams not defined" +#endif + +#if STM32_UART_USE_USART2 && (!defined(STM32_UART_USART2_RX_DMA_STREAM) || \ + !defined(STM32_UART_USART2_TX_DMA_STREAM)) +#error "USART2 DMA streams not defined" +#endif + +#if STM32_UART_USE_USART3 && (!defined(STM32_UART_USART3_RX_DMA_STREAM) || \ + !defined(STM32_UART_USART3_TX_DMA_STREAM)) +#error "USART3 DMA streams not defined" +#endif + +/* Check on the validity of the assigned DMA channels.*/ +#if STM32_UART_USE_USART1 && \ + !STM32_DMA_IS_VALID_ID(STM32_UART_USART1_RX_DMA_STREAM, \ + STM32_USART1_RX_DMA_MSK) +#error "invalid DMA stream associated to USART1 RX" +#endif + +#if STM32_UART_USE_USART1 && \ + !STM32_DMA_IS_VALID_ID(STM32_UART_USART1_TX_DMA_STREAM, \ + STM32_USART1_TX_DMA_MSK) +#error "invalid DMA stream associated to USART1 TX" +#endif + +#if STM32_UART_USE_USART2 && \ + !STM32_DMA_IS_VALID_ID(STM32_UART_USART2_RX_DMA_STREAM, \ + STM32_USART2_RX_DMA_MSK) +#error "invalid DMA stream associated to USART2 RX" +#endif + +#if STM32_UART_USE_USART2 && \ + !STM32_DMA_IS_VALID_ID(STM32_UART_USART2_TX_DMA_STREAM, \ + STM32_USART2_TX_DMA_MSK) +#error "invalid DMA stream associated to USART2 TX" +#endif + +#if STM32_UART_USE_USART3 && \ + !STM32_DMA_IS_VALID_ID(STM32_UART_USART3_RX_DMA_STREAM, \ + STM32_USART3_RX_DMA_MSK) +#error "invalid DMA stream associated to USART3 RX" +#endif + +#if STM32_UART_USE_USART3 && \ + !STM32_DMA_IS_VALID_ID(STM32_UART_USART3_TX_DMA_STREAM, \ + STM32_USART3_TX_DMA_MSK) +#error "invalid DMA stream associated to USART3 TX" +#endif +#endif /* STM32_ADVANCED_DMA */ + +#if !defined(STM32_DMA_REQUIRED) +#define STM32_DMA_REQUIRED +#endif + +/*===========================================================================*/ +/* Driver data structures and types. */ +/*===========================================================================*/ + +/** + * @brief UART driver condition flags type. + */ +typedef uint32_t uartflags_t; + +/** + * @brief Structure representing an UART driver. + */ +typedef struct UARTDriver UARTDriver; + +/** + * @brief Generic UART notification callback type. + * + * @param[in] uartp pointer to the @p UARTDriver object + */ +typedef void (*uartcb_t)(UARTDriver *uartp); + +/** + * @brief Character received UART notification callback type. + * + * @param[in] uartp pointer to the @p UARTDriver object + * @param[in] c received character + */ +typedef void (*uartccb_t)(UARTDriver *uartp, uint16_t c); + +/** + * @brief Receive error UART notification callback type. + * + * @param[in] uartp pointer to the @p UARTDriver object + * @param[in] e receive error mask + */ +typedef void (*uartecb_t)(UARTDriver *uartp, uartflags_t e); + +/** + * @brief Driver configuration structure. + * @note It could be empty on some architectures. + */ +typedef struct { + /** + * @brief End of transmission buffer callback. + */ + uartcb_t txend1_cb; + /** + * @brief Physical end of transmission callback. + */ + uartcb_t txend2_cb; + /** + * @brief Receive buffer filled callback. + */ + uartcb_t rxend_cb; + /** + * @brief Character received while out if the @p UART_RECEIVE state. + */ + uartccb_t rxchar_cb; + /** + * @brief Receive error callback. + */ + uartecb_t rxerr_cb; + /* End of the mandatory fields.*/ + /** + * @brief Bit rate. + */ + uint32_t speed; + /** + * @brief Initialization value for the CR1 register. + */ + uint32_t cr1; + /** + * @brief Initialization value for the CR2 register. + */ + uint32_t cr2; + /** + * @brief Initialization value for the CR3 register. + */ + uint32_t cr3; +} UARTConfig; + +/** + * @brief Structure representing an UART driver. + */ +struct UARTDriver { + /** + * @brief Driver state. + */ + uartstate_t state; + /** + * @brief Transmitter state. + */ + uarttxstate_t txstate; + /** + * @brief Receiver state. + */ + uartrxstate_t rxstate; + /** + * @brief Current configuration data. + */ + const UARTConfig *config; +#if defined(UART_DRIVER_EXT_FIELDS) + UART_DRIVER_EXT_FIELDS +#endif + /* End of the mandatory fields.*/ + /** + * @brief Pointer to the USART registers block. + */ + USART_TypeDef *usart; + /** + * @brief DMA mode bit mask. + */ + uint32_t dmamode; + /** + * @brief Receive DMA channel. + */ + const stm32_dma_stream_t *dmarx; + /** + * @brief Transmit DMA channel. + */ + const stm32_dma_stream_t *dmatx; + /** + * @brief Default receive buffer while into @p UART_RX_IDLE state. + */ + volatile uint16_t rxbuf; +}; + +/*===========================================================================*/ +/* Driver macros. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +#if STM32_UART_USE_USART1 && !defined(__DOXYGEN__) +extern UARTDriver UARTD1; +#endif + +#if STM32_UART_USE_USART2 && !defined(__DOXYGEN__) +extern UARTDriver UARTD2; +#endif + +#if STM32_UART_USE_USART3 && !defined(__DOXYGEN__) +extern UARTDriver UARTD3; +#endif + +#ifdef __cplusplus +extern "C" { +#endif + void uart_lld_init(void); + void uart_lld_start(UARTDriver *uartp); + void uart_lld_stop(UARTDriver *uartp); + void uart_lld_start_send(UARTDriver *uartp, size_t n, const void *txbuf); + size_t uart_lld_stop_send(UARTDriver *uartp); + void uart_lld_start_receive(UARTDriver *uartp, size_t n, void *rxbuf); + size_t uart_lld_stop_receive(UARTDriver *uartp); +#ifdef __cplusplus +} +#endif + +#endif /* HAL_USE_UART */ + +#endif /* _UART_LLD_H_ */ + +/** @} */ diff --git a/os/hal/ports/STM32/USBv1/stm32_usb.h b/os/hal/ports/STM32/USBv1/stm32_usb.h new file mode 100644 index 000000000..83f349e42 --- /dev/null +++ b/os/hal/ports/STM32/USBv1/stm32_usb.h @@ -0,0 +1,243 @@ +/* + ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file stm32_usb.h + * @brief STM32 USB registers layout header. + * @note This file requires definitions from the ST STM32 header files + * stm32f10x.h or stm32l1xx.h. + * + * @addtogroup USB + * @{ + */ + +#ifndef _STM32_USB_H_ +#define _STM32_USB_H_ + +/** + * @brief Number of the available endpoints. + * @details This value does not include the endpoint 0 which is always present. + */ +#define USB_ENDOPOINTS_NUMBER 7 + +/** + * @brief USB registers block. + */ +typedef struct { + /** + * @brief Endpoint registers. + */ + volatile uint32_t EPR[USB_ENDOPOINTS_NUMBER + 1]; + /* + * @brief Reserved space. + */ + volatile uint32_t _r20[8]; + /* + * @brief Control Register. + */ + volatile uint32_t CNTR; + /* + * @brief Interrupt Status Register. + */ + volatile uint32_t ISTR; + /* + * @brief Frame Number Register. + */ + volatile uint32_t FNR; + /* + * @brief Device Address Register. + */ + volatile uint32_t DADDR; + /* + * @brief Buffer Table Address. + */ + volatile uint32_t BTABLE; +} stm32_usb_t; + +/** + * @brief USB descriptor registers block. + */ +typedef struct { + /** + * @brief TX buffer offset register. + */ + volatile uint32_t TXADDR0; + /** + * @brief TX counter register 0. + */ + volatile uint16_t TXCOUNT0; + /** + * @brief TX counter register 1. + */ + volatile uint16_t TXCOUNT1; + /** + * @brief RX buffer offset register. + */ + volatile uint32_t RXADDR0; + /** + * @brief RX counter register 0. + */ + volatile uint16_t RXCOUNT0; + /** + * @brief RX counter register 1. + */ + volatile uint16_t RXCOUNT1; +} stm32_usb_descriptor_t; + +/** + * @name Register aliases + * @{ + */ +#define RXADDR1 TXADDR0 +#define TXADDR1 RXADDR0 +/** @} */ + +/** + * @brief USB registers block numeric address. + */ +#define STM32_USB_BASE (APB1PERIPH_BASE + 0x5C00) + +/** + * @brief USB RAM numeric address. + */ +#define STM32_USBRAM_BASE (APB1PERIPH_BASE + 0x6000) + +/** + * @brief Pointer to the USB registers block. + */ +#define STM32_USB ((stm32_usb_t *)STM32_USB_BASE) + +/** + * @brief Pointer to the USB RAM. + */ +#define STM32_USBRAM ((uint32_t *)STM32_USBRAM_BASE) + +/** + * @brief Size of the dedicated packet memory. + */ +#define USB_PMA_SIZE 512 + +/** + * @brief Mask of all the toggling bits in the EPR register. + */ +#define EPR_TOGGLE_MASK (EPR_STAT_TX_MASK | EPR_DTOG_TX | \ + EPR_STAT_RX_MASK | EPR_DTOG_RX | \ + EPR_SETUP) + +#define EPR_EA_MASK 0x000F +#define EPR_STAT_TX_MASK 0x0030 +#define EPR_STAT_TX_DIS 0x0000 +#define EPR_STAT_TX_STALL 0x0010 +#define EPR_STAT_TX_NAK 0x0020 +#define EPR_STAT_TX_VALID 0x0030 +#define EPR_DTOG_TX 0x0040 +#define EPR_SWBUF_RX EPR_DTOG_TX +#define EPR_CTR_TX 0x0080 +#define EPR_EP_KIND 0x0100 +#define EPR_EP_DBL_BUF EPR_EP_KIND +#define EPR_EP_STATUS_OUT EPR_EP_KIND +#define EPR_EP_TYPE_MASK 0x0600 +#define EPR_EP_TYPE_BULK 0x0000 +#define EPR_EP_TYPE_CONTROL 0x0200 +#define EPR_EP_TYPE_ISO 0x0400 +#define EPR_EP_TYPE_INTERRUPT 0x0600 +#define EPR_SETUP 0x0800 +#define EPR_STAT_RX_MASK 0x3000 +#define EPR_STAT_RX_DIS 0x0000 +#define EPR_STAT_RX_STALL 0x1000 +#define EPR_STAT_RX_NAK 0x2000 +#define EPR_STAT_RX_VALID 0x3000 +#define EPR_DTOG_RX 0x4000 +#define EPR_SWBUF_TX EPR_DTOG_RX +#define EPR_CTR_RX 0x8000 + +#define CNTR_FRES 0x0001 +#define CNTR_PDWN 0x0002 +#define CNTR_LP_MODE 0x0004 +#define CNTR_FSUSP 0x0008 +#define CNTR_RESUME 0x0010 +#define CNTR_ESOFM 0x0100 +#define CNTR_SOFM 0x0200 +#define CNTR_RESETM 0x0400 +#define CNTR_SUSPM 0x0800 +#define CNTR_WKUPM 0x1000 +#define CNTR_ERRM 0x2000 +#define CNTR_PMAOVRM 0x4000 +#define CNTR_CTRM 0x8000 + +#define ISTR_EP_ID_MASK 0x000F +#define ISTR_DIR 0x0010 +#define ISTR_ESOF 0x0100 +#define ISTR_SOF 0x0200 +#define ISTR_RESET 0x0400 +#define ISTR_SUSP 0x0800 +#define ISTR_WKUP 0x1000 +#define ISTR_ERR 0x2000 +#define ISTR_PMAOVR 0x4000 +#define ISTR_CTR 0x8000 + +#define FNR_FN_MASK 0x07FF +#define FNR_LSOF 0x1800 +#define FNR_LCK 0x2000 +#define FNR_RXDM 0x4000 +#define FNR_RXDP 0x8000 + +#define DADDR_ADD_MASK 0x007F +#define DADDR_EF 0x0080 + +#define RXCOUNT_COUNT_MASK 0x03FF +#define TXCOUNT_COUNT_MASK 0x03FF + +#define EPR_SET(ep, epr) \ + STM32_USB->EPR[ep] = (epr) & ~EPR_TOGGLE_MASK + +#define EPR_TOGGLE(ep, epr) \ + STM32_USB->EPR[ep] = (STM32_USB->EPR[ep] ^ ((epr) & EPR_TOGGLE_MASK)) + +#define EPR_SET_STAT_RX(ep, epr) \ + STM32_USB->EPR[ep] = (STM32_USB->EPR[ep] & \ + ~(EPR_TOGGLE_MASK & ~EPR_STAT_RX_MASK)) ^ \ + (epr) + +#define EPR_SET_STAT_TX(ep, epr) \ + STM32_USB->EPR[ep] = (STM32_USB->EPR[ep] & \ + ~(EPR_TOGGLE_MASK & ~EPR_STAT_TX_MASK)) ^ \ + (epr) + +#define EPR_CLEAR_CTR_RX(ep) \ + STM32_USB->EPR[ep] &= ~EPR_CTR_RX & ~EPR_TOGGLE_MASK + +#define EPR_CLEAR_CTR_TX(ep) \ + STM32_USB->EPR[ep] &= ~EPR_CTR_TX & ~EPR_TOGGLE_MASK + +/** + * @brief Returns an endpoint descriptor pointer. + */ +#define USB_GET_DESCRIPTOR(ep) \ + ((stm32_usb_descriptor_t *)((uint32_t)STM32_USBRAM_BASE + \ + (uint32_t)STM32_USB->BTABLE * 2 + \ + (uint32_t)(ep) * \ + sizeof(stm32_usb_descriptor_t))) + +/** + * @brief Converts from a PMA address to a physical address. + */ +#define USB_ADDR2PTR(addr) \ + ((uint32_t *)((addr) * 2 + STM32_USBRAM_BASE)) + +#endif /* _STM32_USB_H_ */ + +/** @} */ diff --git a/os/hal/ports/STM32/USBv1/usb_lld.c b/os/hal/ports/STM32/USBv1/usb_lld.c new file mode 100644 index 000000000..1a44a678f --- /dev/null +++ b/os/hal/ports/STM32/USBv1/usb_lld.c @@ -0,0 +1,824 @@ +/* + ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file STM32/USBv1/usb_lld.c + * @brief STM32 USB subsystem low level driver source. + * + * @addtogroup USB + * @{ + */ + +#include + +#include "hal.h" + +#if HAL_USE_USB || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver local definitions. */ +/*===========================================================================*/ + +#define BTABLE_ADDR 0x0000 + +/*===========================================================================*/ +/* Driver exported variables. */ +/*===========================================================================*/ + +/** @brief USB1 driver identifier.*/ +#if STM32_USB_USE_USB1 || defined(__DOXYGEN__) +USBDriver USBD1; +#endif + +/*===========================================================================*/ +/* Driver local variables and types. */ +/*===========================================================================*/ + +/** + * @brief EP0 state. + * @note It is an union because IN and OUT endpoints are never used at the + * same time for EP0. + */ +static union { + /** + * @brief IN EP0 state. + */ + USBInEndpointState in; + /** + * @brief OUT EP0 state. + */ + USBOutEndpointState out; +} ep0_state; + +/** + * @brief Buffer for the EP0 setup packets. + */ +static uint8_t ep0setup_buffer[8]; + +/** + * @brief EP0 initialization structure. + */ +static const USBEndpointConfig ep0config = { + USB_EP_MODE_TYPE_CTRL, + _usb_ep0setup, + _usb_ep0in, + _usb_ep0out, + 0x40, + 0x40, + &ep0_state.in, + &ep0_state.out, + 1, + ep0setup_buffer +}; + +/*===========================================================================*/ +/* Driver local functions. */ +/*===========================================================================*/ + +/** + * @brief Resets the packet memory allocator. + * + * @param[in] usbp pointer to the @p USBDriver object + */ +static void usb_pm_reset(USBDriver *usbp) { + + /* The first 64 bytes are reserved for the descriptors table. The effective + available RAM for endpoint buffers is just 448 bytes.*/ + usbp->pmnext = 64; +} + +/** + * @brief Resets the packet memory allocator. + * + * @param[in] usbp pointer to the @p USBDriver object + * @param[in] size size of the packet buffer to allocate + */ +static uint32_t usb_pm_alloc(USBDriver *usbp, size_t size) { + uint32_t next; + + next = usbp->pmnext; + usbp->pmnext += size; + osalDbgAssert(usbp->pmnext <= USB_PMA_SIZE, "PMA overflow"); + return next; +} + +/** + * @brief Reads from a dedicated packet buffer. + * + * @param[in] udp pointer to a @p stm32_usb_descriptor_t + * @param[out] buf buffer where to copy the packet data + * @param[in] n maximum number of bytes to copy. This value must + * not exceed the maximum packet size for this endpoint. + * + * @notapi + */ +static void usb_packet_read_to_buffer(stm32_usb_descriptor_t *udp, + uint8_t *buf, size_t n) { + uint32_t *pmap= USB_ADDR2PTR(udp->RXADDR0); + + n = (n + 1) / 2; + while (n > 0) { + /* Note, this line relies on the Cortex-M3/M4 ability to perform + unaligned word accesses.*/ + *(uint16_t *)buf = (uint16_t)*pmap++; + buf += 2; + n--; + } +} + +/** + * @brief Reads from a dedicated packet buffer. + * + * @param[in] udp pointer to a @p stm32_usb_descriptor_t + * @param[in] iqp pointer to an @p input_queue_t object + * @param[in] n maximum number of bytes to copy. This value must + * not exceed the maximum packet size for this endpoint. + * + * @notapi + */ +static void usb_packet_read_to_queue(stm32_usb_descriptor_t *udp, + input_queue_t *iqp, size_t n) { + size_t nhw; + uint32_t *pmap= USB_ADDR2PTR(udp->RXADDR0); + + nhw = n / 2; + while (nhw > 0) { + uint32_t w; + + w = *pmap++; + *iqp->q_wrptr++ = (uint8_t)w; + if (iqp->q_wrptr >= iqp->q_top) + iqp->q_wrptr = iqp->q_buffer; + *iqp->q_wrptr++ = (uint8_t)(w >> 8); + if (iqp->q_wrptr >= iqp->q_top) + iqp->q_wrptr = iqp->q_buffer; + nhw--; + } + /* Last byte for odd numbers.*/ + if ((n & 1) != 0) { + *iqp->q_wrptr++ = (uint8_t)*pmap; + if (iqp->q_wrptr >= iqp->q_top) + iqp->q_wrptr = iqp->q_buffer; + } + + /* Updating queue.*/ + osalSysLockFromISR(); + + iqp->q_counter += n; + osalQueueWakeupAllI(&iqp->q_waiting, Q_OK); + + osalSysUnlockFromISR(); +} + +/** + * @brief Writes to a dedicated packet buffer. + * + * @param[in] udp pointer to a @p stm32_usb_descriptor_t + * @param[in] buf buffer where to fetch the packet data + * @param[in] n maximum number of bytes to copy. This value must + * not exceed the maximum packet size for this endpoint. + * + * @notapi + */ +static void usb_packet_write_from_buffer(stm32_usb_descriptor_t *udp, + const uint8_t *buf, + size_t n) { + uint32_t *pmap = USB_ADDR2PTR(udp->TXADDR0); + + udp->TXCOUNT0 = (uint16_t)n; + n = (n + 1) / 2; + while (n > 0) { + /* Note, this line relies on the Cortex-M3/M4 ability to perform + unaligned word accesses.*/ + *pmap++ = *(uint16_t *)buf; + buf += 2; + n--; + } +} + +/** + * @brief Writes to a dedicated packet buffer. + * + * @param[in] udp pointer to a @p stm32_usb_descriptor_t + * @param[in] buf buffer where to fetch the packet data + * @param[in] n maximum number of bytes to copy. This value must + * not exceed the maximum packet size for this endpoint. + * + * @notapi + */ +static void usb_packet_write_from_queue(stm32_usb_descriptor_t *udp, + output_queue_t *oqp, size_t n) { + size_t nhw; + syssts_t sts; + uint32_t *pmap = USB_ADDR2PTR(udp->TXADDR0); + + udp->TXCOUNT0 = (uint16_t)n; + nhw = n / 2; + while (nhw > 0) { + uint32_t w; + + w = (uint32_t)*oqp->q_rdptr++; + if (oqp->q_rdptr >= oqp->q_top) + oqp->q_rdptr = oqp->q_buffer; + w |= (uint32_t)*oqp->q_rdptr++ << 8; + if (oqp->q_rdptr >= oqp->q_top) + oqp->q_rdptr = oqp->q_buffer; + *pmap++ = w; + nhw--; + } + + /* Last byte for odd numbers.*/ + if ((n & 1) != 0) { + *pmap = (uint32_t)*oqp->q_rdptr++; + if (oqp->q_rdptr >= oqp->q_top) + oqp->q_rdptr = oqp->q_buffer; + } + + /* Updating queue.*/ + sts = osalSysGetStatusAndLockX(); + + oqp->q_counter += n; + osalQueueWakeupAllI(&oqp->q_waiting, Q_OK); + + osalSysRestoreStatusX(sts); +} + +/*===========================================================================*/ +/* Driver interrupt handlers. */ +/*===========================================================================*/ + +#if STM32_USB_USE_USB1 || defined(__DOXYGEN__) +#if !defined(STM32_USB1_HP_HANDLER) +#error "STM32_USB1_HP_HANDLER not defined" +#endif +/** + * @brief USB high priority interrupt handler. + * + * @isr + */ +CH_IRQ_HANDLER(STM32_USB1_HP_HANDLER) { + + CH_IRQ_PROLOGUE(); + + CH_IRQ_EPILOGUE(); +} + +#if !defined(STM32_USB1_LP_HANDLER) +#error "STM32_USB1_LP_HANDLER not defined" +#endif +/** + * @brief USB low priority interrupt handler. + * + * @isr + */ +CH_IRQ_HANDLER(STM32_USB1_LP_HANDLER) { + uint32_t istr; + USBDriver *usbp = &USBD1; + + CH_IRQ_PROLOGUE(); + + istr = STM32_USB->ISTR; + + /* USB bus reset condition handling.*/ + if (istr & ISTR_RESET) { + _usb_reset(usbp); + _usb_isr_invoke_event_cb(usbp, USB_EVENT_RESET); + STM32_USB->ISTR = ~ISTR_RESET; + } + + /* USB bus SUSPEND condition handling.*/ + if (istr & ISTR_SUSP) { + STM32_USB->CNTR |= CNTR_FSUSP; + _usb_isr_invoke_event_cb(usbp, USB_EVENT_SUSPEND); +#if STM32_USB_LOW_POWER_ON_SUSPEND + STM32_USB->CNTR |= CNTR_LP_MODE; +#endif + STM32_USB->ISTR = ~ISTR_SUSP; + } + + /* USB bus WAKEUP condition handling.*/ + if (istr & ISTR_WKUP) { + uint32_t fnr = STM32_USB->FNR; + if (!(fnr & FNR_RXDP)) { + STM32_USB->CNTR &= ~CNTR_FSUSP; + _usb_isr_invoke_event_cb(usbp, USB_EVENT_WAKEUP); + } +#if STM32_USB_LOW_POWER_ON_SUSPEND + else { + /* Just noise, going back in SUSPEND mode, reference manual 22.4.5, + table 169.*/ + STM32_USB->CNTR |= CNTR_LP_MODE; + } +#endif + STM32_USB->ISTR = ~ISTR_WKUP; + } + + /* SOF handling.*/ + if (istr & ISTR_SOF) { + _usb_isr_invoke_sof_cb(usbp); + STM32_USB->ISTR = ~ISTR_SOF; + } + + /* Endpoint events handling.*/ + while (istr & ISTR_CTR) { + size_t n; + uint32_t ep; + uint32_t epr = STM32_USB->EPR[ep = istr & ISTR_EP_ID_MASK]; + const USBEndpointConfig *epcp = usbp->epc[ep]; + + if (epr & EPR_CTR_TX) { + size_t transmitted; + /* IN endpoint, transmission.*/ + EPR_CLEAR_CTR_TX(ep); + + transmitted = (size_t)USB_GET_DESCRIPTOR(ep)->TXCOUNT0; + epcp->in_state->txcnt += transmitted; + n = epcp->in_state->txsize - epcp->in_state->txcnt; + if (n > 0) { + /* Transfer not completed, there are more packets to send.*/ + if (n > epcp->in_maxsize) + n = epcp->in_maxsize; + + if (epcp->in_state->txqueued) + usb_packet_write_from_queue(USB_GET_DESCRIPTOR(ep), + epcp->in_state->mode.queue.txqueue, + n); + else { + epcp->in_state->mode.linear.txbuf += transmitted; + usb_packet_write_from_buffer(USB_GET_DESCRIPTOR(ep), + epcp->in_state->mode.linear.txbuf, + n); + } + osalSysLockFromISR(); + usb_lld_start_in(usbp, ep); + osalSysUnlockFromISR(); + } + else { + /* Transfer completed, invokes the callback.*/ + _usb_isr_invoke_in_cb(usbp, ep); + } + } + if (epr & EPR_CTR_RX) { + EPR_CLEAR_CTR_RX(ep); + /* OUT endpoint, receive.*/ + if (epr & EPR_SETUP) { + /* Setup packets handling, setup packets are handled using a + specific callback.*/ + _usb_isr_invoke_setup_cb(usbp, ep); + } + else { + stm32_usb_descriptor_t *udp = USB_GET_DESCRIPTOR(ep); + n = (size_t)udp->RXCOUNT0 & RXCOUNT_COUNT_MASK; + + /* Reads the packet into the defined buffer.*/ + if (epcp->out_state->rxqueued) + usb_packet_read_to_queue(udp, + epcp->out_state->mode.queue.rxqueue, + n); + else { + usb_packet_read_to_buffer(udp, + epcp->out_state->mode.linear.rxbuf, + n); + epcp->out_state->mode.linear.rxbuf += n; + } + /* Transaction data updated.*/ + epcp->out_state->rxcnt += n; + epcp->out_state->rxsize -= n; + epcp->out_state->rxpkts -= 1; + + /* The transaction is completed if the specified number of packets + has been received or the current packet is a short packet.*/ + if ((n < epcp->out_maxsize) || (epcp->out_state->rxpkts == 0)) { + /* Transfer complete, invokes the callback.*/ + _usb_isr_invoke_out_cb(usbp, ep); + } + else { + /* Transfer not complete, there are more packets to receive.*/ + EPR_SET_STAT_RX(ep, EPR_STAT_RX_VALID); + } + } + } + istr = STM32_USB->ISTR; + } + + CH_IRQ_EPILOGUE(); +} +#endif + +/*===========================================================================*/ +/* Driver exported functions. */ +/*===========================================================================*/ + +/** + * @brief Low level USB driver initialization. + * + * @notapi + */ +void usb_lld_init(void) { + + /* Driver initialization.*/ + usbObjectInit(&USBD1); +} + +/** + * @brief Configures and activates the USB peripheral. + * + * @param[in] usbp pointer to the @p USBDriver object + * + * @notapi + */ +void usb_lld_start(USBDriver *usbp) { + + if (usbp->state == USB_STOP) { + /* Clock activation.*/ +#if STM32_USB_USE_USB1 + if (&USBD1 == usbp) { + /* USB clock enabled.*/ + rccEnableUSB(FALSE); + /* Powers up the transceiver while holding the USB in reset state.*/ + STM32_USB->CNTR = CNTR_FRES; + /* Enabling the USB IRQ vectors, this also gives enough time to allow + the transceiver power up (1uS).*/ + nvicEnableVector(STM32_USB1_HP_NUMBER, STM32_USB_USB1_HP_IRQ_PRIORITY); + nvicEnableVector(STM32_USB1_LP_NUMBER, STM32_USB_USB1_LP_IRQ_PRIORITY); + /* Releases the USB reset.*/ + STM32_USB->CNTR = 0; + } +#endif + /* Reset procedure enforced on driver start.*/ + _usb_reset(usbp); + } + /* Configuration.*/ +} + +/** + * @brief Deactivates the USB peripheral. + * + * @param[in] usbp pointer to the @p USBDriver object + * + * @notapi + */ +void usb_lld_stop(USBDriver *usbp) { + + /* If in ready state then disables the USB clock.*/ + if (usbp->state == USB_STOP) { +#if STM32_USB_USE_USB1 + if (&USBD1 == usbp) { + nvicDisableVector(STM32_USB1_HP_NUMBER); + nvicDisableVector(STM32_USB1_LP_NUMBER); + STM32_USB->CNTR = CNTR_PDWN | CNTR_FRES; + rccDisableUSB(FALSE); + } +#endif + } +} + +/** + * @brief USB low level reset routine. + * + * @param[in] usbp pointer to the @p USBDriver object + * + * @notapi + */ +void usb_lld_reset(USBDriver *usbp) { + uint32_t cntr; + + /* Post reset initialization.*/ + STM32_USB->BTABLE = 0; + STM32_USB->ISTR = 0; + STM32_USB->DADDR = DADDR_EF; + cntr = /*CNTR_ESOFM | */ CNTR_RESETM | CNTR_SUSPM | + CNTR_WKUPM | /*CNTR_ERRM | CNTR_PMAOVRM |*/ CNTR_CTRM; + /* The SOF interrupt is only enabled if a callback is defined for + this service because it is an high rate source.*/ + if (usbp->config->sof_cb != NULL) + cntr |= CNTR_SOFM; + STM32_USB->CNTR = cntr; + + /* Resets the packet memory allocator.*/ + usb_pm_reset(usbp); + + /* EP0 initialization.*/ + usbp->epc[0] = &ep0config; + usb_lld_init_endpoint(usbp, 0); +} + +/** + * @brief Sets the USB address. + * + * @param[in] usbp pointer to the @p USBDriver object + * + * @notapi + */ +void usb_lld_set_address(USBDriver *usbp) { + + STM32_USB->DADDR = (uint32_t)(usbp->address) | DADDR_EF; +} + +/** + * @brief Enables an endpoint. + * + * @param[in] usbp pointer to the @p USBDriver object + * @param[in] ep endpoint number + * + * @notapi + */ +void usb_lld_init_endpoint(USBDriver *usbp, usbep_t ep) { + uint16_t nblocks, epr; + stm32_usb_descriptor_t *dp; + const USBEndpointConfig *epcp = usbp->epc[ep]; + + /* Setting the endpoint type.*/ + switch (epcp->ep_mode & USB_EP_MODE_TYPE) { + case USB_EP_MODE_TYPE_ISOC: + epr = EPR_EP_TYPE_ISO; + break; + case USB_EP_MODE_TYPE_BULK: + epr = EPR_EP_TYPE_BULK; + break; + case USB_EP_MODE_TYPE_INTR: + epr = EPR_EP_TYPE_INTERRUPT; + break; + default: + epr = EPR_EP_TYPE_CONTROL; + } + + /* IN endpoint initially in NAK mode.*/ + if (epcp->in_cb != NULL) + epr |= EPR_STAT_TX_NAK; + + /* OUT endpoint initially in NAK mode.*/ + if (epcp->out_cb != NULL) + epr |= EPR_STAT_RX_NAK; + + /* EPxR register setup.*/ + EPR_SET(ep, epr | ep); + EPR_TOGGLE(ep, epr); + + /* Endpoint size and address initialization.*/ + if (epcp->out_maxsize > 62) + nblocks = (((((epcp->out_maxsize - 1) | 0x1f) + 1) / 32) << 10) | + 0x8000; + else + nblocks = ((((epcp->out_maxsize - 1) | 1) + 1) / 2) << 10; + dp = USB_GET_DESCRIPTOR(ep); + dp->TXCOUNT0 = 0; + dp->RXCOUNT0 = nblocks; + dp->TXADDR0 = usb_pm_alloc(usbp, epcp->in_maxsize); + dp->RXADDR0 = usb_pm_alloc(usbp, epcp->out_maxsize); +} + +/** + * @brief Disables all the active endpoints except the endpoint zero. + * + * @param[in] usbp pointer to the @p USBDriver object + * + * @notapi + */ +void usb_lld_disable_endpoints(USBDriver *usbp) { + unsigned i; + + /* Resets the packet memory allocator.*/ + usb_pm_reset(usbp); + + /* Disabling all endpoints.*/ + for (i = 1; i <= USB_ENDOPOINTS_NUMBER; i++) { + EPR_TOGGLE(i, 0); + EPR_SET(i, 0); + } +} + +/** + * @brief Returns the status of an OUT endpoint. + * + * @param[in] usbp pointer to the @p USBDriver object + * @param[in] ep endpoint number + * @return The endpoint status. + * @retval EP_STATUS_DISABLED The endpoint is not active. + * @retval EP_STATUS_STALLED The endpoint is stalled. + * @retval EP_STATUS_ACTIVE The endpoint is active. + * + * @notapi + */ +usbepstatus_t usb_lld_get_status_out(USBDriver *usbp, usbep_t ep) { + + (void)usbp; + switch (STM32_USB->EPR[ep] & EPR_STAT_RX_MASK) { + case EPR_STAT_RX_DIS: + return EP_STATUS_DISABLED; + case EPR_STAT_RX_STALL: + return EP_STATUS_STALLED; + default: + return EP_STATUS_ACTIVE; + } +} + +/** + * @brief Returns the status of an IN endpoint. + * + * @param[in] usbp pointer to the @p USBDriver object + * @param[in] ep endpoint number + * @return The endpoint status. + * @retval EP_STATUS_DISABLED The endpoint is not active. + * @retval EP_STATUS_STALLED The endpoint is stalled. + * @retval EP_STATUS_ACTIVE The endpoint is active. + * + * @notapi + */ +usbepstatus_t usb_lld_get_status_in(USBDriver *usbp, usbep_t ep) { + + (void)usbp; + switch (STM32_USB->EPR[ep] & EPR_STAT_TX_MASK) { + case EPR_STAT_TX_DIS: + return EP_STATUS_DISABLED; + case EPR_STAT_TX_STALL: + return EP_STATUS_STALLED; + default: + return EP_STATUS_ACTIVE; + } +} + +/** + * @brief Reads a setup packet from the dedicated packet buffer. + * @details This function must be invoked in the context of the @p setup_cb + * callback in order to read the received setup packet. + * @pre In order to use this function the endpoint must have been + * initialized as a control endpoint. + * @post The endpoint is ready to accept another packet. + * + * @param[in] usbp pointer to the @p USBDriver object + * @param[in] ep endpoint number + * @param[out] buf buffer where to copy the packet data + * + * @notapi + */ +void usb_lld_read_setup(USBDriver *usbp, usbep_t ep, uint8_t *buf) { + uint32_t *pmap; + stm32_usb_descriptor_t *udp; + uint32_t n; + + (void)usbp; + udp = USB_GET_DESCRIPTOR(ep); + pmap = USB_ADDR2PTR(udp->RXADDR0); + for (n = 0; n < 4; n++) { + *(uint16_t *)buf = (uint16_t)*pmap++; + buf += 2; + } +} + +/** + * @brief Prepares for a receive operation. + * + * @param[in] usbp pointer to the @p USBDriver object + * @param[in] ep endpoint number + * + * @notapi + */ +void usb_lld_prepare_receive(USBDriver *usbp, usbep_t ep) { + USBOutEndpointState *osp = usbp->epc[ep]->out_state; + + /* Transfer initialization.*/ + if (osp->rxsize == 0) /* Special case for zero sized packets.*/ + osp->rxpkts = 1; + else + osp->rxpkts = (uint16_t)((osp->rxsize + usbp->epc[ep]->out_maxsize - 1) / + usbp->epc[ep]->out_maxsize); +} + +/** + * @brief Prepares for a transmit operation. + * + * @param[in] usbp pointer to the @p USBDriver object + * @param[in] ep endpoint number + * + * @notapi + */ +void usb_lld_prepare_transmit(USBDriver *usbp, usbep_t ep) { + size_t n; + USBInEndpointState *isp = usbp->epc[ep]->in_state; + + /* Transfer initialization.*/ + n = isp->txsize; + if (n > (size_t)usbp->epc[ep]->in_maxsize) + n = (size_t)usbp->epc[ep]->in_maxsize; + + if (isp->txqueued) + usb_packet_write_from_queue(USB_GET_DESCRIPTOR(ep), + isp->mode.queue.txqueue, n); + else + usb_packet_write_from_buffer(USB_GET_DESCRIPTOR(ep), + isp->mode.linear.txbuf, n); +} + +/** + * @brief Starts a receive operation on an OUT endpoint. + * + * @param[in] usbp pointer to the @p USBDriver object + * @param[in] ep endpoint number + * + * @notapi + */ +void usb_lld_start_out(USBDriver *usbp, usbep_t ep) { + + (void)usbp; + + EPR_SET_STAT_RX(ep, EPR_STAT_RX_VALID); +} + +/** + * @brief Starts a transmit operation on an IN endpoint. + * + * @param[in] usbp pointer to the @p USBDriver object + * @param[in] ep endpoint number + * + * @notapi + */ +void usb_lld_start_in(USBDriver *usbp, usbep_t ep) { + + (void)usbp; + + EPR_SET_STAT_TX(ep, EPR_STAT_TX_VALID); +} + +/** + * @brief Brings an OUT endpoint in the stalled state. + * + * @param[in] usbp pointer to the @p USBDriver object + * @param[in] ep endpoint number + * + * @notapi + */ +void usb_lld_stall_out(USBDriver *usbp, usbep_t ep) { + + (void)usbp; + + EPR_SET_STAT_RX(ep, EPR_STAT_RX_STALL); +} + +/** + * @brief Brings an IN endpoint in the stalled state. + * + * @param[in] usbp pointer to the @p USBDriver object + * @param[in] ep endpoint number + * + * @notapi + */ +void usb_lld_stall_in(USBDriver *usbp, usbep_t ep) { + + (void)usbp; + + EPR_SET_STAT_TX(ep, EPR_STAT_TX_STALL); +} + +/** + * @brief Brings an OUT endpoint in the active state. + * + * @param[in] usbp pointer to the @p USBDriver object + * @param[in] ep endpoint number + * + * @notapi + */ +void usb_lld_clear_out(USBDriver *usbp, usbep_t ep) { + + (void)usbp; + + /* Makes sure to not put to NAK an endpoint that is already + transferring.*/ + if ((STM32_USB->EPR[ep] & EPR_STAT_RX_MASK) != EPR_STAT_RX_VALID) + EPR_SET_STAT_TX(ep, EPR_STAT_RX_NAK); +} + +/** + * @brief Brings an IN endpoint in the active state. + * + * @param[in] usbp pointer to the @p USBDriver object + * @param[in] ep endpoint number + * + * @notapi + */ +void usb_lld_clear_in(USBDriver *usbp, usbep_t ep) { + + (void)usbp; + + /* Makes sure to not put to NAK an endpoint that is already + transferring.*/ + if ((STM32_USB->EPR[ep] & EPR_STAT_TX_MASK) != EPR_STAT_TX_VALID) + EPR_SET_STAT_TX(ep, EPR_STAT_TX_NAK); +} + +#endif /* HAL_USE_USB */ + +/** @} */ diff --git a/os/hal/ports/STM32/USBv1/usb_lld.h b/os/hal/ports/STM32/USBv1/usb_lld.h new file mode 100644 index 000000000..042129758 --- /dev/null +++ b/os/hal/ports/STM32/USBv1/usb_lld.h @@ -0,0 +1,437 @@ +/* + ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file STM32/USBv1/usb_lld.h + * @brief STM32 USB subsystem low level driver header. + * + * @addtogroup USB + * @{ + */ + +#ifndef _USB_LLD_H_ +#define _USB_LLD_H_ + +#if HAL_USE_USB || defined(__DOXYGEN__) + +#include "stm32_usb.h" + +/*===========================================================================*/ +/* Driver constants. */ +/*===========================================================================*/ + +/** + * @brief Maximum endpoint address. + */ +#define USB_MAX_ENDPOINTS USB_ENDOPOINTS_NUMBER + +/** + * @brief This device requires the address change after the status packet. + */ +#define USB_SET_ADDRESS_MODE USB_LATE_SET_ADDRESS + +/*===========================================================================*/ +/* Driver pre-compile time settings. */ +/*===========================================================================*/ + +/** + * @brief USB1 driver enable switch. + * @details If set to @p TRUE the support for USB1 is included. + * @note The default is @p TRUE. + */ +#if !defined(STM32_USB_USE_USB1) || defined(__DOXYGEN__) +#define STM32_USB_USE_USB1 FALSE +#endif + +/** + * @brief Enables the USB device low power mode on suspend. + */ +#if !defined(STM32_USB_LOW_POWER_ON_SUSPEND) || defined(__DOXYGEN__) +#define STM32_USB_LOW_POWER_ON_SUSPEND FALSE +#endif + +/** + * @brief USB1 interrupt priority level setting. + */ +#if !defined(STM32_USB_USB1_HP_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_USB_USB1_HP_IRQ_PRIORITY 13 +#endif + +/** + * @brief USB1 interrupt priority level setting. + */ +#if !defined(STM32_USB_USB1_LP_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_USB_USB1_LP_IRQ_PRIORITY 14 +#endif + +/*===========================================================================*/ +/* Derived constants and error checks. */ +/*===========================================================================*/ + +#if STM32_USB_USE_USB1 && !STM32_HAS_USB +#error "USB not present in the selected device" +#endif + +#if !STM32_USB_USE_USB1 +#error "USB driver activated but no USB peripheral assigned" +#endif + +#if STM32_USB_USE_USB1 && \ + !CORTEX_IS_VALID_KERNEL_PRIORITY(STM32_USB_USB1_HP_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to USB HP" +#endif + +#if STM32_USB_USE_USB1 && \ + !CORTEX_IS_VALID_KERNEL_PRIORITY(STM32_USB_USB1_LP_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to USB LP" +#endif + +#if STM32_USBCLK != 48000000 +#error "the USB driver requires a 48MHz clock" +#endif + +/*===========================================================================*/ +/* Driver data structures and types. */ +/*===========================================================================*/ + +/** + * @brief Type of an IN endpoint state structure. + */ +typedef struct { + /** + * @brief Buffer mode, queue or linear. + */ + bool txqueued; + /** + * @brief Requested transmit transfer size. + */ + size_t txsize; + /** + * @brief Transmitted bytes so far. + */ + size_t txcnt; + union { + struct { + /** + * @brief Pointer to the transmission linear buffer. + */ + const uint8_t *txbuf; + } linear; + struct { + /** + * @brief Pointer to the output queue. + */ + output_queue_t *txqueue; + } queue; + /* End of the mandatory fields.*/ + } mode; +} USBInEndpointState; + +/** + * @brief Type of an OUT endpoint state structure. + */ +typedef struct { + /** + * @brief Buffer mode, queue or linear. + */ + bool rxqueued; + /** + * @brief Requested receive transfer size. + */ + size_t rxsize; + /** + * @brief Received bytes so far. + */ + size_t rxcnt; + union { + struct { + /** + * @brief Pointer to the receive linear buffer. + */ + uint8_t *rxbuf; + } linear; + struct { + /** + * @brief Pointer to the input queue. + */ + input_queue_t *rxqueue; + } queue; + } mode; + /* End of the mandatory fields.*/ + /** + * @brief Number of packets to receive. + */ + uint16_t rxpkts; +} USBOutEndpointState; + +/** + * @brief Type of an USB endpoint configuration structure. + * @note Platform specific restrictions may apply to endpoints. + */ +typedef struct { + /** + * @brief Type and mode of the endpoint. + */ + uint32_t ep_mode; + /** + * @brief Setup packet notification callback. + * @details This callback is invoked when a setup packet has been + * received. + * @post The application must immediately call @p usbReadPacket() in + * order to access the received packet. + * @note This field is only valid for @p USB_EP_MODE_TYPE_CTRL + * endpoints, it should be set to @p NULL for other endpoint + * types. + */ + usbepcallback_t setup_cb; + /** + * @brief IN endpoint notification callback. + * @details This field must be set to @p NULL if the IN endpoint is not + * used. + */ + usbepcallback_t in_cb; + /** + * @brief OUT endpoint notification callback. + * @details This field must be set to @p NULL if the OUT endpoint is not + * used. + */ + usbepcallback_t out_cb; + /** + * @brief IN endpoint maximum packet size. + * @details This field must be set to zero if the IN endpoint is not + * used. + */ + uint16_t in_maxsize; + /** + * @brief OUT endpoint maximum packet size. + * @details This field must be set to zero if the OUT endpoint is not + * used. + */ + uint16_t out_maxsize; + /** + * @brief @p USBEndpointState associated to the IN endpoint. + * @details This structure maintains the state of the IN endpoint. + */ + USBInEndpointState *in_state; + /** + * @brief @p USBEndpointState associated to the OUT endpoint. + * @details This structure maintains the state of the OUT endpoint. + */ + USBOutEndpointState *out_state; + /* End of the mandatory fields.*/ + /** + * @brief Reserved field, not currently used. + * @note Initialize this field to 1 in order to be forward compatible. + */ + uint16_t ep_buffers; + /** + * @brief Pointer to a buffer for setup packets. + * @details Setup packets require a dedicated 8-bytes buffer, set this + * field to @p NULL for non-control endpoints. + */ + uint8_t *setup_buf; +} USBEndpointConfig; + +/** + * @brief Type of an USB driver configuration structure. + */ +typedef struct { + /** + * @brief USB events callback. + * @details This callback is invoked when an USB driver event is registered. + */ + usbeventcb_t event_cb; + /** + * @brief Device GET_DESCRIPTOR request callback. + * @note This callback is mandatory and cannot be set to @p NULL. + */ + usbgetdescriptor_t get_descriptor_cb; + /** + * @brief Requests hook callback. + * @details This hook allows to be notified of standard requests or to + * handle non standard requests. + */ + usbreqhandler_t requests_hook_cb; + /** + * @brief Start Of Frame callback. + */ + usbcallback_t sof_cb; + /* End of the mandatory fields.*/ +} USBConfig; + +/** + * @brief Structure representing an USB driver. + */ +struct USBDriver { + /** + * @brief Driver state. + */ + usbstate_t state; + /** + * @brief Current configuration data. + */ + const USBConfig *config; + /** + * @brief Bit map of the transmitting IN endpoints. + */ + uint16_t transmitting; + /** + * @brief Bit map of the receiving OUT endpoints. + */ + uint16_t receiving; + /** + * @brief Active endpoints configurations. + */ + const USBEndpointConfig *epc[USB_MAX_ENDPOINTS + 1]; + /** + * @brief Fields available to user, it can be used to associate an + * application-defined handler to an IN endpoint. + * @note The base index is one, the endpoint zero does not have a + * reserved element in this array. + */ + void *in_params[USB_MAX_ENDPOINTS]; + /** + * @brief Fields available to user, it can be used to associate an + * application-defined handler to an OUT endpoint. + * @note The base index is one, the endpoint zero does not have a + * reserved element in this array. + */ + void *out_params[USB_MAX_ENDPOINTS]; + /** + * @brief Endpoint 0 state. + */ + usbep0state_t ep0state; + /** + * @brief Next position in the buffer to be transferred through endpoint 0. + */ + uint8_t *ep0next; + /** + * @brief Number of bytes yet to be transferred through endpoint 0. + */ + size_t ep0n; + /** + * @brief Endpoint 0 end transaction callback. + */ + usbcallback_t ep0endcb; + /** + * @brief Setup packet buffer. + */ + uint8_t setup[8]; + /** + * @brief Current USB device status. + */ + uint16_t status; + /** + * @brief Assigned USB address. + */ + uint8_t address; + /** + * @brief Current USB device configuration. + */ + uint8_t configuration; +#if defined(USB_DRIVER_EXT_FIELDS) + USB_DRIVER_EXT_FIELDS +#endif + /* End of the mandatory fields.*/ + /** + * @brief Pointer to the next address in the packet memory. + */ + uint32_t pmnext; +}; + +/*===========================================================================*/ +/* Driver macros. */ +/*===========================================================================*/ + +/** + * @brief Returns the current frame number. + * + * @param[in] usbp pointer to the @p USBDriver object + * @return The current frame number. + * + * @notapi + */ +#define usb_lld_get_frame_number(usbp) (STM32_USB->FNR & FNR_FN_MASK) + +/** + * @brief Returns the exact size of a receive transaction. + * @details The received size can be different from the size specified in + * @p usbStartReceiveI() because the last packet could have a size + * different from the expected one. + * @pre The OUT endpoint must have been configured in transaction mode + * in order to use this function. + * + * @param[in] usbp pointer to the @p USBDriver object + * @param[in] ep endpoint number + * @return Received data size. + * + * @notapi + */ +#define usb_lld_get_transaction_size(usbp, ep) \ + ((usbp)->epc[ep]->out_state->rxcnt) + +/** + * @brief Returns the exact size of a received packet. + * @pre The OUT endpoint must have been configured in packet mode + * in order to use this function. + * + * @param[in] usbp pointer to the @p USBDriver object + * @param[in] ep endpoint number + * @return Received data size. + * + * @notapi + */ +#define usb_lld_get_packet_size(usbp, ep) \ + ((size_t)USB_GET_DESCRIPTOR(ep)->RXCOUNT & RXCOUNT_COUNT_MASK) + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +#if STM32_USB_USE_USB1 && !defined(__DOXYGEN__) +extern USBDriver USBD1; +#endif + +#ifdef __cplusplus +extern "C" { +#endif + void usb_lld_init(void); + void usb_lld_start(USBDriver *usbp); + void usb_lld_stop(USBDriver *usbp); + void usb_lld_reset(USBDriver *usbp); + void usb_lld_set_address(USBDriver *usbp); + void usb_lld_init_endpoint(USBDriver *usbp, usbep_t ep); + void usb_lld_disable_endpoints(USBDriver *usbp); + usbepstatus_t usb_lld_get_status_in(USBDriver *usbp, usbep_t ep); + usbepstatus_t usb_lld_get_status_out(USBDriver *usbp, usbep_t ep); + void usb_lld_read_setup(USBDriver *usbp, usbep_t ep, uint8_t *buf); + void usb_lld_prepare_receive(USBDriver *usbp, usbep_t ep); + void usb_lld_prepare_transmit(USBDriver *usbp, usbep_t ep); + void usb_lld_start_out(USBDriver *usbp, usbep_t ep); + void usb_lld_start_in(USBDriver *usbp, usbep_t ep); + void usb_lld_stall_out(USBDriver *usbp, usbep_t ep); + void usb_lld_stall_in(USBDriver *usbp, usbep_t ep); + void usb_lld_clear_out(USBDriver *usbp, usbep_t ep); + void usb_lld_clear_in(USBDriver *usbp, usbep_t ep); +#ifdef __cplusplus +} +#endif + +#endif /* HAL_USE_USB */ + +#endif /* _USB_LLD_H_ */ + +/** @} */ diff --git a/os/hal/ports/STM32/can_lld.c b/os/hal/ports/STM32/can_lld.c new file mode 100644 index 000000000..a53a8fe27 --- /dev/null +++ b/os/hal/ports/STM32/can_lld.c @@ -0,0 +1,702 @@ +/* + ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file STM32/can_lld.c + * @brief STM32 CAN subsystem low level driver source. + * + * @addtogroup CAN + * @{ + */ + +#include "hal.h" + +#if HAL_USE_CAN || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver local definitions. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver exported variables. */ +/*===========================================================================*/ + +/** @brief CAN1 driver identifier.*/ +#if STM32_CAN_USE_CAN1 || defined(__DOXYGEN__) +CANDriver CAND1; +#endif + +/** @brief CAN2 driver identifier.*/ +#if STM32_CAN_USE_CAN2 || defined(__DOXYGEN__) +CANDriver CAND2; +#endif + +/*===========================================================================*/ +/* Driver local variables and types. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local functions. */ +/*===========================================================================*/ + +/** + * @brief Programs the filters. + * + * @param[in] can2sb number of the first filter assigned to CAN2 + * @param[in] num number of entries in the filters array, if zero then + * a default filter is programmed + * @param[in] cfp pointer to the filters array, can be @p NULL if + * (num == 0) + * + * @notapi + */ +static void can_lld_set_filters(uint32_t can2sb, + uint32_t num, + const CANFilter *cfp) { + + /* Temporarily enabling CAN1 clock.*/ + rccEnableCAN1(FALSE); + + /* Filters initialization.*/ + CAN1->FMR = (CAN1->FMR & 0xFFFF0000) | (can2sb << 8) | CAN_FMR_FINIT; + if (num > 0) { + uint32_t i, fmask; + + /* All filters cleared.*/ + CAN1->FA1R = 0; + CAN1->FM1R = 0; + CAN1->FS1R = 0; + CAN1->FFA1R = 0; + for (i = 0; i < STM32_CAN_MAX_FILTERS; i++) { + CAN1->sFilterRegister[i].FR1 = 0; + CAN1->sFilterRegister[i].FR2 = 0; + } + + /* Scanning the filters array.*/ + for (i = 0; i < num; i++) { + fmask = 1 << cfp->filter; + if (cfp->mode) + CAN1->FM1R |= fmask; + if (cfp->scale) + CAN1->FS1R |= fmask; + if (cfp->assignment) + CAN1->FFA1R |= fmask; + CAN1->sFilterRegister[cfp->filter].FR1 = cfp->register1; + CAN1->sFilterRegister[cfp->filter].FR2 = cfp->register2; + CAN1->FA1R |= fmask; + cfp++; + } + } + else { + /* Setting up a single default filter that enables everything for both + CANs.*/ + CAN1->sFilterRegister[0].FR1 = 0; + CAN1->sFilterRegister[0].FR2 = 0; + CAN1->sFilterRegister[can2sb].FR1 = 0; + CAN1->sFilterRegister[can2sb].FR2 = 0; + CAN1->FM1R = 0; + CAN1->FFA1R = 0; + CAN1->FS1R = 1 | (1 << can2sb); + CAN1->FA1R = 1 | (1 << can2sb); + } + CAN1->FMR &= ~CAN_FMR_FINIT; + + /* Clock disabled, it will be enabled again in can_lld_start().*/ + rccDisableCAN1(FALSE); +} + +/** + * @brief Common TX ISR handler. + * + * @param[in] canp pointer to the @p CANDriver object + * + * @notapi + */ +static void can_lld_tx_handler(CANDriver *canp) { + + /* No more events until a message is transmitted.*/ + canp->can->TSR = CAN_TSR_RQCP0 | CAN_TSR_RQCP1 | CAN_TSR_RQCP2; + osalSysLockFromISR(); + osalQueueWakeupAllI(&canp->txqueue, MSG_OK); + osalEventBroadcastFlagsI(&canp->txempty_event, CAN_MAILBOX_TO_MASK(1)); + osalSysUnlockFromISR(); +} + +/** + * @brief Common RX0 ISR handler. + * + * @param[in] canp pointer to the @p CANDriver object + * + * @notapi + */ +static void can_lld_rx0_handler(CANDriver *canp) { + uint32_t rf0r; + + rf0r = canp->can->RF0R; + if ((rf0r & CAN_RF0R_FMP0) > 0) { + /* No more receive events until the queue 0 has been emptied.*/ + canp->can->IER &= ~CAN_IER_FMPIE0; + osalSysLockFromISR(); + osalQueueWakeupAllI(&canp->rxqueue, MSG_OK); + osalEventBroadcastFlagsI(&canp->rxfull_event, CAN_MAILBOX_TO_MASK(1)); + osalSysUnlockFromISR(); + } + if ((rf0r & CAN_RF0R_FOVR0) > 0) { + /* Overflow events handling.*/ + canp->can->RF0R = CAN_RF0R_FOVR0; + osalSysLockFromISR(); + osalEventBroadcastFlagsI(&canp->error_event, CAN_OVERFLOW_ERROR); + osalSysUnlockFromISR(); + } +} + +/** + * @brief Common RX1 ISR handler. + * + * @param[in] canp pointer to the @p CANDriver object + * + * @notapi + */ +static void can_lld_rx1_handler(CANDriver *canp) { + uint32_t rf1r; + + rf1r = canp->can->RF1R; + if ((rf1r & CAN_RF1R_FMP1) > 0) { + /* No more receive events until the queue 0 has been emptied.*/ + canp->can->IER &= ~CAN_IER_FMPIE1; + osalSysLockFromISR(); + osalQueueWakeupAllI(&canp->rxqueue, MSG_OK); + osalEventBroadcastFlagsI(&canp->rxfull_event, CAN_MAILBOX_TO_MASK(2)); + osalSysUnlockFromISR(); + } + if ((rf1r & CAN_RF1R_FOVR1) > 0) { + /* Overflow events handling.*/ + canp->can->RF1R = CAN_RF1R_FOVR1; + osalSysLockFromISR(); + osalEventBroadcastFlagsI(&canp->error_event, CAN_OVERFLOW_ERROR); + osalSysUnlockFromISR(); + } +} + +/** + * @brief Common SCE ISR handler. + * + * @param[in] canp pointer to the @p CANDriver object + * + * @notapi + */ +static void can_lld_sce_handler(CANDriver *canp) { + uint32_t msr; + + msr = canp->can->MSR; + canp->can->MSR = CAN_MSR_ERRI | CAN_MSR_WKUI | CAN_MSR_SLAKI; + /* Wakeup event.*/ +#if CAN_USE_SLEEP_MODE + if (msr & CAN_MSR_WKUI) { + canp->state = CAN_READY; + canp->can->MCR &= ~CAN_MCR_SLEEP; + osalSysLockFromISR(); + osalEventBroadcastFlagsI(&canp->wakeup_event, 0); + osalSysUnlockFromISR(); + } +#endif /* CAN_USE_SLEEP_MODE */ + /* Error event.*/ + if (msr & CAN_MSR_ERRI) { + eventflags_t flags; + uint32_t esr = canp->can->ESR; + + canp->can->ESR &= ~CAN_ESR_LEC; + flags = (eventflags_t)(esr & 7); + if ((esr & CAN_ESR_LEC) > 0) + flags |= CAN_FRAMING_ERROR; + + osalSysLockFromISR(); + /* The content of the ESR register is copied unchanged in the upper + half word of the listener flags mask.*/ + osalEventBroadcastFlagsI(&canp->error_event, flags | (eventflags_t)(esr << 16)); + osalSysUnlockFromISR(); + } +} + +/*===========================================================================*/ +/* Driver interrupt handlers. */ +/*===========================================================================*/ + +#if STM32_CAN_USE_CAN1 || defined(__DOXYGEN__) +/** + * @brief CAN1 TX interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(STM32_CAN1_TX_HANDLER) { + + OSAL_IRQ_PROLOGUE(); + + can_lld_tx_handler(&CAND1); + + OSAL_IRQ_EPILOGUE(); +} + +/* + * @brief CAN1 RX0 interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(STM32_CAN1_RX0_HANDLER) { + + OSAL_IRQ_PROLOGUE(); + + can_lld_rx0_handler(&CAND1); + + OSAL_IRQ_EPILOGUE(); +} + +/** + * @brief CAN1 RX1 interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(STM32_CAN1_RX1_HANDLER) { + + OSAL_IRQ_PROLOGUE(); + + can_lld_rx1_handler(&CAND1); + + OSAL_IRQ_EPILOGUE(); +} + +/** + * @brief CAN1 SCE interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(STM32_CAN1_SCE_HANDLER) { + + OSAL_IRQ_PROLOGUE(); + + can_lld_sce_handler(&CAND1); + + OSAL_IRQ_EPILOGUE(); +} +#endif /* STM32_CAN_USE_CAN1 */ + +#if STM32_CAN_USE_CAN2 || defined(__DOXYGEN__) +/** + * @brief CAN2 TX interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(STM32_CAN2_TX_HANDLER) { + + OSAL_IRQ_PROLOGUE(); + + can_lld_tx_handler(&CAND2); + + OSAL_IRQ_EPILOGUE(); +} + +/* + * @brief CAN2 RX0 interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(STM32_CAN2_RX0_HANDLER) { + + OSAL_IRQ_PROLOGUE(); + + can_lld_rx0_handler(&CAND2); + + OSAL_IRQ_EPILOGUE(); +} + +/** + * @brief CAN2 RX1 interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(STM32_CAN2_RX1_HANDLER) { + + OSAL_IRQ_PROLOGUE(); + + can_lld_rx1_handler(&CAND2); + + OSAL_IRQ_EPILOGUE(); +} + +/** + * @brief CAN2 SCE interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(STM32_CAN2_SCE_HANDLER) { + + OSAL_IRQ_PROLOGUE(); + + can_lld_sce_handler(&CAND2); + + OSAL_IRQ_EPILOGUE(); +} +#endif /* STM32_CAN_USE_CAN2 */ + +/*===========================================================================*/ +/* Driver exported functions. */ +/*===========================================================================*/ + +/** + * @brief Low level CAN driver initialization. + * + * @notapi + */ +void can_lld_init(void) { + +#if STM32_CAN_USE_CAN1 + /* Driver initialization.*/ + canObjectInit(&CAND1); + CAND1.can = CAN1; +#endif +#if STM32_CAN_USE_CAN2 + /* Driver initialization.*/ + canObjectInit(&CAND2); + CAND2.can = CAN2; +#endif + + /* Filters initialization.*/ +#if STM32_HAS_CAN2 + can_lld_set_filters(STM32_CAN_MAX_FILTERS / 2, 0, NULL); +#else + can_lld_set_filters(STM32_CAN_MAX_FILTERS, 0, NULL); +#endif + +} + +/** + * @brief Configures and activates the CAN peripheral. + * + * @param[in] canp pointer to the @p CANDriver object + * + * @notapi + */ +void can_lld_start(CANDriver *canp) { + + /* Clock activation.*/ +#if STM32_CAN_USE_CAN1 + if (&CAND1 == canp) { + nvicEnableVector(STM32_CAN1_TX_NUMBER, STM32_CAN_CAN1_IRQ_PRIORITY); + nvicEnableVector(STM32_CAN1_RX0_NUMBER, STM32_CAN_CAN1_IRQ_PRIORITY); + nvicEnableVector(STM32_CAN1_RX1_NUMBER, STM32_CAN_CAN1_IRQ_PRIORITY); + nvicEnableVector(STM32_CAN1_SCE_NUMBER, STM32_CAN_CAN1_IRQ_PRIORITY); + rccEnableCAN1(FALSE); + } +#endif +#if STM32_CAN_USE_CAN2 + if (&CAND2 == canp) { + + osalDbgAssert(CAND1.state != CAN_STOP, "CAN1 must be started"); + + nvicEnableVector(STM32_CAN2_TX_NUMBER, STM32_CAN_CAN2_IRQ_PRIORITY); + nvicEnableVector(STM32_CAN2_RX0_NUMBER, STM32_CAN_CAN2_IRQ_PRIORITY); + nvicEnableVector(STM32_CAN2_RX1_NUMBER, STM32_CAN_CAN2_IRQ_PRIORITY); + nvicEnableVector(STM32_CAN2_SCE_NUMBER, STM32_CAN_CAN2_IRQ_PRIORITY); + rccEnableCAN2(FALSE); + } +#endif + + /* Entering initialization mode. */ + canp->state = CAN_STARTING; + canp->can->MCR = CAN_MCR_INRQ; + while ((canp->can->MSR & CAN_MSR_INAK) == 0) + osalThreadSleepS(1); + /* BTR initialization.*/ + canp->can->BTR = canp->config->btr; + /* MCR initialization.*/ + canp->can->MCR = canp->config->mcr; + + /* Interrupt sources initialization.*/ + canp->can->IER = CAN_IER_TMEIE | CAN_IER_FMPIE0 | CAN_IER_FMPIE1 | + CAN_IER_WKUIE | CAN_IER_ERRIE | CAN_IER_LECIE | + CAN_IER_BOFIE | CAN_IER_EPVIE | CAN_IER_EWGIE | + CAN_IER_FOVIE0 | CAN_IER_FOVIE1; +} + +/** + * @brief Deactivates the CAN peripheral. + * + * @param[in] canp pointer to the @p CANDriver object + * + * @notapi + */ +void can_lld_stop(CANDriver *canp) { + + /* If in ready state then disables the CAN peripheral.*/ + if (canp->state == CAN_READY) { +#if STM32_CAN_USE_CAN1 + if (&CAND1 == canp) { + +#if STM32_CAN_USE_CAN2 + osalDbgAssert(CAND2.state == CAN_STOP, "CAN2 must be stopped"); +#endif + + CAN1->MCR = 0x00010002; /* Register reset value. */ + CAN1->IER = 0x00000000; /* All sources disabled. */ + nvicDisableVector(STM32_CAN1_TX_NUMBER); + nvicDisableVector(STM32_CAN1_RX0_NUMBER); + nvicDisableVector(STM32_CAN1_RX1_NUMBER); + nvicDisableVector(STM32_CAN1_SCE_NUMBER); + rccDisableCAN1(FALSE); + } +#endif +#if STM32_CAN_USE_CAN2 + if (&CAND2 == canp) { + CAN2->MCR = 0x00010002; /* Register reset value. */ + CAN2->IER = 0x00000000; /* All sources disabled. */ + nvicDisableVector(STM32_CAN2_TX_NUMBER); + nvicDisableVector(STM32_CAN2_RX0_NUMBER); + nvicDisableVector(STM32_CAN2_RX1_NUMBER); + nvicDisableVector(STM32_CAN2_SCE_NUMBER); + rccDisableCAN2(FALSE); + } +#endif + } +} + +/** + * @brief Determines whether a frame can be transmitted. + * + * @param[in] canp pointer to the @p CANDriver object + * @param[in] mailbox mailbox number, @p CAN_ANY_MAILBOX for any mailbox + * + * @return The queue space availability. + * @retval FALSE no space in the transmit queue. + * @retval TRUE transmit slot available. + * + * @notapi + */ +bool_t can_lld_is_tx_empty(CANDriver *canp, canmbx_t mailbox) { + + switch (mailbox) { + case CAN_ANY_MAILBOX: + return (canp->can->TSR & CAN_TSR_TME) != 0; + case 1: + return (canp->can->TSR & CAN_TSR_TME0) != 0; + case 2: + return (canp->can->TSR & CAN_TSR_TME1) != 0; + case 3: + return (canp->can->TSR & CAN_TSR_TME2) != 0; + default: + return FALSE; + } +} + +/** + * @brief Inserts a frame into the transmit queue. + * + * @param[in] canp pointer to the @p CANDriver object + * @param[in] ctfp pointer to the CAN frame to be transmitted + * @param[in] mailbox mailbox number, @p CAN_ANY_MAILBOX for any mailbox + * + * @notapi + */ +void can_lld_transmit(CANDriver *canp, + canmbx_t mailbox, + const CANTxFrame *ctfp) { + uint32_t tir; + CAN_TxMailBox_TypeDef *tmbp; + + /* Pointer to a free transmission mailbox.*/ + switch (mailbox) { + case CAN_ANY_MAILBOX: + tmbp = &canp->can->sTxMailBox[(canp->can->TSR & CAN_TSR_CODE) >> 24]; + break; + case 1: + tmbp = &canp->can->sTxMailBox[0]; + break; + case 2: + tmbp = &canp->can->sTxMailBox[1]; + break; + case 3: + tmbp = &canp->can->sTxMailBox[2]; + break; + default: + return; + } + + /* Preparing the message.*/ + if (ctfp->IDE) + tir = ((uint32_t)ctfp->EID << 3) | ((uint32_t)ctfp->RTR << 1) | + CAN_TI0R_IDE; + else + tir = ((uint32_t)ctfp->SID << 21) | ((uint32_t)ctfp->RTR << 1); + tmbp->TDTR = ctfp->DLC; + tmbp->TDLR = ctfp->data32[0]; + tmbp->TDHR = ctfp->data32[1]; + tmbp->TIR = tir | CAN_TI0R_TXRQ; +} + +/** + * @brief Determines whether a frame has been received. + * + * @param[in] canp pointer to the @p CANDriver object + * @param[in] mailbox mailbox number, @p CAN_ANY_MAILBOX for any mailbox + * + * @return The queue space availability. + * @retval FALSE no space in the transmit queue. + * @retval TRUE transmit slot available. + * + * @notapi + */ +bool_t can_lld_is_rx_nonempty(CANDriver *canp, canmbx_t mailbox) { + + switch (mailbox) { + case CAN_ANY_MAILBOX: + return ((canp->can->RF0R & CAN_RF0R_FMP0) != 0 || + (canp->can->RF1R & CAN_RF1R_FMP1) != 0); + case 1: + return (canp->can->RF0R & CAN_RF0R_FMP0) != 0; + case 2: + return (canp->can->RF1R & CAN_RF1R_FMP1) != 0; + default: + return FALSE; + } +} + +/** + * @brief Receives a frame from the input queue. + * + * @param[in] canp pointer to the @p CANDriver object + * @param[in] mailbox mailbox number, @p CAN_ANY_MAILBOX for any mailbox + * @param[out] crfp pointer to the buffer where the CAN frame is copied + * + * @notapi + */ +void can_lld_receive(CANDriver *canp, + canmbx_t mailbox, + CANRxFrame *crfp) { + uint32_t rir, rdtr; + + if (mailbox == CAN_ANY_MAILBOX) { + if ((canp->can->RF0R & CAN_RF0R_FMP0) != 0) + mailbox = 1; + else if ((canp->can->RF1R & CAN_RF1R_FMP1) != 0) + mailbox = 2; + else { + /* Should not happen, do nothing.*/ + return; + } + } + switch (mailbox) { + case 1: + /* Fetches the message.*/ + rir = canp->can->sFIFOMailBox[0].RIR; + rdtr = canp->can->sFIFOMailBox[0].RDTR; + crfp->data32[0] = canp->can->sFIFOMailBox[0].RDLR; + crfp->data32[1] = canp->can->sFIFOMailBox[0].RDHR; + + /* Releases the mailbox.*/ + canp->can->RF0R = CAN_RF0R_RFOM0; + + /* If the queue is empty re-enables the interrupt in order to generate + events again.*/ + if ((canp->can->RF0R & CAN_RF0R_FMP0) == 0) + canp->can->IER |= CAN_IER_FMPIE0; + break; + case 2: + /* Fetches the message.*/ + rir = canp->can->sFIFOMailBox[1].RIR; + rdtr = canp->can->sFIFOMailBox[1].RDTR; + crfp->data32[0] = canp->can->sFIFOMailBox[1].RDLR; + crfp->data32[1] = canp->can->sFIFOMailBox[1].RDHR; + + /* Releases the mailbox.*/ + canp->can->RF1R = CAN_RF1R_RFOM1; + + /* If the queue is empty re-enables the interrupt in order to generate + events again.*/ + if ((canp->can->RF1R & CAN_RF1R_FMP1) == 0) + canp->can->IER |= CAN_IER_FMPIE1; + break; + default: + /* Should not happen, do nothing.*/ + return; + } + + /* Decodes the various fields in the RX frame.*/ + crfp->RTR = (rir & CAN_RI0R_RTR) >> 1; + crfp->IDE = (rir & CAN_RI0R_IDE) >> 2; + if (crfp->IDE) + crfp->EID = rir >> 3; + else + crfp->SID = rir >> 21; + crfp->DLC = rdtr & CAN_RDT0R_DLC; + crfp->FMI = (uint8_t)(rdtr >> 8); + crfp->TIME = (uint16_t)(rdtr >> 16); +} + +#if CAN_USE_SLEEP_MODE || defined(__DOXYGEN__) +/** + * @brief Enters the sleep mode. + * + * @param[in] canp pointer to the @p CANDriver object + * + * @notapi + */ +void can_lld_sleep(CANDriver *canp) { + + canp->can->MCR |= CAN_MCR_SLEEP; +} + +/** + * @brief Enforces leaving the sleep mode. + * + * @param[in] canp pointer to the @p CANDriver object + * + * @notapi + */ +void can_lld_wakeup(CANDriver *canp) { + + canp->can->MCR &= ~CAN_MCR_SLEEP; +} +#endif /* CAN_USE_SLEEP_MODE */ + +/** + * @brief Programs the filters. + * @note This is an STM32-specific API. + * + * @param[in] can2sb number of the first filter assigned to CAN2 + * @param[in] num number of entries in the filters array, if zero then + * a default filter is programmed + * @param[in] cfp pointer to the filters array, can be @p NULL if + * (num == 0) + * + * @api + */ +void canSTM32SetFilters(uint32_t can2sb, uint32_t num, const CANFilter *cfp) { + + osalDbgCheck((can2sb > 1) && (can2sb < STM32_CAN_MAX_FILTERS) && + (num < STM32_CAN_MAX_FILTERS)); + +#if STM32_CAN_USE_CAN1 + osalDbgAssert(CAND1.state == CAN_STOP, "invalid state"); +#endif +#if STM32_CAN_USE_CAN2 + osalDbgAssert(CAND2.state == CAN_STOP, "invalid state"); +#endif + + can_lld_set_filters(can2sb, num, cfp); +} + +#endif /* HAL_USE_CAN */ + +/** @} */ diff --git a/os/hal/ports/STM32/can_lld.h b/os/hal/ports/STM32/can_lld.h new file mode 100644 index 000000000..9f3797029 --- /dev/null +++ b/os/hal/ports/STM32/can_lld.h @@ -0,0 +1,366 @@ +/* + ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file STM32/can_lld.h + * @brief STM32 CAN subsystem low level driver header. + * + * @addtogroup CAN + * @{ + */ + +#ifndef _CAN_LLD_H_ +#define _CAN_LLD_H_ + +#if HAL_USE_CAN || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver constants. */ +/*===========================================================================*/ + +/* + * The following macros from the ST header file are replaced with better + * equivalents. + */ +#undef CAN_BTR_BRP +#undef CAN_BTR_TS1 +#undef CAN_BTR_TS2 +#undef CAN_BTR_SJW + +/** + * @brief This switch defines whether the driver implementation supports + * a low power switch mode with automatic an wakeup feature. + */ +#define CAN_SUPPORTS_SLEEP TRUE + +/** + * @brief This implementation supports three transmit mailboxes. + */ +#define CAN_TX_MAILBOXES 3 + +/** + * @brief This implementation supports two receive mailboxes. + */ +#define CAN_RX_MAILBOXES 2 + +/** + * @name CAN registers helper macros + * @{ + */ +#define CAN_BTR_BRP(n) (n) /**< @brief BRP field macro.*/ +#define CAN_BTR_TS1(n) ((n) << 16) /**< @brief TS1 field macro.*/ +#define CAN_BTR_TS2(n) ((n) << 20) /**< @brief TS2 field macro.*/ +#define CAN_BTR_SJW(n) ((n) << 24) /**< @brief SJW field macro.*/ + +#define CAN_IDE_STD 0 /**< @brief Standard id. */ +#define CAN_IDE_EXT 1 /**< @brief Extended id. */ + +#define CAN_RTR_DATA 0 /**< @brief Data frame. */ +#define CAN_RTR_REMOTE 1 /**< @brief Remote frame. */ +/** @} */ + +/*===========================================================================*/ +/* Driver pre-compile time settings. */ +/*===========================================================================*/ + +/** + * @name Configuration options + * @{ + */ +/** + * @brief CAN1 driver enable switch. + * @details If set to @p TRUE the support for CAN1 is included. + */ +#if !defined(STM32_CAN_USE_CAN1) || defined(__DOXYGEN__) +#define STM32_CAN_USE_CAN1 FALSE +#endif + +/** + * @brief CAN2 driver enable switch. + * @details If set to @p TRUE the support for CAN2 is included. + */ +#if !defined(STM32_CAN_USE_CAN2) || defined(__DOXYGEN__) +#define STM32_CAN_USE_CAN2 FALSE +#endif + +/** + * @brief CAN1 interrupt priority level setting. + */ +#if !defined(STM32_CAN_CAN1_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_CAN_CAN1_IRQ_PRIORITY 11 +#endif +/** @} */ + +/** + * @brief CAN2 interrupt priority level setting. + */ +#if !defined(STM32_CAN_CAN2_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_CAN_CAN2_IRQ_PRIORITY 11 +#endif +/** @} */ + +/*===========================================================================*/ +/* Derived constants and error checks. */ +/*===========================================================================*/ + +#if STM32_CAN_USE_CAN1 && !STM32_HAS_CAN1 +#error "CAN1 not present in the selected device" +#endif + +#if STM32_CAN_USE_CAN2 && !STM32_HAS_CAN2 +#error "CAN2 not present in the selected device" +#endif + +#if !STM32_CAN_USE_CAN1 && !STM32_CAN_USE_CAN2 +#error "CAN driver activated but no CAN peripheral assigned" +#endif + +#if !STM32_CAN_USE_CAN1 && STM32_CAN_USE_CAN2 +#error "CAN2 requires CAN1, it cannot operate independently" +#endif + +#if CAN_USE_SLEEP_MODE && !CAN_SUPPORTS_SLEEP +#error "CAN sleep mode not supported in this architecture" +#endif + +/*===========================================================================*/ +/* Driver data structures and types. */ +/*===========================================================================*/ + +/** + * @brief Type of a transmission mailbox index. + */ +typedef uint32_t canmbx_t; + +/** + * @brief CAN transmission frame. + * @note Accessing the frame data as word16 or word32 is not portable because + * machine data endianness, it can be still useful for a quick filling. + */ +typedef struct { + struct { + uint8_t DLC:4; /**< @brief Data length. */ + uint8_t RTR:1; /**< @brief Frame type. */ + uint8_t IDE:1; /**< @brief Identifier type. */ + }; + union { + struct { + uint32_t SID:11; /**< @brief Standard identifier.*/ + }; + struct { + uint32_t EID:29; /**< @brief Extended identifier.*/ + }; + }; + union { + uint8_t data8[8]; /**< @brief Frame data. */ + uint16_t data16[4]; /**< @brief Frame data. */ + uint32_t data32[2]; /**< @brief Frame data. */ + }; +} CANTxFrame; + +/** + * @brief CAN received frame. + * @note Accessing the frame data as word16 or word32 is not portable because + * machine data endianness, it can be still useful for a quick filling. + */ +typedef struct { + struct { + uint8_t FMI; /**< @brief Filter id. */ + uint16_t TIME; /**< @brief Time stamp. */ + }; + struct { + uint8_t DLC:4; /**< @brief Data length. */ + uint8_t RTR:1; /**< @brief Frame type. */ + uint8_t IDE:1; /**< @brief Identifier type. */ + }; + union { + struct { + uint32_t SID:11; /**< @brief Standard identifier.*/ + }; + struct { + uint32_t EID:29; /**< @brief Extended identifier.*/ + }; + }; + union { + uint8_t data8[8]; /**< @brief Frame data. */ + uint16_t data16[4]; /**< @brief Frame data. */ + uint32_t data32[2]; /**< @brief Frame data. */ + }; +} CANRxFrame; + +/** + * @brief CAN filter. + * @note Refer to the STM32 reference manual for info about filters. + */ +typedef struct { + /** + * @brief Number of the filter to be programmed. + */ + uint32_t filter; + /** + * @brief Filter mode. + * @note This bit represent the CAN_FM1R register bit associated to this + * filter (0=mask mode, 1=list mode). + */ + uint32_t mode:1; + /** + * @brief Filter scale. + * @note This bit represent the CAN_FS1R register bit associated to this + * filter (0=16 bits mode, 1=32 bits mode). + */ + uint32_t scale:1; + /** + * @brief Filter mode. + * @note This bit represent the CAN_FFA1R register bit associated to this + * filter, must be set to zero in this version of the driver. + */ + uint32_t assignment:1; + /** + * @brief Filter register 1 (identifier). + */ + uint32_t register1; + /** + * @brief Filter register 2 (mask/identifier depending on mode=0/1). + */ + uint32_t register2; +} CANFilter; + +/** + * @brief Driver configuration structure. + */ +typedef struct { + /** + * @brief CAN MCR register initialization data. + * @note Some bits in this register are enforced by the driver regardless + * their status in this field. + */ + uint32_t mcr; + /** + * @brief CAN BTR register initialization data. + * @note Some bits in this register are enforced by the driver regardless + * their status in this field. + */ + uint32_t btr; +} CANConfig; + +/** + * @brief Structure representing an CAN driver. + */ +typedef struct { + /** + * @brief Driver state. + */ + canstate_t state; + /** + * @brief Current configuration data. + */ + const CANConfig *config; + /** + * @brief Transmission threads queue. + */ + threads_queue_t txqueue; + /** + * @brief Receive threads queue. + */ + threads_queue_t rxqueue; + /** + * @brief One or more frames become available. + * @note After broadcasting this event it will not be broadcasted again + * until the received frames queue has been completely emptied. It + * is not broadcasted for each received frame. It is + * responsibility of the application to empty the queue by + * repeatedly invoking @p chReceive() when listening to this event. + * This behavior minimizes the interrupt served by the system + * because CAN traffic. + * @note The flags associated to the listeners will indicate which + * receive mailboxes become non-empty. + */ + event_source_t rxfull_event; + /** + * @brief One or more transmission mailbox become available. + * @note The flags associated to the listeners will indicate which + * transmit mailboxes become empty. + * + */ + event_source_t txempty_event; + /** + * @brief A CAN bus error happened. + * @note The flags associated to the listeners will indicate the + * error(s) that have occurred. + */ + event_source_t error_event; +#if CAN_USE_SLEEP_MODE || defined (__DOXYGEN__) + /** + * @brief Entering sleep state event. + */ + event_source_t sleep_event; + /** + * @brief Exiting sleep state event. + */ + event_source_t wakeup_event; +#endif /* CAN_USE_SLEEP_MODE */ + /* End of the mandatory fields.*/ + /** + * @brief Pointer to the CAN registers. + */ + CAN_TypeDef *can; +} CANDriver; + +/*===========================================================================*/ +/* Driver macros. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +#if STM32_CAN_USE_CAN1 && !defined(__DOXYGEN__) +extern CANDriver CAND1; +#endif + +#if STM32_CAN_USE_CAN2 && !defined(__DOXYGEN__) +extern CANDriver CAND2; +#endif + +#ifdef __cplusplus +extern "C" { +#endif + void can_lld_init(void); + void can_lld_start(CANDriver *canp); + void can_lld_stop(CANDriver *canp); + bool_t can_lld_is_tx_empty(CANDriver *canp, + canmbx_t mailbox); + void can_lld_transmit(CANDriver *canp, + canmbx_t mailbox, + const CANTxFrame *crfp); + bool_t can_lld_is_rx_nonempty(CANDriver *canp, + canmbx_t mailbox); + void can_lld_receive(CANDriver *canp, + canmbx_t mailbox, + CANRxFrame *ctfp); +#if CAN_USE_SLEEP_MODE + void can_lld_sleep(CANDriver *canp); + void can_lld_wakeup(CANDriver *canp); +#endif /* CAN_USE_SLEEP_MODE */ +#ifdef __cplusplus +} +#endif + +#endif /* HAL_USE_CAN */ + +#endif /* _CAN_LLD_H_ */ + +/** @} */ diff --git a/os/hal/ports/STM32/ext_lld.c b/os/hal/ports/STM32/ext_lld.c new file mode 100644 index 000000000..80b222124 --- /dev/null +++ b/os/hal/ports/STM32/ext_lld.c @@ -0,0 +1,220 @@ +/* + ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file STM32/ext_lld.c + * @brief STM32 EXT subsystem low level driver source. + * + * @addtogroup EXT + * @{ + */ + +#include "hal.h" + +#if HAL_USE_EXT || defined(__DOXYGEN__) + +#include "ext_lld_isr.h" + +/*===========================================================================*/ +/* Driver local definitions. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver exported variables. */ +/*===========================================================================*/ + +/** + * @brief EXTD1 driver identifier. + */ +EXTDriver EXTD1; + +/*===========================================================================*/ +/* Driver local variables and types. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local functions. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver interrupt handlers. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver exported functions. */ +/*===========================================================================*/ + +/** + * @brief Low level EXT driver initialization. + * + * @notapi + */ +void ext_lld_init(void) { + + /* Driver initialization.*/ + extObjectInit(&EXTD1); +} + +/** + * @brief Configures and activates the EXT peripheral. + * + * @param[in] extp pointer to the @p EXTDriver object + * + * @notapi + */ +void ext_lld_start(EXTDriver *extp) { + unsigned i; + + if (extp->state == EXT_STOP) + ext_lld_exti_irq_enable(); + + /* Configuration of automatic channels.*/ + for (i = 0; i < EXT_MAX_CHANNELS; i++) + if (extp->config->channels[i].mode & EXT_CH_MODE_AUTOSTART) + ext_lld_channel_enable(extp, i); + else + ext_lld_channel_disable(extp, i); +} + +/** + * @brief Deactivates the EXT peripheral. + * + * @param[in] extp pointer to the @p EXTDriver object + * + * @notapi + */ +void ext_lld_stop(EXTDriver *extp) { + + if (extp->state == EXT_ACTIVE) + ext_lld_exti_irq_disable(); + + EXTI->EMR = 0; + EXTI->IMR = 0; + EXTI->PR = 0xFFFFFFFF; +#if STM32_EXTI_NUM_CHANNELS > 32 + EXTI->PR2 = 0xFFFFFFFF; +#endif +} + +/** + * @brief Enables an EXT channel. + * + * @param[in] extp pointer to the @p EXTDriver object + * @param[in] channel channel to be enabled + * + * @notapi + */ +void ext_lld_channel_enable(EXTDriver *extp, expchannel_t channel) { + +#if STM32_EXTI_NUM_CHANNELS > 32 + if (channel < 32) { +#endif + /* Programming edge registers.*/ + if (extp->config->channels[channel].mode & EXT_CH_MODE_RISING_EDGE) + EXTI->RTSR |= (1 << channel); + else + EXTI->RTSR &= ~(1 << channel); + if (extp->config->channels[channel].mode & EXT_CH_MODE_FALLING_EDGE) + EXTI->FTSR |= (1 << channel); + else + EXTI->FTSR &= ~(1 << channel); + + /* Programming interrupt and event registers.*/ + if (extp->config->channels[channel].cb != NULL) { + EXTI->IMR |= (1 << channel); + EXTI->EMR &= ~(1 << channel); + } + else { + EXTI->EMR |= (1 << channel); + EXTI->IMR &= ~(1 << channel); + } +#if STM32_EXTI_NUM_CHANNELS > 32 + } + else { + /* Programming edge registers.*/ + if (extp->config->channels[channel].mode & EXT_CH_MODE_RISING_EDGE) + EXTI->RTSR2 |= (1 << (32 - channel)); + else + EXTI->RTSR2 &= ~(1 << (32 - channel)); + if (extp->config->channels[channel].mode & EXT_CH_MODE_FALLING_EDGE) + EXTI->FTSR2 |= (1 << (32 - channel)); + else + EXTI->FTSR2 &= ~(1 << (32 - channel)); + + /* Programming interrupt and event registers.*/ + if (extp->config->channels[channel].cb != NULL) { + EXTI->IMR2 |= (1 << (32 - channel)); + EXTI->EMR2 &= ~(1 << (32 - channel)); + } + else { + EXTI->EMR2 |= (1 << (32 - channel)); + EXTI->IMR2 &= ~(1 << (32 - channel)); + } + } +#endif + + /* Setting the associated GPIO for external channels.*/ + if (channel < 16) { + uint32_t n = channel >> 2; + uint32_t mask = ~(0xF << ((channel & 3) * 4)); + uint32_t port = ((extp->config->channels[channel].mode & + EXT_MODE_GPIO_MASK) >> + EXT_MODE_GPIO_OFF) << ((channel & 3) * 4); + +#if defined(STM32L1XX_MD) || defined(STM32F0XX) || defined(STM32F2XX) || \ + defined(STM32F30X) || defined(STM32F37X) || defined(STM32F4XX) + SYSCFG->EXTICR[n] = (SYSCFG->EXTICR[n] & mask) | port; +#else /* STM32F1XX */ + AFIO->EXTICR[n] = (AFIO->EXTICR[n] & mask) | port; +#endif /* STM32F1XX */ + } +} + +/** + * @brief Disables an EXT channel. + * + * @param[in] extp pointer to the @p EXTDriver object + * @param[in] channel channel to be disabled + * + * @notapi + */ +void ext_lld_channel_disable(EXTDriver *extp, expchannel_t channel) { + + (void)extp; + +#if STM32_EXTI_NUM_CHANNELS > 32 + if (channel < 32) { +#endif + EXTI->IMR &= ~(1 << channel); + EXTI->EMR &= ~(1 << channel); + EXTI->RTSR &= ~(1 << channel); + EXTI->FTSR &= ~(1 << channel); + EXTI->PR = (1 << channel); +#if STM32_EXTI_NUM_CHANNELS > 32 + } + else { + EXTI->IMR2 &= ~(1 << (32 - channel)); + EXTI->EMR2 &= ~(1 << (32 - channel)); + EXTI->RTSR2 &= ~(1 << (32 - channel)); + EXTI->FTSR2 &= ~(1 << (32 - channel)); + EXTI->PR2 = (1 << (32 - channel)); + } +#endif +} + +#endif /* HAL_USE_EXT */ + +/** @} */ diff --git a/os/hal/ports/STM32/ext_lld.h b/os/hal/ports/STM32/ext_lld.h new file mode 100644 index 000000000..7a59fa728 --- /dev/null +++ b/os/hal/ports/STM32/ext_lld.h @@ -0,0 +1,153 @@ +/* + ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file STM32/ext_lld.h + * @brief STM32 EXT subsystem low level driver header. + * + * @addtogroup EXT + * @{ + */ + +#ifndef _EXT_LLD_H_ +#define _EXT_LLD_H_ + +#if HAL_USE_EXT || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver constants. */ +/*===========================================================================*/ + +/** + * @brief Available number of EXT channels. + */ +#define EXT_MAX_CHANNELS STM32_EXTI_NUM_CHANNELS + +/** + * @name STM32-specific EXT channel modes + * @{ + */ +#define EXT_MODE_GPIO_MASK 0xF0 /**< @brief Port field mask. */ +#define EXT_MODE_GPIO_OFF 4 /**< @brief Port field offset. */ +#define EXT_MODE_GPIOA 0x00 /**< @brief GPIOA identifier. */ +#define EXT_MODE_GPIOB 0x10 /**< @brief GPIOB identifier. */ +#define EXT_MODE_GPIOC 0x20 /**< @brief GPIOC identifier. */ +#define EXT_MODE_GPIOD 0x30 /**< @brief GPIOD identifier. */ +#define EXT_MODE_GPIOE 0x40 /**< @brief GPIOE identifier. */ +#define EXT_MODE_GPIOF 0x50 /**< @brief GPIOF identifier. */ +#define EXT_MODE_GPIOG 0x60 /**< @brief GPIOG identifier. */ +#define EXT_MODE_GPIOH 0x70 /**< @brief GPIOH identifier. */ +#define EXT_MODE_GPIOI 0x80 /**< @brief GPIOI identifier. */ +/** @} */ + +/*===========================================================================*/ +/* Driver pre-compile time settings. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Derived constants and error checks. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver data structures and types. */ +/*===========================================================================*/ + +/** + * @brief EXT channel identifier. + */ +typedef uint32_t expchannel_t; + +/** + * @brief Type of an EXT generic notification callback. + * + * @param[in] extp pointer to the @p EXPDriver object triggering the + * callback + */ +typedef void (*extcallback_t)(EXTDriver *extp, expchannel_t channel); + +/** + * @brief Channel configuration structure. + */ +typedef struct { + /** + * @brief Channel mode. + */ + uint32_t mode; + /** + * @brief Channel callback. + * @details In the STM32 implementation a @p NULL callback pointer is + * valid and configures the channel as an event sources instead + * of an interrupt source. + */ + extcallback_t cb; +} EXTChannelConfig; + +/** + * @brief Driver configuration structure. + * @note It could be empty on some architectures. + */ +typedef struct { + /** + * @brief Channel configurations. + */ + EXTChannelConfig channels[EXT_MAX_CHANNELS]; + /* End of the mandatory fields.*/ +} EXTConfig; + +/** + * @brief Structure representing an EXT driver. + */ +struct EXTDriver { + /** + * @brief Driver state. + */ + extstate_t state; + /** + * @brief Current configuration data. + */ + const EXTConfig *config; + /* End of the mandatory fields.*/ +}; + +/*===========================================================================*/ +/* Driver macros. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +#if !defined(__DOXYGEN__) +extern EXTDriver EXTD1; +#endif + +#ifdef __cplusplus +extern "C" { +#endif + void ext_lld_init(void); + void ext_lld_start(EXTDriver *extp); + void ext_lld_stop(EXTDriver *extp); + void ext_lld_channel_enable(EXTDriver *extp, expchannel_t channel); + void ext_lld_channel_disable(EXTDriver *extp, expchannel_t channel); +#ifdef __cplusplus +} +#endif + +#endif /* HAL_USE_EXT */ + +#endif /* _EXT_LLD_H_ */ + +/** @} */ diff --git a/os/hal/ports/STM32/i2s_lld.c b/os/hal/ports/STM32/i2s_lld.c new file mode 100644 index 000000000..b7eaf4b0c --- /dev/null +++ b/os/hal/ports/STM32/i2s_lld.c @@ -0,0 +1,161 @@ +/* + ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file STM32/i2s_lld.c + * @brief I2S Driver subsystem low level driver source template. + * + * @addtogroup I2S + * @{ + */ + +#include "ch.h" +#include "hal.h" + +#if HAL_USE_I2S || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver local definitions. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver exported variables. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local variables and types. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local functions. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver interrupt handlers. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver exported functions. */ +/*===========================================================================*/ + +/** + * @brief Low level I2S driver initialization. + * + * @notapi + */ +void i2s_lld_init(void) { + +#if STM32_I2S_USE_I2S2 + spiObjectInit(&I2SD2); + I2SD2.spi = SPI2; +#endif + +#if STM32_I2S_USE_I2S3 + spiObjectInit(&I2SD3); + I2SD3.spi = SPI3; +#endif +} + +/** + * @brief Configures and activates the I2S peripheral. + * + * @param[in] i2sp pointer to the @p I2SDriver object + * + * @notapi + */ +void i2s_lld_start(I2SDriver *i2sp) { + + /* If in stopped state then enables the SPI and DMA clocks.*/ + if (i2sp->state == I2S_STOP) { +#if STM32_SPI_USE_SPI2 + if (&SPID2 == spip) { + bool_t b; + b = dmaStreamAllocate(spip->dma, + STM32_I2S_I2S2_IRQ_PRIORITY, + (stm32_dmaisr_t)i2s_lld_serve_rx_interrupt, + (void *)spip); + chDbgAssert(!b, "spi_lld_start(), #1", "stream already allocated"); + rccEnableSPI2(FALSE); + } +#endif +#if STM32_SPI_USE_SPI3 + if (&SPID3 == spip) { + bool_t b; + b = dmaStreamAllocate(spip->dma, + STM32_I2S_I2S3_IRQ_PRIORITY, + (stm32_dmaisr_t)i2s_lld_serve_rx_interrupt, + (void *)spip); + chDbgAssert(!b, "spi_lld_start(), #2", "stream already allocated"); + rccEnableSPI3(FALSE); + } +#endif + } + /* Configuration.*/ +} + +/** + * @brief Deactivates the I2S peripheral. + * + * @param[in] i2sp pointer to the @p I2SDriver object + * + * @notapi + */ +void i2s_lld_stop(I2SDriver *i2sp) { + + if (i2sp->state == I2S_READY) { + /* Clock deactivation.*/ + + } +} + +/** + * @brief Starts a I2S data exchange. + * + * @param[in] i2sp pointer to the @p I2SDriver object + * + * @notapi + */ +void i2s_lld_start_exchange(I2SDriver *i2sp) { + +} + +/** + * @brief Starts a I2S data exchange in continuous mode. + * + * @param[in] i2sp pointer to the @p I2SDriver object + * + * @notapi + */ +void i2s_lld_start_exchange_continuous(I2SDriver *i2sp) { + +} + +/** + * @brief Stops the ongoing data exchange. + * @details The ongoing data exchange, if any, is stopped, if the driver + * was not active the function does nothing. + * + * @param[in] i2sp pointer to the @p I2SDriver object + * + * @notapi + */ +void i2s_lld_stop_exchange(I2SDriver *i2sp) { + +} + +#endif /* HAL_USE_I2S */ + +/** @} */ diff --git a/os/hal/ports/STM32/i2s_lld.h b/os/hal/ports/STM32/i2s_lld.h new file mode 100644 index 000000000..3f9c640b3 --- /dev/null +++ b/os/hal/ports/STM32/i2s_lld.h @@ -0,0 +1,317 @@ +/* + ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file STM32/i2s_lld.h + * @brief I2S Driver subsystem low level driver header template. + * + * @addtogroup I2S + * @{ + */ + +#ifndef _I2S_LLD_H_ +#define _I2S_LLD_H_ + +#if HAL_USE_I2S || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver constants. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver pre-compile time settings. */ +/*===========================================================================*/ + +/** + * @name Configuration options + * @{ + */ +/** + * @brief I2S2 driver enable switch. + * @details If set to @p TRUE the support for I2S2 is included. + * @note The default is @p TRUE. + */ +#if !defined(STM32_I2S_USE_I2S2) || defined(__DOXYGEN__) +#define STM32_I2S_USE_I2S2 FALSE +#endif + +/** + * @brief I2S3 driver enable switch. + * @details If set to @p TRUE the support for I2S3 is included. + * @note The default is @p TRUE. + */ +#if !defined(STM32_I2S_USE_I2S3) || defined(__DOXYGEN__) +#define STM32_I2S_USE_I2S3 FALSE +#endif + +/** + * @brief I2S2 interrupt priority level setting. + */ +#if !defined(STM32_I2S_I2S2_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_I2S_I2S2_IRQ_PRIORITY 10 +#endif + +/** + * @brief I2S3 interrupt priority level setting. + */ +#if !defined(STM32_I2S_I2S3_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_I2S_I2S3_IRQ_PRIORITY 10 +#endif + +/** + * @brief I2S2 DMA priority (0..3|lowest..highest). + */ +#if !defined(STM32_I2S_I2S2_DMA_PRIORITY) || defined(__DOXYGEN__) +#define STM32_I2S_I2S2_DMA_PRIORITY 1 +#endif + +/** + * @brief I2S3 DMA priority (0..3|lowest..highest). + */ +#if !defined(STM32_I2S_I2S2_DMA_PRIORITY) || defined(__DOXYGEN__) +#define STM32_I2S_I2S2_DMA_PRIORITY 1 +#endif + +/** + * @brief I2S DMA error hook. + */ +#if !defined(STM32_I2S_DMA_ERROR_HOOK) || defined(__DOXYGEN__) +#define STM32_I2S_DMA_ERROR_HOOK(i2sp) chSysHalt() +#endif + +#if STM32_ADVANCED_DMA || defined(__DOXYGEN__) + +/** + * @brief DMA stream used for I2S2 RX operations. + * @note This option is only available on platforms with enhanced DMA. + */ +#if !defined(STM32_I2S_I2S2_RX_DMA_STREAM) || defined(__DOXYGEN__) +#define STM32_I2S_I2S2_RX_DMA_STREAM STM32_DMA_STREAM_ID(2, 0) +#endif + +/** + * @brief DMA stream used for I2S2 TX operations. + * @note This option is only available on platforms with enhanced DMA. + */ +#if !defined(STM32_I2S_I2S2_TX_DMA_STREAM) || defined(__DOXYGEN__) +#define STM32_I2S_I2S2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) +#endif + +/** + * @brief DMA stream used for I2S3 RX operations. + * @note This option is only available on platforms with enhanced DMA. + */ +#if !defined(STM32_I2S_I2S3_RX_DMA_STREAM) || defined(__DOXYGEN__) +#define STM32_I2S_I2S3_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 0) +#endif + +/** + * @brief DMA stream used for I2S3 TX operations. + * @note This option is only available on platforms with enhanced DMA. + */ +#if !defined(STM32_I2S_I2S3_TX_DMA_STREAM) || defined(__DOXYGEN__) +#define STM32_I2S_I2S3_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7) +#endif + +#else /* !STM32_ADVANCED_DMA */ + +/* Fixed streams for platforms using the old DMA peripheral, the values are + valid for both STM32F1xx and STM32L1xx.*/ +#define STM32_I2S_I2S2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) +#define STM32_I2S_I2S2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 5) +#define STM32_I2S_I2S3_RX_DMA_STREAM STM32_DMA_STREAM_ID(2, 1) +#define STM32_I2S_I2S3_TX_DMA_STREAM STM32_DMA_STREAM_ID(2, 2) + +#endif /* !STM32_ADVANCED_DMA */ +/** @} */ + +/*===========================================================================*/ +/* Derived constants and error checks. */ +/*===========================================================================*/ + +#if STM32_I2S_USE_I2S2 && !STM32_HAS_SPI2 +#error "SPI2 not present in the selected device" +#endif + +#if STM32_I2S_USE_I2S3 && !STM32_HAS_SPI3 +#error "SPI3 not present in the selected device" +#endif + +#if !STM32_I2S_USE_I2S2 && !STM32_I2S_USE_I2S3 +#error "I2S driver activated but no I2S peripheral assigned" +#endif + +#if STM32_I2S_USE_I2S2 && \ + !STM32_DMA_IS_VALID_ID(STM32_I2S_I2S2_RX_DMA_STREAM, STM32_SPI2_RX_DMA_MSK) +#error "invalid DMA stream associated to I2S2 RX" +#endif + +#if STM32_I2S_USE_I2S2 && \ + !STM32_DMA_IS_VALID_ID(STM32_I2S_I2S2_TX_DMA_STREAM, STM32_SPI2_TX_DMA_MSK) +#error "invalid DMA stream associated to I2S2 TX" +#endif + +#if STM32_I2S_USE_I2S3 && \ + !STM32_DMA_IS_VALID_ID(STM32_I2S_I2S3_RX_DMA_STREAM, STM32_SPI3_RX_DMA_MSK) +#error "invalid DMA stream associated to I2S3 RX" +#endif + +#if STM32_I2S_USE_I2S3 && \ + !STM32_DMA_IS_VALID_ID(STM32_I2S_I2S3_TX_DMA_STREAM, STM32_SPI3_TX_DMA_MSK) +#error "invalid DMA stream associated to I2S3 TX" +#endif + +#if !defined(STM32_DMA_REQUIRED) +#define STM32_DMA_REQUIRED +#endif + +/*===========================================================================*/ +/* Driver data structures and types. */ +/*===========================================================================*/ + +/** + * @brief I2S mode type. + */ +typedef uint32_t i2smode_t; + +/** + * @brief Type of a structure representing an I2S driver. + */ +typedef struct I2SDriver I2SDriver; + +/** + * @brief I2S notification callback type. + * + * @param[in] i2sp pointer to the @p I2SDriver object + * @param[in] buffer pointer to the buffer + * @param[in] n number of sample positions starting from @p buffer + */ +typedef void (*i2scallback_t)(I2SDriver *i2sp, void *buffer, size_t n); + +/** + * @brief Driver configuration structure. + * @note It could be empty on some architectures. + */ +typedef struct { + /** + * @brief I2S mode selection. + */ + i2smode_t mode; + /** + * @brief Transmission buffer pointer. + */ + const void *tx_buffer; + /** + * @brief Transmission buffer size in number of samples. + */ + size_t tx_size; + /** + * @brief Callback function associated to the transmission or @p NULL. + */ + i2scallback_t tx_cb; + /** + * @brief Receive buffer pointer. + */ + void *rx_buffer; + /** + * @brief Receive buffer size in number of samples. + */ + size_t rx_size; + /** + * @brief Callback function associated to the reception or @p NULL. + */ + i2scallback_t rx_cb;; + /* End of the mandatory fields.*/ + /** + * @brief Configuration of the I2SCFGR register. + * @details See the STM32 reference manual, this register is used for + * the I2S configuration, the following bits must not be + * specified because handled directly by the driver: + * - I2SMOD + * - I2SE + * - I2SCFG + * . + */ + int16_t i2scfgr; + /** + * @brief Configuration of the I2SPR register. + * @details See the STM32 reference manual, this register is used for + * the I2S clock setup. + */ + int16_t i2spr; +} I2SConfig; + +/** + * @brief Structure representing an I2S driver. + */ +struct I2SDriver { + /** + * @brief Driver state. + */ + i2sstate_t state; + /** + * @brief Current configuration data. + */ + const I2SConfig *config; + /* End of the mandatory fields.*/ + /** + * @brief Pointer to the SPIx registers block. + */ + SPI_TypeDef *spi; + /** + * @brief DMA stream. + */ + const stm32_dma_stream_t *dma; + /** + * @brief DMA mode bit mask. + */ + uint32_t dmamode; +}; + +/*===========================================================================*/ +/* Driver macros. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +#if STM32_I2S_USE_I2S2 && !defined(__DOXYGEN__) +extern I2SDriver I2SD2; +#endif + +#if STM32_I2S_USE_I2S3 && !defined(__DOXYGEN__) +extern I2SDriver I2SD3; +#endif + +#ifdef __cplusplus +extern "C" { +#endif + void i2s_lld_init(void); + void i2s_lld_start(I2SDriver *i2sp); + void i2s_lld_stop(I2SDriver *i2sp); + void i2s_lld_start_exchange(I2SDriver *i2sp); + void i2s_lld_start_exchange_continuous(I2SDriver *i2sp); + void i2s_lld_stop_exchange(I2SDriver *i2sp); +#ifdef __cplusplus +} +#endif + +#endif /* HAL_USE_I2S */ + +#endif /* _I2S_LLD_H_ */ + +/** @} */ diff --git a/os/hal/ports/STM32/mac_lld.c b/os/hal/ports/STM32/mac_lld.c new file mode 100644 index 000000000..f766698e8 --- /dev/null +++ b/os/hal/ports/STM32/mac_lld.c @@ -0,0 +1,740 @@ +/* + ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file STM32/mac_lld.c + * @brief STM32 low level MAC driver code. + * + * @addtogroup MAC + * @{ + */ + +#include + +#include "ch.h" +#include "hal.h" + +#if HAL_USE_MAC || defined(__DOXYGEN__) + +#include "mii.h" + +/*===========================================================================*/ +/* Driver local definitions. */ +/*===========================================================================*/ + +#define BUFFER_SIZE ((((STM32_MAC_BUFFERS_SIZE - 1) | 3) + 1) / 4) + +/* MII divider optimal value.*/ +#if (STM32_HCLK >= 150000000) +#define MACMIIDR_CR ETH_MACMIIAR_CR_Div102 +#elif (STM32_HCLK >= 100000000) +#define MACMIIDR_CR ETH_MACMIIAR_CR_Div62 +#elif (STM32_HCLK >= 60000000) +#define MACMIIDR_CR ETH_MACMIIAR_CR_Div42 +#elif (STM32_HCLK >= 35000000) +#define MACMIIDR_CR ETH_MACMIIAR_CR_Div26 +#elif (STM32_HCLK >= 20000000) +#define MACMIIDR_CR ETH_MACMIIAR_CR_Div16 +#else +#error "STM32_HCLK below minimum frequency for ETH operations (20MHz)" +#endif + +/*===========================================================================*/ +/* Driver exported variables. */ +/*===========================================================================*/ + +/** + * @brief Ethernet driver 1. + */ +MACDriver ETHD1; + +/*===========================================================================*/ +/* Driver local variables and types. */ +/*===========================================================================*/ + +static const uint8_t default_mac_address[] = {0xAA, 0x55, 0x13, + 0x37, 0x01, 0x10}; + +static stm32_eth_rx_descriptor_t rd[STM32_MAC_RECEIVE_BUFFERS]; +static stm32_eth_tx_descriptor_t td[STM32_MAC_TRANSMIT_BUFFERS]; + +static uint32_t rb[STM32_MAC_RECEIVE_BUFFERS][BUFFER_SIZE]; +static uint32_t tb[STM32_MAC_TRANSMIT_BUFFERS][BUFFER_SIZE]; + +/*===========================================================================*/ +/* Driver local functions. */ +/*===========================================================================*/ + +/** + * @brief Writes a PHY register. + * + * @param[in] macp pointer to the @p MACDriver object + * @param[in] reg register number + * @param[in] value new register value + */ +static void mii_write(MACDriver *macp, uint32_t reg, uint32_t value) { + + ETH->MACMIIDR = value; + ETH->MACMIIAR = macp->phyaddr | (reg << 6) | MACMIIDR_CR | + ETH_MACMIIAR_MW | ETH_MACMIIAR_MB; + while ((ETH->MACMIIAR & ETH_MACMIIAR_MB) != 0) + ; +} + +/** + * @brief Reads a PHY register. + * + * @param[in] macp pointer to the @p MACDriver object + * @param[in] reg register number + * + * @return The PHY register content. + */ +static uint32_t mii_read(MACDriver *macp, uint32_t reg) { + + ETH->MACMIIAR = macp->phyaddr | (reg << 6) | MACMIIDR_CR | ETH_MACMIIAR_MB; + while ((ETH->MACMIIAR & ETH_MACMIIAR_MB) != 0) + ; + return ETH->MACMIIDR; +} + +#if !defined(BOARD_PHY_ADDRESS) +/** + * @brief PHY address detection. + * + * @param[in] macp pointer to the @p MACDriver object + */ +static void mii_find_phy(MACDriver *macp) { + uint32_t i; + +#if STM32_MAC_PHY_TIMEOUT > 0 + halrtcnt_t start = halGetCounterValue(); + halrtcnt_t timeout = start + MS2RTT(STM32_MAC_PHY_TIMEOUT); + while (halIsCounterWithin(start, timeout)) { +#endif + for (i = 0; i < 31; i++) { + macp->phyaddr = i << 11; + ETH->MACMIIDR = (i << 6) | MACMIIDR_CR; + if ((mii_read(macp, MII_PHYSID1) == (BOARD_PHY_ID >> 16)) && + ((mii_read(macp, MII_PHYSID2) & 0xFFF0) == (BOARD_PHY_ID & 0xFFF0))) { + return; + } + } +#if STM32_MAC_PHY_TIMEOUT > 0 + } +#endif + /* Wrong or defective board.*/ + chSysHalt(); +} +#endif + +/** + * @brief MAC address setup. + * + * @param[in] p pointer to a six bytes buffer containing the MAC + * address + */ +static void mac_lld_set_address(const uint8_t *p) { + + /* MAC address configuration, only a single address comparator is used, + hash table not used.*/ + ETH->MACA0HR = ((uint32_t)p[5] << 8) | + ((uint32_t)p[4] << 0); + ETH->MACA0LR = ((uint32_t)p[3] << 24) | + ((uint32_t)p[2] << 16) | + ((uint32_t)p[1] << 8) | + ((uint32_t)p[0] << 0); + ETH->MACA1HR = 0x0000FFFF; + ETH->MACA1LR = 0xFFFFFFFF; + ETH->MACA2HR = 0x0000FFFF; + ETH->MACA2LR = 0xFFFFFFFF; + ETH->MACA3HR = 0x0000FFFF; + ETH->MACA3LR = 0xFFFFFFFF; + ETH->MACHTHR = 0; + ETH->MACHTLR = 0; +} + +/*===========================================================================*/ +/* Driver interrupt handlers. */ +/*===========================================================================*/ + +CH_IRQ_HANDLER(ETH_IRQHandler) { + uint32_t dmasr; + + CH_IRQ_PROLOGUE(); + + dmasr = ETH->DMASR; + ETH->DMASR = dmasr; /* Clear status bits.*/ + + if (dmasr & ETH_DMASR_RS) { + /* Data Received.*/ + chSysLockFromIsr(); + chSemResetI(ÐD1.rdsem, 0); +#if MAC_USE_EVENTS + chEvtBroadcastI(ÐD1.rdevent); +#endif + chSysUnlockFromIsr(); + } + + if (dmasr & ETH_DMASR_TS) { + /* Data Transmitted.*/ + chSysLockFromIsr(); + chSemResetI(ÐD1.tdsem, 0); + chSysUnlockFromIsr(); + } + + CH_IRQ_EPILOGUE(); +} + +/*===========================================================================*/ +/* Driver exported functions. */ +/*===========================================================================*/ + +/** + * @brief Low level MAC initialization. + * + * @notapi + */ +void mac_lld_init(void) { + unsigned i; + + macObjectInit(ÐD1); + ETHD1.link_up = FALSE; + + /* Descriptor tables are initialized in chained mode, note that the first + word is not initialized here but in mac_lld_start().*/ + for (i = 0; i < STM32_MAC_RECEIVE_BUFFERS; i++) { + rd[i].rdes1 = STM32_RDES1_RCH | STM32_MAC_BUFFERS_SIZE; + rd[i].rdes2 = (uint32_t)rb[i]; + rd[i].rdes3 = (uint32_t)&rd[(i + 1) % STM32_MAC_RECEIVE_BUFFERS]; + } + for (i = 0; i < STM32_MAC_TRANSMIT_BUFFERS; i++) { + td[i].tdes1 = 0; + td[i].tdes2 = (uint32_t)tb[i]; + td[i].tdes3 = (uint32_t)&td[(i + 1) % STM32_MAC_TRANSMIT_BUFFERS]; + } + + /* Selection of the RMII or MII mode based on info exported by board.h.*/ +#if defined(STM32F10X_CL) +#if defined(BOARD_PHY_RMII) + AFIO->MAPR |= AFIO_MAPR_MII_RMII_SEL; +#else + AFIO->MAPR &= ~AFIO_MAPR_MII_RMII_SEL; +#endif +#elif defined(STM32F2XX) || defined(STM32F4XX) +#if defined(BOARD_PHY_RMII) + SYSCFG->PMC |= SYSCFG_PMC_MII_RMII_SEL; +#else + SYSCFG->PMC &= ~SYSCFG_PMC_MII_RMII_SEL; +#endif +#else +#error "unsupported STM32 platform for MAC driver" +#endif + + /* Reset of the MAC core.*/ + rccResetETH(); + + /* MAC clocks temporary activation.*/ + rccEnableETH(FALSE); + + /* PHY address setup.*/ +#if defined(BOARD_PHY_ADDRESS) + ETHD1.phyaddr = BOARD_PHY_ADDRESS << 11; +#else + mii_find_phy(ÐD1); +#endif + +#if defined(BOARD_PHY_RESET) + /* PHY board-specific reset procedure.*/ + BOARD_PHY_RESET(); +#else + /* PHY soft reset procedure.*/ + mii_write(ÐD1, MII_BMCR, BMCR_RESET); +#if defined(BOARD_PHY_RESET_DELAY) + halPolledDelay(BOARD_PHY_RESET_DELAY); +#endif + while (mii_read(ÐD1, MII_BMCR) & BMCR_RESET) + ; +#endif + +#if STM32_MAC_ETH1_CHANGE_PHY_STATE + /* PHY in power down mode until the driver will be started.*/ + mii_write(ÐD1, MII_BMCR, mii_read(ÐD1, MII_BMCR) | BMCR_PDOWN); +#endif + + /* MAC clocks stopped again.*/ + rccDisableETH(FALSE); +} + +/** + * @brief Configures and activates the MAC peripheral. + * + * @param[in] macp pointer to the @p MACDriver object + * + * @notapi + */ +void mac_lld_start(MACDriver *macp) { + unsigned i; + + /* Resets the state of all descriptors.*/ + for (i = 0; i < STM32_MAC_RECEIVE_BUFFERS; i++) + rd[i].rdes0 = STM32_RDES0_OWN; + macp->rxptr = (stm32_eth_rx_descriptor_t *)rd; + for (i = 0; i < STM32_MAC_TRANSMIT_BUFFERS; i++) + td[i].tdes0 = STM32_TDES0_TCH; + macp->txptr = (stm32_eth_tx_descriptor_t *)td; + + /* MAC clocks activation and commanded reset procedure.*/ + rccEnableETH(FALSE); + ETH->DMABMR |= ETH_DMABMR_SR; + while(ETH->DMABMR & ETH_DMABMR_SR) + ; + + /* ISR vector enabled.*/ + nvicEnableVector(ETH_IRQn, + CORTEX_PRIORITY_MASK(STM32_MAC_ETH1_IRQ_PRIORITY)); + +#if STM32_MAC_ETH1_CHANGE_PHY_STATE + /* PHY in power up mode.*/ + mii_write(macp, MII_BMCR, mii_read(macp, MII_BMCR) & ~BMCR_PDOWN); +#endif + + /* MAC configuration.*/ + ETH->MACFFR = 0; + ETH->MACFCR = 0; + ETH->MACVLANTR = 0; + + /* MAC address setup.*/ + if (macp->config->mac_address == NULL) + mac_lld_set_address(default_mac_address); + else + mac_lld_set_address(macp->config->mac_address); + + /* Transmitter and receiver enabled. + Note that the complete setup of the MAC is performed when the link + status is detected.*/ +#if STM32_MAC_IP_CHECKSUM_OFFLOAD + ETH->MACCR = ETH_MACCR_IPCO | ETH_MACCR_RE | ETH_MACCR_TE; +#else + ETH->MACCR = ETH_MACCR_RE | ETH_MACCR_TE; +#endif + + /* DMA configuration: + Descriptor chains pointers.*/ + ETH->DMARDLAR = (uint32_t)rd; + ETH->DMATDLAR = (uint32_t)td; + + /* Enabling required interrupt sources.*/ + ETH->DMASR = ETH->DMASR; + ETH->DMAIER = ETH_DMAIER_NISE | ETH_DMAIER_RIE | ETH_DMAIER_TIE; + + /* DMA general settings.*/ + ETH->DMABMR = ETH_DMABMR_AAB | ETH_DMABMR_RDP_1Beat | ETH_DMABMR_PBL_1Beat; + + /* Transmit FIFO flush.*/ + ETH->DMAOMR = ETH_DMAOMR_FTF; + while (ETH->DMAOMR & ETH_DMAOMR_FTF) + ; + + /* DMA final configuration and start.*/ + ETH->DMAOMR = ETH_DMAOMR_DTCEFD | ETH_DMAOMR_RSF | ETH_DMAOMR_TSF | + ETH_DMAOMR_ST | ETH_DMAOMR_SR; +} + +/** + * @brief Deactivates the MAC peripheral. + * + * @param[in] macp pointer to the @p MACDriver object + * + * @notapi + */ +void mac_lld_stop(MACDriver *macp) { + + if (macp->state != MAC_STOP) { +#if STM32_MAC_ETH1_CHANGE_PHY_STATE + /* PHY in power down mode until the driver will be restarted.*/ + mii_write(macp, MII_BMCR, mii_read(macp, MII_BMCR) | BMCR_PDOWN); +#endif + + /* MAC and DMA stopped.*/ + ETH->MACCR = 0; + ETH->DMAOMR = 0; + ETH->DMAIER = 0; + ETH->DMASR = ETH->DMASR; + + /* MAC clocks stopped.*/ + rccDisableETH(FALSE); + + /* ISR vector disabled.*/ + nvicDisableVector(ETH_IRQn); + } +} + +/** + * @brief Returns a transmission descriptor. + * @details One of the available transmission descriptors is locked and + * returned. + * + * @param[in] macp pointer to the @p MACDriver object + * @param[out] tdp pointer to a @p MACTransmitDescriptor structure + * @return The operation status. + * @retval RDY_OK the descriptor has been obtained. + * @retval RDY_TIMEOUT descriptor not available. + * + * @notapi + */ +msg_t mac_lld_get_transmit_descriptor(MACDriver *macp, + MACTransmitDescriptor *tdp) { + stm32_eth_tx_descriptor_t *tdes; + + if (!macp->link_up) + return RDY_TIMEOUT; + + chSysLock(); + + /* Get Current TX descriptor.*/ + tdes = macp->txptr; + + /* Ensure that descriptor isn't owned by the Ethernet DMA or locked by + another thread.*/ + if (tdes->tdes0 & (STM32_TDES0_OWN | STM32_TDES0_LOCKED)) { + chSysUnlock(); + return RDY_TIMEOUT; + } + + /* Marks the current descriptor as locked using a reserved bit.*/ + tdes->tdes0 |= STM32_TDES0_LOCKED; + + /* Next TX descriptor to use.*/ + macp->txptr = (stm32_eth_tx_descriptor_t *)tdes->tdes3; + + chSysUnlock(); + + /* Set the buffer size and configuration.*/ + tdp->offset = 0; + tdp->size = STM32_MAC_BUFFERS_SIZE; + tdp->physdesc = tdes; + + return RDY_OK; +} + +/** + * @brief Releases a transmit descriptor and starts the transmission of the + * enqueued data as a single frame. + * + * @param[in] tdp the pointer to the @p MACTransmitDescriptor structure + * + * @notapi + */ +void mac_lld_release_transmit_descriptor(MACTransmitDescriptor *tdp) { + + chDbgAssert(!(tdp->physdesc->tdes0 & STM32_TDES0_OWN), + "mac_lld_release_transmit_descriptor(), #1", + "attempt to release descriptor already owned by DMA"); + + chSysLock(); + + /* Unlocks the descriptor and returns it to the DMA engine.*/ + tdp->physdesc->tdes1 = tdp->offset; + tdp->physdesc->tdes0 = STM32_TDES0_CIC(STM32_MAC_IP_CHECKSUM_OFFLOAD) | + STM32_TDES0_IC | STM32_TDES0_LS | STM32_TDES0_FS | + STM32_TDES0_TCH | STM32_TDES0_OWN; + + /* If the DMA engine is stalled then a restart request is issued.*/ + if ((ETH->DMASR & ETH_DMASR_TPS) == ETH_DMASR_TPS_Suspended) { + ETH->DMASR = ETH_DMASR_TBUS; + ETH->DMATPDR = ETH_DMASR_TBUS; /* Any value is OK.*/ + } + + chSysUnlock(); +} + +/** + * @brief Returns a receive descriptor. + * + * @param[in] macp pointer to the @p MACDriver object + * @param[out] rdp pointer to a @p MACReceiveDescriptor structure + * @return The operation status. + * @retval RDY_OK the descriptor has been obtained. + * @retval RDY_TIMEOUT descriptor not available. + * + * @notapi + */ +msg_t mac_lld_get_receive_descriptor(MACDriver *macp, + MACReceiveDescriptor *rdp) { + stm32_eth_rx_descriptor_t *rdes; + + chSysLock(); + + /* Get Current RX descriptor.*/ + rdes = macp->rxptr; + + /* Iterates through received frames until a valid one is found, invalid + frames are discarded.*/ + while (!(rdes->rdes0 & STM32_RDES0_OWN)) { + if (!(rdes->rdes0 & (STM32_RDES0_AFM | STM32_RDES0_ES)) +#if STM32_MAC_IP_CHECKSUM_OFFLOAD + && (rdes->rdes0 & STM32_RDES0_FT) + && !(rdes->rdes0 & (STM32_RDES0_IPHCE | STM32_RDES0_PCE)) +#endif + && (rdes->rdes0 & STM32_RDES0_FS) && (rdes->rdes0 & STM32_RDES0_LS)) { + /* Found a valid one.*/ + rdp->offset = 0; + rdp->size = ((rdes->rdes0 & STM32_RDES0_FL_MASK) >> 16) - 4; + rdp->physdesc = rdes; + macp->rxptr = (stm32_eth_rx_descriptor_t *)rdes->rdes3; + + chSysUnlock(); + return RDY_OK; + } + /* Invalid frame found, purging.*/ + rdes->rdes0 = STM32_RDES0_OWN; + rdes = (stm32_eth_rx_descriptor_t *)rdes->rdes3; + } + + /* Next descriptor to check.*/ + macp->rxptr = rdes; + + chSysUnlock(); + return RDY_TIMEOUT; +} + +/** + * @brief Releases a receive descriptor. + * @details The descriptor and its buffer are made available for more incoming + * frames. + * + * @param[in] rdp the pointer to the @p MACReceiveDescriptor structure + * + * @notapi + */ +void mac_lld_release_receive_descriptor(MACReceiveDescriptor *rdp) { + + chDbgAssert(!(rdp->physdesc->rdes0 & STM32_RDES0_OWN), + "mac_lld_release_receive_descriptor(), #1", + "attempt to release descriptor already owned by DMA"); + + chSysLock(); + + /* Give buffer back to the Ethernet DMA.*/ + rdp->physdesc->rdes0 = STM32_RDES0_OWN; + + /* If the DMA engine is stalled then a restart request is issued.*/ + if ((ETH->DMASR & ETH_DMASR_RPS) == ETH_DMASR_RPS_Suspended) { + ETH->DMASR = ETH_DMASR_RBUS; + ETH->DMARPDR = ETH_DMASR_RBUS; /* Any value is OK.*/ + } + + chSysUnlock(); +} + +/** + * @brief Updates and returns the link status. + * + * @param[in] macp pointer to the @p MACDriver object + * @return The link status. + * @retval TRUE if the link is active. + * @retval FALSE if the link is down. + * + * @notapi + */ +bool_t mac_lld_poll_link_status(MACDriver *macp) { + uint32_t maccr, bmsr, bmcr; + + maccr = ETH->MACCR; + + /* PHY CR and SR registers read.*/ + (void)mii_read(macp, MII_BMSR); + bmsr = mii_read(macp, MII_BMSR); + bmcr = mii_read(macp, MII_BMCR); + + /* Check on auto-negotiation mode.*/ + if (bmcr & BMCR_ANENABLE) { + uint32_t lpa; + + /* Auto-negotiation must be finished without faults and link established.*/ + if ((bmsr & (BMSR_LSTATUS | BMSR_RFAULT | BMSR_ANEGCOMPLETE)) != + (BMSR_LSTATUS | BMSR_ANEGCOMPLETE)) + return macp->link_up = FALSE; + + /* Auto-negotiation enabled, checks the LPA register.*/ + lpa = mii_read(macp, MII_LPA); + + /* Check on link speed.*/ + if (lpa & (LPA_100HALF | LPA_100FULL | LPA_100BASE4)) + maccr |= ETH_MACCR_FES; + else + maccr &= ~ETH_MACCR_FES; + + /* Check on link mode.*/ + if (lpa & (LPA_10FULL | LPA_100FULL)) + maccr |= ETH_MACCR_DM; + else + maccr &= ~ETH_MACCR_DM; + } + else { + /* Link must be established.*/ + if (!(bmsr & BMSR_LSTATUS)) + return macp->link_up = FALSE; + + /* Check on link speed.*/ + if (bmcr & BMCR_SPEED100) + maccr |= ETH_MACCR_FES; + else + maccr &= ~ETH_MACCR_FES; + + /* Check on link mode.*/ + if (bmcr & BMCR_FULLDPLX) + maccr |= ETH_MACCR_DM; + else + maccr &= ~ETH_MACCR_DM; + } + + /* Changes the mode in the MAC.*/ + ETH->MACCR = maccr; + + /* Returns the link status.*/ + return macp->link_up = TRUE; +} + +/** + * @brief Writes to a transmit descriptor's stream. + * + * @param[in] tdp pointer to a @p MACTransmitDescriptor structure + * @param[in] buf pointer to the buffer containing the data to be + * written + * @param[in] size number of bytes to be written + * @return The number of bytes written into the descriptor's + * stream, this value can be less than the amount + * specified in the parameter @p size if the maximum + * frame size is reached. + * + * @notapi + */ +size_t mac_lld_write_transmit_descriptor(MACTransmitDescriptor *tdp, + uint8_t *buf, + size_t size) { + + chDbgAssert(!(tdp->physdesc->tdes0 & STM32_TDES0_OWN), + "mac_lld_write_transmit_descriptor(), #1", + "attempt to write descriptor already owned by DMA"); + + if (size > tdp->size - tdp->offset) + size = tdp->size - tdp->offset; + + if (size > 0) { + memcpy((uint8_t *)(tdp->physdesc->tdes2) + tdp->offset, buf, size); + tdp->offset += size; + } + return size; +} + +/** + * @brief Reads from a receive descriptor's stream. + * + * @param[in] rdp pointer to a @p MACReceiveDescriptor structure + * @param[in] buf pointer to the buffer that will receive the read data + * @param[in] size number of bytes to be read + * @return The number of bytes read from the descriptor's + * stream, this value can be less than the amount + * specified in the parameter @p size if there are + * no more bytes to read. + * + * @notapi + */ +size_t mac_lld_read_receive_descriptor(MACReceiveDescriptor *rdp, + uint8_t *buf, + size_t size) { + + chDbgAssert(!(rdp->physdesc->rdes0 & STM32_RDES0_OWN), + "mac_lld_read_receive_descriptor(), #1", + "attempt to read descriptor already owned by DMA"); + + if (size > rdp->size - rdp->offset) + size = rdp->size - rdp->offset; + + if (size > 0) { + memcpy(buf, (uint8_t *)(rdp->physdesc->rdes2) + rdp->offset, size); + rdp->offset += size; + } + return size; +} + +#if MAC_USE_ZERO_COPY || defined(__DOXYGEN__) +/** + * @brief Returns a pointer to the next transmit buffer in the descriptor + * chain. + * @note The API guarantees that enough buffers can be requested to fill + * a whole frame. + * + * @param[in] tdp pointer to a @p MACTransmitDescriptor structure + * @param[in] size size of the requested buffer. Specify the frame size + * on the first call then scale the value down subtracting + * the amount of data already copied into the previous + * buffers. + * @param[out] sizep pointer to variable receiving the buffer size, it is + * zero when the last buffer has already been returned. + * Note that a returned size lower than the amount + * requested means that more buffers must be requested + * in order to fill the frame data entirely. + * @return Pointer to the returned buffer. + * @retval NULL if the buffer chain has been entirely scanned. + * + * @notapi + */ +uint8_t *mac_lld_get_next_transmit_buffer(MACTransmitDescriptor *tdp, + size_t size, + size_t *sizep) { + + if (tdp->offset == 0) { + *sizep = tdp->size; + tdp->offset = size; + return (uint8_t *)tdp->physdesc->tdes2; + } + *sizep = 0; + return NULL; +} + +/** + * @brief Returns a pointer to the next receive buffer in the descriptor + * chain. + * @note The API guarantees that the descriptor chain contains a whole + * frame. + * + * @param[in] rdp pointer to a @p MACReceiveDescriptor structure + * @param[out] sizep pointer to variable receiving the buffer size, it is + * zero when the last buffer has already been returned. + * @return Pointer to the returned buffer. + * @retval NULL if the buffer chain has been entirely scanned. + * + * @notapi + */ +const uint8_t *mac_lld_get_next_receive_buffer(MACReceiveDescriptor *rdp, + size_t *sizep) { + + if (rdp->size > 0) { + *sizep = rdp->size; + rdp->offset = rdp->size; + rdp->size = 0; + return (uint8_t *)rdp->physdesc->rdes2; + } + *sizep = 0; + return NULL; +} +#endif /* MAC_USE_ZERO_COPY */ + +#endif /* HAL_USE_MAC */ + +/** @} */ diff --git a/os/hal/ports/STM32/mac_lld.h b/os/hal/ports/STM32/mac_lld.h new file mode 100644 index 000000000..bde7e0345 --- /dev/null +++ b/os/hal/ports/STM32/mac_lld.h @@ -0,0 +1,362 @@ +/* + ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file STM32/mac_lld.h + * @brief STM32 low level MAC driver header. + * + * @addtogroup MAC + * @{ + */ + +#ifndef _MAC_LLD_H_ +#define _MAC_LLD_H_ + +#if HAL_USE_MAC || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver constants. */ +/*===========================================================================*/ + +/** + * @brief This implementation supports the zero-copy mode API. + */ +#define MAC_SUPPORTS_ZERO_COPY TRUE + +/** + * @name RDES0 constants + * @{ + */ +#define STM32_RDES0_OWN 0x80000000 +#define STM32_RDES0_AFM 0x40000000 +#define STM32_RDES0_FL_MASK 0x3FFF0000 +#define STM32_RDES0_ES 0x00008000 +#define STM32_RDES0_DESERR 0x00004000 +#define STM32_RDES0_SAF 0x00002000 +#define STM32_RDES0_LE 0x00001000 +#define STM32_RDES0_OE 0x00000800 +#define STM32_RDES0_VLAN 0x00000400 +#define STM32_RDES0_FS 0x00000200 +#define STM32_RDES0_LS 0x00000100 +#define STM32_RDES0_IPHCE 0x00000080 +#define STM32_RDES0_LCO 0x00000040 +#define STM32_RDES0_FT 0x00000020 +#define STM32_RDES0_RWT 0x00000010 +#define STM32_RDES0_RE 0x00000008 +#define STM32_RDES0_DE 0x00000004 +#define STM32_RDES0_CE 0x00000002 +#define STM32_RDES0_PCE 0x00000001 +/** @} */ + +/** + * @name RDES1 constants + * @{ + */ +#define STM32_RDES1_DIC 0x80000000 +#define STM32_RDES1_RBS2_MASK 0x1FFF0000 +#define STM32_RDES1_RER 0x00008000 +#define STM32_RDES1_RCH 0x00004000 +#define STM32_RDES1_RBS1_MASK 0x00001FFF +/** @} */ + +/** + * @name TDES0 constants + * @{ + */ +#define STM32_TDES0_OWN 0x80000000 +#define STM32_TDES0_IC 0x40000000 +#define STM32_TDES0_LS 0x20000000 +#define STM32_TDES0_FS 0x10000000 +#define STM32_TDES0_DC 0x08000000 +#define STM32_TDES0_DP 0x04000000 +#define STM32_TDES0_TTSE 0x02000000 +#define STM32_TDES0_LOCKED 0x01000000 /* NOTE: Pseudo flag. */ +#define STM32_TDES0_CIC_MASK 0x00C00000 +#define STM32_TDES0_CIC(n) ((n) << 22) +#define STM32_TDES0_TER 0x00200000 +#define STM32_TDES0_TCH 0x00100000 +#define STM32_TDES0_TTSS 0x00020000 +#define STM32_TDES0_IHE 0x00010000 +#define STM32_TDES0_ES 0x00008000 +#define STM32_TDES0_JT 0x00004000 +#define STM32_TDES0_FF 0x00002000 +#define STM32_TDES0_IPE 0x00001000 +#define STM32_TDES0_LCA 0x00000800 +#define STM32_TDES0_NC 0x00000400 +#define STM32_TDES0_LCO 0x00000200 +#define STM32_TDES0_EC 0x00000100 +#define STM32_TDES0_VF 0x00000080 +#define STM32_TDES0_CC_MASK 0x00000078 +#define STM32_TDES0_ED 0x00000004 +#define STM32_TDES0_UF 0x00000002 +#define STM32_TDES0_DB 0x00000001 +/** @} */ + +/** + * @name TDES1 constants + * @{ + */ +#define STM32_TDES1_TBS2_MASK 0x1FFF0000 +#define STM32_TDES1_TBS1_MASK 0x00001FFF +/** @} */ + +/*===========================================================================*/ +/* Driver pre-compile time settings. */ +/*===========================================================================*/ + +/** + * @name Configuration options + * @{ + */ +/** + * @brief Number of available transmit buffers. + */ +#if !defined(STM32_MAC_TRANSMIT_BUFFERS) || defined(__DOXYGEN__) +#define STM32_MAC_TRANSMIT_BUFFERS 2 +#endif + +/** + * @brief Number of available receive buffers. + */ +#if !defined(STM32_MAC_RECEIVE_BUFFERS) || defined(__DOXYGEN__) +#define STM32_MAC_RECEIVE_BUFFERS 4 +#endif + +/** + * @brief Maximum supported frame size. + */ +#if !defined(STM32_MAC_BUFFERS_SIZE) || defined(__DOXYGEN__) +#define STM32_MAC_BUFFERS_SIZE 1522 +#endif + +/** + * @brief PHY detection timeout. + * @details Timeout, in milliseconds, for PHY address detection, if a PHY + * is not detected within the timeout then the driver halts during + * initialization. This setting applies only if the PHY address is + * not explicitly set in the board header file using + * @p BOARD_PHY_ADDRESS. A zero value disables the timeout and a + * single search path is performed. + */ +#if !defined(STM32_MAC_PHY_TIMEOUT) || defined(__DOXYGEN__) +#define STM32_MAC_PHY_TIMEOUT 100 +#endif + +/** + * @brief Change the PHY power state inside the driver. + */ +#if !defined(STM32_MAC_ETH1_CHANGE_PHY_STATE) || defined(__DOXYGEN__) +#define STM32_MAC_ETH1_CHANGE_PHY_STATE TRUE +#endif + +/** + * @brief ETHD1 interrupt priority level setting. + */ +#if !defined(STM32_MAC_ETH1_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_MAC_ETH1_IRQ_PRIORITY 13 +#endif + +/** + * @brief IP checksum offload. + * @details The following modes are available: + * - 0 Function disabled. + * - 1 Only IP header checksum calculation and insertion are enabled. + * - 2 IP header checksum and payload checksum calculation and + * insertion are enabled, but pseudo-header checksum is not + * calculated in hardware. + * - 3 IP Header checksum and payload checksum calculation and + * insertion are enabled, and pseudo-header checksum is + * calculated in hardware. + * . + */ +#if !defined(STM32_MAC_IP_CHECKSUM_OFFLOAD) || defined(__DOXYGEN__) +#define STM32_MAC_IP_CHECKSUM_OFFLOAD 0 +#endif +/** @} */ + +/*===========================================================================*/ +/* Derived constants and error checks. */ +/*===========================================================================*/ + +#if (STM32_MAC_PHY_TIMEOUT > 0) && !HAL_IMPLEMENTS_COUNTERS +#error "STM32_MAC_PHY_TIMEOUT requires the realtime counter service" +#endif + +/*===========================================================================*/ +/* Driver data structures and types. */ +/*===========================================================================*/ + +/** + * @brief Type of an STM32 Ethernet receive descriptor. + */ +typedef struct { + volatile uint32_t rdes0; + volatile uint32_t rdes1; + volatile uint32_t rdes2; + volatile uint32_t rdes3; +} stm32_eth_rx_descriptor_t; + +/** + * @brief Type of an STM32 Ethernet transmit descriptor. + */ +typedef struct { + volatile uint32_t tdes0; + volatile uint32_t tdes1; + volatile uint32_t tdes2; + volatile uint32_t tdes3; +} stm32_eth_tx_descriptor_t; + +/** + * @brief Driver configuration structure. + */ +typedef struct { + /** + * @brief MAC address. + */ + uint8_t *mac_address; + /* End of the mandatory fields.*/ +} MACConfig; + +/** + * @brief Structure representing a MAC driver. + */ +struct MACDriver { + /** + * @brief Driver state. + */ + macstate_t state; + /** + * @brief Current configuration data. + */ + const MACConfig *config; + /** + * @brief Transmit semaphore. + */ + Semaphore tdsem; + /** + * @brief Receive semaphore. + */ + Semaphore rdsem; +#if MAC_USE_EVENTS || defined(__DOXYGEN__) + /** + * @brief Receive event. + */ + EventSource rdevent; +#endif + /* End of the mandatory fields.*/ + /** + * @brief Link status flag. + */ + bool_t link_up; + /** + * @brief PHY address (pre shifted). + */ + uint32_t phyaddr; + /** + * @brief Receive next frame pointer. + */ + stm32_eth_rx_descriptor_t *rxptr; + /** + * @brief Transmit next frame pointer. + */ + stm32_eth_tx_descriptor_t *txptr; +}; + +/** + * @brief Structure representing a transmit descriptor. + */ +typedef struct { + /** + * @brief Current write offset. + */ + size_t offset; + /** + * @brief Available space size. + */ + size_t size; + /* End of the mandatory fields.*/ + /** + * @brief Pointer to the physical descriptor. + */ + stm32_eth_tx_descriptor_t *physdesc; +} MACTransmitDescriptor; + +/** + * @brief Structure representing a receive descriptor. + */ +typedef struct { + /** + * @brief Current read offset. + */ + size_t offset; + /** + * @brief Available data size. + */ + size_t size; + /* End of the mandatory fields.*/ + /** + * @brief Pointer to the physical descriptor. + */ + stm32_eth_rx_descriptor_t *physdesc; +} MACReceiveDescriptor; + +/*===========================================================================*/ +/* Driver macros. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +#if !defined(__DOXYGEN__) +extern MACDriver ETHD1; +#endif + +#ifdef __cplusplus +extern "C" { +#endif + void mac_lld_init(void); + void mac_lld_start(MACDriver *macp); + void mac_lld_stop(MACDriver *macp); + msg_t mac_lld_get_transmit_descriptor(MACDriver *macp, + MACTransmitDescriptor *tdp); + void mac_lld_release_transmit_descriptor(MACTransmitDescriptor *tdp); + msg_t mac_lld_get_receive_descriptor(MACDriver *macp, + MACReceiveDescriptor *rdp); + void mac_lld_release_receive_descriptor(MACReceiveDescriptor *rdp); + bool_t mac_lld_poll_link_status(MACDriver *macp); + size_t mac_lld_write_transmit_descriptor(MACTransmitDescriptor *tdp, + uint8_t *buf, + size_t size); + size_t mac_lld_read_receive_descriptor(MACReceiveDescriptor *rdp, + uint8_t *buf, + size_t size); +#if MAC_USE_ZERO_COPY + uint8_t *mac_lld_get_next_transmit_buffer(MACTransmitDescriptor *tdp, + size_t size, + size_t *sizep); + const uint8_t *mac_lld_get_next_receive_buffer(MACReceiveDescriptor *rdp, + size_t *sizep); +#endif /* MAC_USE_ZERO_COPY */ +#ifdef __cplusplus +} +#endif + +#endif /* HAL_USE_MAC */ + +#endif /* _MAC_LLD_H_ */ + +/** @} */ diff --git a/os/hal/ports/STM32/sdc_lld.c b/os/hal/ports/STM32/sdc_lld.c new file mode 100644 index 000000000..69873d5f0 --- /dev/null +++ b/os/hal/ports/STM32/sdc_lld.c @@ -0,0 +1,788 @@ +/* + ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file STM32/sdc_lld.c + * @brief STM32 SDC subsystem low level driver source. + * + * @addtogroup SDC + * @{ + */ + +/* + TODO: Try preerase blocks before writing (ACMD23). + */ + +#include + +#include "ch.h" +#include "hal.h" + +#if HAL_USE_SDC || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver local definitions. */ +/*===========================================================================*/ + +#define DMA_CHANNEL \ + STM32_DMA_GETCHANNEL(STM32_SDC_SDIO_DMA_STREAM, \ + STM32_SDC_SDIO_DMA_CHN) + +/*===========================================================================*/ +/* Driver exported variables. */ +/*===========================================================================*/ + +/** @brief SDCD1 driver identifier.*/ +SDCDriver SDCD1; + +/*===========================================================================*/ +/* Driver local variables and types. */ +/*===========================================================================*/ + +#if STM32_SDC_SDIO_UNALIGNED_SUPPORT +/** + * @brief Buffer for temporary storage during unaligned transfers. + */ +static union { + uint32_t alignment; + uint8_t buf[MMCSD_BLOCK_SIZE]; +} u; +#endif /* STM32_SDC_SDIO_UNALIGNED_SUPPORT */ + +/*===========================================================================*/ +/* Driver local functions. */ +/*===========================================================================*/ + +/** + * @brief Prepares card to handle read transaction. + * + * @param[in] sdcp pointer to the @p SDCDriver object + * @param[in] startblk first block to read + * @param[in] n number of blocks to read + * @param[in] resp pointer to the response buffer + * + * @return The operation status. + * @retval CH_SUCCESS operation succeeded. + * @retval CH_FAILED operation failed. + * + * @notapi + */ +static bool_t sdc_lld_prepare_read(SDCDriver *sdcp, uint32_t startblk, + uint32_t n, uint32_t *resp) { + + /* Driver handles data in 512 bytes blocks (just like HC cards). But if we + have not HC card than we must convert address from blocks to bytes.*/ + if (!(sdcp->cardmode & SDC_MODE_HIGH_CAPACITY)) + startblk *= MMCSD_BLOCK_SIZE; + + if (n > 1) { + /* Send read multiple blocks command to card.*/ + if (sdc_lld_send_cmd_short_crc(sdcp, MMCSD_CMD_READ_MULTIPLE_BLOCK, + startblk, resp) || MMCSD_R1_ERROR(resp[0])) + return CH_FAILED; + } + else{ + /* Send read single block command.*/ + if (sdc_lld_send_cmd_short_crc(sdcp, MMCSD_CMD_READ_SINGLE_BLOCK, + startblk, resp) || MMCSD_R1_ERROR(resp[0])) + return CH_FAILED; + } + + return CH_SUCCESS; +} + +/** + * @brief Prepares card to handle write transaction. + * + * @param[in] sdcp pointer to the @p SDCDriver object + * @param[in] startblk first block to read + * @param[in] n number of blocks to write + * @param[in] resp pointer to the response buffer + * + * @return The operation status. + * @retval CH_SUCCESS operation succeeded. + * @retval CH_FAILED operation failed. + * + * @notapi + */ +static bool_t sdc_lld_prepare_write(SDCDriver *sdcp, uint32_t startblk, + uint32_t n, uint32_t *resp) { + + /* Driver handles data in 512 bytes blocks (just like HC cards). But if we + have not HC card than we must convert address from blocks to bytes.*/ + if (!(sdcp->cardmode & SDC_MODE_HIGH_CAPACITY)) + startblk *= MMCSD_BLOCK_SIZE; + + if (n > 1) { + /* Write multiple blocks command.*/ + if (sdc_lld_send_cmd_short_crc(sdcp, MMCSD_CMD_WRITE_MULTIPLE_BLOCK, + startblk, resp) || MMCSD_R1_ERROR(resp[0])) + return CH_FAILED; + } + else{ + /* Write single block command.*/ + if (sdc_lld_send_cmd_short_crc(sdcp, MMCSD_CMD_WRITE_BLOCK, + startblk, resp) || MMCSD_R1_ERROR(resp[0])) + return CH_FAILED; + } + + return CH_SUCCESS; +} + +/** + * @brief Wait end of data transaction and performs finalizations. + * + * @param[in] sdcp pointer to the @p SDCDriver object + * @param[in] n number of blocks in transaction + * @param[in] resp pointer to the response buffer + * + * @return The operation status. + * @retval CH_SUCCESS operation succeeded. + * @retval CH_FAILED operation failed. + */ +static bool_t sdc_lld_wait_transaction_end(SDCDriver *sdcp, uint32_t n, + uint32_t *resp) { + + /* Note the mask is checked before going to sleep because the interrupt + may have occurred before reaching the critical zone.*/ + chSysLock(); + if (SDIO->MASK != 0) { + chDbgAssert(sdcp->thread == NULL, + "sdc_lld_start_data_transaction(), #1", "not NULL"); + sdcp->thread = chThdSelf(); + chSchGoSleepS(THD_STATE_SUSPENDED); + chDbgAssert(sdcp->thread == NULL, + "sdc_lld_start_data_transaction(), #2", "not NULL"); + } + if ((SDIO->STA & SDIO_STA_DATAEND) == 0) { + chSysUnlock(); + return CH_FAILED; + } + +#if (defined(STM32F4XX) || defined(STM32F2XX)) + /* Wait until DMA channel enabled to be sure that all data transferred.*/ + while (sdcp->dma->stream->CR & STM32_DMA_CR_EN) + ; + + /* DMA event flags must be manually cleared.*/ + dmaStreamClearInterrupt(sdcp->dma); + + SDIO->ICR = STM32_SDIO_ICR_ALL_FLAGS; + SDIO->DCTRL = 0; + chSysUnlock(); + + /* Wait until interrupt flags to be cleared.*/ + /*while (((DMA2->LISR) >> (sdcp->dma->ishift)) & STM32_DMA_ISR_TCIF) + dmaStreamClearInterrupt(sdcp->dma);*/ +#else + /* Waits for transfer completion at DMA level, the the stream is + disabled and cleared.*/ + dmaWaitCompletion(sdcp->dma); + + SDIO->ICR = STM32_SDIO_ICR_ALL_FLAGS; + SDIO->DCTRL = 0; + chSysUnlock(); +#endif + + /* Finalize transaction.*/ + if (n > 1) + return sdc_lld_send_cmd_short_crc(sdcp, MMCSD_CMD_STOP_TRANSMISSION, 0, resp); + + return CH_SUCCESS; +} + +/** + * @brief Gets SDC errors. + * + * @param[in] sdcp pointer to the @p SDCDriver object + * @param[in] sta value of the STA register + * + * @notapi + */ +static void sdc_lld_collect_errors(SDCDriver *sdcp, uint32_t sta) { + uint32_t errors = SDC_NO_ERROR; + + if (sta & SDIO_STA_CCRCFAIL) + errors |= SDC_CMD_CRC_ERROR; + if (sta & SDIO_STA_DCRCFAIL) + errors |= SDC_DATA_CRC_ERROR; + if (sta & SDIO_STA_CTIMEOUT) + errors |= SDC_COMMAND_TIMEOUT; + if (sta & SDIO_STA_DTIMEOUT) + errors |= SDC_DATA_TIMEOUT; + if (sta & SDIO_STA_TXUNDERR) + errors |= SDC_TX_UNDERRUN; + if (sta & SDIO_STA_RXOVERR) + errors |= SDC_RX_OVERRUN; + if (sta & SDIO_STA_STBITERR) + errors |= SDC_STARTBIT_ERROR; + + sdcp->errors |= errors; +} + +/** + * @brief Performs clean transaction stopping in case of errors. + * + * @param[in] sdcp pointer to the @p SDCDriver object + * @param[in] n number of blocks in transaction + * @param[in] resp pointer to the response buffer + * + * @notapi + */ +static void sdc_lld_error_cleanup(SDCDriver *sdcp, + uint32_t n, + uint32_t *resp) { + uint32_t sta = SDIO->STA; + + dmaStreamClearInterrupt(sdcp->dma); + dmaStreamDisable(sdcp->dma); + SDIO->ICR = STM32_SDIO_ICR_ALL_FLAGS; + SDIO->MASK = 0; + SDIO->DCTRL = 0; + sdc_lld_collect_errors(sdcp, sta); + if (n > 1) + sdc_lld_send_cmd_short_crc(sdcp, MMCSD_CMD_STOP_TRANSMISSION, 0, resp); +} + +/*===========================================================================*/ +/* Driver interrupt handlers. */ +/*===========================================================================*/ + +#if !defined(STM32_SDIO_HANDLER) +#error "STM32_SDIO_HANDLER not defined" +#endif +/** + * @brief SDIO IRQ handler. + * @details It just wakes transaction thread. All error handling performs in + * that thread. + * + * @isr + */ +CH_IRQ_HANDLER(STM32_SDIO_HANDLER) { + + CH_IRQ_PROLOGUE(); + + chSysLockFromIsr() + + /* Disables the source but the status flags are not reset because the + read/write functions needs to check them.*/ + SDIO->MASK = 0; + + if (SDCD1.thread != NULL) { + chSchReadyI(SDCD1.thread); + SDCD1.thread = NULL; + } + + chSysUnlockFromIsr(); + + CH_IRQ_EPILOGUE(); +} + +/*===========================================================================*/ +/* Driver exported functions. */ +/*===========================================================================*/ + +/** + * @brief Low level SDC driver initialization. + * + * @notapi + */ +void sdc_lld_init(void) { + + sdcObjectInit(&SDCD1); + SDCD1.thread = NULL; + SDCD1.dma = STM32_DMA_STREAM(STM32_SDC_SDIO_DMA_STREAM); +#if CH_DBG_ENABLE_ASSERTS + SDCD1.sdio = SDIO; +#endif +} + +/** + * @brief Configures and activates the SDC peripheral. + * + * @param[in] sdcp pointer to the @p SDCDriver object + * + * @notapi + */ +void sdc_lld_start(SDCDriver *sdcp) { + + sdcp->dmamode = STM32_DMA_CR_CHSEL(DMA_CHANNEL) | + STM32_DMA_CR_PL(STM32_SDC_SDIO_DMA_PRIORITY) | + STM32_DMA_CR_PSIZE_WORD | + STM32_DMA_CR_MSIZE_WORD | + STM32_DMA_CR_MINC; + +#if (defined(STM32F4XX) || defined(STM32F2XX)) + sdcp->dmamode |= STM32_DMA_CR_PFCTRL | + STM32_DMA_CR_PBURST_INCR4 | + STM32_DMA_CR_MBURST_INCR4; +#endif + + if (sdcp->state == BLK_STOP) { + /* Note, the DMA must be enabled before the IRQs.*/ + bool_t b; + b = dmaStreamAllocate(sdcp->dma, STM32_SDC_SDIO_IRQ_PRIORITY, NULL, NULL); + chDbgAssert(!b, "sdc_lld_start(), #1", "stream already allocated"); + dmaStreamSetPeripheral(sdcp->dma, &SDIO->FIFO); +#if (defined(STM32F4XX) || defined(STM32F2XX)) + dmaStreamSetFIFO(sdcp->dma, STM32_DMA_FCR_DMDIS | STM32_DMA_FCR_FTH_FULL); +#endif + nvicEnableVector(STM32_SDIO_NUMBER, + CORTEX_PRIORITY_MASK(STM32_SDC_SDIO_IRQ_PRIORITY)); + rccEnableSDIO(FALSE); + } + + /* Configuration, card clock is initially stopped.*/ + SDIO->POWER = 0; + SDIO->CLKCR = 0; + SDIO->DCTRL = 0; + SDIO->DTIMER = 0; +} + +/** + * @brief Deactivates the SDC peripheral. + * + * @param[in] sdcp pointer to the @p SDCDriver object + * + * @notapi + */ +void sdc_lld_stop(SDCDriver *sdcp) { + + if (sdcp->state != BLK_STOP) { + + /* SDIO deactivation.*/ + SDIO->POWER = 0; + SDIO->CLKCR = 0; + SDIO->DCTRL = 0; + SDIO->DTIMER = 0; + + /* Clock deactivation.*/ + nvicDisableVector(STM32_SDIO_NUMBER); + dmaStreamRelease(sdcp->dma); + rccDisableSDIO(FALSE); + } +} + +/** + * @brief Starts the SDIO clock and sets it to init mode (400kHz or less). + * + * @param[in] sdcp pointer to the @p SDCDriver object + * + * @notapi + */ +void sdc_lld_start_clk(SDCDriver *sdcp) { + + (void)sdcp; + + /* Initial clock setting: 400kHz, 1bit mode.*/ + SDIO->CLKCR = STM32_SDIO_DIV_LS; + SDIO->POWER |= SDIO_POWER_PWRCTRL_0 | SDIO_POWER_PWRCTRL_1; + SDIO->CLKCR |= SDIO_CLKCR_CLKEN; +} + +/** + * @brief Sets the SDIO clock to data mode (25MHz or less). + * + * @param[in] sdcp pointer to the @p SDCDriver object + * + * @notapi + */ +void sdc_lld_set_data_clk(SDCDriver *sdcp) { + + (void)sdcp; + + SDIO->CLKCR = (SDIO->CLKCR & 0xFFFFFF00) | STM32_SDIO_DIV_HS; +} + +/** + * @brief Stops the SDIO clock. + * + * @param[in] sdcp pointer to the @p SDCDriver object + * + * @notapi + */ +void sdc_lld_stop_clk(SDCDriver *sdcp) { + + (void)sdcp; + + SDIO->CLKCR = 0; + SDIO->POWER = 0; +} + +/** + * @brief Switches the bus to 4 bits mode. + * + * @param[in] sdcp pointer to the @p SDCDriver object + * @param[in] mode bus mode + * + * @notapi + */ +void sdc_lld_set_bus_mode(SDCDriver *sdcp, sdcbusmode_t mode) { + uint32_t clk = SDIO->CLKCR & ~SDIO_CLKCR_WIDBUS; + + (void)sdcp; + + switch (mode) { + case SDC_MODE_1BIT: + SDIO->CLKCR = clk; + break; + case SDC_MODE_4BIT: + SDIO->CLKCR = clk | SDIO_CLKCR_WIDBUS_0; + break; + case SDC_MODE_8BIT: + SDIO->CLKCR = clk | SDIO_CLKCR_WIDBUS_1; + break; + } +} + +/** + * @brief Sends an SDIO command with no response expected. + * + * @param[in] sdcp pointer to the @p SDCDriver object + * @param[in] cmd card command + * @param[in] arg command argument + * + * @notapi + */ +void sdc_lld_send_cmd_none(SDCDriver *sdcp, uint8_t cmd, uint32_t arg) { + + (void)sdcp; + + SDIO->ARG = arg; + SDIO->CMD = (uint32_t)cmd | SDIO_CMD_CPSMEN; + while ((SDIO->STA & SDIO_STA_CMDSENT) == 0) + ; + SDIO->ICR = SDIO_ICR_CMDSENTC; +} + +/** + * @brief Sends an SDIO command with a short response expected. + * @note The CRC is not verified. + * + * @param[in] sdcp pointer to the @p SDCDriver object + * @param[in] cmd card command + * @param[in] arg command argument + * @param[out] resp pointer to the response buffer (one word) + * + * @return The operation status. + * @retval CH_SUCCESS operation succeeded. + * @retval CH_FAILED operation failed. + * + * @notapi + */ +bool_t sdc_lld_send_cmd_short(SDCDriver *sdcp, uint8_t cmd, uint32_t arg, + uint32_t *resp) { + uint32_t sta; + + (void)sdcp; + + SDIO->ARG = arg; + SDIO->CMD = (uint32_t)cmd | SDIO_CMD_WAITRESP_0 | SDIO_CMD_CPSMEN; + while (((sta = SDIO->STA) & (SDIO_STA_CMDREND | SDIO_STA_CTIMEOUT | + SDIO_STA_CCRCFAIL)) == 0) + ; + SDIO->ICR = sta; + if ((sta & (SDIO_STA_CTIMEOUT)) != 0) { + sdc_lld_collect_errors(sdcp, sta); + return CH_FAILED; + } + *resp = SDIO->RESP1; + return CH_SUCCESS; +} + +/** + * @brief Sends an SDIO command with a short response expected and CRC. + * + * @param[in] sdcp pointer to the @p SDCDriver object + * @param[in] cmd card command + * @param[in] arg command argument + * @param[out] resp pointer to the response buffer (one word) + * + * @return The operation status. + * @retval CH_SUCCESS operation succeeded. + * @retval CH_FAILED operation failed. + * + * @notapi + */ +bool_t sdc_lld_send_cmd_short_crc(SDCDriver *sdcp, uint8_t cmd, uint32_t arg, + uint32_t *resp) { + uint32_t sta; + + (void)sdcp; + + SDIO->ARG = arg; + SDIO->CMD = (uint32_t)cmd | SDIO_CMD_WAITRESP_0 | SDIO_CMD_CPSMEN; + while (((sta = SDIO->STA) & (SDIO_STA_CMDREND | SDIO_STA_CTIMEOUT | + SDIO_STA_CCRCFAIL)) == 0) + ; + SDIO->ICR = sta; + if ((sta & (SDIO_STA_CTIMEOUT | SDIO_STA_CCRCFAIL)) != 0) { + sdc_lld_collect_errors(sdcp, sta); + return CH_FAILED; + } + *resp = SDIO->RESP1; + return CH_SUCCESS; +} + +/** + * @brief Sends an SDIO command with a long response expected and CRC. + * + * @param[in] sdcp pointer to the @p SDCDriver object + * @param[in] cmd card command + * @param[in] arg command argument + * @param[out] resp pointer to the response buffer (four words) + * + * @return The operation status. + * @retval CH_SUCCESS operation succeeded. + * @retval CH_FAILED operation failed. + * + * @notapi + */ +bool_t sdc_lld_send_cmd_long_crc(SDCDriver *sdcp, uint8_t cmd, uint32_t arg, + uint32_t *resp) { + uint32_t sta; + + (void)sdcp; + + SDIO->ARG = arg; + SDIO->CMD = (uint32_t)cmd | SDIO_CMD_WAITRESP_0 | SDIO_CMD_WAITRESP_1 | + SDIO_CMD_CPSMEN; + while (((sta = SDIO->STA) & (SDIO_STA_CMDREND | SDIO_STA_CTIMEOUT | + SDIO_STA_CCRCFAIL)) == 0) + ; + SDIO->ICR = sta; + if ((sta & (STM32_SDIO_STA_ERROR_MASK)) != 0) { + sdc_lld_collect_errors(sdcp, sta); + return CH_FAILED; + } + /* Save bytes in reverse order because MSB in response comes first.*/ + *resp++ = SDIO->RESP4; + *resp++ = SDIO->RESP3; + *resp++ = SDIO->RESP2; + *resp = SDIO->RESP1; + return CH_SUCCESS; +} + +/** + * @brief Reads one or more blocks. + * + * @param[in] sdcp pointer to the @p SDCDriver object + * @param[in] startblk first block to read + * @param[out] buf pointer to the read buffer + * @param[in] n number of blocks to read + * + * @return The operation status. + * @retval CH_SUCCESS operation succeeded. + * @retval CH_FAILED operation failed. + * + * @notapi + */ +bool_t sdc_lld_read_aligned(SDCDriver *sdcp, uint32_t startblk, + uint8_t *buf, uint32_t n) { + uint32_t resp[1]; + + chDbgCheck((n < (0x1000000 / MMCSD_BLOCK_SIZE)), "max transaction size"); + + SDIO->DTIMER = STM32_SDC_READ_TIMEOUT; + + /* Checks for errors and waits for the card to be ready for reading.*/ + if (_sdc_wait_for_transfer_state(sdcp)) + return CH_FAILED; + + /* Prepares the DMA channel for writing.*/ + dmaStreamSetMemory0(sdcp->dma, buf); + dmaStreamSetTransactionSize(sdcp->dma, + (n * MMCSD_BLOCK_SIZE) / sizeof (uint32_t)); + dmaStreamSetMode(sdcp->dma, sdcp->dmamode | STM32_DMA_CR_DIR_P2M); + dmaStreamEnable(sdcp->dma); + + /* Setting up data transfer.*/ + SDIO->ICR = STM32_SDIO_ICR_ALL_FLAGS; + SDIO->MASK = SDIO_MASK_DCRCFAILIE | + SDIO_MASK_DTIMEOUTIE | + SDIO_MASK_STBITERRIE | + SDIO_MASK_RXOVERRIE | + SDIO_MASK_DATAENDIE; + SDIO->DLEN = n * MMCSD_BLOCK_SIZE; + + /* Talk to card what we want from it.*/ + if (sdc_lld_prepare_read(sdcp, startblk, n, resp) == TRUE) + goto error; + + /* Transaction starts just after DTEN bit setting.*/ + SDIO->DCTRL = SDIO_DCTRL_DTDIR | + SDIO_DCTRL_DBLOCKSIZE_3 | + SDIO_DCTRL_DBLOCKSIZE_0 | + SDIO_DCTRL_DMAEN | + SDIO_DCTRL_DTEN; + if (sdc_lld_wait_transaction_end(sdcp, n, resp) == TRUE) + goto error; + + return CH_SUCCESS; + +error: + sdc_lld_error_cleanup(sdcp, n, resp); + return CH_FAILED; +} + +/** + * @brief Writes one or more blocks. + * + * @param[in] sdcp pointer to the @p SDCDriver object + * @param[in] startblk first block to write + * @param[out] buf pointer to the write buffer + * @param[in] n number of blocks to write + * + * @return The operation status. + * @retval CH_SUCCESS operation succeeded. + * @retval CH_FAILED operation failed. + * + * @notapi + */ +bool_t sdc_lld_write_aligned(SDCDriver *sdcp, uint32_t startblk, + const uint8_t *buf, uint32_t n) { + uint32_t resp[1]; + + chDbgCheck((n < (0x1000000 / MMCSD_BLOCK_SIZE)), "max transaction size"); + + SDIO->DTIMER = STM32_SDC_WRITE_TIMEOUT; + + /* Checks for errors and waits for the card to be ready for writing.*/ + if (_sdc_wait_for_transfer_state(sdcp)) + return CH_FAILED; + + /* Prepares the DMA channel for writing.*/ + dmaStreamSetMemory0(sdcp->dma, buf); + dmaStreamSetTransactionSize(sdcp->dma, + (n * MMCSD_BLOCK_SIZE) / sizeof (uint32_t)); + dmaStreamSetMode(sdcp->dma, sdcp->dmamode | STM32_DMA_CR_DIR_M2P); + dmaStreamEnable(sdcp->dma); + + /* Setting up data transfer.*/ + SDIO->ICR = STM32_SDIO_ICR_ALL_FLAGS; + SDIO->MASK = SDIO_MASK_DCRCFAILIE | + SDIO_MASK_DTIMEOUTIE | + SDIO_MASK_STBITERRIE | + SDIO_MASK_TXUNDERRIE | + SDIO_MASK_DATAENDIE; + SDIO->DLEN = n * MMCSD_BLOCK_SIZE; + + /* Talk to card what we want from it.*/ + if (sdc_lld_prepare_write(sdcp, startblk, n, resp) == TRUE) + goto error; + + /* Transaction starts just after DTEN bit setting.*/ + SDIO->DCTRL = SDIO_DCTRL_DBLOCKSIZE_3 | + SDIO_DCTRL_DBLOCKSIZE_0 | + SDIO_DCTRL_DMAEN | + SDIO_DCTRL_DTEN; + if (sdc_lld_wait_transaction_end(sdcp, n, resp) == TRUE) + goto error; + + return CH_SUCCESS; + +error: + sdc_lld_error_cleanup(sdcp, n, resp); + return CH_FAILED; +} + +/** + * @brief Reads one or more blocks. + * + * @param[in] sdcp pointer to the @p SDCDriver object + * @param[in] startblk first block to read + * @param[out] buf pointer to the read buffer + * @param[in] n number of blocks to read + * + * @return The operation status. + * @retval CH_SUCCESS operation succeeded. + * @retval CH_FAILED operation failed. + * + * @notapi + */ +bool_t sdc_lld_read(SDCDriver *sdcp, uint32_t startblk, + uint8_t *buf, uint32_t n) { + +#if STM32_SDC_SDIO_UNALIGNED_SUPPORT + if (((unsigned)buf & 3) != 0) { + uint32_t i; + for (i = 0; i < n; i++) { + if (sdc_lld_read_aligned(sdcp, startblk, u.buf, 1)) + return CH_FAILED; + memcpy(buf, u.buf, MMCSD_BLOCK_SIZE); + buf += MMCSD_BLOCK_SIZE; + startblk++; + } + return CH_SUCCESS; + } +#endif /* STM32_SDC_SDIO_UNALIGNED_SUPPORT */ + return sdc_lld_read_aligned(sdcp, startblk, buf, n); +} + +/** + * @brief Writes one or more blocks. + * + * @param[in] sdcp pointer to the @p SDCDriver object + * @param[in] startblk first block to write + * @param[out] buf pointer to the write buffer + * @param[in] n number of blocks to write + * + * @return The operation status. + * @retval CH_SUCCESS operation succeeded. + * @retval CH_FAILED operation failed. + * + * @notapi + */ +bool_t sdc_lld_write(SDCDriver *sdcp, uint32_t startblk, + const uint8_t *buf, uint32_t n) { + +#if STM32_SDC_SDIO_UNALIGNED_SUPPORT + if (((unsigned)buf & 3) != 0) { + uint32_t i; + for (i = 0; i < n; i++) { + memcpy(u.buf, buf, MMCSD_BLOCK_SIZE); + buf += MMCSD_BLOCK_SIZE; + if (sdc_lld_write_aligned(sdcp, startblk, u.buf, 1)) + return CH_FAILED; + startblk++; + } + return CH_SUCCESS; + } +#endif /* STM32_SDC_SDIO_UNALIGNED_SUPPORT */ + return sdc_lld_write_aligned(sdcp, startblk, buf, n); +} + +/** + * @brief Waits for card idle condition. + * + * @param[in] sdcp pointer to the @p SDCDriver object + * + * @return The operation status. + * @retval CH_SUCCESS the operation succeeded. + * @retval CH_FAILED the operation failed. + * + * @api + */ +bool_t sdc_lld_sync(SDCDriver *sdcp) { + + /* TODO: Implement.*/ + (void)sdcp; + return CH_SUCCESS; +} + +#endif /* HAL_USE_SDC */ + +/** @} */ diff --git a/os/hal/ports/STM32/sdc_lld.h b/os/hal/ports/STM32/sdc_lld.h new file mode 100644 index 000000000..8b01ba915 --- /dev/null +++ b/os/hal/ports/STM32/sdc_lld.h @@ -0,0 +1,310 @@ +/* + ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file STM32/sdc_lld.h + * @brief STM32 SDC subsystem low level driver header. + * + * @addtogroup SDC + * @{ + */ + +#ifndef _SDC_LLD_H_ +#define _SDC_LLD_H_ + +#if HAL_USE_SDC || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver constants. */ +/*===========================================================================*/ + +/** + * @brief Value to clear all interrupts flag at once. + */ +#define STM32_SDIO_ICR_ALL_FLAGS (SDIO_ICR_CCRCFAILC | SDIO_ICR_DCRCFAILC | \ + SDIO_ICR_CTIMEOUTC | SDIO_ICR_DTIMEOUTC | \ + SDIO_ICR_TXUNDERRC | SDIO_ICR_RXOVERRC | \ + SDIO_ICR_CMDRENDC | SDIO_ICR_CMDSENTC | \ + SDIO_ICR_DATAENDC | SDIO_ICR_STBITERRC | \ + SDIO_ICR_DBCKENDC | SDIO_ICR_SDIOITC | \ + SDIO_ICR_CEATAENDC) + +/** + * @brief Mask of error flags in STA register. + */ +#define STM32_SDIO_STA_ERROR_MASK (SDIO_STA_CCRCFAIL | SDIO_STA_DCRCFAIL | \ + SDIO_STA_CTIMEOUT | SDIO_STA_DTIMEOUT | \ + SDIO_STA_TXUNDERR | SDIO_STA_RXOVERR) + +/*===========================================================================*/ +/* Driver pre-compile time settings. */ +/*===========================================================================*/ + +/** + * @name Configuration options + * @{ + */ +/** + * @brief SDIO DMA priority (0..3|lowest..highest). + */ +#if !defined(STM32_SDC_SDIO_DMA_PRIORITY) || defined(__DOXYGEN__) +#define STM32_SDC_SDIO_DMA_PRIORITY 3 +#endif + +/** + * @brief SDIO interrupt priority level setting. + */ +#if !defined(STM32_SDC_SDIO_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_SDC_SDIO_IRQ_PRIORITY 9 +#endif + +/** + * @brief Write timeout in milliseconds. + */ +#if !defined(SDC_WRITE_TIMEOUT_MS) || defined(__DOXYGEN__) +#define SDC_WRITE_TIMEOUT_MS 250 +#endif + +/** + * @brief Read timeout in milliseconds. + */ +#if !defined(SDC_READ_TIMEOUT_MS) || defined(__DOXYGEN__) +#define SDC_READ_TIMEOUT_MS 5 +#endif + +/** + * @brief Support for unaligned transfers. + * @note Unaligned transfers are much slower. + */ +#if !defined(STM32_SDC_SDIO_UNALIGNED_SUPPORT) || defined(__DOXYGEN__) +#define STM32_SDC_SDIO_UNALIGNED_SUPPORT TRUE +#endif + +#if STM32_ADVANCED_DMA || defined(__DOXYGEN__) + +/** + * @brief DMA stream used for SDC operations. + * @note This option is only available on platforms with enhanced DMA. + */ +#if !defined(STM32_SDC_SDIO_DMA_STREAM) || defined(__DOXYGEN__) +#define STM32_SDC_SDIO_DMA_STREAM STM32_DMA_STREAM_ID(2, 3) +#endif + +#else /* !STM32_ADVANCED_DMA*/ +#define STM32_SDC_SDIO_DMA_STREAM STM32_DMA_STREAM_ID(2, 4) + +#endif /* !STM32_ADVANCED_DMA*/ +/** @} */ + +/*===========================================================================*/ +/* Derived constants and error checks. */ +/*===========================================================================*/ + +#if !STM32_HAS_SDIO +#error "SDIO not present in the selected device" +#endif + +#if !CORTEX_IS_VALID_KERNEL_PRIORITY(STM32_SDC_SDIO_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to SDIO" +#endif + +#if !STM32_DMA_IS_VALID_PRIORITY(STM32_SDC_SDIO_DMA_PRIORITY) +#error "Invalid DMA priority assigned to SDIO" +#endif + +#if !defined(STM32_DMA_REQUIRED) +#define STM32_DMA_REQUIRED +#endif + +/* + * SDIO clock divider. + */ +#if (defined(STM32F4XX) || defined(STM32F2XX)) +#define STM32_SDIO_DIV_HS 0 +#define STM32_SDIO_DIV_LS 120 + +#elif STM32_HCLK > 48000000 +#define STM32_SDIO_DIV_HS 1 +#define STM32_SDIO_DIV_LS 178 +#else + +#define STM32_SDIO_DIV_HS 0 +#define STM32_SDIO_DIV_LS 118 +#endif + +/** + * @brief SDIO data timeouts in SDIO clock cycles. + */ +#if (defined(STM32F4XX) || defined(STM32F2XX)) +#if !STM32_CLOCK48_REQUIRED +#error "SDIO requires STM32_CLOCK48_REQUIRED to be enabled" +#endif + +#define STM32_SDC_WRITE_TIMEOUT \ + (((STM32_PLL48CLK / (STM32_SDIO_DIV_HS + 2)) / 1000) * SDC_WRITE_TIMEOUT_MS) +#define STM32_SDC_READ_TIMEOUT \ + (((STM32_PLL48CLK / (STM32_SDIO_DIV_HS + 2)) / 1000) * SDC_READ_TIMEOUT_MS) + +#else +#define STM32_SDC_WRITE_TIMEOUT \ + (((STM32_HCLK / (STM32_SDIO_DIV_HS + 2)) / 1000) * SDC_WRITE_TIMEOUT_MS) +#define STM32_SDC_READ_TIMEOUT \ + (((STM32_HCLK / (STM32_SDIO_DIV_HS + 2)) / 1000) * SDC_READ_TIMEOUT_MS) +#endif + +/*===========================================================================*/ +/* Driver data structures and types. */ +/*===========================================================================*/ + +/** + * @brief Type of SDIO bus mode. + */ +typedef enum { + SDC_MODE_1BIT = 0, + SDC_MODE_4BIT, + SDC_MODE_8BIT +} sdcbusmode_t; + +/** + * @brief Type of card flags. + */ +typedef uint32_t sdcmode_t; + +/** + * @brief SDC Driver condition flags type. + */ +typedef uint32_t sdcflags_t; + +/** + * @brief Type of a structure representing an SDC driver. + */ +typedef struct SDCDriver SDCDriver; + +/** + * @brief Driver configuration structure. + * @note It could be empty on some architectures. + */ +typedef struct { + uint32_t dummy; +} SDCConfig; + +/** + * @brief @p SDCDriver specific methods. + */ +#define _sdc_driver_methods \ + _mmcsd_block_device_methods + +/** + * @extends MMCSDBlockDeviceVMT + * + * @brief @p SDCDriver virtual methods table. + */ +struct SDCDriverVMT { + _sdc_driver_methods +}; + +/** + * @brief Structure representing an SDC driver. + */ +struct SDCDriver { + /** + * @brief Virtual Methods Table. + */ + const struct SDCDriverVMT *vmt; + _mmcsd_block_device_data + /** + * @brief Current configuration data. + */ + const SDCConfig *config; + /** + * @brief Various flags regarding the mounted card. + */ + sdcmode_t cardmode; + /** + * @brief Errors flags. + */ + sdcflags_t errors; + /** + * @brief Card RCA. + */ + uint32_t rca; + /* End of the mandatory fields.*/ + /** + * @brief Thread waiting for I/O completion IRQ. + */ + Thread *thread; + /** + * @brief DMA mode bit mask. + */ + uint32_t dmamode; + /** + * @brief Transmit DMA channel. + */ + const stm32_dma_stream_t *dma; + /** + * @brief Pointer to the SDIO registers block. + * @note Used only for dubugging purpose. + */ +#if CH_DBG_ENABLE_ASSERTS + SDIO_TypeDef *sdio; +#endif +}; + +/*===========================================================================*/ +/* Driver macros. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +#if !defined(__DOXYGEN__) +extern SDCDriver SDCD1; +#endif + +#ifdef __cplusplus +extern "C" { +#endif + void sdc_lld_init(void); + void sdc_lld_start(SDCDriver *sdcp); + void sdc_lld_stop(SDCDriver *sdcp); + void sdc_lld_start_clk(SDCDriver *sdcp); + void sdc_lld_set_data_clk(SDCDriver *sdcp); + void sdc_lld_stop_clk(SDCDriver *sdcp); + void sdc_lld_set_bus_mode(SDCDriver *sdcp, sdcbusmode_t mode); + void sdc_lld_send_cmd_none(SDCDriver *sdcp, uint8_t cmd, uint32_t arg); + bool_t sdc_lld_send_cmd_short(SDCDriver *sdcp, uint8_t cmd, uint32_t arg, + uint32_t *resp); + bool_t sdc_lld_send_cmd_short_crc(SDCDriver *sdcp, uint8_t cmd, uint32_t arg, + uint32_t *resp); + bool_t sdc_lld_send_cmd_long_crc(SDCDriver *sdcp, uint8_t cmd, uint32_t arg, + uint32_t *resp); + bool_t sdc_lld_read(SDCDriver *sdcp, uint32_t startblk, + uint8_t *buf, uint32_t n); + bool_t sdc_lld_write(SDCDriver *sdcp, uint32_t startblk, + const uint8_t *buf, uint32_t n); + bool_t sdc_lld_sync(SDCDriver *sdcp); + bool_t sdc_lld_is_card_inserted(SDCDriver *sdcp); + bool_t sdc_lld_is_write_protected(SDCDriver *sdcp); +#ifdef __cplusplus +} +#endif + +#endif /* HAL_USE_SDC */ + +#endif /* _SDC_LLD_H_ */ + +/** @} */ diff --git a/os/hal/ports/STM32/stm32.h b/os/hal/ports/STM32/stm32.h new file mode 100644 index 000000000..eb8ea8140 --- /dev/null +++ b/os/hal/ports/STM32/stm32.h @@ -0,0 +1,120 @@ +/* + ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file STM32/stm32.h + * @brief STM32 common header. + * @pre One of the following macros must be defined before including + * this header, the macro selects the inclusion of the appropriate + * vendor header: + * - STM32F0XX for Entry Level devices. + * - STM32F10X_LD_VL for Value Line Low Density devices. + * - STM32F10X_MD_VL for Value Line Medium Density devices. + * - STM32F10X_LD for Performance Low Density devices. + * - STM32F10X_MD for Performance Medium Density devices. + * - STM32F10X_HD for Performance High Density devices. + * - STM32F10X_XL for Performance eXtra Density devices. + * - STM32F10X_CL for Connectivity Line devices. + * - STM32F2XX for High-performance STM32 F-2 devices. + * - STM32F30X for Analog & DSP devices. + * - STM32F37X for Analog & DSP devices. + * - STM32F4XX for High-performance STM32 F-4 devices. + * - STM32L1XX_MD for Ultra Low Power Medium-density devices. + * . + * + * @addtogroup HAL + * @{ + */ + +#ifndef _STM32_H_ +#define _STM32_H_ + + +#if defined(STM32F10X_LD_VL) || defined(STM32F10X_MD_VL) || \ + defined(STM32F10X_HD_VL) || defined(STM32F10X_LD) || \ + defined(STM32F10X_MD) || defined(STM32F10X_HD) || \ + defined(STM32F10X_XL) || defined(STM32F10X_CL) || \ + defined(__DOXYGEN__) +#include "stm32f10x.h" + +#else /* !STM32F1XX_XX */ + +#if defined(STM32F0XX) +#include "stm32f0xx.h" + +#elif defined(STM32F2XX) +#include "stm32f2xx.h" + +#elif defined(STM32F30X) +#include "stm32f30x.h" + +#elif defined(STM32F37X) +#include "stm32f37x.h" + +#elif defined(STM32F4XX) +#include "stm32f4xx.h" + +#elif defined(STM32L1XX_MD) +#include "stm32l1xx.h" + +#else +#error "STM32 device not specified" +#endif + +/* Discarded definitions from the ST headers, the PAL driver uses its own + definitions in order to have an unified handling for all devices. + Unfortunately the ST headers have no uniform definitions for the same + objects across the various sub-families.*/ +#undef GPIOA +#undef GPIOB +#undef GPIOC +#undef GPIOD +#undef GPIOE +#undef GPIOF +#undef GPIOG +#undef GPIOH +#undef GPIOI + +#endif /* !STM32F1XX_XX */ + + +/*===========================================================================*/ +/* Driver constants. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver pre-compile time settings. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Derived constants and error checks. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver data structures and types. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver macros. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +#endif /* _STM32_H_ */ + +/** @} */ diff --git a/os/hal/ports/STM32F0xx/adc_lld.c b/os/hal/ports/STM32F0xx/adc_lld.c new file mode 100644 index 000000000..1c4ffce7f --- /dev/null +++ b/os/hal/ports/STM32F0xx/adc_lld.c @@ -0,0 +1,296 @@ +/* + ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file STM32F0xx/adc_lld.c + * @brief STM32F0xx ADC subsystem low level driver source. + * + * @addtogroup ADC + * @{ + */ + +#include "hal.h" + +#if HAL_USE_ADC || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver local definitions. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver exported variables. */ +/*===========================================================================*/ + +/** @brief ADC1 driver identifier.*/ +#if STM32_ADC_USE_ADC1 || defined(__DOXYGEN__) +ADCDriver ADCD1; +#endif + +/*===========================================================================*/ +/* Driver local variables and types. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local functions. */ +/*===========================================================================*/ + +/** + * @brief Stops an ongoing conversion, if any. + * + * @param[in] adc pointer to the ADC registers block + */ +static void adc_lld_stop_adc(ADC_TypeDef *adc) { + + if (adc->CR & ADC_CR_ADSTART) { + adc->CR |= ADC_CR_ADSTP; + while (adc->CR & ADC_CR_ADSTP) + ; + } +} + +/** + * @brief ADC DMA ISR service routine. + * + * @param[in] adcp pointer to the @p ADCDriver object + * @param[in] flags pre-shifted content of the ISR register + */ +static void adc_lld_serve_rx_interrupt(ADCDriver *adcp, uint32_t flags) { + + /* DMA errors handling.*/ + if ((flags & (STM32_DMA_ISR_TEIF | STM32_DMA_ISR_DMEIF)) != 0) { + /* DMA, this could help only if the DMA tries to access an unmapped + address space or violates alignment rules.*/ + _adc_isr_error_code(adcp, ADC_ERR_DMAFAILURE); + } + else { + /* It is possible that the conversion group has already be reset by the + ADC error handler, in this case this interrupt is spurious.*/ + if (adcp->grpp != NULL) { + if ((flags & STM32_DMA_ISR_HTIF) != 0) { + /* Half transfer processing.*/ + _adc_isr_half_code(adcp); + } + if ((flags & STM32_DMA_ISR_TCIF) != 0) { + /* Transfer complete processing.*/ + _adc_isr_full_code(adcp); + } + } + } +} + +/*===========================================================================*/ +/* Driver interrupt handlers. */ +/*===========================================================================*/ + +#if STM32_ADC_USE_ADC1 || defined(__DOXYGEN__) +/** + * @brief ADC interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(Vector70) { + uint32_t isr; + + OSAL_IRQ_PROLOGUE(); + + isr = ADC1->ISR; + ADC1->ISR = isr; + + /* It could be a spurious interrupt caused by overflows after DMA disabling, + just ignore it in this case.*/ + if (ADCD1.grpp != NULL) { + /* Note, an overflow may occur after the conversion ended before the driver + is able to stop the ADC, this is why the DMA channel is checked too.*/ + if ((isr & ADC_ISR_OVR) && + (dmaStreamGetTransactionSize(ADCD1.dmastp) > 0)) { + /* ADC overflow condition, this could happen only if the DMA is unable + to read data fast enough.*/ + _adc_isr_error_code(&ADCD1, ADC_ERR_OVERFLOW); + } + if (isr & ADC_ISR_AWD) { + /* Analog watchdog error.*/ + _adc_isr_error_code(&ADCD1, ADC_ERR_AWD); + } + } + + OSAL_IRQ_EPILOGUE(); +} +#endif + +/*===========================================================================*/ +/* Driver exported functions. */ +/*===========================================================================*/ + +/** + * @brief Low level ADC driver initialization. + * + * @notapi + */ +void adc_lld_init(void) { + +#if STM32_ADC_USE_ADC1 + /* Driver initialization.*/ + adcObjectInit(&ADCD1); + ADCD1.adc = ADC1; + ADCD1.dmastp = STM32_DMA1_STREAM1; + ADCD1.dmamode = STM32_DMA_CR_PL(STM32_ADC_ADC1_DMA_PRIORITY) | + STM32_DMA_CR_DIR_P2M | + STM32_DMA_CR_MSIZE_HWORD | STM32_DMA_CR_PSIZE_HWORD | + STM32_DMA_CR_MINC | STM32_DMA_CR_TCIE | + STM32_DMA_CR_DMEIE | STM32_DMA_CR_TEIE; +#endif + + /* The shared vector is initialized on driver initialization and never + disabled.*/ + nvicEnableVector(ADC1_COMP_IRQn, STM32_ADC_IRQ_PRIORITY); + + /* Calibration procedure.*/ + rccEnableADC1(FALSE); + osalDbgAssert(ADC1->CR == 0, "invalid register state"); + ADC1->CR |= ADC_CR_ADCAL; + while (ADC1->CR & ADC_CR_ADCAL) + ; + rccDisableADC1(FALSE); +} + +/** + * @brief Configures and activates the ADC peripheral. + * + * @param[in] adcp pointer to the @p ADCDriver object + * + * @notapi + */ +void adc_lld_start(ADCDriver *adcp) { + + /* If in stopped state then enables the ADC and DMA clocks.*/ + if (adcp->state == ADC_STOP) { +#if STM32_ADC_USE_ADC1 + if (&ADCD1 == adcp) { + bool_t b; + b = dmaStreamAllocate(adcp->dmastp, + STM32_ADC_ADC1_DMA_IRQ_PRIORITY, + (stm32_dmaisr_t)adc_lld_serve_rx_interrupt, + (void *)adcp); + osalDbgAssert(!b, "stream already allocated"); + dmaStreamSetPeripheral(adcp->dmastp, &ADC1->DR); + rccEnableADC1(FALSE); +#if STM32_ADCSW == STM32_ADCSW_HSI14 + /* Clock from HSI14, no need for jitter removal.*/ + ADC1->CFGR2 = 0x00001000; +#else +#if STM32_ADCPRE == STM32_ADCPRE_DIV2 + ADC1->CFGR2 = 0x00001000 | ADC_CFGR2_JITOFFDIV2; +#else + ADC1->CFGR2 = 0x00001000 | ADC_CFGR2_JITOFFDIV4; +#endif +#endif + } +#endif /* STM32_ADC_USE_ADC1 */ + + /* ADC initial setup, starting the analog part here in order to reduce + the latency when starting a conversion.*/ + adcp->adc->CR = ADC_CR_ADEN; + while (!(adcp->adc->ISR & ADC_ISR_ADRDY)) + ; + } +} + +/** + * @brief Deactivates the ADC peripheral. + * + * @param[in] adcp pointer to the @p ADCDriver object + * + * @notapi + */ +void adc_lld_stop(ADCDriver *adcp) { + + /* If in ready state then disables the ADC clock and analog part.*/ + if (adcp->state == ADC_READY) { + + dmaStreamRelease(adcp->dmastp); + + /* Disabling ADC.*/ + if (adcp->adc->CR & ADC_CR_ADEN) { + adc_lld_stop_adc(adcp->adc); + adcp->adc->CR |= ADC_CR_ADDIS; + while (adcp->adc->CR & ADC_CR_ADDIS) + ; + } + +#if STM32_ADC_USE_ADC1 + if (&ADCD1 == adcp) + rccDisableADC1(FALSE); +#endif + } +} + +/** + * @brief Starts an ADC conversion. + * + * @param[in] adcp pointer to the @p ADCDriver object + * + * @notapi + */ +void adc_lld_start_conversion(ADCDriver *adcp) { + uint32_t mode; + const ADCConversionGroup *grpp = adcp->grpp; + + /* DMA setup.*/ + mode = adcp->dmamode; + if (grpp->circular) { + mode |= STM32_DMA_CR_CIRC; + } + if (adcp->depth > 1) { + /* If the buffer depth is greater than one then the half transfer interrupt + interrupt is enabled in order to allows streaming processing.*/ + mode |= STM32_DMA_CR_HTIE; + } + dmaStreamSetMemory0(adcp->dmastp, adcp->samples); + dmaStreamSetTransactionSize(adcp->dmastp, (uint32_t)grpp->num_channels * + (uint32_t)adcp->depth); + dmaStreamSetMode(adcp->dmastp, mode); + dmaStreamEnable(adcp->dmastp); + + /* ADC setup, if it is defined a callback for the analog watch dog then it + is enabled.*/ + adcp->adc->ISR = adcp->adc->ISR; + adcp->adc->IER = ADC_IER_OVRIE | ADC_IER_AWDIE; + adcp->adc->TR = grpp->tr; + adcp->adc->SMPR = grpp->smpr; + adcp->adc->CHSELR = grpp->chselr; + + /* ADC configuration and start.*/ + adcp->adc->CFGR1 = grpp->cfgr1 | ADC_CFGR1_CONT | ADC_CFGR1_DMACFG | + ADC_CFGR1_DMAEN; + adcp->adc->CR |= ADC_CR_ADSTART; +} + +/** + * @brief Stops an ongoing conversion. + * + * @param[in] adcp pointer to the @p ADCDriver object + * + * @notapi + */ +void adc_lld_stop_conversion(ADCDriver *adcp) { + + dmaStreamDisable(adcp->dmastp); + adc_lld_stop_adc(adcp->adc); +} + +#endif /* HAL_USE_ADC */ + +/** @} */ diff --git a/os/hal/ports/STM32F0xx/adc_lld.h b/os/hal/ports/STM32F0xx/adc_lld.h new file mode 100644 index 000000000..635dcefaa --- /dev/null +++ b/os/hal/ports/STM32F0xx/adc_lld.h @@ -0,0 +1,329 @@ +/* + ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file STM32F0xx/adc_lld.h + * @brief STM32F0xx ADC subsystem low level driver header. + * + * @addtogroup ADC + * @{ + */ + +#ifndef _ADC_LLD_H_ +#define _ADC_LLD_H_ + +#if HAL_USE_ADC || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver constants. */ +/*===========================================================================*/ + +/** + * @name Sampling rates + * @{ + */ +#define ADC_SMPR_SMP_1P5 0 /**< @brief 14 cycles conversion time */ +#define ADC_SMPR_SMP_7P5 1 /**< @brief 21 cycles conversion time. */ +#define ADC_SMPR_SMP_13P5 2 /**< @brief 28 cycles conversion time. */ +#define ADC_SMPR_SMP_28P5 3 /**< @brief 41 cycles conversion time. */ +#define ADC_SMPR_SMP_41P5 4 /**< @brief 54 cycles conversion time. */ +#define ADC_SMPR_SMP_55P5 5 /**< @brief 68 cycles conversion time. */ +#define ADC_SMPR_SMP_71P5 6 /**< @brief 84 cycles conversion time. */ +#define ADC_SMPR_SMP_239P5 7 /**< @brief 252 cycles conversion time. */ +/** @} */ + +/** + * @name Resolution + * @{ + */ +#define ADC_CFGR1_RES_12BIT (0 << 3) +#define ADC_CFGR1_RES_10BIT (1 << 3) +#define ADC_CFGR1_RES_8BIT (2 << 3) +#define ADC_CFGR1_RES_6BIT (3 << 3) +/** @} */ + +/** + * @name Threashold register initializer + * @{ + */ +#define ADC_TR(low, high) (((uint32_t)(high) << 16) | (uint32_t)(low)) +/** @} */ + +/*===========================================================================*/ +/* Driver pre-compile time settings. */ +/*===========================================================================*/ + +/** + * @name Configuration options + * @{ + */ +/** + * @brief ADC1 driver enable switch. + * @details If set to @p TRUE the support for ADC1 is included. + * @note The default is @p FALSE. + */ +#if !defined(STM32_ADC_USE_ADC1) || defined(__DOXYGEN__) +#define STM32_ADC_USE_ADC1 FALSE +#endif + +/** + * @brief ADC1 DMA priority (0..3|lowest..highest). + */ +#if !defined(STM32_ADC_ADC1_DMA_PRIORITY) || defined(__DOXYGEN__) +#define STM32_ADC_ADC1_DMA_PRIORITY 2 +#endif + +/** + * @brief ADC interrupt priority level setting. + */ +#if !defined(STM32_ADC_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_ADC_IRQ_PRIORITY 2 +#endif + +/** + * @brief ADC1 DMA interrupt priority level setting. + */ +#if !defined(STM32_ADC_ADC1_DMA_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_ADC_ADC1_DMA_IRQ_PRIORITY 2 +#endif + +/** @} */ + +/*===========================================================================*/ +/* Derived constants and error checks. */ +/*===========================================================================*/ + +#if STM32_ADC_USE_ADC1 && !STM32_HAS_ADC1 +#error "ADC1 not present in the selected device" +#endif + +#if !STM32_ADC_USE_ADC1 +#error "ADC driver activated but no ADC peripheral assigned" +#endif + +#if STM32_ADC_USE_ADC1 && \ + !CORTEX_IS_VALID_KERNEL_PRIORITY(STM32_ADC_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to ADC1" +#endif + +#if STM32_ADC_USE_ADC1 && \ + !CORTEX_IS_VALID_KERNEL_PRIORITY(STM32_ADC_ADC1_DMA_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to ADC1 DMA" +#endif + +#if STM32_ADC_USE_ADC1 && \ + !STM32_DMA_IS_VALID_PRIORITY(STM32_ADC_ADC1_DMA_PRIORITY) +#error "Invalid DMA priority assigned to ADC1" +#endif + +#if !defined(STM32_DMA_REQUIRED) +#define STM32_DMA_REQUIRED +#endif + +/*===========================================================================*/ +/* Driver data structures and types. */ +/*===========================================================================*/ + +/** + * @brief ADC sample data type. + */ +typedef uint16_t adcsample_t; + +/** + * @brief Channels number in a conversion group. + */ +typedef uint16_t adc_channels_num_t; + +/** + * @brief Possible ADC failure causes. + * @note Error codes are architecture dependent and should not relied + * upon. + */ +typedef enum { + ADC_ERR_DMAFAILURE = 0, /**< DMA operations failure. */ + ADC_ERR_OVERFLOW = 1, /**< ADC overflow condition. */ + ADC_ERR_AWD = 2 /**< Analog watchdog triggered. */ +} adcerror_t; + +/** + * @brief Type of a structure representing an ADC driver. + */ +typedef struct ADCDriver ADCDriver; + +/** + * @brief ADC notification callback type. + * + * @param[in] adcp pointer to the @p ADCDriver object triggering the + * callback + * @param[in] buffer pointer to the most recent samples data + * @param[in] n number of buffer rows available starting from @p buffer + */ +typedef void (*adccallback_t)(ADCDriver *adcp, adcsample_t *buffer, size_t n); + +/** + * @brief ADC error callback type. + * + * @param[in] adcp pointer to the @p ADCDriver object triggering the + * callback + * @param[in] err ADC error code + */ +typedef void (*adcerrorcallback_t)(ADCDriver *adcp, adcerror_t err); + +/** + * @brief Conversion group configuration structure. + * @details This implementation-dependent structure describes a conversion + * operation. + * @note The use of this configuration structure requires knowledge of + * STM32 ADC cell registers interface, please refer to the STM32 + * reference manual for details. + */ +typedef struct { + /** + * @brief Enables the circular buffer mode for the group. + */ + bool_t circular; + /** + * @brief Number of the analog channels belonging to the conversion group. + */ + adc_channels_num_t num_channels; + /** + * @brief Callback function associated to the group or @p NULL. + */ + adccallback_t end_cb; + /** + * @brief Error callback or @p NULL. + */ + adcerrorcallback_t error_cb; + /* End of the mandatory fields.*/ + /** + * @brief ADC CFGR1 register initialization data. + */ + uint32_t cfgr1; + /** + * @brief ADC TR register initialization data. + */ + uint32_t tr; + /** + * @brief ADC SMPR register initialization data. + */ + uint32_t smpr; + /** + * @brief ADC CHSELR register initialization data. + * @details The number of bits at logic level one in this register must + * be equal to the number in the @p num_channels field. + */ + uint32_t chselr; +} ADCConversionGroup; + +/** + * @brief Driver configuration structure. + * @note It could be empty on some architectures. + */ +typedef struct { + uint32_t dummy; +} ADCConfig; + +/** + * @brief Structure representing an ADC driver. + */ +struct ADCDriver { + /** + * @brief Driver state. + */ + adcstate_t state; + /** + * @brief Current configuration data. + */ + const ADCConfig *config; + /** + * @brief Current samples buffer pointer or @p NULL. + */ + adcsample_t *samples; + /** + * @brief Current samples buffer depth or @p 0. + */ + size_t depth; + /** + * @brief Current conversion group pointer or @p NULL. + */ + const ADCConversionGroup *grpp; +#if ADC_USE_WAIT || defined(__DOXYGEN__) + /** + * @brief Waiting thread. + */ + thread_reference_t thread; +#endif +#if ADC_USE_MUTUAL_EXCLUSION || defined(__DOXYGEN__) + /** + * @brief Mutex protecting the peripheral. + */ + mutex_t mutex; +#endif /* ADC_USE_MUTUAL_EXCLUSION */ +#if defined(ADC_DRIVER_EXT_FIELDS) + ADC_DRIVER_EXT_FIELDS +#endif + /* End of the mandatory fields.*/ + /** + * @brief Pointer to the ADCx registers block. + */ + ADC_TypeDef *adc; + /** + * @brief Pointer to associated DMA channel. + */ + const stm32_dma_stream_t *dmastp; + /** + * @brief DMA mode bit mask. + */ + uint32_t dmamode; +}; + +/*===========================================================================*/ +/* Driver macros. */ +/*===========================================================================*/ + +/** + * @brief Changes the value of the ADC CCR register. + * @details Use this function in order to enable or disable the internal + * analog sources. See the documentation in the STM32F0xx Reference + * Manual. + */ +#define adcSTM32SetCCR(ccr) (ADC->CCR = (ccr)) + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +#if STM32_ADC_USE_ADC1 && !defined(__DOXYGEN__) +extern ADCDriver ADCD1; +#endif + +#ifdef __cplusplus +extern "C" { +#endif + void adc_lld_init(void); + void adc_lld_start(ADCDriver *adcp); + void adc_lld_stop(ADCDriver *adcp); + void adc_lld_start_conversion(ADCDriver *adcp); + void adc_lld_stop_conversion(ADCDriver *adcp); +#ifdef __cplusplus +} +#endif + +#endif /* HAL_USE_ADC */ + +#endif /* _ADC_LLD_H_ */ + +/** @} */ diff --git a/os/hal/ports/STM32F0xx/ext_lld_isr.c b/os/hal/ports/STM32F0xx/ext_lld_isr.c new file mode 100644 index 000000000..fb5100e8c --- /dev/null +++ b/os/hal/ports/STM32F0xx/ext_lld_isr.c @@ -0,0 +1,197 @@ +/* + ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file STM32F0xx/ext_lld_isr.c + * @brief STM32F0xx EXT subsystem low level driver ISR code. + * + * @addtogroup EXT + * @{ + */ + +#include "hal.h" + +#if HAL_USE_EXT || defined(__DOXYGEN__) + +#include "ext_lld_isr.h" + +/*===========================================================================*/ +/* Driver local definitions. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver exported variables. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local variables. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local functions. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver interrupt handlers. */ +/*===========================================================================*/ + +/** + * @brief EXTI[0]...EXTI[1] interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(Vector54) { + uint32_t pr; + + OSAL_IRQ_PROLOGUE(); + + pr = EXTI->PR & ((1 << 0) | (1 << 1)); + EXTI->PR = pr; + if (pr & (1 << 0)) + EXTD1.config->channels[0].cb(&EXTD1, 0); + if (pr & (1 << 1)) + EXTD1.config->channels[1].cb(&EXTD1, 1); + + OSAL_IRQ_EPILOGUE(); +} + +/** + * @brief EXTI[2]...EXTI[3] interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(Vector58) { + uint32_t pr; + + OSAL_IRQ_PROLOGUE(); + + pr = EXTI->PR & ((1 << 2) | (1 << 3)); + EXTI->PR = pr; + if (pr & (1 << 2)) + EXTD1.config->channels[2].cb(&EXTD1, 2); + if (pr & (1 << 3)) + EXTD1.config->channels[3].cb(&EXTD1, 3); + + OSAL_IRQ_EPILOGUE(); +} + +/** + * @brief EXTI[4]...EXTI[15] interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(Vector5C) { + uint32_t pr; + + OSAL_IRQ_PROLOGUE(); + + pr = EXTI->PR & ((1 << 4) | (1 << 5) | (1 << 6) | (1 << 7) | (1 << 8) | + (1 << 9) | (1 << 10) | (1 << 11) | (1 << 12) | (1 << 13) | + (1 << 14) | (1 << 15)); + EXTI->PR = pr; + if (pr & (1 << 4)) + EXTD1.config->channels[4].cb(&EXTD1, 4); + if (pr & (1 << 5)) + EXTD1.config->channels[5].cb(&EXTD1, 5); + if (pr & (1 << 6)) + EXTD1.config->channels[6].cb(&EXTD1, 6); + if (pr & (1 << 7)) + EXTD1.config->channels[7].cb(&EXTD1, 7); + if (pr & (1 << 8)) + EXTD1.config->channels[8].cb(&EXTD1, 8); + if (pr & (1 << 9)) + EXTD1.config->channels[9].cb(&EXTD1, 9); + if (pr & (1 << 10)) + EXTD1.config->channels[10].cb(&EXTD1, 10); + if (pr & (1 << 11)) + EXTD1.config->channels[11].cb(&EXTD1, 11); + if (pr & (1 << 12)) + EXTD1.config->channels[12].cb(&EXTD1, 12); + if (pr & (1 << 13)) + EXTD1.config->channels[13].cb(&EXTD1, 13); + if (pr & (1 << 14)) + EXTD1.config->channels[14].cb(&EXTD1, 14); + if (pr & (1 << 15)) + EXTD1.config->channels[15].cb(&EXTD1, 15); + + OSAL_IRQ_EPILOGUE(); +} + +/** + * @brief EXTI[16] interrupt handler (PVD). + * + * @isr + */ +OSAL_IRQ_HANDLER(Vector44) { + + OSAL_IRQ_PROLOGUE(); + + EXTI->PR = (1 << 16); + EXTD1.config->channels[16].cb(&EXTD1, 16); + + OSAL_IRQ_EPILOGUE(); +} + +/** + * @brief EXTI[17] interrupt handler (RTC). + * + * @isr + */ +OSAL_IRQ_HANDLER(Vector48) { + + OSAL_IRQ_PROLOGUE(); + + EXTI->PR = (1 << 17); + EXTD1.config->channels[17].cb(&EXTD1, 17); + + OSAL_IRQ_EPILOGUE(); +} + +/*===========================================================================*/ +/* Driver exported functions. */ +/*===========================================================================*/ + +/** + * @brief Enables EXTI IRQ sources. + * + * @notapi + */ +void ext_lld_exti_irq_enable(void) { + + nvicEnableVector(EXTI0_1_IRQn, STM32_EXT_EXTI0_1_IRQ_PRIORITY); + nvicEnableVector(EXTI2_3_IRQn, STM32_EXT_EXTI2_3_IRQ_PRIORITY); + nvicEnableVector(EXTI4_15_IRQn, STM32_EXT_EXTI4_15_IRQ_PRIORITY); + nvicEnableVector(PVD_IRQn, STM32_EXT_EXTI16_IRQ_PRIORITY); + nvicEnableVector(RTC_IRQn, STM32_EXT_EXTI17_IRQ_PRIORITY); +} + +/** + * @brief Disables EXTI IRQ sources. + * + * @notapi + */ +void ext_lld_exti_irq_disable(void) { + + nvicDisableVector(EXTI0_1_IRQn); + nvicDisableVector(EXTI2_3_IRQn); + nvicDisableVector(EXTI4_15_IRQn); + nvicDisableVector(PVD_IRQn); + nvicDisableVector(RTC_IRQn); +} + +#endif /* HAL_USE_EXT */ + +/** @} */ diff --git a/os/hal/ports/STM32F0xx/ext_lld_isr.h b/os/hal/ports/STM32F0xx/ext_lld_isr.h new file mode 100644 index 000000000..9885fbc65 --- /dev/null +++ b/os/hal/ports/STM32F0xx/ext_lld_isr.h @@ -0,0 +1,107 @@ +/* + ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file STM32F0xx/ext_lld_isr.h + * @brief STM32F0xx EXT subsystem low level driver ISR header. + * + * @addtogroup EXT + * @{ + */ + +#ifndef _EXT_LLD_ISR_H_ +#define _EXT_LLD_ISR_H_ + +#if HAL_USE_EXT || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver constants. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver pre-compile time settings. */ +/*===========================================================================*/ + +/** + * @name Configuration options + * @{ + */ +/** + * @brief EXTI0..1 interrupt priority level setting. + */ +#if !defined(STM32_EXT_EXTI0_1_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_EXT_EXTI0_1_IRQ_PRIORITY 3 +#endif + +/** + * @brief EXTI2..3 interrupt priority level setting. + */ +#if !defined(STM32_EXT_EXTI2_3_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_EXT_EXTI2_3_IRQ_PRIORITY 3 +#endif + +/** + * @brief EXTI4..15 interrupt priority level setting. + */ +#if !defined(STM32_EXT_EXTI4_15_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_EXT_EXTI4_15_IRQ_PRIORITY 3 +#endif + +/** + * @brief EXTI16 interrupt priority level setting. + */ +#if !defined(STM32_EXT_EXTI16_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_EXT_EXTI16_IRQ_PRIORITY 3 +#endif + +/** + * @brief EXTI17 interrupt priority level setting. + */ +#if !defined(STM32_EXT_EXTI17_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_EXT_EXTI17_IRQ_PRIORITY 3 +#endif +/** @} */ + +/*===========================================================================*/ +/* Derived constants and error checks. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver data structures and types. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver macros. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +#ifdef __cplusplus +extern "C" { +#endif + void ext_lld_exti_irq_enable(void); + void ext_lld_exti_irq_disable(void); +#ifdef __cplusplus +} +#endif + +#endif /* HAL_USE_EXT */ + +#endif /* _EXT_LLD_ISR_H_ */ + +/** @} */ diff --git a/os/hal/ports/STM32F0xx/hal_lld.c b/os/hal/ports/STM32F0xx/hal_lld.c new file mode 100644 index 000000000..09ab62923 --- /dev/null +++ b/os/hal/ports/STM32F0xx/hal_lld.c @@ -0,0 +1,199 @@ +/* + ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file STM32F0xx/hal_lld.c + * @brief STM32F0xx HAL subsystem low level driver source. + * + * @addtogroup HAL + * @{ + */ + +#include "hal.h" + +/*===========================================================================*/ +/* Driver local definitions. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver exported variables. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local variables and types. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local functions. */ +/*===========================================================================*/ + +/** + * @brief Initializes the backup domain. + * @note WARNING! Changing clock source impossible without resetting + * of the whole BKP domain. + */ +static void hal_lld_backup_domain_init(void) { + + /* Backup domain access enabled and left open.*/ + PWR->CR |= PWR_CR_DBP; + + /* Reset BKP domain if different clock source selected.*/ + if ((RCC->BDCR & STM32_RTCSEL_MASK) != STM32_RTCSEL){ + /* Backup domain reset.*/ + RCC->BDCR = RCC_BDCR_BDRST; + RCC->BDCR = 0; + } + + /* If enabled then the LSE is started.*/ +#if STM32_LSE_ENABLED +#if defined(STM32_LSE_BYPASS) + /* LSE Bypass.*/ + RCC->BDCR = STM32_LSEDRV | RCC_BDCR_LSEON | RCC_BDCR_LSEBYP; +#else + /* No LSE Bypass.*/ + RCC->BDCR = STM32_LSEDRV | RCC_BDCR_LSEON; +#endif + while ((RCC->BDCR & RCC_BDCR_LSERDY) == 0) + ; /* Waits until LSE is stable. */ +#endif + +#if STM32_RTCSEL != STM32_RTCSEL_NOCLOCK + /* If the backup domain hasn't been initialized yet then proceed with + initialization.*/ + if ((RCC->BDCR & RCC_BDCR_RTCEN) == 0) { + /* Selects clock source.*/ + RCC->BDCR |= STM32_RTCSEL; + + /* RTC clock enabled.*/ + RCC->BDCR |= RCC_BDCR_RTCEN; + } +#endif /* STM32_RTCSEL != STM32_RTCSEL_NOCLOCK */ +} + +/*===========================================================================*/ +/* Driver interrupt handlers. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver exported functions. */ +/*===========================================================================*/ + +/** + * @brief Low level HAL driver initialization. + * + * @notapi + */ +void hal_lld_init(void) { + + /* Reset of all peripherals.*/ + rccResetAPB1(0xFFFFFFFF); + rccResetAPB2(~RCC_APB2RSTR_DBGMCURST); + + /* PWR clock enabled.*/ + rccEnablePWRInterface(FALSE); + + /* Initializes the backup domain.*/ + hal_lld_backup_domain_init(); + +#if defined(STM32_DMA_REQUIRED) + dmaInit(); +#endif + + /* Programmable voltage detector enable.*/ +#if STM32_PVD_ENABLE + PWR->CR |= PWR_CR_PVDE | (STM32_PLS & STM32_PLS_MASK); +#endif /* STM32_PVD_ENABLE */ +} + +/** + * @brief STM32 clocks and PLL initialization. + * @note All the involved constants come from the file @p board.h. + * @note This function should be invoked just after the system reset. + * + * @special + */ +void stm32_clock_init(void) { + +#if !STM32_NO_INIT + /* HSI setup, it enforces the reset situation in order to handle possible + problems with JTAG probes and re-initializations.*/ + RCC->CR |= RCC_CR_HSION; /* Make sure HSI is ON. */ + while (!(RCC->CR & RCC_CR_HSIRDY)) + ; /* Wait until HSI is stable. */ + RCC->CR &= RCC_CR_HSITRIM | RCC_CR_HSION; /* CR Reset value. */ + RCC->CFGR = 0; /* CFGR reset value. */ + while ((RCC->CFGR & RCC_CFGR_SWS) != RCC_CFGR_SWS_HSI) + ; /* Waits until HSI is selected. */ + +#if STM32_HSE_ENABLED + /* HSE activation.*/ +#if defined(STM32_HSE_BYPASS) + /* HSE Bypass.*/ + RCC->CR |= RCC_CR_HSEON | RCC_CR_HSEBYP; +#else + /* No HSE Bypass.*/ + RCC->CR |= RCC_CR_HSEON; +#endif + while (!(RCC->CR & RCC_CR_HSERDY)) + ; /* Waits until HSE is stable. */ +#endif + +#if STM32_HSE14_ENABLED + /* HSI14 activation.*/ + RCC->CR2 |= RCC_CR2_HSI14ON; + while (!(RCC->CR2 & RCC_CR2_HSI14RDY)) + ; /* Waits until HSI14 is stable. */ +#endif + +#if STM32_LSI_ENABLED + /* LSI activation.*/ + RCC->CSR |= RCC_CSR_LSION; + while ((RCC->CSR & RCC_CSR_LSIRDY) == 0) + ; /* Waits until LSI is stable. */ +#endif + + /* Clock settings.*/ + RCC->CFGR = STM32_MCOSEL | STM32_PLLMUL | STM32_PLLSRC | + STM32_ADCPRE | STM32_PPRE | STM32_HPRE; + RCC->CFGR2 = STM32_PREDIV; + RCC->CFGR3 = STM32_ADCSW | STM32_CECSW | STM32_I2C1SW | + STM32_USART1SW; + +#if STM32_ACTIVATE_PLL + /* PLL activation.*/ + RCC->CR |= RCC_CR_PLLON; + while (!(RCC->CR & RCC_CR_PLLRDY)) + ; /* Waits until PLL is stable. */ +#endif + + /* Flash setup and final clock selection. */ + FLASH->ACR = STM32_FLASHBITS; + + /* Switching to the configured clock source if it is different from HSI.*/ +#if (STM32_SW != STM32_SW_HSI) + /* Switches clock source.*/ + RCC->CFGR |= STM32_SW; + while ((RCC->CFGR & RCC_CFGR_SWS) != (STM32_SW << 2)) + ; /* Waits selection complete. */ +#endif + + /* SYSCFG clock enabled here because it is a multi-functional unit shared + among multiple drivers.*/ + rccEnableAPB2(RCC_APB2ENR_SYSCFGEN, TRUE); +#endif /* !STM32_NO_INIT */ +} + +/** @} */ diff --git a/os/hal/ports/STM32F0xx/hal_lld.h b/os/hal/ports/STM32F0xx/hal_lld.h new file mode 100644 index 000000000..c7238de56 --- /dev/null +++ b/os/hal/ports/STM32F0xx/hal_lld.h @@ -0,0 +1,781 @@ +/* + ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file STM32F0xx/hal_lld.h + * @brief STM32F0xx HAL subsystem low level driver header. + * @pre This module requires the following macros to be defined in the + * @p board.h file: + * - STM32_LSECLK. + * - STM32_LSEDRV. + * - STM32_LSE_BYPASS (optionally). + * - STM32_HSECLK. + * - STM32_HSE_BYPASS (optionally). + * . + * One of the following macros must also be defined: + * - STM32F0XX for Entry Level devices. + * . + * + * @addtogroup HAL + * @{ + */ + +#ifndef _HAL_LLD_H_ +#define _HAL_LLD_H_ + +#include "stm32.h" +#include "stm32_registry.h" + +/*===========================================================================*/ +/* Driver constants. */ +/*===========================================================================*/ + +/** + * @brief Defines the support for realtime counters in the HAL. + */ +#define HAL_IMPLEMENTS_COUNTERS FALSE + +/** + * @name Platform identification + * @{ + */ +#define PLATFORM_NAME "STM32F05x Entry Level" +/** @} */ + +/** + * @name Absolute Maximum Ratings + * @{ + */ +/** + * @brief Maximum system clock frequency. + */ +#define STM32_SYSCLK_MAX 48000000 + +/** + * @brief Maximum HSE clock frequency. + */ +#define STM32_HSECLK_MAX 32000000 + +/** + * @brief Minimum HSE clock frequency. + */ +#define STM32_HSECLK_MIN 1000000 + +/** + * @brief Maximum LSE clock frequency. + */ +#define STM32_LSECLK_MAX 1000000 + +/** + * @brief Minimum LSE clock frequency. + */ +#define STM32_LSECLK_MIN 32768 + +/** + * @brief Maximum PLLs input clock frequency. + */ +#define STM32_PLLIN_MAX 25000000 + +/** + * @brief Minimum PLLs input clock frequency. + */ +#define STM32_PLLIN_MIN 1000000 + +/** + * @brief Maximum PLL output clock frequency. + */ +#define STM32_PLLOUT_MAX 48000000 + +/** + * @brief Minimum PLL output clock frequency. + */ +#define STM32_PLLOUT_MIN 16000000 + +/** + * @brief Maximum APB clock frequency. + */ +#define STM32_PCLK_MAX 48000000 + +/** + * @brief Maximum ADC clock frequency. + */ +#define STM32_ADCCLK_MAX 14000000 +/** @} */ + +/** + * @name Internal clock sources + * @{ + */ +#define STM32_HSICLK 8000000 /**< High speed internal clock. */ +#define STM32_HSI14CLK 14000000 /**< 14MHz speed internal clock.*/ +#define STM32_LSICLK 40000 /**< Low speed internal clock. */ +/** @} */ + +/** + * @name PWR_CR register bits definitions + * @{ + */ +#define STM32_PLS_MASK (7 << 5) /**< PLS bits mask. */ +#define STM32_PLS_LEV0 (0 << 5) /**< PVD level 0. */ +#define STM32_PLS_LEV1 (1 << 5) /**< PVD level 1. */ +#define STM32_PLS_LEV2 (2 << 5) /**< PVD level 2. */ +#define STM32_PLS_LEV3 (3 << 5) /**< PVD level 3. */ +#define STM32_PLS_LEV4 (4 << 5) /**< PVD level 4. */ +#define STM32_PLS_LEV5 (5 << 5) /**< PVD level 5. */ +#define STM32_PLS_LEV6 (6 << 5) /**< PVD level 6. */ +#define STM32_PLS_LEV7 (7 << 5) /**< PVD level 7. */ +/** @} */ + +/** + * @name RCC_CFGR register bits definitions + * @{ + */ +#define STM32_SW_HSI (0 << 0) /**< SYSCLK source is HSI. */ +#define STM32_SW_HSE (1 << 0) /**< SYSCLK source is HSE. */ +#define STM32_SW_PLL (2 << 0) /**< SYSCLK source is PLL. */ + +#define STM32_HPRE_DIV1 (0 << 4) /**< SYSCLK divided by 1. */ +#define STM32_HPRE_DIV2 (8 << 4) /**< SYSCLK divided by 2. */ +#define STM32_HPRE_DIV4 (9 << 4) /**< SYSCLK divided by 4. */ +#define STM32_HPRE_DIV8 (10 << 4) /**< SYSCLK divided by 8. */ +#define STM32_HPRE_DIV16 (11 << 4) /**< SYSCLK divided by 16. */ +#define STM32_HPRE_DIV64 (12 << 4) /**< SYSCLK divided by 64. */ +#define STM32_HPRE_DIV128 (13 << 4) /**< SYSCLK divided by 128. */ +#define STM32_HPRE_DIV256 (14 << 4) /**< SYSCLK divided by 256. */ +#define STM32_HPRE_DIV512 (15 << 4) /**< SYSCLK divided by 512. */ + +#define STM32_PPRE_DIV1 (0 << 8) /**< HCLK divided by 1. */ +#define STM32_PPRE_DIV2 (4 << 8) /**< HCLK divided by 2. */ +#define STM32_PPRE_DIV4 (5 << 8) /**< HCLK divided by 4. */ +#define STM32_PPRE_DIV8 (6 << 8) /**< HCLK divided by 8. */ +#define STM32_PPRE_DIV16 (7 << 8) /**< HCLK divided by 16. */ + +#define STM32_ADCPRE_DIV2 (0 << 14) /**< PCLK divided by 2. */ +#define STM32_ADCPRE_DIV4 (1 << 14) /**< PCLK divided by 4. */ + +#define STM32_PLLSRC_HSI (0 << 16) /**< PLL clock source is HSI. */ +#define STM32_PLLSRC_HSE (1 << 16) /**< PLL clock source is HSE. */ + +#define STM32_MCOSEL_NOCLOCK (0 << 24) /**< No clock on MCO pin. */ +#define STM32_MCOSEL_HSI14 (3 << 24) /**< HSI14 clock on MCO pin. */ +#define STM32_MCOSEL_SYSCLK (4 << 24) /**< SYSCLK on MCO pin. */ +#define STM32_MCOSEL_HSI (5 << 24) /**< HSI clock on MCO pin. */ +#define STM32_MCOSEL_HSE (6 << 24) /**< HSE clock on MCO pin. */ +#define STM32_MCOSEL_PLLDIV2 (7 << 24) /**< PLL/2 clock on MCO pin. */ +/** @} */ + +/** + * @name RCC_BDCR register bits definitions + * @{ + */ +#define STM32_RTCSEL_MASK (3 << 8) /**< RTC clock source mask. */ +#define STM32_RTCSEL_NOCLOCK (0 << 8) /**< No clock. */ +#define STM32_RTCSEL_LSE (1 << 8) /**< LSE used as RTC clock. */ +#define STM32_RTCSEL_LSI (2 << 8) /**< LSI used as RTC clock. */ +#define STM32_RTCSEL_HSEDIV (3 << 8) /**< HSE divided by 32 used as + RTC clock. */ +/** @} */ + +/** + * @name RCC_CFGR3 register bits definitions + * @{ + */ +#define STM32_USART1SW_MASK (3 << 0) /**< USART1 clock source mask. */ +#define STM32_USART1SW_PCLK (0 << 0) /**< USART1 clock is PCLK. */ +#define STM32_USART1SW_SYSCLK (1 << 0) /**< USART1 clock is SYSCLK. */ +#define STM32_USART1SW_LSE (2 << 0) /**< USART1 clock is LSE. */ +#define STM32_USART1SW_HSI (3 << 0) /**< USART1 clock is HSI. */ +#define STM32_I2C1SW_MASK (1 << 4) /**< I2C clock source mask. */ +#define STM32_I2C1SW_HSI (0 << 4) /**< I2C clock is HSI. */ +#define STM32_I2C1SW_SYSCLK (1 << 4) /**< I2C clock is SYSCLK. */ +#define STM32_CECSW_MASK (1 << 6) /**< CEC clock source mask. */ +#define STM32_CECSW_HSI (0 << 6) /**< CEC clock is HSI/244. */ +#define STM32_CECSW_LSE (1 << 6) /**< CEC clock is LSE. */ +#define STM32_ADCSW_MASK (1 << 8) /**< ADC clock source mask. */ +#define STM32_ADCSW_HSI14 (0 << 8) /**< ADC clock is HSI14. */ +#define STM32_ADCSW_PCLK (1 << 8) /**< ADC clock is PCLK/2|4. */ +/** @} */ + +/*===========================================================================*/ +/* Driver pre-compile time settings. */ +/*===========================================================================*/ + +/** + * @name Configuration options + * @{ + */ +/** + * @brief Disables the PWR/RCC initialization in the HAL. + */ +#if !defined(STM32_NO_INIT) || defined(__DOXYGEN__) +#define STM32_NO_INIT FALSE +#endif + +/** + * @brief Enables or disables the programmable voltage detector. + */ +#if !defined(STM32_PVD_ENABLE) || defined(__DOXYGEN__) +#define STM32_PVD_ENABLE FALSE +#endif + +/** + * @brief Sets voltage level for programmable voltage detector. + */ +#if !defined(STM32_PLS) || defined(__DOXYGEN__) +#define STM32_PLS STM32_PLS_LEV0 +#endif + +/** + * @brief Enables or disables the HSI clock source. + */ +#if !defined(STM32_HSI_ENABLED) || defined(__DOXYGEN__) +#define STM32_HSI_ENABLED TRUE +#endif + +/** + * @brief Enables or disables the HSI14 clock source. + */ +#if !defined(STM32_HSI14_ENABLED) || defined(__DOXYGEN__) +#define STM32_HSI14_ENABLED TRUE +#endif + +/** + * @brief Enables or disables the LSI clock source. + */ +#if !defined(STM32_LSI_ENABLED) || defined(__DOXYGEN__) +#define STM32_LSI_ENABLED FALSE +#endif + +/** + * @brief Enables or disables the HSE clock source. + */ +#if !defined(STM32_HSE_ENABLED) || defined(__DOXYGEN__) +#define STM32_HSE_ENABLED TRUE +#endif + +/** + * @brief Enables or disables the LSE clock source. + */ +#if !defined(STM32_LSE_ENABLED) || defined(__DOXYGEN__) +#define STM32_LSE_ENABLED FALSE +#endif + +/** + * @brief Main clock source selection. + * @note If the selected clock source is not the PLL then the PLL is not + * initialized and started. + * @note The default value is calculated for a 48MHz system clock from + * a 8MHz crystal using the PLL. + */ +#if !defined(STM32_SW) || defined(__DOXYGEN__) +#define STM32_SW STM32_SW_PLL +#endif + +/** + * @brief Clock source for the PLL. + * @note This setting has only effect if the PLL is selected as the + * system clock source. + * @note The default value is calculated for a 48MHz system clock from + * a 8MHz crystal using the PLL. + */ +#if !defined(STM32_PLLSRC) || defined(__DOXYGEN__) +#define STM32_PLLSRC STM32_PLLSRC_HSE +#endif + +/** + * @brief Crystal PLL pre-divider. + * @note This setting has only effect if the PLL is selected as the + * system clock source. + * @note The default value is calculated for a 72MHz system clock from + * a 8MHz crystal using the PLL. + */ +#if !defined(STM32_PREDIV_VALUE) || defined(__DOXYGEN__) +#define STM32_PREDIV_VALUE 1 +#endif + +/** + * @brief PLL multiplier value. + * @note The allowed range is 2...16. + * @note The default value is calculated for a 48MHz system clock from + * a 8MHz crystal using the PLL. + */ +#if !defined(STM32_PLLMUL_VALUE) || defined(__DOXYGEN__) +#define STM32_PLLMUL_VALUE 6 +#endif + +/** + * @brief AHB prescaler value. + * @note The default value is calculated for a 48MHz system clock from + * a 8MHz crystal using the PLL. + */ +#if !defined(STM32_HPRE) || defined(__DOXYGEN__) +#define STM32_HPRE STM32_HPRE_DIV1 +#endif + +/** + * @brief APB1 prescaler value. + */ +#if !defined(STM32_PPRE) || defined(__DOXYGEN__) +#define STM32_PPRE STM32_PPRE_DIV1 +#endif + +/** + * @brief MCO pin setting. + */ +#if !defined(STM32_MCOSEL) || defined(__DOXYGEN__) +#define STM32_MCOSEL STM32_MCOSEL_NOCLOCK +#endif + +/** + * @brief ADC prescaler value. + */ +#if !defined(STM32_ADCPRE) || defined(__DOXYGEN__) +#define STM32_ADCPRE STM32_ADCPRE_DIV4 +#endif + +/** + * @brief ADC clock source. + */ +#if !defined(STM32_ADCSW) || defined(__DOXYGEN__) +#define STM32_ADCSW STM32_ADCSW_HSI14 +#endif + +/** + * @brief CEC clock source. + */ +#if !defined(STM32_CECSW) || defined(__DOXYGEN__) +#define STM32_CECSW STM32_CECSW_HSI +#endif + +/** + * @brief I2C1 clock source. + */ +#if !defined(STM32_I2C1SW) || defined(__DOXYGEN__) +#define STM32_I2C1SW STM32_I2C1SW_HSI +#endif + +/** + * @brief USART1 clock source. + */ +#if !defined(STM32_USART1SW) || defined(__DOXYGEN__) +#define STM32_USART1SW STM32_USART1SW_PCLK +#endif + +/** + * @brief RTC clock source. + */ +#if !defined(STM32_RTCSEL) || defined(__DOXYGEN__) +#define STM32_RTCSEL STM32_RTCSEL_LSI +#endif +/** @} */ + +/*===========================================================================*/ +/* Derived constants and error checks. */ +/*===========================================================================*/ + +/* + * Configuration-related checks. + */ +#if !defined(STM32F0xx_MCUCONF) +#error "Using a wrong mcuconf.h file, STM32F0xx_MCUCONF not defined" +#endif + +/* + * HSI related checks. + */ +#if STM32_HSI_ENABLED +#else /* !STM32_HSI_ENABLED */ + +#if STM32_SW == STM32_SW_HSI +#error "HSI not enabled, required by STM32_SW" +#endif + +#if STM32_CECSW == STM32_CECSW_HSI +#error "HSI not enabled, required by STM32_CECSW" +#endif + +#if STM32_I2C1SW == STM32_I2C1SW_HSI +#error "HSI not enabled, required by STM32_I2C1SW" +#endif + +#if STM32_USART1SW == STM32_USART1SW_HSI +#error "HSI not enabled, required by STM32_USART1SW" +#endif + +#if (STM32_SW == STM32_SW_PLL) && (STM32_PLLSRC == STM32_PLLSRC_HSI) +#error "HSI not enabled, required by STM32_SW and STM32_PLLSRC" +#endif + +#if (STM32_MCOSEL == STM32_MCOSEL_HSI) || \ + ((STM32_MCOSEL == STM32_MCOSEL_PLLDIV2) && \ + (STM32_PLLSRC == STM32_PLLSRC_HSI)) +#error "HSI not enabled, required by STM32_MCOSEL" +#endif + +#endif /* !STM32_HSI_ENABLED */ + +/* + * HSI14 related checks. + */ +#if STM32_HSI14_ENABLED +#else /* !STM32_HSI14_ENABLED */ + +#if STM32_MCOSEL == STM32_MCOSEL_HSI14 +#error "HSI14 not enabled, required by STM32_MCOSEL" +#endif + +#if STM32_ADCSW == STM32_ADCSW_HSI14 +#error "HSI14 not enabled, required by STM32_ADCSW" +#endif + +#endif /* !STM32_HSI14_ENABLED */ + +/* + * HSE related checks. + */ +#if STM32_HSE_ENABLED + +#if STM32_HSECLK == 0 +#error "HSE frequency not defined" +#elif (STM32_HSECLK < STM32_HSECLK_MIN) || (STM32_HSECLK > STM32_HSECLK_MAX) +#error "STM32_HSECLK outside acceptable range (STM32_HSECLK_MIN...STM32_HSECLK_MAX)" +#endif + +#else /* !STM32_HSE_ENABLED */ + +#if STM32_SW == STM32_SW_HSE +#error "HSE not enabled, required by STM32_SW" +#endif + +#if (STM32_SW == STM32_SW_PLL) && (STM32_PLLSRC == STM32_PLLSRC_HSE) +#error "HSE not enabled, required by STM32_SW and STM32_PLLSRC" +#endif + +#if (STM32_MCOSEL == STM32_MCOSEL_HSE) || \ + ((STM32_MCOSEL == STM32_MCOSEL_PLLDIV2) && \ + (STM32_PLLSRC == STM32_PLLSRC_HSE)) +#error "HSE not enabled, required by STM32_MCOSEL" +#endif + +#if STM32_RTCSEL == STM32_RTCSEL_HSEDIV +#error "HSE not enabled, required by STM32_RTCSEL" +#endif + +#endif /* !STM32_HSE_ENABLED */ + +/* + * LSI related checks. + */ +#if STM32_LSI_ENABLED +#else /* !STM32_LSI_ENABLED */ + +#if STM32_RTCSEL == STM32_RTCSEL_LSI +#error "LSI not enabled, required by STM32_RTCSEL" +#endif + +#endif /* !STM32_LSI_ENABLED */ + +/* + * LSE related checks. + */ +#if STM32_LSE_ENABLED + +#if (STM32_LSECLK == 0) +#error "LSE frequency not defined" +#endif + +#if (STM32_LSECLK < STM32_LSECLK_MIN) || (STM32_LSECLK > STM32_LSECLK_MAX) +#error "STM32_LSECLK outside acceptable range (STM32_LSECLK_MIN...STM32_LSECLK_MAX)" +#endif + +#if !defined(STM32_LSEDRV) +#error "STM32_LSEDRV not defined" +#endif + +#if (STM32_LSEDRV >> 3) > 3 +#error "STM32_LSEDRV outside acceptable range ((0<<3)...(3<<3))" +#endif + +#if STM32_CECSW == STM32_CECSW_LSE +#error "LSE not enabled, required by STM32_CECSW" +#endif + +#if STM32_USART1SW == STM32_USART1SW_LSE +#error "LSE not enabled, required by STM32_USART1SW" +#endif + +#else /* !STM32_LSE_ENABLED */ + +#if STM32_RTCSEL == STM32_RTCSEL_LSE +#error "LSE not enabled, required by STM32_RTCSEL" +#endif + +#endif /* !STM32_LSE_ENABLED */ + +/* PLL activation conditions.*/ +#if (STM32_SW == STM32_SW_PLL) || \ + (STM32_MCOSEL == STM32_MCOSEL_PLLDIV2) || \ + defined(__DOXYGEN__) +/** + * @brief PLL activation flag. + */ +#define STM32_ACTIVATE_PLL TRUE +#else +#define STM32_ACTIVATE_PLL FALSE +#endif + +/* HSE prescaler setting check.*/ +#if ((STM32_PREDIV_VALUE >= 1) || (STM32_PREDIV_VALUE <= 16)) +#define STM32_PREDIV ((STM32_PREDIV_VALUE - 1) << 0) +#else +#error "invalid STM32_PREDIV value specified" +#endif + +/** + * @brief PLLMUL field. + */ +#if ((STM32_PLLMUL_VALUE >= 2) && (STM32_PLLMUL_VALUE <= 16)) || \ + defined(__DOXYGEN__) +#define STM32_PLLMUL ((STM32_PLLMUL_VALUE - 2) << 18) +#else +#error "invalid STM32_PLLMUL_VALUE value specified" +#endif + +/** + * @brief PLL input clock frequency. + */ +#if (STM32_PLLSRC == STM32_PLLSRC_HSE) || defined(__DOXYGEN__) +#define STM32_PLLCLKIN (STM32_HSECLK / STM32_PREDIV_VALUE) +#elif STM32_PLLSRC == STM32_PLLSRC_HSI +#define STM32_PLLCLKIN (STM32_HSICLK / 2) +#else +#error "invalid STM32_PLLSRC value specified" +#endif + +/* PLL input frequency range check.*/ +#if (STM32_PLLCLKIN < STM32_PLLIN_MIN) || (STM32_PLLCLKIN > STM32_PLLIN_MAX) +#error "STM32_PLLCLKIN outside acceptable range (STM32_PLLIN_MIN...STM32_PLLIN_MAX)" +#endif + +/** + * @brief PLL output clock frequency. + */ +#define STM32_PLLCLKOUT (STM32_PLLCLKIN * STM32_PLLMUL_VALUE) + +/* PLL output frequency range check.*/ +#if (STM32_PLLCLKOUT < STM32_PLLOUT_MIN) || (STM32_PLLCLKOUT > STM32_PLLOUT_MAX) +#error "STM32_PLLCLKOUT outside acceptable range (STM32_PLLOUT_MIN...STM32_PLLOUT_MAX)" +#endif + +/** + * @brief System clock source. + */ +#if (STM32_SW == STM32_SW_PLL) || defined(__DOXYGEN__) +#define STM32_SYSCLK STM32_PLLCLKOUT +#elif (STM32_SW == STM32_SW_HSI) +#define STM32_SYSCLK STM32_HSICLK +#elif (STM32_SW == STM32_SW_HSE) +#define STM32_SYSCLK STM32_HSECLK +#else +#error "invalid STM32_SW value specified" +#endif + +/* Check on the system clock.*/ +#if STM32_SYSCLK > STM32_SYSCLK_MAX +#error "STM32_SYSCLK above maximum rated frequency (STM32_SYSCLK_MAX)" +#endif + +/** + * @brief AHB frequency. + */ +#if (STM32_HPRE == STM32_HPRE_DIV1) || defined(__DOXYGEN__) +#define STM32_HCLK (STM32_SYSCLK / 1) +#elif STM32_HPRE == STM32_HPRE_DIV2 +#define STM32_HCLK (STM32_SYSCLK / 2) +#elif STM32_HPRE == STM32_HPRE_DIV4 +#define STM32_HCLK (STM32_SYSCLK / 4) +#elif STM32_HPRE == STM32_HPRE_DIV8 +#define STM32_HCLK (STM32_SYSCLK / 8) +#elif STM32_HPRE == STM32_HPRE_DIV16 +#define STM32_HCLK (STM32_SYSCLK / 16) +#elif STM32_HPRE == STM32_HPRE_DIV64 +#define STM32_HCLK (STM32_SYSCLK / 64) +#elif STM32_HPRE == STM32_HPRE_DIV128 +#define STM32_HCLK (STM32_SYSCLK / 128) +#elif STM32_HPRE == STM32_HPRE_DIV256 +#define STM32_HCLK (STM32_SYSCLK / 256) +#elif STM32_HPRE == STM32_HPRE_DIV512 +#define STM32_HCLK (STM32_SYSCLK / 512) +#else +#error "invalid STM32_HPRE value specified" +#endif + +/* AHB frequency check.*/ +#if STM32_HCLK > STM32_SYSCLK_MAX +#error "STM32_HCLK exceeding maximum frequency (STM32_SYSCLK_MAX)" +#endif + +/** + * @brief APB frequency. + */ +#if (STM32_PPRE == STM32_PPRE_DIV1) || defined(__DOXYGEN__) +#define STM32_PCLK (STM32_HCLK / 1) +#elif STM32_PPRE == STM32_PPRE_DIV2 +#define STM32_PCLK (STM32_HCLK / 2) +#elif STM32_PPRE == STM32_PPRE_DIV4 +#define STM32_PCLK (STM32_HCLK / 4) +#elif STM32_PPRE == STM32_PPRE_DIV8 +#define STM32_PCLK (STM32_HCLK / 8) +#elif STM32_PPRE == STM32_PPRE_DIV16 +#define STM32_PCLK (STM32_HCLK / 16) +#else +#error "invalid STM32_PPRE value specified" +#endif + +/* APB frequency check.*/ +#if STM32_PCLK > STM32_PCLK_MAX +#error "STM32_PCLK exceeding maximum frequency (STM32_PCLK_MAX)" +#endif + +/** + * @brief RTC clock. + */ +#if (STM32_RTCSEL == STM32_RTCSEL_LSE) || defined(__DOXYGEN__) +#define STM32_RTCCLK STM32_LSECLK +#elif STM32_RTCSEL == STM32_RTCSEL_LSI +#define STM32_RTCCLK STM32_LSICLK +#elif STM32_RTCSEL == STM32_RTCSEL_HSEDIV +#define STM32_RTCCLK (STM32_HSECLK / 32) +#elif STM32_RTCSEL == STM32_RTCSEL_NOCLOCK +#define STM32_RTCCLK 0 +#else +#error "invalid source selected for RTC clock" +#endif + +/** + * @brief ADC frequency. + */ +#if STM32_ADCSW == STM32_ADCSW_HSI14 +#define STM32_ADCCLK STM32_HSI14CLK +#elif STM32_ADCSW == STM32_ADCSW_PCLK +#if (STM32_ADCPRE == STM32_ADCPRE_DIV2) || defined(__DOXYGEN__) +#define STM32_ADCCLK (STM32_PCLK / 2) +#elif STM32_ADCPRE == STM32_ADCPRE_DIV4 +#define STM32_ADCCLK (STM32_PCLK / 4) +#else +#error "invalid STM32_ADCPRE value specified" +#endif +#else +#error "invalid source selected for ADC clock" +#endif + +/* ADC frequency check.*/ +#if STM32_ADCCLK > STM32_ADCCLK_MAX +#error "STM32_ADCCLK exceeding maximum frequency (STM32_ADCCLK_MAX)" +#endif + +/** + * @brief CEC frequency. + */ +#if STM32_CECSW == STM32_CECSW_HSI +#define STM32_CECCLK STM32_HSICLK +#elif STM32_CECSW == STM32_CECSW_LSE +#define STM32_CECCLK STM32_LSECLK +#else +#error "invalid source selected for CEC clock" +#endif + +/** + * @brief I2C1 frequency. + */ +#if STM32_I2CSW == STM32_I2C1SW_HSI +#define STM32_I2C1CLK STM32_HSICLK +#elif STM32_I2CSW == STM32_I2C1SW_SYSCLK +#define STM32_I2C1CLK STM32_SYSCLK +#else +#error "invalid source selected for I2C1 clock" +#endif + +/** + * @brief USART1 frequency. + */ +#if STM32_USART1SW == STM32_USART1SW_PCLK +#define STM32_USART1CLK STM32_PCLK +#elif STM32_USART1SW == STM32_USART1SW_SYSCLK +#define STM32_USART1CLK STM32_SYSCLK +#elif STM32_USART1SW == STM32_USART1SW_LSECLK +#define STM32_USART1CLK STM32_LSECLK +#elif STM32_USART1SW == STM32_USART1SW_HSICLK +#define STM32_USART1CLK STM32_HSICLK +#else +#error "invalid source selected for USART1 clock" +#endif + +/** + * @brief USART2 frequency. + */ +#define STM32_USART2CLK STM32_PCLK + +/** + * @brief Timers clock. + */ +#if (STM32_PPRE == STM32_PPRE_DIV1) || defined(__DOXYGEN__) +#define STM32_TIMCLK1 (STM32_PCLK * 1) +#define STM32_TIMCLK2 (STM32_PCLK * 1) +#else +#define STM32_TIMCLK1 (STM32_PCLK * 2) +#define STM32_TIMCLK2 (STM32_PCLK * 2) +#endif + +/** + * @brief Flash settings. + */ +#if (STM32_HCLK <= 24000000) || defined(__DOXYGEN__) +#define STM32_FLASHBITS 0x00000010 +#else +#define STM32_FLASHBITS 0x00000011 +#endif + +/*===========================================================================*/ +/* Driver data structures and types. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver macros. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +/* Various helpers.*/ +#include "nvic.h" +#include "stm32_isr.h" +#include "stm32_dma.h" +#include "stm32_rcc.h" + +#ifdef __cplusplus +extern "C" { +#endif + void hal_lld_init(void); + void stm32_clock_init(void); +#ifdef __cplusplus +} +#endif + +#endif /* _HAL_LLD_H_ */ + +/** @} */ diff --git a/os/hal/ports/STM32F0xx/platform.mk b/os/hal/ports/STM32F0xx/platform.mk new file mode 100644 index 000000000..0a5c73362 --- /dev/null +++ b/os/hal/ports/STM32F0xx/platform.mk @@ -0,0 +1,28 @@ +# List of all the STM32F0xx platform files. +PLATFORMSRC = ${CHIBIOS}/os/hal/platforms/common/ARMCMx/nvic.c \ + ${CHIBIOS}/os/hal/platforms/STM32F0xx/stm32_dma.c \ + ${CHIBIOS}/os/hal/platforms/STM32F0xx/hal_lld.c \ + ${CHIBIOS}/os/hal/platforms/STM32F0xx/adc_lld.c \ + ${CHIBIOS}/os/hal/platforms/STM32F0xx/ext_lld_isr.c \ + ${CHIBIOS}/os/hal/platforms/STM32/ext_lld.c \ + ${CHIBIOS}/os/hal/platforms/STM32/GPIOv2/pal_lld.c \ + ${CHIBIOS}/os/hal/platforms/STM32/I2Cv2/i2c_lld.c \ + ${CHIBIOS}/os/hal/platforms/STM32/SPIv2/spi_lld.c \ + ${CHIBIOS}/os/hal/platforms/STM32/TIMv1/gpt_lld.c \ + ${CHIBIOS}/os/hal/platforms/STM32/TIMv1/icu_lld.c \ + ${CHIBIOS}/os/hal/platforms/STM32/TIMv1/pwm_lld.c \ + ${CHIBIOS}/os/hal/platforms/STM32/TIMv1/st_lld.c \ + ${CHIBIOS}/os/hal/platforms/STM32/USARTv2/serial_lld.c \ + ${CHIBIOS}/os/hal/platforms/STM32/USARTv2/uart_lld.c \ + ${CHIBIOS}/os/hal/platforms/STM32/USBv1/usb_lld.c + +# Required include directories +PLATFORMINC = ${CHIBIOS}/os/hal/platforms/common/ARMCMx \ + ${CHIBIOS}/os/hal/platforms/STM32F0xx \ + ${CHIBIOS}/os/hal/platforms/STM32 \ + ${CHIBIOS}/os/hal/platforms/STM32/GPIOv2 \ + ${CHIBIOS}/os/hal/platforms/STM32/I2Cv2 \ + ${CHIBIOS}/os/hal/platforms/STM32/SPIv2 \ + ${CHIBIOS}/os/hal/platforms/STM32/TIMv1 \ + ${CHIBIOS}/os/hal/platforms/STM32/USARTv2 \ + ${CHIBIOS}/os/hal/platforms/STM32/USBv1 diff --git a/os/hal/ports/STM32F0xx/stm32_dma.c b/os/hal/ports/STM32F0xx/stm32_dma.c new file mode 100644 index 000000000..623c9d11b --- /dev/null +++ b/os/hal/ports/STM32F0xx/stm32_dma.c @@ -0,0 +1,291 @@ +/* + ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file STM32F0xx/stm32_dma.c + * @brief DMA helper driver code. + * + * @addtogroup STM32F0xx_DMA + * @details DMA sharing helper driver. In the STM32 the DMA streams are a + * shared resource, this driver allows to allocate and free DMA + * streams at runtime in order to allow all the other device + * drivers to coordinate the access to the resource. + * @note The DMA ISR handlers are all declared into this module because + * sharing, the various device drivers can associate a callback to + * ISRs when allocating streams. + * @{ + */ + +#include "hal.h" + +/* The following macro is only defined if some driver requiring DMA services + has been enabled.*/ +#if defined(STM32_DMA_REQUIRED) || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver local definitions. */ +/*===========================================================================*/ + +/** + * @brief Mask of the DMA1 streams in @p dma_streams_mask. + */ +#define STM32_DMA1_STREAMS_MASK 0x0000007F + +/** + * @brief Mask of the DMA2 streams in @p dma_streams_mask. + */ +#define STM32_DMA2_STREAMS_MASK 0x00000F80 + +/** + * @brief Post-reset value of the stream CCR register. + */ +#define STM32_DMA_CCR_RESET_VALUE 0x00000000 + +/*===========================================================================*/ +/* Driver exported variables. */ +/*===========================================================================*/ + +/** + * @brief DMA streams descriptors. + * @details This table keeps the association between an unique stream + * identifier and the involved physical registers. + * @note Don't use this array directly, use the appropriate wrapper macros + * instead: @p STM32_DMA1_STREAM1, @p STM32_DMA1_STREAM2 etc. + */ +const stm32_dma_stream_t _stm32_dma_streams[STM32_DMA_STREAMS] = { + {DMA1_Channel1, &DMA1->IFCR, 0, 0, DMA1_Channel1_IRQn}, + {DMA1_Channel2, &DMA1->IFCR, 4, 1, DMA1_Channel2_3_IRQn}, + {DMA1_Channel3, &DMA1->IFCR, 8, 2, DMA1_Channel2_3_IRQn}, + {DMA1_Channel4, &DMA1->IFCR, 12, 3, DMA1_Channel4_5_IRQn}, + {DMA1_Channel5, &DMA1->IFCR, 16, 4, DMA1_Channel4_5_IRQn} +}; + +/*===========================================================================*/ +/* Driver local variables and types. */ +/*===========================================================================*/ + +/** + * @brief DMA ISR redirector type. + */ +typedef struct { + stm32_dmaisr_t dma_func; /**< @brief DMA callback function. */ + void *dma_param; /**< @brief DMA callback parameter. */ +} dma_isr_redir_t; + +/** + * @brief Mask of the allocated streams. + */ +static uint32_t dma_streams_mask; + +/** + * @brief DMA IRQ redirectors. + */ +static dma_isr_redir_t dma_isr_redir[STM32_DMA_STREAMS]; + +/*===========================================================================*/ +/* Driver local functions. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver interrupt handlers. */ +/*===========================================================================*/ + +/** + * @brief DMA1 stream 1 shared interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(Vector64) { + uint32_t flags; + + OSAL_IRQ_PROLOGUE(); + + flags = (DMA1->ISR >> 0) & STM32_DMA_ISR_MASK; + DMA1->IFCR = STM32_DMA_ISR_MASK << 0; + if (dma_isr_redir[0].dma_func) + dma_isr_redir[0].dma_func(dma_isr_redir[0].dma_param, flags); + + OSAL_IRQ_EPILOGUE(); +} + +/** + * @brief DMA1 streams 2 and 3 shared interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(Vector68) { + uint32_t flags; + + OSAL_IRQ_PROLOGUE(); + + /* Check on channel 2.*/ + flags = (DMA1->ISR >> 4) & STM32_DMA_ISR_MASK; + if (flags & STM32_DMA_ISR_MASK) { + DMA1->IFCR = STM32_DMA_ISR_MASK << 4; + if (dma_isr_redir[1].dma_func) + dma_isr_redir[1].dma_func(dma_isr_redir[1].dma_param, flags); + } + + /* Check on channel 3.*/ + flags = (DMA1->ISR >> 8) & STM32_DMA_ISR_MASK; + if (flags & STM32_DMA_ISR_MASK) { + DMA1->IFCR = STM32_DMA_ISR_MASK << 8; + if (dma_isr_redir[2].dma_func) + dma_isr_redir[2].dma_func(dma_isr_redir[2].dma_param, flags); + } + + OSAL_IRQ_EPILOGUE(); +} + +/** + * @brief DMA1 streams 4 and 5 shared interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(Vector6C) { + uint32_t flags; + + OSAL_IRQ_PROLOGUE(); + + /* Check on channel 4.*/ + flags = (DMA1->ISR >> 12) & STM32_DMA_ISR_MASK; + if (flags & STM32_DMA_ISR_MASK) { + DMA1->IFCR = STM32_DMA_ISR_MASK << 12; + if (dma_isr_redir[3].dma_func) + dma_isr_redir[3].dma_func(dma_isr_redir[3].dma_param, flags); + } + + /* Check on channel 5.*/ + flags = (DMA1->ISR >> 16) & STM32_DMA_ISR_MASK; + if (flags & STM32_DMA_ISR_MASK) { + DMA1->IFCR = STM32_DMA_ISR_MASK << 16; + if (dma_isr_redir[4].dma_func) + dma_isr_redir[4].dma_func(dma_isr_redir[4].dma_param, flags); + } + + OSAL_IRQ_EPILOGUE(); +} + +/*===========================================================================*/ +/* Driver exported functions. */ +/*===========================================================================*/ + +/** + * @brief STM32 DMA helper initialization. + * + * @init + */ +void dmaInit(void) { + int i; + + dma_streams_mask = 0; + for (i = 0; i < STM32_DMA_STREAMS; i++) { + _stm32_dma_streams[i].channel->CCR = 0; + dma_isr_redir[i].dma_func = NULL; + } + DMA1->IFCR = 0xFFFFFFFF; +} + +/** + * @brief Allocates a DMA stream. + * @details The stream is allocated and, if required, the DMA clock enabled. + * The function also enables the IRQ vector associated to the stream + * and initializes its priority. + * @pre The stream must not be already in use or an error is returned. + * @post The stream is allocated and the default ISR handler redirected + * to the specified function. + * @post The stream ISR vector is enabled and its priority configured. + * @post The stream must be freed using @p dmaStreamRelease() before it can + * be reused with another peripheral. + * @post The stream is in its post-reset state. + * @note This function can be invoked in both ISR or thread context. + * + * @param[in] dmastp pointer to a stm32_dma_stream_t structure + * @param[in] priority IRQ priority mask for the DMA stream + * @param[in] func handling function pointer, can be @p NULL + * @param[in] param a parameter to be passed to the handling function + * @return The operation status. + * @retval FALSE no error, stream taken. + * @retval TRUE error, stream already taken. + * + * @special + */ +bool_t dmaStreamAllocate(const stm32_dma_stream_t *dmastp, + uint32_t priority, + stm32_dmaisr_t func, + void *param) { + + osalDbgCheck(dmastp != NULL); + + /* Checks if the stream is already taken.*/ + if ((dma_streams_mask & (1 << dmastp->selfindex)) != 0) + return TRUE; + + /* Marks the stream as allocated.*/ + dma_isr_redir[dmastp->selfindex].dma_func = func; + dma_isr_redir[dmastp->selfindex].dma_param = param; + dma_streams_mask |= (1 << dmastp->selfindex); + + /* Enabling DMA clocks required by the current streams set.*/ + if ((dma_streams_mask & STM32_DMA1_STREAMS_MASK) != 0) + rccEnableDMA1(FALSE); + + /* Putting the stream in a safe state.*/ + dmaStreamDisable(dmastp); + dmastp->channel->CCR = STM32_DMA_CCR_RESET_VALUE; + + /* Enables the associated IRQ vector if a callback is defined.*/ + if (func != NULL) + nvicEnableVector(dmastp->vector, priority); + + return FALSE; +} + +/** + * @brief Releases a DMA stream. + * @details The stream is freed and, if required, the DMA clock disabled. + * Trying to release a unallocated stream is an illegal operation + * and is trapped if assertions are enabled. + * @pre The stream must have been allocated using @p dmaStreamAllocate(). + * @post The stream is again available. + * @note This function can be invoked in both ISR or thread context. + * + * @param[in] dmastp pointer to a stm32_dma_stream_t structure + * + * @special + */ +void dmaStreamRelease(const stm32_dma_stream_t *dmastp) { + + osalDbgCheck(dmastp != NULL); + + /* Check if the streams is not taken.*/ + osalDbgAssert((dma_streams_mask & (1 << dmastp->selfindex)) != 0, + "not allocated"); + + /* Disables the associated IRQ vector.*/ + nvicDisableVector(dmastp->vector); + + /* Marks the stream as not allocated.*/ + dma_streams_mask &= ~(1 << dmastp->selfindex); + + /* Shutting down clocks that are no more required, if any.*/ + if ((dma_streams_mask & STM32_DMA1_STREAMS_MASK) == 0) + rccDisableDMA1(FALSE); +} + +#endif /* STM32_DMA_REQUIRED */ + +/** @} */ diff --git a/os/hal/ports/STM32F0xx/stm32_dma.h b/os/hal/ports/STM32F0xx/stm32_dma.h new file mode 100644 index 000000000..277ebf4d4 --- /dev/null +++ b/os/hal/ports/STM32F0xx/stm32_dma.h @@ -0,0 +1,394 @@ +/* + ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file STM32F0xx/stm32_dma.h + * @brief DMA helper driver header. + * @note This file requires definitions from the ST header file stm32f0xx.h. + * @note This driver uses the new naming convention used for the STM32F2xx + * so the "DMA channels" are referred as "DMA streams". + * + * @addtogroup STM32F0xx_DMA + * @{ + */ + +#ifndef _STM32_DMA_H_ +#define _STM32_DMA_H_ + +/*===========================================================================*/ +/* Driver constants. */ +/*===========================================================================*/ + +/** + * @brief Total number of DMA streams. + * @note This is the total number of streams among all the DMA units. + */ +#define STM32_DMA_STREAMS 5 + +/** + * @brief Mask of the ISR bits passed to the DMA callback functions. + */ +#define STM32_DMA_ISR_MASK 0x0F + +/** + * @brief Returns the channel associated to the specified stream. + * + * @param[in] n the stream number (0...STM32_DMA_STREAMS-1) + * @param[in] c a stream/channel association word, one channel per + * nibble, not associated channels must be set to 0xF + * @return Always zero, in this platform there is no dynamic + * association between streams and channels. + */ +#define STM32_DMA_GETCHANNEL(n, c) 0 + +/** + * @brief Checks if a DMA priority is within the valid range. + * @param[in] prio DMA priority + * + * @retval The check result. + * @retval FALSE invalid DMA priority. + * @retval TRUE correct DMA priority. + */ +#define STM32_DMA_IS_VALID_PRIORITY(prio) (((prio) >= 0) && ((prio) <= 3)) + +/** + * @brief Returns an unique numeric identifier for a DMA stream. + * + * @param[in] dma the DMA unit number + * @param[in] stream the stream number + * @return An unique numeric stream identifier. + */ +#define STM32_DMA_STREAM_ID(dma, stream) ((stream) - 1) + +/** + * @brief Returns a DMA stream identifier mask. + * + * + * @param[in] dma the DMA unit number + * @param[in] stream the stream number + * @return A DMA stream identifier mask. + */ +#define STM32_DMA_STREAM_ID_MSK(dma, stream) \ + (1 << STM32_DMA_STREAM_ID(dma, stream)) + +/** + * @brief Checks if a DMA stream unique identifier belongs to a mask. + * @param[in] id the stream numeric identifier + * @param[in] mask the stream numeric identifiers mask + * + * @retval The check result. + * @retval FALSE id does not belong to the mask. + * @retval TRUE id belongs to the mask. + */ +#define STM32_DMA_IS_VALID_ID(id, mask) (((1 << (id)) & (mask))) + +/** + * @name DMA streams identifiers + * @{ + */ +/** + * @brief Returns a pointer to a stm32_dma_stream_t structure. + * + * @param[in] id the stream numeric identifier + * @return A pointer to the stm32_dma_stream_t constant structure + * associated to the DMA stream. + */ +#define STM32_DMA_STREAM(id) (&_stm32_dma_streams[id]) + +#define STM32_DMA1_STREAM1 STM32_DMA_STREAM(0) +#define STM32_DMA1_STREAM2 STM32_DMA_STREAM(1) +#define STM32_DMA1_STREAM3 STM32_DMA_STREAM(2) +#define STM32_DMA1_STREAM4 STM32_DMA_STREAM(3) +#define STM32_DMA1_STREAM5 STM32_DMA_STREAM(4) +/** @} */ + +/** + * @name CR register constants common to all DMA types + * @{ + */ +#define STM32_DMA_CR_EN DMA_CCR_EN +#define STM32_DMA_CR_TEIE DMA_CCR_TEIE +#define STM32_DMA_CR_HTIE DMA_CCR_HTIE +#define STM32_DMA_CR_TCIE DMA_CCR_TCIE +#define STM32_DMA_CR_DIR_MASK (DMA_CCR_DIR | DMA_CCR_MEM2MEM) +#define STM32_DMA_CR_DIR_P2M 0 +#define STM32_DMA_CR_DIR_M2P DMA_CCR_DIR +#define STM32_DMA_CR_DIR_M2M DMA_CCR_MEM2MEM +#define STM32_DMA_CR_CIRC DMA_CCR_CIRC +#define STM32_DMA_CR_PINC DMA_CCR_PINC +#define STM32_DMA_CR_MINC DMA_CCR_MINC +#define STM32_DMA_CR_PSIZE_MASK DMA_CCR_PSIZE +#define STM32_DMA_CR_PSIZE_BYTE 0 +#define STM32_DMA_CR_PSIZE_HWORD DMA_CCR_PSIZE_0 +#define STM32_DMA_CR_PSIZE_WORD DMA_CCR_PSIZE_1 +#define STM32_DMA_CR_MSIZE_MASK DMA_CCR_MSIZE +#define STM32_DMA_CR_MSIZE_BYTE 0 +#define STM32_DMA_CR_MSIZE_HWORD DMA_CCR_MSIZE_0 +#define STM32_DMA_CR_MSIZE_WORD DMA_CCR_MSIZE_1 +#define STM32_DMA_CR_SIZE_MASK (STM32_DMA_CR_PSIZE_MASK | \ + STM32_DMA_CR_MSIZE_MASK) +#define STM32_DMA_CR_PL_MASK DMA_CCR_PL +#define STM32_DMA_CR_PL(n) ((n) << 12) +/** @} */ + +/** + * @name CR register constants only found in enhanced DMA + * @{ + */ +#define STM32_DMA_CR_DMEIE 0 /**< @brief Ignored by normal DMA. */ +#define STM32_DMA_CR_CHSEL_MASK 0 /**< @brief Ignored by normal DMA. */ +#define STM32_DMA_CR_CHSEL(n) 0 /**< @brief Ignored by normal DMA. */ +/** @} */ + +/** + * @name Status flags passed to the ISR callbacks + * @{ + */ +#define STM32_DMA_ISR_FEIF 0 +#define STM32_DMA_ISR_DMEIF 0 +#define STM32_DMA_ISR_TEIF DMA_ISR_TEIF1 +#define STM32_DMA_ISR_HTIF DMA_ISR_HTIF1 +#define STM32_DMA_ISR_TCIF DMA_ISR_TCIF1 +/** @} */ + +/*===========================================================================*/ +/* Driver pre-compile time settings. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Derived constants and error checks. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver data structures and types. */ +/*===========================================================================*/ + +/** + * @brief STM32 DMA stream descriptor structure. + */ +typedef struct { + DMA_Channel_TypeDef *channel; /**< @brief Associated DMA channel. */ + volatile uint32_t *ifcr; /**< @brief Associated IFCR reg. */ + uint8_t ishift; /**< @brief Bits offset in xIFCR + register. */ + uint8_t selfindex; /**< @brief Index to self in array. */ + uint8_t vector; /**< @brief Associated IRQ vector. */ +} stm32_dma_stream_t; + +/** + * @brief STM32 DMA ISR function type. + * + * @param[in] p parameter for the registered function + * @param[in] flags pre-shifted content of the ISR register, the bits + * are aligned to bit zero + */ +typedef void (*stm32_dmaisr_t)(void *p, uint32_t flags); + +/*===========================================================================*/ +/* Driver macros. */ +/*===========================================================================*/ + +/** + * @name Macro Functions + * @{ + */ +/** + * @brief Associates a peripheral data register to a DMA stream. + * @note This function can be invoked in both ISR or thread context. + * @pre The stream must have been allocated using @p dmaStreamAllocate(). + * @post After use the stream can be released using @p dmaStreamRelease(). + * + * @param[in] dmastp pointer to a stm32_dma_stream_t structure + * @param[in] addr value to be written in the CPAR register + * + * @special + */ +#define dmaStreamSetPeripheral(dmastp, addr) { \ + (dmastp)->channel->CPAR = (uint32_t)(addr); \ +} + +/** + * @brief Associates a memory destination to a DMA stream. + * @note This function can be invoked in both ISR or thread context. + * @pre The stream must have been allocated using @p dmaStreamAllocate(). + * @post After use the stream can be released using @p dmaStreamRelease(). + * + * @param[in] dmastp pointer to a stm32_dma_stream_t structure + * @param[in] addr value to be written in the CMAR register + * + * @special + */ +#define dmaStreamSetMemory0(dmastp, addr) { \ + (dmastp)->channel->CMAR = (uint32_t)(addr); \ +} + +/** + * @brief Sets the number of transfers to be performed. + * @note This function can be invoked in both ISR or thread context. + * @pre The stream must have been allocated using @p dmaStreamAllocate(). + * @post After use the stream can be released using @p dmaStreamRelease(). + * + * @param[in] dmastp pointer to a stm32_dma_stream_t structure + * @param[in] size value to be written in the CNDTR register + * + * @special + */ +#define dmaStreamSetTransactionSize(dmastp, size) { \ + (dmastp)->channel->CNDTR = (uint32_t)(size); \ +} + +/** + * @brief Returns the number of transfers to be performed. + * @note This function can be invoked in both ISR or thread context. + * @pre The stream must have been allocated using @p dmaStreamAllocate(). + * @post After use the stream can be released using @p dmaStreamRelease(). + * + * @param[in] dmastp pointer to a stm32_dma_stream_t structure + * @return The number of transfers to be performed. + * + * @special + */ +#define dmaStreamGetTransactionSize(dmastp) ((size_t)((dmastp)->channel->CNDTR)) + +/** + * @brief Programs the stream mode settings. + * @note This function can be invoked in both ISR or thread context. + * @pre The stream must have been allocated using @p dmaStreamAllocate(). + * @post After use the stream can be released using @p dmaStreamRelease(). + * + * @param[in] dmastp pointer to a stm32_dma_stream_t structure + * @param[in] mode value to be written in the CCR register + * + * @special + */ +#define dmaStreamSetMode(dmastp, mode) { \ + (dmastp)->channel->CCR = (uint32_t)(mode); \ +} + +/** + * @brief DMA stream enable. + * @note This function can be invoked in both ISR or thread context. + * @pre The stream must have been allocated using @p dmaStreamAllocate(). + * @post After use the stream can be released using @p dmaStreamRelease(). + * + * @param[in] dmastp pointer to a stm32_dma_stream_t structure + * + * @special + */ +#define dmaStreamEnable(dmastp) { \ + (dmastp)->channel->CCR |= STM32_DMA_CR_EN; \ +} + +/** + * @brief DMA stream disable. + * @details The function disables the specified stream and then clears any + * pending interrupt. + * @note This function can be invoked in both ISR or thread context. + * @note Interrupts enabling flags are set to zero after this call, see + * bug 3607518. + * @pre The stream must have been allocated using @p dmaStreamAllocate(). + * @post After use the stream can be released using @p dmaStreamRelease(). + * + * @param[in] dmastp pointer to a stm32_dma_stream_t structure + * + * @special + */ +#define dmaStreamDisable(dmastp) { \ + (dmastp)->channel->CCR &= ~(STM32_DMA_CR_TCIE | STM32_DMA_CR_HTIE | \ + STM32_DMA_CR_TEIE | STM32_DMA_CR_EN); \ + dmaStreamClearInterrupt(dmastp); \ +} + +/** + * @brief DMA stream interrupt sources clear. + * @note This function can be invoked in both ISR or thread context. + * @pre The stream must have been allocated using @p dmaStreamAllocate(). + * @post After use the stream can be released using @p dmaStreamRelease(). + * + * @param[in] dmastp pointer to a stm32_dma_stream_t structure + * + * @special + */ +#define dmaStreamClearInterrupt(dmastp) { \ + *(dmastp)->ifcr = STM32_DMA_ISR_MASK << (dmastp)->ishift; \ +} + +/** + * @brief Starts a memory to memory operation using the specified stream. + * @note The default transfer data mode is "byte to byte" but it can be + * changed by specifying extra options in the @p mode parameter. + * @pre The stream must have been allocated using @p dmaStreamAllocate(). + * @post After use the stream can be released using @p dmaStreamRelease(). + * + * @param[in] dmastp pointer to a stm32_dma_stream_t structure + * @param[in] mode value to be written in the CCR register, this value + * is implicitly ORed with: + * - @p STM32_DMA_CR_MINC + * - @p STM32_DMA_CR_PINC + * - @p STM32_DMA_CR_DIR_M2M + * - @p STM32_DMA_CR_EN + * . + * @param[in] src source address + * @param[in] dst destination address + * @param[in] n number of data units to copy + */ +#define dmaStartMemCopy(dmastp, mode, src, dst, n) { \ + dmaStreamSetPeripheral(dmastp, src); \ + dmaStreamSetMemory0(dmastp, dst); \ + dmaStreamSetTransactionSize(dmastp, n); \ + dmaStreamSetMode(dmastp, (mode) | \ + STM32_DMA_CR_MINC | STM32_DMA_CR_PINC | \ + STM32_DMA_CR_DIR_M2M | STM32_DMA_CR_EN); \ +} + +/** + * @brief Polled wait for DMA transfer end. + * @pre The stream must have been allocated using @p dmaStreamAllocate(). + * @post After use the stream can be released using @p dmaStreamRelease(). + * + * @param[in] dmastp pointer to a stm32_dma_stream_t structure + */ +#define dmaWaitCompletion(dmastp) { \ + while ((dmastp)->channel->CNDTR > 0) \ + ; \ + dmaStreamDisable(dmastp); \ +} +/** @} */ + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +#if !defined(__DOXYGEN__) +extern const stm32_dma_stream_t _stm32_dma_streams[STM32_DMA_STREAMS]; +#endif + +#ifdef __cplusplus +extern "C" { +#endif + void dmaInit(void); + bool_t dmaStreamAllocate(const stm32_dma_stream_t *dmastp, + uint32_t priority, + stm32_dmaisr_t func, + void *param); + void dmaStreamRelease(const stm32_dma_stream_t *dmastp); +#ifdef __cplusplus +} +#endif + +#endif /* _STM32_DMA_H_ */ + +/** @} */ diff --git a/os/hal/ports/STM32F0xx/stm32_isr.h b/os/hal/ports/STM32F0xx/stm32_isr.h new file mode 100644 index 000000000..52421a4d5 --- /dev/null +++ b/os/hal/ports/STM32F0xx/stm32_isr.h @@ -0,0 +1,91 @@ +/* + ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file STM32F0xx/stm32_isr.h + * @brief ISR remapper driver header. + * + * @addtogroup STM32F0xx_ISR + * @{ + */ + +#ifndef _STM32_ISR_H_ +#define _STM32_ISR_H_ + +/*===========================================================================*/ +/* Driver constants. */ +/*===========================================================================*/ + +/** + * @name ISR names and numbers remapping + * @{ + */ + +/* + * I2C units. + */ +#define STM32_I2C1_GLOBAL_HANDLER Vector9C +#define STM32_I2C1_GLOBAL_NUMBER 23 + +#define STM32_I2C2_GLOBAL_HANDLER VectorA0 +#define STM32_I2C2_GLOBAL_NUMBER 24 + +/* + * TIM units. + */ +#define STM32_TIM1_UP_HANDLER Vector74 +#define STM32_TIM1_CC_HANDLER Vector78 +#define STM32_TIM2_HANDLER Vector7C +#define STM32_TIM3_HANDLER Vector80 + +#define STM32_TIM1_UP_NUMBER 13 +#define STM32_TIM1_CC_NUMBER 14 +#define STM32_TIM2_NUMBER 15 +#define STM32_TIM3_NUMBER 16 + +/* + * USART units. + */ +#define STM32_USART1_HANDLER VectorAC +#define STM32_USART2_HANDLER VectorB0 + +#define STM32_USART1_NUMBER 27 +#define STM32_USART2_NUMBER 28 +/** @} */ + +/*===========================================================================*/ +/* Driver pre-compile time settings. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Derived constants and error checks. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver data structures and types. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver macros. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +#endif /* _STM32_ISR_H_ */ + +/** @} */ diff --git a/os/hal/ports/STM32F0xx/stm32_rcc.h b/os/hal/ports/STM32F0xx/stm32_rcc.h new file mode 100644 index 000000000..88e47f2c0 --- /dev/null +++ b/os/hal/ports/STM32F0xx/stm32_rcc.h @@ -0,0 +1,596 @@ +/* + ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file STM32F0xx/stm32_rcc.h + * @brief RCC helper driver header. + * @note This file requires definitions from the ST header file + * @p stm32f0xx.h. + * + * @addtogroup STM32F0xx_RCC + * @{ + */ + +#ifndef _STM32_RCC_ +#define _STM32_RCC_ + +/*===========================================================================*/ +/* Driver constants. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver pre-compile time settings. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Derived constants and error checks. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver data structures and types. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver macros. */ +/*===========================================================================*/ + +/** + * @name Generic RCC operations + * @{ + */ +/** + * @brief Enables the clock of one or more peripheral on the APB1 bus. + * @note The @p lp parameter is ignored in this family. + * + * @param[in] mask APB1 peripherals mask + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableAPB1(mask, lp) { \ + RCC->APB1ENR |= (mask); \ +} + +/** + * @brief Disables the clock of one or more peripheral on the APB1 bus. + * @note The @p lp parameter is ignored in this family. + * + * @param[in] mask APB1 peripherals mask + * @param[in] lp low power enable flag + * + * @api + */ +#define rccDisableAPB1(mask, lp) { \ + RCC->APB1ENR &= ~(mask); \ +} + +/** + * @brief Resets one or more peripheral on the APB1 bus. + * + * @param[in] mask APB1 peripherals mask + * + * @api + */ +#define rccResetAPB1(mask) { \ + RCC->APB1RSTR |= (mask); \ + RCC->APB1RSTR = 0; \ +} + +/** + * @brief Enables the clock of one or more peripheral on the APB2 bus. + * @note The @p lp parameter is ignored in this family. + * + * @param[in] mask APB2 peripherals mask + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableAPB2(mask, lp) { \ + RCC->APB2ENR |= (mask); \ +} + +/** + * @brief Disables the clock of one or more peripheral on the APB2 bus. + * @note The @p lp parameter is ignored in this family. + * + * @param[in] mask APB2 peripherals mask + * @param[in] lp low power enable flag + * + * @api + */ +#define rccDisableAPB2(mask, lp) { \ + RCC->APB2ENR &= ~(mask); \ +} + +/** + * @brief Resets one or more peripheral on the APB2 bus. + * + * @param[in] mask APB2 peripherals mask + * + * @api + */ +#define rccResetAPB2(mask) { \ + RCC->APB2RSTR |= (mask); \ + RCC->APB2RSTR = 0; \ +} + +/** + * @brief Enables the clock of one or more peripheral on the AHB bus. + * @note The @p lp parameter is ignored in this family. + * + * @param[in] mask AHB peripherals mask + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableAHB(mask, lp) { \ + RCC->AHBENR |= (mask); \ +} + +/** + * @brief Disables the clock of one or more peripheral on the AHB bus. + * @note The @p lp parameter is ignored in this family. + * + * @param[in] mask AHB peripherals mask + * @param[in] lp low power enable flag + * + * @api + */ +#define rccDisableAHB(mask, lp) { \ + RCC->AHBENR &= ~(mask); \ +} + +/** + * @brief Resets one or more peripheral on the AHB bus. + * + * @param[in] mask AHB peripherals mask + * + * @api + */ +#define rccResetAHB(mask) { \ + RCC->AHBRSTR |= (mask); \ + RCC->AHBRSTR = 0; \ +} +/** @} */ + +/** + * @name ADC peripherals specific RCC operations + * @{ + */ +/** + * @brief Enables the ADC1 peripheral clock. + * @note The @p lp parameter is ignored in this family. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableADC1(lp) rccEnableAPB2(RCC_APB2ENR_ADC1EN, lp) + +/** + * @brief Disables the ADC1 peripheral clock. + * @note The @p lp parameter is ignored in this family. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccDisableADC1(lp) rccDisableAPB2(RCC_APB2ENR_ADC1EN, lp) + +/** + * @brief Resets the ADC1 peripheral. + * + * @api + */ +#define rccResetADC1() rccResetAPB2(RCC_APB2RSTR_ADC1RST) +/** @} */ + +/** + * @name PWR interface specific RCC operations + * @{ + */ +/** + * @brief Enables the PWR interface clock. + * @note The @p lp parameter is ignored in this family. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnablePWRInterface(lp) rccEnableAPB1(RCC_APB1ENR_PWREN, lp) + +/** + * @brief Disables PWR interface clock. + * @note The @p lp parameter is ignored in this family. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccDisablePWRInterface(lp) rccDisableAPB1(RCC_APB1ENR_PWREN, lp) + +/** + * @brief Resets the PWR interface. + * + * @api + */ +#define rccResetPWRInterface() rccResetAPB1(RCC_APB1RSTR_PWRRST) +/** @} */ + +/** + * @name DMA peripherals specific RCC operations + * @{ + */ +/** + * @brief Enables the DMA1 peripheral clock. + * @note The @p lp parameter is ignored in this family. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableDMA1(lp) rccEnableAHB(RCC_AHBENR_DMA1EN, lp) + +/** + * @brief Disables the DMA1 peripheral clock. + * @note The @p lp parameter is ignored in this family. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccDisableDMA1(lp) rccDisableAHB(RCC_AHBENR_DMA1EN, lp) + +/** + * @brief Resets the DMA1 peripheral. + * @note Not supported in this family, does nothing. + * + * @api + */ +#define rccResetDMA1() +/** @} */ + +/** + * @name I2C peripherals specific RCC operations + * @{ + */ +/** + * @brief Enables the I2C1 peripheral clock. + * @note The @p lp parameter is ignored in this family. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableI2C1(lp) rccEnableAPB1(RCC_APB1ENR_I2C1EN, lp) + +/** + * @brief Disables the I2C1 peripheral clock. + * @note The @p lp parameter is ignored in this family. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccDisableI2C1(lp) rccDisableAPB1(RCC_APB1ENR_I2C1EN, lp) + +/** + * @brief Resets the I2C1 peripheral. + * + * @api + */ +#define rccResetI2C1() rccResetAPB1(RCC_APB1RSTR_I2C1RST) + +/** + * @brief Enables the I2C2 peripheral clock. + * @note The @p lp parameter is ignored in this family. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableI2C2(lp) rccEnableAPB1(RCC_APB1ENR_I2C2EN, lp) + +/** + * @brief Disables the I2C2 peripheral clock. + * @note The @p lp parameter is ignored in this family. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccDisableI2C2(lp) rccDisableAPB1(RCC_APB1ENR_I2C2EN, lp) + +/** + * @brief Resets the I2C2 peripheral. + * + * @api + */ +#define rccResetI2C2() rccResetAPB1(RCC_APB1RSTR_I2C2RST) +/** @} */ + +/** + * @name SPI peripherals specific RCC operations + * @{ + */ +/** + * @brief Enables the SPI1 peripheral clock. + * @note The @p lp parameter is ignored in this family. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableSPI1(lp) rccEnableAPB2(RCC_APB2ENR_SPI1EN, lp) + +/** + * @brief Disables the SPI1 peripheral clock. + * @note The @p lp parameter is ignored in this family. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccDisableSPI1(lp) rccDisableAPB2(RCC_APB2ENR_SPI1EN, lp) + +/** + * @brief Resets the SPI1 peripheral. + * + * @api + */ +#define rccResetSPI1() rccResetAPB2(RCC_APB2RSTR_SPI1RST) + +/** + * @brief Enables the SPI2 peripheral clock. + * @note The @p lp parameter is ignored in this family. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableSPI2(lp) rccEnableAPB1(RCC_APB1ENR_SPI2EN, lp) + +/** + * @brief Disables the SPI2 peripheral clock. + * @note The @p lp parameter is ignored in this family. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccDisableSPI2(lp) rccDisableAPB1(RCC_APB1ENR_SPI2EN, lp) + +/** + * @brief Resets the SPI2 peripheral. + * + * @api + */ +#define rccResetSPI2() rccResetAPB1(RCC_APB1RSTR_SPI2RST) +/** @} */ + +/** + * @name TIM peripherals specific RCC operations + * @{ + */ +/** + * @brief Enables the TIM1 peripheral clock. + * @note The @p lp parameter is ignored in this family. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableTIM1(lp) rccEnableAPB2(RCC_APB2ENR_TIM1EN, lp) + +/** + * @brief Disables the TIM1 peripheral clock. + * @note The @p lp parameter is ignored in this family. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccDisableTIM1(lp) rccDisableAPB2(RCC_APB2ENR_TIM1EN, lp) + +/** + * @brief Resets the TIM1 peripheral. + * + * @api + */ +#define rccResetTIM1() rccResetAPB2(RCC_APB2RSTR_TIM1RST) + +/** + * @brief Enables the TIM2 peripheral clock. + * @note The @p lp parameter is ignored in this family. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableTIM2(lp) rccEnableAPB1(RCC_APB1ENR_TIM2EN, lp) + +/** + * @brief Disables the TIM2 peripheral clock. + * @note The @p lp parameter is ignored in this family. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccDisableTIM2(lp) rccDisableAPB1(RCC_APB1ENR_TIM2EN, lp) + +/** + * @brief Resets the TIM2 peripheral. + * + * @api + */ +#define rccResetTIM2() rccResetAPB1(RCC_APB1RSTR_TIM2RST) + +/** + * @brief Enables the TIM3 peripheral clock. + * @note The @p lp parameter is ignored in this family. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableTIM3(lp) rccEnableAPB1(RCC_APB1ENR_TIM3EN, lp) + +/** + * @brief Disables the TIM3 peripheral clock. + * @note The @p lp parameter is ignored in this family. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccDisableTIM3(lp) rccDisableAPB1(RCC_APB1ENR_TIM3EN, lp) + +/** + * @brief Resets the TIM3 peripheral. + * + * @api + */ +#define rccResetTIM3() rccResetAPB1(RCC_APB1RSTR_TIM3RST) +/** @} */ + +/** + * @name USART/UART peripherals specific RCC operations + * @{ + */ +/** + * @brief Enables the USART1 peripheral clock. + * @note The @p lp parameter is ignored in this family. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableUSART1(lp) rccEnableAPB2(RCC_APB2ENR_USART1EN, lp) + +/** + * @brief Disables the USART1 peripheral clock. + * @note The @p lp parameter is ignored in this family. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccDisableUSART1(lp) rccDisableAPB2(RCC_APB2ENR_USART1EN, lp) + +/** + * @brief Resets the USART1 peripheral. + * + * @api + */ +#define rccResetUSART1() rccResetAPB2(RCC_APB2RSTR_USART1RST) + +/** + * @brief Enables the USART2 peripheral clock. + * @note The @p lp parameter is ignored in this family. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableUSART2(lp) rccEnableAPB1(RCC_APB1ENR_USART2EN, lp) + +/** + * @brief Disables the USART2 peripheral clock. + * @note The @p lp parameter is ignored in this family. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccDisableUSART2(lp) rccDisableAPB1(RCC_APB1ENR_USART2EN, lp) + +/** + * @brief Resets the USART2 peripheral. + * + * @api + */ +#define rccResetUSART2() rccResetAPB1(RCC_APB1RSTR_USART2RST) + +/** + * @brief Enables the CRC peripheral clock. + * @note The @p lp parameter is ignored in this family. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableCRC(lp) rccEnableAHB(RCC_AHBENR_CRCEN, lp) + +/** + * @brief Disables the CRC peripheral clock. + * @note The @p lp parameter is ignored in this family. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccDisableCRC(lp) rccDisableAHB(RCC_AHBENR_CRCEN, lp) + +/** + * @brief Resets the CRC peripheral. + * + * @api + */ +#define rccResetCRC() rccResetAHB(RCC_AHBRSTR_CRCRST) + +/** + * @brief Enables the WWDG peripheral clock. + * @note The @p lp parameter is ignored in this family. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableWWDG(lp) rccEnableAPB1(RCC_APB1ENR_WWDGEN, lp) + +/** + * @brief Disables the WWDG peripheral clock. + * @note The @p lp parameter is ignored in this family. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccDisableWWDG(lp) rccDisableAPB1(RCC_APB1ENR_WWDGEN, lp) + +/** + * @brief Resets the WWDG peripheral. + * + * @api + */ +#define rccResetWWDG() rccResetAPB1(RCC_APB1RSTR_WWDGRST) +/** @} */ + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +#ifdef __cplusplus +extern "C" { +#endif +#ifdef __cplusplus +} +#endif + +#endif /* _STM32_RCC_ */ + +/** @} */ diff --git a/os/hal/ports/STM32F0xx/stm32_registry.h b/os/hal/ports/STM32F0xx/stm32_registry.h new file mode 100644 index 000000000..0b12f7bb0 --- /dev/null +++ b/os/hal/ports/STM32F0xx/stm32_registry.h @@ -0,0 +1,168 @@ +/* + ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file STM32F0xx/stm32_registry.h + * @brief STM32F0xx capabilities registry. + * + * @addtogroup HAL + * @{ + */ + +#ifndef _STM32_REGISTRY_H_ +#define _STM32_REGISTRY_H_ + +/*===========================================================================*/ +/* Platform capabilities. */ +/*===========================================================================*/ + +/** + * @name STM32F0xx capabilities + * @{ + */ +/* ADC attributes.*/ +#define STM32_HAS_ADC1 TRUE +#define STM32_HAS_ADC2 FALSE +#define STM32_HAS_ADC3 FALSE +#define STM32_HAS_ADC4 FALSE + +/* CAN attributes.*/ +#define STM32_HAS_CAN1 FALSE +#define STM32_HAS_CAN2 FALSE + +/* DAC attributes.*/ +#define STM32_HAS_DAC TRUE + +/* DMA attributes.*/ +#define STM32_ADVANCED_DMA FALSE +#define STM32_HAS_DMA1 TRUE +#define STM32_HAS_DMA2 FALSE + +/* ETH attributes.*/ +#define STM32_HAS_ETH FALSE + +/* EXTI attributes.*/ +#define STM32_EXTI_NUM_CHANNELS 28 + +/* GPIO attributes.*/ +#define STM32_HAS_GPIOA TRUE +#define STM32_HAS_GPIOB TRUE +#define STM32_HAS_GPIOC TRUE +#define STM32_HAS_GPIOD TRUE +#define STM32_HAS_GPIOE FALSE +#define STM32_HAS_GPIOF TRUE +#define STM32_HAS_GPIOG FALSE +#define STM32_HAS_GPIOH FALSE +#define STM32_HAS_GPIOI FALSE + +/* I2C attributes.*/ +#define STM32_HAS_I2C1 TRUE +#define STM32_I2C_I2C1_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 3) +#define STM32_I2C_I2C1_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2) + +#define STM32_HAS_I2C2 TRUE +#define STM32_I2C_I2C2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 5) +#define STM32_I2C_I2C2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) + +#define STM32_HAS_I2C3 FALSE + +/* RTC attributes.*/ +#define STM32_HAS_RTC TRUE +#define STM32_RTC_HAS_SUBSECONDS FALSE +#define STM32_RTC_IS_CALENDAR TRUE + +/* SDIO attributes.*/ +#define STM32_HAS_SDIO FALSE + +/* SPI attributes.*/ +#define STM32_HAS_SPI1 TRUE +#define STM32_SPI_SPI1_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2) +#define STM32_SPI_SPI1_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 3) + +#define STM32_HAS_SPI2 TRUE +#define STM32_SPI_SPI2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) +#define STM32_SPI_SPI2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 5) + +#define STM32_HAS_SPI3 FALSE + +/* TIM attributes.*/ +#define STM32_HAS_TIM1 TRUE +#define STM32_TIM1_IS_32BITS FALSE +#define STM32_TIM1_CHANNELS 4 + +#define STM32_HAS_TIM2 TRUE +#define STM32_TIM2_IS_32BITS TRUE +#define STM32_TIM2_CHANNELS 4 + +#define STM32_HAS_TIM3 TRUE +#define STM32_TIM3_IS_32BITS FALSE +#define STM32_TIM3_CHANNELS 4 + +#define STM32_HAS_TIM6 TRUE +#define STM32_TIM6_IS_32BITS FALSE +#define STM32_TIM6_CHANNELS 0 + +#define STM32_HAS_TIM14 TRUE +#define STM32_TIM14_IS_32BITS FALSE +#define STM32_TIM14_CHANNELS 1 + +#define STM32_HAS_TIM15 TRUE +#define STM32_TIM15_IS_32BITS FALSE +#define STM32_TIM15_CHANNELS 2 + +#define STM32_HAS_TIM16 TRUE +#define STM32_TIM16_IS_32BITS FALSE +#define STM32_TIM16_CHANNELS 2 + +#define STM32_HAS_TIM17 TRUE +#define STM32_TIM17_IS_32BITS FALSE +#define STM32_TIM17_CHANNELS 2 + +#define STM32_HAS_TIM4 FALSE +#define STM32_HAS_TIM5 FALSE +#define STM32_HAS_TIM7 FALSE +#define STM32_HAS_TIM8 FALSE +#define STM32_HAS_TIM9 FALSE +#define STM32_HAS_TIM10 FALSE +#define STM32_HAS_TIM11 FALSE +#define STM32_HAS_TIM12 FALSE +#define STM32_HAS_TIM13 FALSE +#define STM32_HAS_TIM18 FALSE +#define STM32_HAS_TIM19 FALSE + +/* USART attributes.*/ +#define STM32_HAS_USART1 TRUE +#define STM32_UART_USART1_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 3) +#define STM32_UART_USART1_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2) + +#define STM32_HAS_USART2 TRUE +#define STM32_UART_USART2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 5) +#define STM32_UART_USART2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) + +#define STM32_HAS_USART3 FALSE +#define STM32_HAS_UART4 FALSE +#define STM32_HAS_UART5 FALSE +#define STM32_HAS_USART6 FALSE + +/* USB attributes.*/ +#define STM32_HAS_USB TRUE +#define STM32_HAS_OTG1 FALSE +#define STM32_HAS_OTG2 FALSE +/** @} */ + +#endif /* _STM32_REGISTRY_H_ */ + +/** @} */ diff --git a/os/hal/ports/STM32F30x/adc_lld.c b/os/hal/ports/STM32F30x/adc_lld.c new file mode 100644 index 000000000..d516cf21b --- /dev/null +++ b/os/hal/ports/STM32F30x/adc_lld.c @@ -0,0 +1,548 @@ +/* + ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file STM32F30x/adc_lld.c + * @brief STM32F30x ADC subsystem low level driver source. + * + * @addtogroup ADC + * @{ + */ + +#include "hal.h" + +#if HAL_USE_ADC || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver local definitions. */ +/*===========================================================================*/ + +#if STM32_ADC_DUAL_MODE +#if STM32_ADC_COMPACT_SAMPLES +/* Compact type dual mode.*/ +#define ADC_DMA_SIZE (STM32_DMA_CR_MSIZE_HWORD | STM32_DMA_CR_PSIZE_HWORD) +#define ADC_DMA_MDMA ADC_CCR_MDMA_HWORD + +#else /* !STM32_ADC_COMPACT_SAMPLES */ +/* Large type dual mode.*/ +#define ADC_DMA_SIZE (STM32_DMA_CR_MSIZE_WORD | STM32_DMA_CR_PSIZE_WORD) +#define ADC_DMA_MDMA ADC_CCR_MDMA_WORD +#endif /* !STM32_ADC_COMPACT_SAMPLES */ + +#else /* !STM32_ADC_DUAL_MODE */ +#if STM32_ADC_COMPACT_SAMPLES +/* Compact type single mode.*/ +#define ADC_DMA_SIZE (STM32_DMA_CR_MSIZE_BYTE | STM32_DMA_CR_PSIZE_BYTE) +#define ADC_DMA_MDMA ADC_CCR_MDMA_DISABLED + +#else /* !STM32_ADC_COMPACT_SAMPLES */ +/* Large type single mode.*/ +#define ADC_DMA_SIZE (STM32_DMA_CR_MSIZE_HWORD | STM32_DMA_CR_PSIZE_HWORD) +#define ADC_DMA_MDMA ADC_CCR_MDMA_DISABLED +#endif /* !STM32_ADC_COMPACT_SAMPLES */ +#endif /* !STM32_ADC_DUAL_MODE */ + +/*===========================================================================*/ +/* Driver exported variables. */ +/*===========================================================================*/ + +/** @brief ADC1 driver identifier.*/ +#if STM32_ADC_USE_ADC1 || defined(__DOXYGEN__) +ADCDriver ADCD1; +#endif + +/** @brief ADC1 driver identifier.*/ +#if STM32_ADC_USE_ADC3 || defined(__DOXYGEN__) +ADCDriver ADCD3; +#endif + +/*===========================================================================*/ +/* Driver local variables and types. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local functions. */ +/*===========================================================================*/ + +/** + * @brief Enables the ADC voltage regulator. + * + * @param[in] adcp pointer to the @p ADCDriver object + */ +static void adc_lld_vreg_on(ADCDriver *adcp) { + + adcp->adcm->CR = 0; /* RM 12.4.3.*/ + adcp->adcm->CR = ADC_CR_ADVREGEN_0; +#if STM32_ADC_DUAL_MODE + adcp->adcs->CR = ADC_CR_ADVREGEN_0; +#endif + osalSysPolledDelayX(US2RTC(10)); +} + +/** + * @brief Disables the ADC voltage regulator. + * + * @param[in] adcp pointer to the @p ADCDriver object + */ +static void adc_lld_vreg_off(ADCDriver *adcp) { + + adcp->adcm->CR = 0; /* RM 12.4.3.*/ + adcp->adcm->CR = ADC_CR_ADVREGEN_1; +#if STM32_ADC_DUAL_MODE + adcp->adcs->CR = ADC_CR_ADVREGEN_1; +#endif +} + +/** + * @brief Enables the ADC analog circuit. + * + * @param[in] adcp pointer to the @p ADCDriver object + */ +static void adc_lld_analog_on(ADCDriver *adcp) { + + adcp->adcm->CR |= ADC_CR_ADEN; + while ((adcp->adcm->ISR & ADC_ISR_ADRDY) == 0) + ; +#if STM32_ADC_DUAL_MODE + adcp->adcs->CR |= ADC_CR_ADEN; + while ((adcp->adcs->ISR & ADC_ISR_ADRDY) == 0) + ; +#endif +} + +/** + * @brief Disables the ADC analog circuit. + * + * @param[in] adcp pointer to the @p ADCDriver object + */ +static void adc_lld_analog_off(ADCDriver *adcp) { + + adcp->adcm->CR |= ADC_CR_ADDIS; + while ((adcp->adcm->CR & ADC_CR_ADDIS) != 0) + ; +#if STM32_ADC_DUAL_MODE + adcp->adcs->CR |= ADC_CR_ADDIS; + while ((adcp->adcs->CR & ADC_CR_ADDIS) != 0) + ; +#endif +} + +/** + * @brief Calibrates and ADC unit. + * + * @param[in] adcp pointer to the @p ADCDriver object + */ +static void adc_lld_calibrate(ADCDriver *adcp) { + + osalDbgAssert(adcp->adcm->CR == ADC_CR_ADVREGEN_0, "invalid register state"); + adcp->adcm->CR |= ADC_CR_ADCAL; + while ((adcp->adcm->CR & ADC_CR_ADCAL) != 0) + ; +#if STM32_ADC_DUAL_MODE + osalDbgAssert(adcp->adcs->CR == ADC_CR_ADVREGEN_0, "invalid register state"); + adcp->adcs->CR |= ADC_CR_ADCAL; + while ((adcp->adcs->CR & ADC_CR_ADCAL) != 0) + ; +#endif +} + +/** + * @brief Stops an ongoing conversion, if any. + * + * @param[in] adcp pointer to the @p ADCDriver object + */ +static void adc_lld_stop_adc(ADCDriver *adcp) { + + if (adcp->adcm->CR & ADC_CR_ADSTART) { + adcp->adcm->CR |= ADC_CR_ADSTP; + while (adcp->adcm->CR & ADC_CR_ADSTP) + ; + } +} + +/** + * @brief ADC DMA ISR service routine. + * + * @param[in] adcp pointer to the @p ADCDriver object + * @param[in] flags pre-shifted content of the ISR register + */ +static void adc_lld_serve_dma_interrupt(ADCDriver *adcp, uint32_t flags) { + + /* DMA errors handling.*/ + if ((flags & (STM32_DMA_ISR_TEIF | STM32_DMA_ISR_DMEIF)) != 0) { + /* DMA, this could help only if the DMA tries to access an unmapped + address space or violates alignment rules.*/ + _adc_isr_error_code(adcp, ADC_ERR_DMAFAILURE); + } + else { + /* It is possible that the conversion group has already be reset by the + ADC error handler, in this case this interrupt is spurious.*/ + if (adcp->grpp != NULL) { + if ((flags & STM32_DMA_ISR_HTIF) != 0) { + /* Half transfer processing.*/ + _adc_isr_half_code(adcp); + } + if ((flags & STM32_DMA_ISR_TCIF) != 0) { + /* Transfer complete processing.*/ + _adc_isr_full_code(adcp); + } + } + } +} + +/** + * @brief ADC ISR service routine. + * + * @param[in] adcp pointer to the @p ADCDriver object + * @param[in] isr content of the ISR register + */ +static void adc_lld_serve_interrupt(ADCDriver *adcp, uint32_t isr) { + + /* It could be a spurious interrupt caused by overflows after DMA disabling, + just ignore it in this case.*/ + if (adcp->grpp != NULL) { + /* Note, an overflow may occur after the conversion ended before the driver + is able to stop the ADC, this is why the DMA channel is checked too.*/ + if ((isr & ADC_ISR_OVR) && + (dmaStreamGetTransactionSize(adcp->dmastp) > 0)) { + /* ADC overflow condition, this could happen only if the DMA is unable + to read data fast enough.*/ + _adc_isr_error_code(adcp, ADC_ERR_OVERFLOW); + } + if (isr & ADC_ISR_AWD1) { + /* Analog watchdog error.*/ + _adc_isr_error_code(adcp, ADC_ERR_AWD1); + } + if (isr & ADC_ISR_AWD2) { + /* Analog watchdog error.*/ + _adc_isr_error_code(adcp, ADC_ERR_AWD2); + } + if (isr & ADC_ISR_AWD3) { + /* Analog watchdog error.*/ + _adc_isr_error_code(adcp, ADC_ERR_AWD3); + } + } +} + +/*===========================================================================*/ +/* Driver interrupt handlers. */ +/*===========================================================================*/ + +#if STM32_ADC_USE_ADC1 || defined(__DOXYGEN__) +/** + * @brief ADC1/ADC2 interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(Vector88) { + uint32_t isr; + + OSAL_IRQ_PROLOGUE(); + +#if STM32_ADC_DUAL_MODE + isr = ADC1->ISR; + isr |= ADC2->ISR; + ADC1->ISR = isr; + ADC2->ISR = isr; +#else /* !STM32_ADC_DUAL_MODE */ + isr = ADC1->ISR; + ADC1->ISR = isr; +#endif /* !STM32_ADC_DUAL_MODE */ + + adc_lld_serve_interrupt(&ADCD1, isr); + + OSAL_IRQ_EPILOGUE(); +} +#endif /* STM32_ADC_USE_ADC1 */ + +#if STM32_ADC_USE_ADC3 || defined(__DOXYGEN__) +/** + * @brief ADC3 interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(VectorFC) { + uint32_t isr; + + OSAL_IRQ_PROLOGUE(); + + isr = ADC3->ISR; + ADC3->ISR = isr; + + adc_lld_serve_interrupt(&ADCD3, isr); + + OSAL_IRQ_EPILOGUE(); +} + +#if STM32_ADC_DUAL_MODE +/** + * @brief ADC4 interrupt handler (as ADC3 slave). + * + * @isr + */ +OSAL_IRQ_HANDLER(Vector134) { + uint32_t isr; + + OSAL_IRQ_PROLOGUE(); + + isr = ADC4->ISR; + ADC4->ISR = isr; + + adc_lld_serve_interrupt(&ADCD3, isr); + + OSAL_IRQ_EPILOGUE(); +} +#endif /* STM32_ADC_DUAL_MODE */ +#endif /* STM32_ADC_USE_ADC3 */ + +/*===========================================================================*/ +/* Driver exported functions. */ +/*===========================================================================*/ + +/** + * @brief Low level ADC driver initialization. + * + * @notapi + */ +void adc_lld_init(void) { + +#if STM32_ADC_USE_ADC1 + /* Driver initialization.*/ + adcObjectInit(&ADCD1); + ADCD1.adcc = ADC1_2; + ADCD1.adcm = ADC1; +#if STM32_ADC_DUAL_MODE + ADCD1.adcs = ADC2; +#endif + ADCD1.dmastp = STM32_DMA1_STREAM1; + ADCD1.dmamode = ADC_DMA_SIZE | + STM32_DMA_CR_PL(STM32_ADC_ADC12_DMA_PRIORITY) | + STM32_DMA_CR_DIR_P2M | + STM32_DMA_CR_MINC | STM32_DMA_CR_TCIE | + STM32_DMA_CR_DMEIE | STM32_DMA_CR_TEIE; + nvicEnableVector(ADC1_2_IRQn, STM32_ADC_ADC12_IRQ_PRIORITY); +#endif /* STM32_ADC_USE_ADC1 */ + +#if STM32_ADC_USE_ADC3 + /* Driver initialization.*/ + adcObjectInit(&ADCD3); + ADCD3.adcc = ADC3_4; + ADCD3.adcm = ADC3; +#if STM32_ADC_DUAL_MODE + ADCD3.adcs = ADC4; +#endif + ADCD3.dmastp = STM32_DMA2_STREAM5; + ADCD3.dmamode = ADC_DMA_SIZE | + STM32_DMA_CR_PL(STM32_ADC_ADC12_DMA_PRIORITY) | + STM32_DMA_CR_DIR_P2M | + STM32_DMA_CR_MINC | STM32_DMA_CR_TCIE | + STM32_DMA_CR_DMEIE | STM32_DMA_CR_TEIE; + nvicEnableVector(ADC3_IRQn, STM32_ADC_ADC34_IRQ_PRIORITY); +#if STM32_ADC_DUAL_MODE + nvicEnableVector(ADC4_IRQn, STM32_ADC_ADC34_IRQ_PRIORITY); +#endif +#endif /* STM32_ADC_USE_ADC3 */ +} + +/** + * @brief Configures and activates the ADC peripheral. + * + * @param[in] adcp pointer to the @p ADCDriver object + * + * @notapi + */ +void adc_lld_start(ADCDriver *adcp) { + + /* If in stopped state then enables the ADC and DMA clocks.*/ + if (adcp->state == ADC_STOP) { +#if STM32_ADC_USE_ADC1 + if (&ADCD1 == adcp) { + bool_t b; + b = dmaStreamAllocate(adcp->dmastp, + STM32_ADC_ADC12_DMA_IRQ_PRIORITY, + (stm32_dmaisr_t)adc_lld_serve_dma_interrupt, + (void *)adcp); + osalDbgAssert(!b, "stream already allocated"); + rccEnableADC12(FALSE); + } +#endif /* STM32_ADC_USE_ADC1 */ + +#if STM32_ADC_USE_ADC3 + if (&ADCD3 == adcp) { + bool_t b; + b = dmaStreamAllocate(adcp->dmastp, + STM32_ADC_ADC34_DMA_IRQ_PRIORITY, + (stm32_dmaisr_t)adc_lld_serve_dma_interrupt, + (void *)adcp); + osalDbgAssert(!b, "stream already allocated"); + rccEnableADC34(FALSE); + } +#endif /* STM32_ADC_USE_ADC2 */ + + /* Setting DMA peripheral-side pointer.*/ +#if STM32_ADC_DUAL_MODE + dmaStreamSetPeripheral(adcp->dmastp, &adcp->adcc->CDR); +#else + dmaStreamSetPeripheral(adcp->dmastp, &adcp->adcm->DR); +#endif + + /* Clock source setting.*/ + adcp->adcc->CCR = STM32_ADC_ADC12_CLOCK_MODE | ADC_DMA_MDMA; + + /* Master ADC calibration.*/ + adc_lld_vreg_on(adcp); + adc_lld_calibrate(adcp); + + /* Master ADC enabled here in order to reduce conversions latencies.*/ + adc_lld_analog_on(adcp); + } +} + +/** + * @brief Deactivates the ADC peripheral. + * + * @param[in] adcp pointer to the @p ADCDriver object + * + * @notapi + */ +void adc_lld_stop(ADCDriver *adcp) { + + /* If in ready state then disables the ADC clock and analog part.*/ + if (adcp->state == ADC_READY) { + + /* Releasing the associated DMA channel.*/ + dmaStreamRelease(adcp->dmastp); + + /* Stopping the ongoing conversion, if any.*/ + adc_lld_stop_adc(adcp); + + /* Disabling ADC analog circuit and regulator.*/ + adc_lld_analog_off(adcp); + adc_lld_vreg_off(adcp); + +#if STM32_ADC_USE_ADC1 + if (&ADCD1 == adcp) + rccDisableADC12(FALSE); +#endif + +#if STM32_ADC_USE_ADC3 + if (&ADCD1 == adcp) + rccDisableADC34(FALSE); +#endif + } +} + +/** + * @brief Starts an ADC conversion. + * + * @param[in] adcp pointer to the @p ADCDriver object + * + * @notapi + */ +void adc_lld_start_conversion(ADCDriver *adcp) { + uint32_t dmamode, ccr, cfgr; + const ADCConversionGroup *grpp = adcp->grpp; + + osalDbgAssert(!STM32_ADC_DUAL_MODE || ((grpp->num_channels & 1) == 0), + "odd number of channels in dual mode"); + + /* Calculating control registers values.*/ + dmamode = adcp->dmamode; + ccr = grpp->ccr | (adcp->adcc->CCR & (ADC_CCR_CKMODE_MASK | + ADC_CCR_MDMA_MASK)); + cfgr = grpp->cfgr | ADC_CFGR_CONT | ADC_CFGR_DMAEN; + if (grpp->circular) { + dmamode |= STM32_DMA_CR_CIRC; +#if STM32_ADC_DUAL_MODE + ccr |= ADC_CCR_DMACFG_CIRCULAR; +#else + cfgr |= ADC_CFGR_DMACFG_CIRCULAR; +#endif + } + + /* DMA setup.*/ + if (adcp->depth > 1) { + /* If the buffer depth is greater than one then the half transfer interrupt + interrupt is enabled in order to allows streaming processing.*/ + dmamode |= STM32_DMA_CR_HTIE; + } + dmaStreamSetMemory0(adcp->dmastp, adcp->samples); +#if STM32_ADC_DUAL_MODE + dmaStreamSetTransactionSize(adcp->dmastp, ((uint32_t)grpp->num_channels/2) * + (uint32_t)adcp->depth); +#else + dmaStreamSetTransactionSize(adcp->dmastp, (uint32_t)grpp->num_channels * + (uint32_t)adcp->depth); +#endif + dmaStreamSetMode(adcp->dmastp, dmamode); + dmaStreamEnable(adcp->dmastp); + + /* Configuring the CCR register with the static settings ORed with + the user-specified settings in the conversion group configuration + structure.*/ + adcp->adcc->CCR = ccr; + + /* ADC setup, if it is defined a callback for the analog watch dog then it + is enabled.*/ + adcp->adcm->ISR = adcp->adcm->ISR; + adcp->adcm->IER = ADC_IER_OVR | ADC_IER_AWD1; + adcp->adcm->TR1 = grpp->tr1; +#if STM32_ADC_DUAL_MODE + adcp->adcm->SMPR1 = grpp->smpr[0]; + adcp->adcm->SMPR2 = grpp->smpr[1]; + adcp->adcm->SQR1 = grpp->sqr[0] | ADC_SQR1_NUM_CH(grpp->num_channels / 2); + adcp->adcm->SQR2 = grpp->sqr[1]; + adcp->adcm->SQR3 = grpp->sqr[2]; + adcp->adcm->SQR4 = grpp->sqr[3]; + adcp->adcs->SMPR1 = grpp->ssmpr[0]; + adcp->adcs->SMPR2 = grpp->ssmpr[1]; + adcp->adcs->SQR1 = grpp->ssqr[0] | ADC_SQR1_NUM_CH(grpp->num_channels / 2); + adcp->adcs->SQR2 = grpp->ssqr[1]; + adcp->adcs->SQR3 = grpp->ssqr[2]; + adcp->adcs->SQR4 = grpp->ssqr[3]; + +#else /* !STM32_ADC_DUAL_MODE */ + adcp->adcm->SMPR1 = grpp->smpr[0]; + adcp->adcm->SMPR2 = grpp->smpr[1]; + adcp->adcm->SQR1 = grpp->sqr[0] | ADC_SQR1_NUM_CH(grpp->num_channels); + adcp->adcm->SQR2 = grpp->sqr[1]; + adcp->adcm->SQR3 = grpp->sqr[2]; + adcp->adcm->SQR4 = grpp->sqr[3]; +#endif /* !STM32_ADC_DUAL_MODE */ + + /* ADC configuration.*/ + adcp->adcm->CFGR = cfgr; + + /* Starting conversion.*/ + adcp->adcm->CR |= ADC_CR_ADSTART; +} + +/** + * @brief Stops an ongoing conversion. + * + * @param[in] adcp pointer to the @p ADCDriver object + * + * @notapi + */ +void adc_lld_stop_conversion(ADCDriver *adcp) { + + dmaStreamDisable(adcp->dmastp); + adc_lld_stop_adc(adcp); +} + +#endif /* HAL_USE_ADC */ + +/** @} */ diff --git a/os/hal/ports/STM32F30x/adc_lld.h b/os/hal/ports/STM32F30x/adc_lld.h new file mode 100644 index 000000000..66c725cdd --- /dev/null +++ b/os/hal/ports/STM32F30x/adc_lld.h @@ -0,0 +1,608 @@ +/* + ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file STM32F30x/adc_lld.h + * @brief STM32F30x ADC subsystem low level driver header. + * + * @addtogroup ADC + * @{ + */ + +#ifndef _ADC_LLD_H_ +#define _ADC_LLD_H_ + +#if HAL_USE_ADC || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver constants. */ +/*===========================================================================*/ + +/** + * @name Available analog channels + * @{ + */ +#define ADC_CHANNEL_IN1 1 /**< @brief External analog input 1. */ +#define ADC_CHANNEL_IN2 2 /**< @brief External analog input 2. */ +#define ADC_CHANNEL_IN3 3 /**< @brief External analog input 3. */ +#define ADC_CHANNEL_IN4 4 /**< @brief External analog input 4. */ +#define ADC_CHANNEL_IN5 5 /**< @brief External analog input 5. */ +#define ADC_CHANNEL_IN6 6 /**< @brief External analog input 6. */ +#define ADC_CHANNEL_IN7 7 /**< @brief External analog input 7. */ +#define ADC_CHANNEL_IN8 8 /**< @brief External analog input 8. */ +#define ADC_CHANNEL_IN9 9 /**< @brief External analog input 9. */ +#define ADC_CHANNEL_IN10 10 /**< @brief External analog input 10. */ +#define ADC_CHANNEL_IN11 11 /**< @brief External analog input 11. */ +#define ADC_CHANNEL_IN12 12 /**< @brief External analog input 12. */ +#define ADC_CHANNEL_IN13 13 /**< @brief External analog input 13. */ +#define ADC_CHANNEL_IN14 14 /**< @brief External analog input 14. */ +#define ADC_CHANNEL_IN15 15 /**< @brief External analog input 15. */ +#define ADC_CHANNEL_IN16 16 /**< @brief External analog input 16. */ +#define ADC_CHANNEL_IN17 17 /**< @brief External analog input 17. */ +#define ADC_CHANNEL_IN18 18 /**< @brief External analog input 18. */ +/** @} */ + +/** + * @name Sampling rates + * @{ + */ +#define ADC_SMPR_SMP_1P5 0 /**< @brief 14 cycles conversion time */ +#define ADC_SMPR_SMP_2P5 1 /**< @brief 15 cycles conversion time. */ +#define ADC_SMPR_SMP_4P5 2 /**< @brief 17 cycles conversion time. */ +#define ADC_SMPR_SMP_7P5 3 /**< @brief 20 cycles conversion time. */ +#define ADC_SMPR_SMP_19P5 4 /**< @brief 32 cycles conversion time. */ +#define ADC_SMPR_SMP_61P5 5 /**< @brief 74 cycles conversion time. */ +#define ADC_SMPR_SMP_181P5 6 /**< @brief 194 cycles conversion time. */ +#define ADC_SMPR_SMP_601P5 7 /**< @brief 614 cycles conversion time. */ +/** @} */ + +/** + * @name Resolution + * @{ + */ +#define ADC_CFGR1_RES_12BIT (0 << 3) +#define ADC_CFGR1_RES_10BIT (1 << 3) +#define ADC_CFGR1_RES_8BIT (2 << 3) +#define ADC_CFGR1_RES_6BIT (3 << 3) +/** @} */ + +/** + * @name CFGR register configuration helpers + * @{ + */ +#define ADC_CFGR_DMACFG_MASK (1 << 1) +#define ADC_CFGR_DMACFG_ONESHOT (0 << 1) +#define ADC_CFGR_DMACFG_CIRCULAR (1 << 1) + +#define ADC_CFGR_RES_MASK (3 << 3) +#define ADC_CFGR_RES_12BITS (0 << 3) +#define ADC_CFGR_RES_10BITS (1 << 3) +#define ADC_CFGR_RES_8BITS (2 << 3) +#define ADC_CFGR_RES_6BITS (3 << 3) + +#define ADC_CFGR_ALIGN_MASK (1 << 5) +#define ADC_CFGR_ALIGN_RIGHT (0 << 5) +#define ADC_CFGR_ALIGN_LEFT (1 << 5) + +#define ADC_CFGR_EXTSEL_MASK (15 << 6) +#define ADC_CFGR_EXTSEL_SRC(n) ((n) << 6) + +#define ADC_CFGR_EXTEN_MASK (3 << 10) +#define ADC_CFGR_EXTEN_DISABLED (0 << 10) +#define ADC_CFGR_EXTEN_RISING (1 << 10) +#define ADC_CFGR_EXTEN_FALLING (2 << 10) +#define ADC_CFGR_EXTEN_BOTH (3 << 10) + +#define ADC_CFGR_DISCEN_MASK (1 << 16) +#define ADC_CFGR_DISCEN_DISABLED (0 << 16) +#define ADC_CFGR_DISCEN_ENABLED (1 << 16) + +#define ADC_CFGR_DISCNUM_MASK (7 << 17) +#define ADC_CFGR_DISCNUM_VAL(n) ((n) << 17) + +#define ADC_CFGR_AWD1_DISABLED 0 +#define ADC_CFGR_AWD1_ALL (1 << 23) +#define ADC_CFGR_AWD1_SINGLE(n) (((n) << 26) | (1 << 23) | (1 << 22)) +/** @} */ + +/** + * @name CCR register configuration helpers + * @{ + */ +#define ADC_CCR_DUAL_MASK (31 << 0) +#define ADC_CCR_DUAL(n) ((n) << 0) +#define ADC_CCR_DELAY_MASK (15 << 8) +#define ADC_CCR_DELAY(n) ((n) << 8) +#define ADC_CCR_DMACFG_MASK (1 << 13) +#define ADC_CCR_DMACFG_ONESHOT (0 << 13) +#define ADC_CCR_DMACFG_CIRCULAR (1 << 13) +#define ADC_CCR_MDMA_MASK (3 << 14) +#define ADC_CCR_MDMA_DISABLED (0 << 14) +#define ADC_CCR_MDMA_WORD (2 << 14) +#define ADC_CCR_MDMA_HWORD (3 << 14) +#define ADC_CCR_CKMODE_MASK (3 << 16) +#define ADC_CCR_CKMODE_ADCCK (0 << 16) +#define ADC_CCR_CKMODE_AHB_DIV1 (1 << 16) +#define ADC_CCR_CKMODE_AHB_DIV2 (2 << 16) +#define ADC_CCR_CKMODE_AHB_DIV4 (3 << 16) +#define ADC_CCR_VREFEN (1 << 22) +#define ADC_CCR_TSEN (1 << 23) +#define ADC_CCR_VBATEN (1 << 24) +/** @} */ + +/*===========================================================================*/ +/* Driver pre-compile time settings. */ +/*===========================================================================*/ + +/** + * @name Configuration options + * @{ + */ +/** + * @brief ADC1 driver enable switch. + * @details If set to @p TRUE the support for ADC1 is included. + * @note The default is @p FALSE. + */ +#if !defined(STM32_ADC_USE_ADC1) || defined(__DOXYGEN__) +#define STM32_ADC_USE_ADC1 FALSE +#endif + +/** + * @brief ADC3 driver enable switch. + * @details If set to @p TRUE the support for ADC3 is included. + * @note The default is @p FALSE. + */ +#if !defined(STM32_ADC_USE_ADC3) || defined(__DOXYGEN__) +#define STM32_ADC_USE_ADC3 FALSE +#endif + +/** + * @brief ADC1/ADC2 DMA priority (0..3|lowest..highest). + */ +#if !defined(STM32_ADC_ADC12_DMA_PRIORITY) || defined(__DOXYGEN__) +#define STM32_ADC_ADC12_DMA_PRIORITY 2 +#endif + +/** + * @brief ADC3/ADC4 DMA priority (0..3|lowest..highest). + */ +#if !defined(STM32_ADC_ADC34_DMA_PRIORITY) || defined(__DOXYGEN__) +#define STM32_ADC_ADC34_DMA_PRIORITY 2 +#endif + +/** + * @brief ADC1/ADC2 interrupt priority level setting. + */ +#if !defined(STM32_ADC_ADC12_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_ADC_ADC12_IRQ_PRIORITY 5 +#endif + +/** + * @brief ADC3/ADC4 interrupt priority level setting. + */ +#if !defined(STM32_ADC34_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_ADC_ADC34_IRQ_PRIORITY 5 +#endif + +/** + * @brief ADC1/ADC2 DMA interrupt priority level setting. + */ +#if !defined(STM32_ADC_ADC12_DMA_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_ADC_ADC12_DMA_IRQ_PRIORITY 5 +#endif + +/** + * @brief ADC3/ADC4 DMA interrupt priority level setting. + */ +#if !defined(STM32_ADC_ADC34_DMA_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_ADC_ADC34_DMA_IRQ_PRIORITY 5 +#endif + +/** + * @brief ADC1/ADC2 clock source and mode. + */ +#if !defined(STM32_ADC_ADC12_CLOCK_MODE) || defined(__DOXYGEN__) +#define STM32_ADC_ADC12_CLOCK_MODE ADC_CCR_CKMODE_AHB_DIV1 +#endif + +/** + * @brief ADC3/ADC4 clock source and mode. + */ +#if !defined(STM32_ADC_ADC34_CLOCK_MODE) || defined(__DOXYGEN__) +#define STM32_ADC_ADC34_CLOCK_MODE ADC_CCR_CKMODE_AHB_DIV1 +#endif + +/** + * @brief Enables the ADC master/slave mode. + */ +#if !defined(STM32_ADC_DUAL_MODE) || defined(__DOXYGEN__) +#define STM32_ADC_DUAL_MODE FALSE +#endif + +/** + * @brief Makes the ADC samples type an 8bits one. + */ +#if !defined(STM32_ADC_COMPACT_SAMPLES) || defined(__DOXYGEN__) +#define STM32_ADC_COMPACT_SAMPLES FALSE +#endif +/** @} */ + +/*===========================================================================*/ +/* Derived constants and error checks. */ +/*===========================================================================*/ + +#if STM32_ADC_USE_ADC1 && !STM32_HAS_ADC1 +#error "ADC1 not present in the selected device" +#endif + +#if STM32_ADC_USE_ADC3 && !STM32_HAS_ADC3 +#error "ADC3 not present in the selected device" +#endif + +#if !STM32_ADC_USE_ADC1 && !STM32_ADC_USE_ADC3 +#error "ADC driver activated but no ADC peripheral assigned" +#endif + +#if STM32_ADC_USE_ADC1 && \ + !CORTEX_IS_VALID_KERNEL_PRIORITY(STM32_ADC_ADC12_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to ADC1" +#endif + +#if STM32_ADC_USE_ADC1 && \ + !CORTEX_IS_VALID_KERNEL_PRIORITY(STM32_ADC_ADC12_DMA_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to ADC1 DMA" +#endif + +#if STM32_ADC_USE_ADC1 && \ + !STM32_DMA_IS_VALID_PRIORITY(STM32_ADC_ADC12_DMA_PRIORITY) +#error "Invalid DMA priority assigned to ADC1" +#endif + +#if STM32_ADC_USE_ADC3 && \ + !CORTEX_IS_VALID_KERNEL_PRIORITY(STM32_ADC_ADC34_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to ADC3" +#endif + +#if STM32_ADC_USE_ADC3 && \ + !CORTEX_IS_VALID_KERNEL_PRIORITY(STM32_ADC_ADC34_DMA_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to ADC3 DMA" +#endif + +#if STM32_ADC_USE_ADC3 && \ + !STM32_DMA_IS_VALID_PRIORITY(STM32_ADC_ADC34_DMA_PRIORITY) +#error "Invalid DMA priority assigned to ADC3" +#endif + +#if STM32_ADC_ADC12_CLOCK_MODE == ADC_CCR_CKMODE_ADCCK +#define STM32_ADC12_CLOCK STM32_ADC12CLK +#elif STM32_ADC_ADC12_CLOCK_MODE == ADC_CCR_CKMODE_AHB_DIV1 +#define STM32_ADC12_CLOCK (STM32_HCLK / 1) +#elif STM32_ADC_ADC12_CLOCK_MODE == ADC_CCR_CKMODE_AHB_DIV2 +#define STM32_ADC12_CLOCK (STM32_HCLK / 2) +#elif STM32_ADC_ADC12_CLOCK_MODE == ADC_CCR_CKMODE_AHB_DIV4 +#define STM32_ADC12_CLOCK (STM32_HCLK / 4) +#else +#error "invalid clock mode selected for STM32_ADC_ADC12_CLOCK_MODE" +#endif + +#if STM32_ADC_ADC34_CLOCK_MODE == ADC_CCR_CKMODE_ADCCK +#define STM32_ADC34_CLOCK STM32_ADC34CLK +#elif STM32_ADC_ADC34_CLOCK_MODE == ADC_CCR_CKMODE_AHB_DIV1 +#define STM32_ADC34_CLOCK (STM32_HCLK / 1) +#elif STM32_ADC_ADC34_CLOCK_MODE == ADC_CCR_CKMODE_AHB_DIV2 +#define STM32_ADC34_CLOCK (STM32_HCLK / 2) +#elif STM32_ADC_ADC34_CLOCK_MODE == ADC_CCR_CKMODE_AHB_DIV4 +#define STM32_ADC34_CLOCK (STM32_HCLK / 4) +#else +#error "invalid clock mode selected for STM32_ADC_ADC12_CLOCK_MODE" +#endif + +#if STM32_ADC12_CLOCK > 72000000 +#error "STM32_ADC12_CLOCK exceeding maximum frequency (72000000)" +#endif + +#if STM32_ADC34_CLOCK > 72000000 +#error "STM32_ADC34_CLOCK exceeding maximum frequency (72000000)" +#endif + +#if !defined(STM32_DMA_REQUIRED) +#define STM32_DMA_REQUIRED +#endif + +/*===========================================================================*/ +/* Driver data structures and types. */ +/*===========================================================================*/ + +/** + * @brief ADC sample data type. + */ +#if !STM32_ADC_COMPACT_SAMPLES || defined(__DOXYGEN__) +typedef uint16_t adcsample_t; +#else +typedef uint8_t adcsample_t; +#endif + +/** + * @brief Channels number in a conversion group. + */ +typedef uint16_t adc_channels_num_t; + +/** + * @brief Possible ADC failure causes. + * @note Error codes are architecture dependent and should not relied + * upon. + */ +typedef enum { + ADC_ERR_DMAFAILURE = 0, /**< DMA operations failure. */ + ADC_ERR_OVERFLOW = 1, /**< ADC overflow condition. */ + ADC_ERR_AWD1 = 2, /**< Watchdog 1 triggered. */ + ADC_ERR_AWD2 = 3, /**< Watchdog 2 triggered. */ + ADC_ERR_AWD3 = 4 /**< Watchdog 3 triggered. */ +} adcerror_t; + +/** + * @brief Type of a structure representing an ADC driver. + */ +typedef struct ADCDriver ADCDriver; + +/** + * @brief ADC notification callback type. + * + * @param[in] adcp pointer to the @p ADCDriver object triggering the + * callback + * @param[in] buffer pointer to the most recent samples data + * @param[in] n number of buffer rows available starting from @p buffer + */ +typedef void (*adccallback_t)(ADCDriver *adcp, adcsample_t *buffer, size_t n); + +/** + * @brief ADC error callback type. + * + * @param[in] adcp pointer to the @p ADCDriver object triggering the + * callback + * @param[in] err ADC error code + */ +typedef void (*adcerrorcallback_t)(ADCDriver *adcp, adcerror_t err); + +/** + * @brief Conversion group configuration structure. + * @details This implementation-dependent structure describes a conversion + * operation. + * @note The use of this configuration structure requires knowledge of + * STM32 ADC cell registers interface, please refer to the STM32 + * reference manual for details. + */ +typedef struct { + /** + * @brief Enables the circular buffer mode for the group. + */ + bool_t circular; + /** + * @brief Number of the analog channels belonging to the conversion group. + */ + adc_channels_num_t num_channels; + /** + * @brief Callback function associated to the group or @p NULL. + */ + adccallback_t end_cb; + /** + * @brief Error callback or @p NULL. + */ + adcerrorcallback_t error_cb; + /* End of the mandatory fields.*/ + /** + * @brief ADC CFGR register initialization data. + * @note The bits DMAEN, DMACFG, OVRMOD, CONT are enforced internally + * to the driver, keep them to zero. + */ + uint32_t cfgr; + /** + * @brief ADC TR1 register initialization data. + */ + uint32_t tr1; + /** + * @brief ADC CCR register initialization data. + * @note The bits CKMODE, MDMA, DMACFG are enforced internally to the + * driver, keep them to zero. + */ + uint32_t ccr; + /** + * @brief ADC SMPRx registers initialization data. + */ + uint32_t smpr[2]; + /** + * @brief ADC SQRx register initialization data. + */ + uint32_t sqr[4]; +#if STM32_ADC_DUAL_MODE || defined(__DOXYGEN__) + /** + * @brief Slave ADC SMPRx registers initialization data. + */ + uint32_t ssmpr[2]; + /** + * @brief Slave ADC SQRx register initialization data. + */ + uint32_t ssqr[4]; +#endif /* STM32_ADC_DUAL_MODE */ +} ADCConversionGroup; + +/** + * @brief Driver configuration structure. + * @note It could be empty on some architectures. + */ +typedef struct { + uint32_t dummy; +} ADCConfig; + +/** + * @brief Structure representing an ADC driver. + */ +struct ADCDriver { + /** + * @brief Driver state. + */ + adcstate_t state; + /** + * @brief Current configuration data. + */ + const ADCConfig *config; + /** + * @brief Current samples buffer pointer or @p NULL. + */ + adcsample_t *samples; + /** + * @brief Current samples buffer depth or @p 0. + */ + size_t depth; + /** + * @brief Current conversion group pointer or @p NULL. + */ + const ADCConversionGroup *grpp; +#if ADC_USE_WAIT || defined(__DOXYGEN__) + /** + * @brief Waiting thread. + */ + thread_reference_t thread; +#endif +#if ADC_USE_MUTUAL_EXCLUSION || defined(__DOXYGEN__) + /** + * @brief Mutex protecting the peripheral. + */ + mutex_t mutex; +#endif /* ADC_USE_MUTUAL_EXCLUSION */ +#if defined(ADC_DRIVER_EXT_FIELDS) + ADC_DRIVER_EXT_FIELDS +#endif + /* End of the mandatory fields.*/ + /** + * @brief Pointer to the common ADCx_y registers block. + */ + ADC_Common_TypeDef *adcc; + /** + * @brief Pointer to the master ADCx registers block. + */ + ADC_TypeDef *adcm; +#if STM32_ADC_DUAL_MODE || defined(__DOXYGEN__) + /** + * @brief Pointer to the slave ADCx registers block. + */ + ADC_TypeDef *adcs; +#endif /* STM32_ADC_DUAL_MODE */ + /** + * @brief Pointer to associated DMA channel. + */ + const stm32_dma_stream_t *dmastp; + /** + * @brief DMA mode bit mask. + */ + uint32_t dmamode; +}; + +/*===========================================================================*/ +/* Driver macros. */ +/*===========================================================================*/ + +/** + * @name Threashold register initializer + * @{ + */ +#define ADC_TR(low, high) (((uint32_t)(high) << 16) | (uint32_t)(low)) +/** @} */ + +/** + * @name Sequences building helper macros + * @{ + */ +/** + * @brief Number of channels in a conversion sequence. + */ +#define ADC_SQR1_NUM_CH(n) (((n) - 1) << 0) + +#define ADC_SQR1_SQ1_N(n) ((n) << 6) /**< @brief 1st channel in seq. */ +#define ADC_SQR1_SQ2_N(n) ((n) << 12) /**< @brief 2nd channel in seq. */ +#define ADC_SQR1_SQ3_N(n) ((n) << 18) /**< @brief 3rd channel in seq. */ +#define ADC_SQR1_SQ4_N(n) ((n) << 24) /**< @brief 4th channel in seq. */ + +#define ADC_SQR2_SQ5_N(n) ((n) << 0) /**< @brief 5th channel in seq. */ +#define ADC_SQR2_SQ6_N(n) ((n) << 6) /**< @brief 6th channel in seq. */ +#define ADC_SQR2_SQ7_N(n) ((n) << 12) /**< @brief 7th channel in seq. */ +#define ADC_SQR2_SQ8_N(n) ((n) << 18) /**< @brief 8th channel in seq. */ +#define ADC_SQR2_SQ9_N(n) ((n) << 24) /**< @brief 9th channel in seq. */ + +#define ADC_SQR3_SQ10_N(n) ((n) << 0) /**< @brief 10th channel in seq.*/ +#define ADC_SQR3_SQ11_N(n) ((n) << 6) /**< @brief 11th channel in seq.*/ +#define ADC_SQR3_SQ12_N(n) ((n) << 12) /**< @brief 12th channel in seq.*/ +#define ADC_SQR3_SQ13_N(n) ((n) << 18) /**< @brief 13th channel in seq.*/ +#define ADC_SQR3_SQ14_N(n) ((n) << 24) /**< @brief 14th channel in seq.*/ + +#define ADC_SQR4_SQ15_N(n) ((n) << 0) /**< @brief 15th channel in seq.*/ +#define ADC_SQR4_SQ16_N(n) ((n) << 6) /**< @brief 16th channel in seq.*/ +/** @} */ + +/** + * @name Sampling rate settings helper macros + * @{ + */ +#define ADC_SMPR1_SMP_AN1(n) ((n) << 3) /**< @brief AN1 sampling time. */ +#define ADC_SMPR1_SMP_AN2(n) ((n) << 6) /**< @brief AN2 sampling time. */ +#define ADC_SMPR1_SMP_AN3(n) ((n) << 9) /**< @brief AN3 sampling time. */ +#define ADC_SMPR1_SMP_AN4(n) ((n) << 12) /**< @brief AN4 sampling time. */ +#define ADC_SMPR1_SMP_AN5(n) ((n) << 15) /**< @brief AN5 sampling time. */ +#define ADC_SMPR1_SMP_AN6(n) ((n) << 18) /**< @brief AN6 sampling time. */ +#define ADC_SMPR1_SMP_AN7(n) ((n) << 21) /**< @brief AN7 sampling time. */ +#define ADC_SMPR1_SMP_AN8(n) ((n) << 24) /**< @brief AN8 sampling time. */ +#define ADC_SMPR1_SMP_AN9(n) ((n) << 27) /**< @brief AN9 sampling time. */ + +#define ADC_SMPR2_SMP_AN10(n) ((n) << 0) /**< @brief AN10 sampling time. */ +#define ADC_SMPR2_SMP_AN11(n) ((n) << 3) /**< @brief AN11 sampling time. */ +#define ADC_SMPR2_SMP_AN12(n) ((n) << 6) /**< @brief AN12 sampling time. */ +#define ADC_SMPR2_SMP_AN13(n) ((n) << 9) /**< @brief AN13 sampling time. */ +#define ADC_SMPR2_SMP_AN14(n) ((n) << 12) /**< @brief AN14 sampling time. */ +#define ADC_SMPR2_SMP_AN15(n) ((n) << 15) /**< @brief AN15 sampling time. */ +#define ADC_SMPR2_SMP_AN16(n) ((n) << 18) /**< @brief AN16 sampling time. */ +#define ADC_SMPR2_SMP_AN17(n) ((n) << 21) /**< @brief AN17 sampling time. */ +#define ADC_SMPR2_SMP_AN18(n) ((n) << 24) /**< @brief AN18 sampling time. */ +/** @} */ + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +#if STM32_ADC_USE_ADC1 && !defined(__DOXYGEN__) +extern ADCDriver ADCD1; +#endif + +#if STM32_ADC_USE_ADC3 && !defined(__DOXYGEN__) +extern ADCDriver ADCD3; +#endif + +#ifdef __cplusplus +extern "C" { +#endif + void adc_lld_init(void); + void adc_lld_start(ADCDriver *adcp); + void adc_lld_stop(ADCDriver *adcp); + void adc_lld_start_conversion(ADCDriver *adcp); + void adc_lld_stop_conversion(ADCDriver *adcp); +#ifdef __cplusplus +} +#endif + +#endif /* HAL_USE_ADC */ + +#endif /* _ADC_LLD_H_ */ + +/** @} */ diff --git a/os/hal/ports/STM32F30x/ext_lld_isr.c b/os/hal/ports/STM32F30x/ext_lld_isr.c new file mode 100644 index 000000000..08af37b19 --- /dev/null +++ b/os/hal/ports/STM32F30x/ext_lld_isr.c @@ -0,0 +1,402 @@ +/* + ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file STM32F30x/ext_lld_isr.c + * @brief STM32F30x EXT subsystem low level driver ISR code. + * + * @addtogroup EXT + * @{ + */ + +#include "hal.h" + +#if HAL_USE_EXT || defined(__DOXYGEN__) + +#include "ext_lld_isr.h" + +/*===========================================================================*/ +/* Driver local definitions. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver exported variables. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local variables. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local functions. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver interrupt handlers. */ +/*===========================================================================*/ + +#if !defined(STM32_DISABLE_EXTI0_HANDLER) +/** + * @brief EXTI[0] interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(Vector58) { + + OSAL_IRQ_PROLOGUE(); + + EXTI->PR = (1 << 0); + EXTD1.config->channels[0].cb(&EXTD1, 0); + + OSAL_IRQ_EPILOGUE(); +} +#endif + +#if !defined(STM32_DISABLE_EXTI1_HANDLER) +/** + * @brief EXTI[1] interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(Vector5C) { + + OSAL_IRQ_PROLOGUE(); + + EXTI->PR = (1 << 1); + EXTD1.config->channels[1].cb(&EXTD1, 1); + + OSAL_IRQ_EPILOGUE(); +} +#endif + +#if !defined(STM32_DISABLE_EXTI2_HANDLER) +/** + * @brief EXTI[2] interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(Vector60) { + + OSAL_IRQ_PROLOGUE(); + + EXTI->PR = (1 << 2); + EXTD1.config->channels[2].cb(&EXTD1, 2); + + OSAL_IRQ_EPILOGUE(); +} +#endif + +#if !defined(STM32_DISABLE_EXTI3_HANDLER) +/** + * @brief EXTI[3] interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(Vector64) { + + OSAL_IRQ_PROLOGUE(); + + EXTI->PR = (1 << 3); + EXTD1.config->channels[3].cb(&EXTD1, 3); + + OSAL_IRQ_EPILOGUE(); +} +#endif + +#if !defined(STM32_DISABLE_EXTI4_HANDLER) +/** + * @brief EXTI[4] interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(Vector68) { + + OSAL_IRQ_PROLOGUE(); + + EXTI->PR = (1 << 4); + EXTD1.config->channels[4].cb(&EXTD1, 4); + + OSAL_IRQ_EPILOGUE(); +} +#endif + +#if !defined(STM32_DISABLE_EXTI5_9_HANDLER) +/** + * @brief EXTI[5]...EXTI[9] interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(Vector9C) { + uint32_t pr; + + OSAL_IRQ_PROLOGUE(); + + pr = EXTI->PR & ((1 << 5) | (1 << 6) | (1 << 7) | (1 << 8) | (1 << 9)); + EXTI->PR = pr; + if (pr & (1 << 5)) + EXTD1.config->channels[5].cb(&EXTD1, 5); + if (pr & (1 << 6)) + EXTD1.config->channels[6].cb(&EXTD1, 6); + if (pr & (1 << 7)) + EXTD1.config->channels[7].cb(&EXTD1, 7); + if (pr & (1 << 8)) + EXTD1.config->channels[8].cb(&EXTD1, 8); + if (pr & (1 << 9)) + EXTD1.config->channels[9].cb(&EXTD1, 9); + + OSAL_IRQ_EPILOGUE(); +} +#endif + +#if !defined(STM32_DISABLE_EXTI10_15_HANDLER) +/** + * @brief EXTI[10]...EXTI[15] interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(VectorE0) { + uint32_t pr; + + OSAL_IRQ_PROLOGUE(); + + pr = EXTI->PR & ((1 << 10) | (1 << 11) | (1 << 12) | (1 << 13) | (1 << 14) | + (1 << 15)); + EXTI->PR = pr; + if (pr & (1 << 10)) + EXTD1.config->channels[10].cb(&EXTD1, 10); + if (pr & (1 << 11)) + EXTD1.config->channels[11].cb(&EXTD1, 11); + if (pr & (1 << 12)) + EXTD1.config->channels[12].cb(&EXTD1, 12); + if (pr & (1 << 13)) + EXTD1.config->channels[13].cb(&EXTD1, 13); + if (pr & (1 << 14)) + EXTD1.config->channels[14].cb(&EXTD1, 14); + if (pr & (1 << 15)) + EXTD1.config->channels[15].cb(&EXTD1, 15); + + OSAL_IRQ_EPILOGUE(); +} +#endif + +#if !defined(STM32_DISABLE_EXTI16_HANDLER) +/** + * @brief EXTI[16] interrupt handler (PVD). + * + * @isr + */ +OSAL_IRQ_HANDLER(Vector44) { + + OSAL_IRQ_PROLOGUE(); + + EXTI->PR = (1 << 16); + EXTD1.config->channels[16].cb(&EXTD1, 16); + + OSAL_IRQ_EPILOGUE(); +} +#endif + +#if !defined(STM32_DISABLE_EXTI17_HANDLER) +/** + * @brief EXTI[17] interrupt handler (RTC Alarm). + * + * @isr + */ +OSAL_IRQ_HANDLER(VectorE4) { + + OSAL_IRQ_PROLOGUE(); + + EXTI->PR = (1 << 17); + EXTD1.config->channels[17].cb(&EXTD1, 17); + + OSAL_IRQ_EPILOGUE(); +} +#endif + +#if !defined(STM32_DISABLE_EXTI18_HANDLER) +/** + * @brief EXTI[18] interrupt handler (USB Wakeup). + * + * @isr + */ +OSAL_IRQ_HANDLER(VectorE8) { + + OSAL_IRQ_PROLOGUE(); + + EXTI->PR = (1 << 18); + EXTD1.config->channels[18].cb(&EXTD1, 18); + + OSAL_IRQ_EPILOGUE(); +} +#endif + +#if !defined(STM32_DISABLE_EXTI19_HANDLER) +/** + * @brief EXTI[19] interrupt handler (Tamper TimeStamp). + * + * @isr + */ +OSAL_IRQ_HANDLER(Vector48) { + + OSAL_IRQ_PROLOGUE(); + + EXTI->PR = (1 << 19); + EXTD1.config->channels[19].cb(&EXTD1, 19); + + OSAL_IRQ_EPILOGUE(); +} +#endif + +#if !defined(STM32_DISABLE_EXTI20_HANDLER) +/** + * @brief EXTI[20] interrupt handler (RTC Wakeup). + * + * @isr + */ +OSAL_IRQ_HANDLER(Vector4C) { + + OSAL_IRQ_PROLOGUE(); + + EXTI->PR = (1 << 20); + EXTD1.config->channels[20].cb(&EXTD1, 20); + + OSAL_IRQ_EPILOGUE(); +} +#endif + +#if !defined(STM32_DISABLE_EXTI21_22_29_HANDLER) +/** + * @brief EXTI[21],EXTI[22],EXTI[29] interrupt handler (COMP1, COMP2, COMP3). + * + * @isr + */ +OSAL_IRQ_HANDLER(Vector140) { + uint32_t pr; + + OSAL_IRQ_PROLOGUE(); + + pr = EXTI->PR & ((1 << 21) | (1 << 22) | (1 << 29)); + EXTI->PR = pr; + if (pr & (1 << 21)) + EXTD1.config->channels[21].cb(&EXTD1, 21); + if (pr & (1 << 22)) + EXTD1.config->channels[22].cb(&EXTD1, 22); + if (pr & (1 << 29)) + EXTD1.config->channels[29].cb(&EXTD1, 29); + + OSAL_IRQ_EPILOGUE(); +} +#endif + +#if !defined(STM32_DISABLE_EXTI30_32_HANDLER) +/** + * @brief EXTI[30]...EXTI[32] interrupt handler (COMP4, COMP5, COMP6). + * + * @isr + */ +OSAL_IRQ_HANDLER(Vector144) { + uint32_t pr; + + OSAL_IRQ_PROLOGUE(); + + pr = EXTI->PR & ((1 << 30) | (1 << 31)); + EXTI->PR = pr; + if (pr & (1 << 30)) + EXTD1.config->channels[30].cb(&EXTD1, 30); + if (pr & (1 << 31)) + EXTD1.config->channels[31].cb(&EXTD1, 31); + + pr = EXTI->PR2 & (1 << 0); + EXTI->PR2 = pr; + if (pr & (1 << 0)) + EXTD1.config->channels[32].cb(&EXTD1, 32); + + OSAL_IRQ_EPILOGUE(); +} +#endif + +#if !defined(STM32_DISABLE_EXTI33_HANDLER) +/** + * @brief EXTI[33] interrupt handler (COMP7). + * + * @isr + */ +OSAL_IRQ_HANDLER(RTC_WKUP_IRQHandler) { + + OSAL_IRQ_PROLOGUE(); + + EXTI->PR2 = (1 << 1); + EXTD1.config->channels[33].cb(&EXTD1, 33); + + OSAL_IRQ_EPILOGUE(); +} +#endif + +/*===========================================================================*/ +/* Driver exported functions. */ +/*===========================================================================*/ + +/** + * @brief Enables EXTI IRQ sources. + * + * @notapi + */ +void ext_lld_exti_irq_enable(void) { + + nvicEnableVector(EXTI0_IRQn, STM32_EXT_EXTI0_IRQ_PRIORITY); + nvicEnableVector(EXTI1_IRQn, STM32_EXT_EXTI1_IRQ_PRIORITY); + nvicEnableVector(EXTI2_TS_IRQn, STM32_EXT_EXTI2_IRQ_PRIORITY); + nvicEnableVector(EXTI3_IRQn, STM32_EXT_EXTI3_IRQ_PRIORITY); + nvicEnableVector(EXTI4_IRQn, STM32_EXT_EXTI4_IRQ_PRIORITY); + nvicEnableVector(EXTI9_5_IRQn, STM32_EXT_EXTI5_9_IRQ_PRIORITY); + nvicEnableVector(EXTI15_10_IRQn, STM32_EXT_EXTI10_15_IRQ_PRIORITY); + nvicEnableVector(PVD_IRQn, STM32_EXT_EXTI16_IRQ_PRIORITY); + nvicEnableVector(RTC_Alarm_IRQn, STM32_EXT_EXTI17_IRQ_PRIORITY); + nvicEnableVector(USBWakeUp_IRQn, STM32_EXT_EXTI18_IRQ_PRIORITY); + nvicEnableVector(TAMPER_STAMP_IRQn, STM32_EXT_EXTI19_IRQ_PRIORITY); + nvicEnableVector(RTC_WKUP_IRQn, STM32_EXT_EXTI20_IRQ_PRIORITY); + nvicEnableVector(COMP1_2_3_IRQn, STM32_EXT_EXTI21_22_29_IRQ_PRIORITY); + nvicEnableVector(COMP4_5_6_IRQn, STM32_EXT_EXTI30_32_IRQ_PRIORITY); + nvicEnableVector(COMP7_IRQn, STM32_EXT_EXTI33_IRQ_PRIORITY); +} + +/** + * @brief Disables EXTI IRQ sources. + * + * @notapi + */ +void ext_lld_exti_irq_disable(void) { + + nvicDisableVector(EXTI0_IRQn); + nvicDisableVector(EXTI1_IRQn); + nvicDisableVector(EXTI2_TS_IRQn); + nvicDisableVector(EXTI3_IRQn); + nvicDisableVector(EXTI4_IRQn); + nvicDisableVector(EXTI9_5_IRQn); + nvicDisableVector(EXTI15_10_IRQn); + nvicDisableVector(PVD_IRQn); + nvicDisableVector(RTC_Alarm_IRQn); + nvicDisableVector(USBWakeUp_IRQn); + nvicDisableVector(TAMPER_STAMP_IRQn); + nvicDisableVector(RTC_WKUP_IRQn); + nvicDisableVector(COMP1_2_3_IRQn); + nvicDisableVector(COMP4_5_6_IRQn); + nvicDisableVector(COMP7_IRQn); +} + +#endif /* HAL_USE_EXT */ + +/** @} */ diff --git a/os/hal/ports/STM32F30x/ext_lld_isr.h b/os/hal/ports/STM32F30x/ext_lld_isr.h new file mode 100644 index 000000000..42f1e30fe --- /dev/null +++ b/os/hal/ports/STM32F30x/ext_lld_isr.h @@ -0,0 +1,177 @@ +/* + ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file STM32F30x/ext_lld_isr.h + * @brief STM32F30x EXT subsystem low level driver ISR header. + * + * @addtogroup EXT + * @{ + */ + +#ifndef _EXT_LLD_ISR_H_ +#define _EXT_LLD_ISR_H_ + +#if HAL_USE_EXT || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver constants. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver pre-compile time settings. */ +/*===========================================================================*/ + +/** + * @name Configuration options + * @{ + */ +/** + * @brief EXTI0 interrupt priority level setting. + */ +#if !defined(STM32_EXT_EXTI0_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_EXT_EXTI0_IRQ_PRIORITY 6 +#endif + +/** + * @brief EXTI1 interrupt priority level setting. + */ +#if !defined(STM32_EXT_EXTI1_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_EXT_EXTI1_IRQ_PRIORITY 6 +#endif + +/** + * @brief EXTI2 interrupt priority level setting. + */ +#if !defined(STM32_EXT_EXTI2_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_EXT_EXTI2_IRQ_PRIORITY 6 +#endif + +/** + * @brief EXTI3 interrupt priority level setting. + */ +#if !defined(STM32_EXT_EXTI3_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_EXT_EXTI3_IRQ_PRIORITY 6 +#endif + +/** + * @brief EXTI4 interrupt priority level setting. + */ +#if !defined(STM32_EXT_EXTI4_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_EXT_EXTI4_IRQ_PRIORITY 6 +#endif + +/** + * @brief EXTI5..9 interrupt priority level setting. + */ +#if !defined(STM32_EXT_EXTI5_9_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_EXT_EXTI5_9_IRQ_PRIORITY 6 +#endif + +/** + * @brief EXTI10..15 interrupt priority level setting. + */ +#if !defined(STM32_EXT_EXTI10_15_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_EXT_EXTI10_15_IRQ_PRIORITY 6 +#endif + +/** + * @brief EXTI16 interrupt priority level setting. + */ +#if !defined(STM32_EXT_EXTI16_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_EXT_EXTI16_IRQ_PRIORITY 6 +#endif + +/** + * @brief EXTI17 interrupt priority level setting. + */ +#if !defined(STM32_EXT_EXTI17_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_EXT_EXTI17_IRQ_PRIORITY 6 +#endif + +/** + * @brief EXTI18 interrupt priority level setting. + */ +#if !defined(STM32_EXT_EXTI18_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_EXT_EXTI18_IRQ_PRIORITY 6 +#endif + +/** + * @brief EXTI19 interrupt priority level setting. + */ +#if !defined(STM32_EXT_EXTI19_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_EXT_EXTI19_IRQ_PRIORITY 6 +#endif + +/** + * @brief EXTI20 interrupt priority level setting. + */ +#if !defined(STM32_EXT_EXTI20_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_EXT_EXTI20_IRQ_PRIORITY 6 +#endif + +/** + * @brief EXTI21,22,29 interrupt priority level setting. + */ +#if !defined(STM32_EXT_EXTI21_22_29_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_EXT_EXTI21_22_29_IRQ_PRIORITY 6 +#endif + +/** + * @brief EXTI30..32 interrupt priority level setting. + */ +#if !defined(STM32_EXT_EXTI30_32_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_EXT_EXTI30_32_IRQ_PRIORITY 6 +#endif + +/** + * @brief EXTI33 interrupt priority level setting. + */ +#if !defined(STM32_EXT_EXTI33_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_EXT_EXTI33_IRQ_PRIORITY 6 +#endif +/** @} */ + +/*===========================================================================*/ +/* Derived constants and error checks. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver data structures and types. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver macros. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +#ifdef __cplusplus +extern "C" { +#endif + void ext_lld_exti_irq_enable(void); + void ext_lld_exti_irq_disable(void); +#ifdef __cplusplus +} +#endif + +#endif /* HAL_USE_EXT */ + +#endif /* _EXT_LLD_ISR_H_ */ + +/** @} */ diff --git a/os/hal/ports/STM32F30x/hal_lld.c b/os/hal/ports/STM32F30x/hal_lld.c new file mode 100644 index 000000000..4521231d5 --- /dev/null +++ b/os/hal/ports/STM32F30x/hal_lld.c @@ -0,0 +1,197 @@ +/* + ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file STM32F30x/hal_lld.c + * @brief STM32F30x HAL subsystem low level driver source. + * + * @addtogroup HAL + * @{ + */ + +#include "hal.h" + +/*===========================================================================*/ +/* Driver local definitions. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver exported variables. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local variables and types. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local functions. */ +/*===========================================================================*/ + +/** + * @brief Initializes the backup domain. + * @note WARNING! Changing clock source impossible without resetting + * of the whole BKP domain. + */ +static void hal_lld_backup_domain_init(void) { + + /* Backup domain access enabled and left open.*/ + PWR->CR |= PWR_CR_DBP; + + /* Reset BKP domain if different clock source selected.*/ + if ((RCC->BDCR & STM32_RTCSEL_MASK) != STM32_RTCSEL){ + /* Backup domain reset.*/ + RCC->BDCR = RCC_BDCR_BDRST; + RCC->BDCR = 0; + } + + /* If enabled then the LSE is started.*/ +#if STM32_LSE_ENABLED +#if defined(STM32_LSE_BYPASS) + /* LSE Bypass.*/ + RCC->BDCR = STM32_LSEDRV | RCC_BDCR_LSEON | RCC_BDCR_LSEBYP; +#else + /* No LSE Bypass.*/ + RCC->BDCR = STM32_LSEDRV | RCC_BDCR_LSEON; +#endif + while ((RCC->BDCR & RCC_BDCR_LSERDY) == 0) + ; /* Waits until LSE is stable. */ +#endif + +#if STM32_RTCSEL != STM32_RTCSEL_NOCLOCK + /* If the backup domain hasn't been initialized yet then proceed with + initialization.*/ + if ((RCC->BDCR & RCC_BDCR_RTCEN) == 0) { + /* Selects clock source.*/ + RCC->BDCR |= STM32_RTCSEL; + + /* RTC clock enabled.*/ + RCC->BDCR |= RCC_BDCR_RTCEN; + } +#endif /* STM32_RTCSEL != STM32_RTCSEL_NOCLOCK */ +} + +/*===========================================================================*/ +/* Driver interrupt handlers. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver exported functions. */ +/*===========================================================================*/ + +/** + * @brief Low level HAL driver initialization. + * + * @notapi + */ +void hal_lld_init(void) { + + /* Reset of all peripherals.*/ + rccResetAPB1(0xFFFFFFFF); + rccResetAPB2(0xFFFFFFFF); + + /* PWR clock enabled.*/ + rccEnablePWRInterface(FALSE); + + /* Initializes the backup domain.*/ + hal_lld_backup_domain_init(); + +#if defined(STM32_DMA_REQUIRED) + dmaInit(); +#endif + + /* Programmable voltage detector enable.*/ +#if STM32_PVD_ENABLE + PWR->CR |= PWR_CR_PVDE | (STM32_PLS & STM32_PLS_MASK); +#endif /* STM32_PVD_ENABLE */ + + /* SYSCFG clock enabled here because it is a multi-functional unit shared + among multiple drivers.*/ + rccEnableAPB2(RCC_APB2ENR_SYSCFGEN, TRUE); + + /* USB IRQ relocated to not conflict with CAN.*/ + SYSCFG->CFGR1 |= SYSCFG_CFGR1_USB_IT_RMP; +} + +/** + * @brief STM32 clocks and PLL initialization. + * @note All the involved constants come from the file @p board.h. + * @note This function should be invoked just after the system reset. + * + * @special + */ +void stm32_clock_init(void) { + +#if !STM32_NO_INIT + /* HSI setup, it enforces the reset situation in order to handle possible + problems with JTAG probes and re-initializations.*/ + RCC->CR |= RCC_CR_HSION; /* Make sure HSI is ON. */ + while (!(RCC->CR & RCC_CR_HSIRDY)) + ; /* Wait until HSI is stable. */ + RCC->CR &= RCC_CR_HSITRIM | RCC_CR_HSION; /* CR Reset value. */ + RCC->CFGR = 0; /* CFGR reset value. */ + while ((RCC->CFGR & RCC_CFGR_SWS) != RCC_CFGR_SWS_HSI) + ; /* Waits until HSI is selected. */ + +#if STM32_HSE_ENABLED + /* HSE activation.*/ +#if defined(STM32_HSE_BYPASS) + /* HSE Bypass.*/ + RCC->CR |= RCC_CR_HSEON | RCC_CR_HSEBYP; +#else + /* No HSE Bypass.*/ + RCC->CR |= RCC_CR_HSEON; +#endif + while (!(RCC->CR & RCC_CR_HSERDY)) + ; /* Waits until HSE is stable. */ +#endif + +#if STM32_LSI_ENABLED + /* LSI activation.*/ + RCC->CSR |= RCC_CSR_LSION; + while ((RCC->CSR & RCC_CSR_LSIRDY) == 0) + ; /* Waits until LSI is stable. */ +#endif + + /* Clock settings.*/ + RCC->CFGR = STM32_MCOSEL | STM32_USBPRE | STM32_PLLMUL | + STM32_PLLSRC | STM32_PPRE1 | STM32_PPRE2 | + STM32_HPRE; + RCC->CFGR2 = STM32_ADC34PRES | STM32_ADC12PRES | STM32_PREDIV; + RCC->CFGR3 = STM32_UART5SW | STM32_UART4SW | STM32_USART3SW | + STM32_USART2SW | STM32_TIM8SW | STM32_TIM1SW | + STM32_I2C2SW | STM32_I2C1SW | STM32_USART1SW; + +#if STM32_ACTIVATE_PLL + /* PLL activation.*/ + RCC->CR |= RCC_CR_PLLON; + while (!(RCC->CR & RCC_CR_PLLRDY)) + ; /* Waits until PLL is stable. */ +#endif + + /* Flash setup and final clock selection. */ + FLASH->ACR = STM32_FLASHBITS; + + /* Switching to the configured clock source if it is different from HSI.*/ +#if (STM32_SW != STM32_SW_HSI) + /* Switches clock source.*/ + RCC->CFGR |= STM32_SW; + while ((RCC->CFGR & RCC_CFGR_SWS) != (STM32_SW << 2)) + ; /* Waits selection complete. */ +#endif +#endif /* !STM32_NO_INIT */ +} + +/** @} */ diff --git a/os/hal/ports/STM32F30x/hal_lld.h b/os/hal/ports/STM32F30x/hal_lld.h new file mode 100644 index 000000000..83174e930 --- /dev/null +++ b/os/hal/ports/STM32F30x/hal_lld.h @@ -0,0 +1,1105 @@ +/* + ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file STM32F30x/hal_lld.h + * @brief STM32F30x HAL subsystem low level driver header. + * @pre This module requires the following macros to be defined in the + * @p board.h file: + * - STM32_LSECLK. + * - STM32_LSEDRV. + * - STM32_LSE_BYPASS (optionally). + * - STM32_HSECLK. + * - STM32_HSE_BYPASS (optionally). + * . + * One of the following macros must also be defined: + * - STM32F30X for Analog & DSP devices. + * . + * + * @addtogroup HAL + * @{ + */ + +#ifndef _HAL_LLD_H_ +#define _HAL_LLD_H_ + +#include "stm32.h" +#include "stm32_registry.h" + +/*===========================================================================*/ +/* Driver constants. */ +/*===========================================================================*/ + +/** + * @brief Defines the support for realtime counters in the HAL. + */ +#define HAL_IMPLEMENTS_COUNTERS TRUE + +/** + * @name Platform identification + * @{ + */ +#define PLATFORM_NAME "STM32F30x Analog & DSP" +/** @} */ + +/** + * @name Absolute Maximum Ratings + * @{ + */ +/** + * @brief Maximum system clock frequency. + */ +#define STM32_SYSCLK_MAX 72000000 + +/** + * @brief Maximum HSE clock frequency. + */ +#define STM32_HSECLK_MAX 32000000 + +/** + * @brief Minimum HSE clock frequency. + */ +#define STM32_HSECLK_MIN 1000000 + +/** + * @brief Maximum LSE clock frequency. + */ +#define STM32_LSECLK_MAX 1000000 + +/** + * @brief Minimum LSE clock frequency. + */ +#define STM32_LSECLK_MIN 32768 + +/** + * @brief Maximum PLLs input clock frequency. + */ +#define STM32_PLLIN_MAX 24000000 + +/** + * @brief Minimum PLLs input clock frequency. + */ +#define STM32_PLLIN_MIN 1000000 + +/** + * @brief Maximum PLL output clock frequency. + */ +#define STM32_PLLOUT_MAX 72000000 + +/** + * @brief Maximum PLL output clock frequency. + */ +#define STM32_PLLOUT_MIN 16000000 + +/** + * @brief Maximum APB1 clock frequency. + */ +#define STM32_PCLK1_MAX 36000000 + +/** + * @brief Maximum APB2 clock frequency. + */ +#define STM32_PCLK2_MAX 72000000 + +/** + * @brief Maximum ADC clock frequency. + */ +#define STM32_ADCCLK_MAX 72000000 +/** @} */ + +/** + * @name Internal clock sources + * @{ + */ +#define STM32_HSICLK 8000000 /**< High speed internal clock. */ +#define STM32_LSICLK 40000 /**< Low speed internal clock. */ +/** @} */ + +/** + * @name PWR_CR register bits definitions + * @{ + */ +#define STM32_PLS_MASK (7 << 5) /**< PLS bits mask. */ +#define STM32_PLS_LEV0 (0 << 5) /**< PVD level 0. */ +#define STM32_PLS_LEV1 (1 << 5) /**< PVD level 1. */ +#define STM32_PLS_LEV2 (2 << 5) /**< PVD level 2. */ +#define STM32_PLS_LEV3 (3 << 5) /**< PVD level 3. */ +#define STM32_PLS_LEV4 (4 << 5) /**< PVD level 4. */ +#define STM32_PLS_LEV5 (5 << 5) /**< PVD level 5. */ +#define STM32_PLS_LEV6 (6 << 5) /**< PVD level 6. */ +#define STM32_PLS_LEV7 (7 << 5) /**< PVD level 7. */ +/** @} */ + +/** + * @name RCC_CFGR register bits definitions + * @{ + */ +#define STM32_SW_HSI (0 << 0) /**< SYSCLK source is HSI. */ +#define STM32_SW_HSE (1 << 0) /**< SYSCLK source is HSE. */ +#define STM32_SW_PLL (2 << 0) /**< SYSCLK source is PLL. */ + +#define STM32_HPRE_DIV1 (0 << 4) /**< SYSCLK divided by 1. */ +#define STM32_HPRE_DIV2 (8 << 4) /**< SYSCLK divided by 2. */ +#define STM32_HPRE_DIV4 (9 << 4) /**< SYSCLK divided by 4. */ +#define STM32_HPRE_DIV8 (10 << 4) /**< SYSCLK divided by 8. */ +#define STM32_HPRE_DIV16 (11 << 4) /**< SYSCLK divided by 16. */ +#define STM32_HPRE_DIV64 (12 << 4) /**< SYSCLK divided by 64. */ +#define STM32_HPRE_DIV128 (13 << 4) /**< SYSCLK divided by 128. */ +#define STM32_HPRE_DIV256 (14 << 4) /**< SYSCLK divided by 256. */ +#define STM32_HPRE_DIV512 (15 << 4) /**< SYSCLK divided by 512. */ + +#define STM32_PPRE1_DIV1 (0 << 8) /**< HCLK divided by 1. */ +#define STM32_PPRE1_DIV2 (4 << 8) /**< HCLK divided by 2. */ +#define STM32_PPRE1_DIV4 (5 << 8) /**< HCLK divided by 4. */ +#define STM32_PPRE1_DIV8 (6 << 8) /**< HCLK divided by 8. */ +#define STM32_PPRE1_DIV16 (7 << 8) /**< HCLK divided by 16. */ + +#define STM32_PPRE2_DIV1 (0 << 11) /**< HCLK divided by 1. */ +#define STM32_PPRE2_DIV2 (4 << 11) /**< HCLK divided by 2. */ +#define STM32_PPRE2_DIV4 (5 << 11) /**< HCLK divided by 4. */ +#define STM32_PPRE2_DIV8 (6 << 11) /**< HCLK divided by 8. */ +#define STM32_PPRE2_DIV16 (7 << 11) /**< HCLK divided by 16. */ + +#define STM32_PLLSRC_HSI (0 << 16) /**< PLL clock source is HSI/2. */ +#define STM32_PLLSRC_HSE (1 << 16) /**< PLL clock source is + HSE/PREDIV. */ + +#define STM32_USBPRE_DIV1P5 (0 << 22) /**< USB clock is PLLCLK/1.5. */ +#define STM32_USBPRE_DIV1 (1 << 22) /**< USB clock is PLLCLK/1. */ + +#define STM32_MCOSEL_NOCLOCK (0 << 24) /**< No clock on MCO pin. */ +#define STM32_MCOSEL_LSI (2 << 24) /**< LSI clock on MCO pin. */ +#define STM32_MCOSEL_LSE (3 << 24) /**< LSE clock on MCO pin. */ +#define STM32_MCOSEL_SYSCLK (4 << 24) /**< SYSCLK on MCO pin. */ +#define STM32_MCOSEL_HSI (5 << 24) /**< HSI clock on MCO pin. */ +#define STM32_MCOSEL_HSE (6 << 24) /**< HSE clock on MCO pin. */ +#define STM32_MCOSEL_PLLDIV2 (7 << 24) /**< PLL/2 clock on MCO pin. */ +/** @} */ + +/** + * @name RCC_BDCR register bits definitions + * @{ + */ +#define STM32_RTCSEL_MASK (3 << 8) /**< RTC clock source mask. */ +#define STM32_RTCSEL_NOCLOCK (0 << 8) /**< No clock. */ +#define STM32_RTCSEL_LSE (1 << 8) /**< LSE used as RTC clock. */ +#define STM32_RTCSEL_LSI (2 << 8) /**< LSI used as RTC clock. */ +#define STM32_RTCSEL_HSEDIV (3 << 8) /**< HSE divided by 32 used as + RTC clock. */ +/** @} */ + +/** + * @name RCC_CFGR2 register bits definitions + * @{ + */ +#define STM32_PREDIV_MASK (15 << 0) /**< PREDIV divisor mask. */ +#define STM32_ADC12PRES_MASK (31 << 4) /**< ADC12 clock source mask. */ +#define STM32_ADC12PRES_NOCLOCK (0 << 4) /**< ADC12 clock is disabled. */ +#define STM32_ADC12PRES_DIV1 (16 << 4) /**< ADC12 clock is PLL/1. */ +#define STM32_ADC12PRES_DIV2 (17 << 4) /**< ADC12 clock is PLL/2. */ +#define STM32_ADC12PRES_DIV4 (18 << 4) /**< ADC12 clock is PLL/4. */ +#define STM32_ADC12PRES_DIV6 (19 << 4) /**< ADC12 clock is PLL/6. */ +#define STM32_ADC12PRES_DIV8 (20 << 4) /**< ADC12 clock is PLL/8. */ +#define STM32_ADC12PRES_DIV10 (21 << 4) /**< ADC12 clock is PLL/10. */ +#define STM32_ADC12PRES_DIV12 (22 << 4) /**< ADC12 clock is PLL/12. */ +#define STM32_ADC12PRES_DIV16 (23 << 4) /**< ADC12 clock is PLL/16. */ +#define STM32_ADC12PRES_DIV32 (24 << 4) /**< ADC12 clock is PLL/32. */ +#define STM32_ADC12PRES_DIV64 (25 << 4) /**< ADC12 clock is PLL/64. */ +#define STM32_ADC12PRES_DIV128 (26 << 4) /**< ADC12 clock is PLL/128. */ +#define STM32_ADC12PRES_DIV256 (27 << 4) /**< ADC12 clock is PLL/256. */ +#define STM32_ADC34PRES_MASK (31 << 4) /**< ADC34 clock source mask. */ +#define STM32_ADC34PRES_NOCLOCK (0 << 4) /**< ADC34 clock is disabled. */ +#define STM32_ADC34PRES_DIV1 (16 << 4) /**< ADC34 clock is PLL/1. */ +#define STM32_ADC34PRES_DIV2 (17 << 4) /**< ADC34 clock is PLL/2. */ +#define STM32_ADC34PRES_DIV4 (18 << 4) /**< ADC34 clock is PLL/4. */ +#define STM32_ADC34PRES_DIV6 (19 << 4) /**< ADC34 clock is PLL/6. */ +#define STM32_ADC34PRES_DIV8 (20 << 4) /**< ADC34 clock is PLL/8. */ +#define STM32_ADC34PRES_DIV10 (21 << 4) /**< ADC34 clock is PLL/10. */ +#define STM32_ADC34PRES_DIV12 (22 << 4) /**< ADC34 clock is PLL/12. */ +#define STM32_ADC34PRES_DIV16 (23 << 4) /**< ADC34 clock is PLL/16. */ +#define STM32_ADC34PRES_DIV32 (24 << 4) /**< ADC34 clock is PLL/32. */ +#define STM32_ADC34PRES_DIV64 (25 << 4) /**< ADC34 clock is PLL/64. */ +#define STM32_ADC34PRES_DIV128 (26 << 4) /**< ADC34 clock is PLL/128. */ +#define STM32_ADC34PRES_DIV256 (27 << 4) /**< ADC34 clock is PLL/256. */ +/** @} */ + +/** + * @name RCC_CFGR3 register bits definitions + * @{ + */ +#define STM32_USART1SW_MASK (3 << 0) /**< USART1 clock source mask. */ +#define STM32_USART1SW_PCLK (0 << 0) /**< USART1 clock is PCLK. */ +#define STM32_USART1SW_SYSCLK (1 << 0) /**< USART1 clock is SYSCLK. */ +#define STM32_USART1SW_LSE (2 << 0) /**< USART1 clock is LSE. */ +#define STM32_USART1SW_HSI (3 << 0) /**< USART1 clock is HSI. */ +#define STM32_I2C1SW_MASK (1 << 4) /**< I2C1 clock source mask. */ +#define STM32_I2C1SW_HSI (0 << 4) /**< I2C1 clock is HSI. */ +#define STM32_I2C1SW_SYSCLK (1 << 4) /**< I2C1 clock is SYSCLK. */ +#define STM32_I2C2SW_MASK (1 << 5) /**< I2C2 clock source mask. */ +#define STM32_I2C2SW_HSI (0 << 5) /**< I2C2 clock is HSI. */ +#define STM32_I2C2SW_SYSCLK (1 << 5) /**< I2C2 clock is SYSCLK. */ +#define STM32_TIM1SW_MASK (1 << 8) /**< TIM1 clock source mask. */ +#define STM32_TIM1SW_PCLK2 (0 << 8) /**< TIM1 clock is PCLK2. */ +#define STM32_TIM1SW_PLLX2 (1 << 10) /**< TIM1 clock is PLL*2. */ +#define STM32_TIM8SW_MASK (1 << 10) /**< TIM8 clock source mask. */ +#define STM32_TIM8SW_PCLK2 (0 << 10) /**< TIM8 clock is PCLK2. */ +#define STM32_TIM8SW_PLLX2 (1 << 10) /**< TIM8 clock is PLL*2. */ +#define STM32_USART2SW_MASK (3 << 16) /**< USART2 clock source mask. */ +#define STM32_USART2SW_PCLK (0 << 16) /**< USART2 clock is PCLK. */ +#define STM32_USART2SW_SYSCLK (1 << 16) /**< USART2 clock is SYSCLK. */ +#define STM32_USART2SW_LSE (2 << 16) /**< USART2 clock is LSE. */ +#define STM32_USART2SW_HSI (3 << 16) /**< USART2 clock is HSI. */ +#define STM32_USART3SW_MASK (3 << 18) /**< USART3 clock source mask. */ +#define STM32_USART3SW_PCLK (0 << 18) /**< USART3 clock is PCLK. */ +#define STM32_USART3SW_SYSCLK (1 << 18) /**< USART3 clock is SYSCLK. */ +#define STM32_USART3SW_LSE (2 << 18) /**< USART3 clock is LSE. */ +#define STM32_USART3SW_HSI (3 << 18) /**< USART3 clock is HSI. */ +#define STM32_UART4SW_MASK (3 << 20) /**< USART4 clock source mask. */ +#define STM32_UART4SW_PCLK (0 << 20) /**< USART4 clock is PCLK. */ +#define STM32_UART4SW_SYSCLK (1 << 20) /**< USART4 clock is SYSCLK. */ +#define STM32_UART4SW_LSE (2 << 20) /**< USART4 clock is LSE. */ +#define STM32_UART4SW_HSI (3 << 20) /**< USART4 clock is HSI. */ +#define STM32_UART5SW_MASK (3 << 22) /**< USART5 clock source mask. */ +#define STM32_UART5SW_PCLK (0 << 22) /**< USART5 clock is PCLK. */ +#define STM32_UART5SW_SYSCLK (1 << 22) /**< USART5 clock is SYSCLK. */ +#define STM32_UART5SW_LSE (2 << 22) /**< USART5 clock is LSE. */ +#define STM32_UART5SW_HSI (3 << 22) /**< USART5 clock is HSI. */ +/** @} */ + +/*===========================================================================*/ +/* Driver pre-compile time settings. */ +/*===========================================================================*/ + +/** + * @name Configuration options + * @{ + */ +/** + * @brief Disables the PWR/RCC initialization in the HAL. + */ +#if !defined(STM32_NO_INIT) || defined(__DOXYGEN__) +#define STM32_NO_INIT FALSE +#endif + +/** + * @brief Enables or disables the programmable voltage detector. + */ +#if !defined(STM32_PVD_ENABLE) || defined(__DOXYGEN__) +#define STM32_PVD_ENABLE FALSE +#endif + +/** + * @brief Sets voltage level for programmable voltage detector. + */ +#if !defined(STM32_PLS) || defined(__DOXYGEN__) +#define STM32_PLS STM32_PLS_LEV0 +#endif + +/** + * @brief Enables or disables the HSI clock source. + */ +#if !defined(STM32_HSI_ENABLED) || defined(__DOXYGEN__) +#define STM32_HSI_ENABLED TRUE +#endif + +/** + * @brief Enables or disables the LSI clock source. + */ +#if !defined(STM32_LSI_ENABLED) || defined(__DOXYGEN__) +#define STM32_LSI_ENABLED TRUE +#endif + +/** + * @brief Enables or disables the HSE clock source. + */ +#if !defined(STM32_HSE_ENABLED) || defined(__DOXYGEN__) +#define STM32_HSE_ENABLED TRUE +#endif + +/** + * @brief Enables or disables the LSE clock source. + */ +#if !defined(STM32_LSE_ENABLED) || defined(__DOXYGEN__) +#define STM32_LSE_ENABLED FALSE +#endif + +/** + * @brief Main clock source selection. + * @note If the selected clock source is not the PLL then the PLL is not + * initialized and started. + * @note The default value is calculated for a 72MHz system clock from + * a 8MHz crystal using the PLL. + */ +#if !defined(STM32_SW) || defined(__DOXYGEN__) +#define STM32_SW STM32_SW_PLL +#endif + +/** + * @brief Clock source for the PLL. + * @note This setting has only effect if the PLL is selected as the + * system clock source. + * @note The default value is calculated for a 72MHz system clock from + * a 8MHz crystal using the PLL. + */ +#if !defined(STM32_PLLSRC) || defined(__DOXYGEN__) +#define STM32_PLLSRC STM32_PLLSRC_HSE +#endif + +/** + * @brief Crystal PLL pre-divider. + * @note This setting has only effect if the PLL is selected as the + * system clock source. + * @note The default value is calculated for a 72MHz system clock from + * a 8MHz crystal using the PLL. + */ +#if !defined(STM32_PREDIV_VALUE) || defined(__DOXYGEN__) +#define STM32_PREDIV_VALUE 1 +#endif + +/** + * @brief PLL multiplier value. + * @note The allowed range is 2...16. + * @note The default value is calculated for a 72MHz system clock from + * a 8MHz crystal using the PLL. + */ +#if !defined(STM32_PLLMUL_VALUE) || defined(__DOXYGEN__) +#define STM32_PLLMUL_VALUE 9 +#endif + +/** + * @brief AHB prescaler value. + * @note The default value is calculated for a 72MHz system clock from + * a 8MHz crystal using the PLL. + */ +#if !defined(STM32_HPRE) || defined(__DOXYGEN__) +#define STM32_HPRE STM32_HPRE_DIV1 +#endif + +/** + * @brief APB1 prescaler value. + */ +#if !defined(STM32_PPRE1) || defined(__DOXYGEN__) +#define STM32_PPRE1 STM32_PPRE1_DIV2 +#endif + +/** + * @brief APB2 prescaler value. + */ +#if !defined(STM32_PPRE2) || defined(__DOXYGEN__) +#define STM32_PPRE2 STM32_PPRE2_DIV2 +#endif + +/** + * @brief MCO pin setting. + */ +#if !defined(STM32_MCOSEL) || defined(__DOXYGEN__) +#define STM32_MCOSEL STM32_MCOSEL_NOCLOCK +#endif + +/** + * @brief ADC12 prescaler value. + */ +#if !defined(STM32_ADC12PRES) || defined(__DOXYGEN__) +#define STM32_ADC12PRES STM32_ADC12PRES_DIV1 +#endif + +/** + * @brief ADC34 prescaler value. + */ +#if !defined(STM32_ADC34PRES) || defined(__DOXYGEN__) +#define STM32_ADC34PRES STM32_ADC34PRES_DIV1 +#endif + +/** + * @brief USART1 clock source. + */ +#if !defined(STM32_USART1SW) || defined(__DOXYGEN__) +#define STM32_USART1SW STM32_USART1SW_PCLK +#endif + +/** + * @brief USART2 clock source. + */ +#if !defined(STM32_USART2SW) || defined(__DOXYGEN__) +#define STM32_USART2SW STM32_USART2SW_PCLK +#endif + +/** + * @brief USART3 clock source. + */ +#if !defined(STM32_USART3SW) || defined(__DOXYGEN__) +#define STM32_USART3SW STM32_USART3SW_PCLK +#endif + +/** + * @brief UART4 clock source. + */ +#if !defined(STM32_UART4SW) || defined(__DOXYGEN__) +#define STM32_UART4SW STM32_UART4SW_PCLK +#endif + +/** + * @brief UART5 clock source. + */ +#if !defined(STM32_UART5SW) || defined(__DOXYGEN__) +#define STM32_UART5SW STM32_UART5SW_PCLK +#endif + +/** + * @brief I2C1 clock source. + */ +#if !defined(STM32_I2C1SW) || defined(__DOXYGEN__) +#define STM32_I2C1SW STM32_I2C1SW_SYSCLK +#endif + +/** + * @brief I2C2 clock source. + */ +#if !defined(STM32_I2C2SW) || defined(__DOXYGEN__) +#define STM32_I2C2SW STM32_I2C2SW_SYSCLK +#endif + +/** + * @brief TIM1 clock source. + */ +#if !defined(STM32_TIM1SW) || defined(__DOXYGEN__) +#define STM32_TIM1SW STM32_TIM1SW_PCLK2 +#endif + +/** + * @brief TIM8 clock source. + */ +#if !defined(STM32_TIM8SW) || defined(__DOXYGEN__) +#define STM32_TIM8SW STM32_TIM8SW_PCLK2 +#endif + +/** + * @brief RTC clock source. + */ +#if !defined(STM32_RTCSEL) || defined(__DOXYGEN__) +#define STM32_RTCSEL STM32_RTCSEL_LSI +#endif + +/** + * @brief USB clock setting. + */ +#if !defined(STM32_USB_CLOCK_REQUIRED) || defined(__DOXYGEN__) +#define STM32_USB_CLOCK_REQUIRED TRUE +#endif + +/** + * @brief USB prescaler initialization. + */ +#if !defined(STM32_USBPRE) || defined(__DOXYGEN__) +#define STM32_USBPRE STM32_USBPRE_DIV1P5 +#endif +/** @} */ + +/*===========================================================================*/ +/* Derived constants and error checks. */ +/*===========================================================================*/ + +/* + * Configuration-related checks. + */ +#if !defined(STM32F30x_MCUCONF) +#error "Using a wrong mcuconf.h file, STM32F30x_MCUCONF not defined" +#endif + +/* + * HSI related checks. + */ +#if STM32_HSI_ENABLED +#else /* !STM32_HSI_ENABLED */ + +#if STM32_SW == STM32_SW_HSI +#error "HSI not enabled, required by STM32_SW" +#endif + +#if STM32_USART1SW == STM32_USART1SW_HSI +#error "HSI not enabled, required by STM32_USART1SW" +#endif + +#if STM32_USART2SW == STM32_USART2SW_HSI +#error "HSI not enabled, required by STM32_USART2SW" +#endif + +#if STM32_USART3SW == STM32_USART3SW_HSI +#error "HSI not enabled, required by STM32_USART3SW" +#endif + +#if STM32_UART4SW == STM32_UART4SW_HSI +#error "HSI not enabled, required by STM32_UART4SW" +#endif + +#if STM32_UART5SW == STM32_UART5SW_HSI +#error "HSI not enabled, required by STM32_UART5SW" +#endif + +#if STM32_I2C1SW == STM32_I2C1SW_HSI +#error "HSI not enabled, required by STM32_I2C1SW" +#endif + +#if STM32_I2C2SW == STM32_I2C2SW_HSI +#error "HSI not enabled, required by STM32_I2C2SW" +#endif + +#if STM32_TIM1SW == STM32_TIM1SW_HSI +#error "HSI not enabled, required by STM32_TIM1SW" +#endif + +#if STM32_TIM8SW == STM32_TIM8SW_HSI +#error "HSI not enabled, required by STM32_TIM8SW" +#endif + +#if (STM32_SW == STM32_SW_PLL) && (STM32_PLLSRC == STM32_PLLSRC_HSI) +#error "HSI not enabled, required by STM32_SW and STM32_PLLSRC" +#endif + +#if (STM32_MCOSEL == STM32_MCOSEL_HSI) || \ + ((STM32_MCOSEL == STM32_MCOSEL_PLLDIV2) && \ + (STM32_PLLSRC == STM32_PLLSRC_HSI)) +#error "HSI not enabled, required by STM32_MCOSEL" +#endif + +#endif /* !STM32_HSI_ENABLED */ + +/* + * HSE related checks. + */ +#if STM32_HSE_ENABLED + +#if STM32_HSECLK == 0 +#error "HSE frequency not defined" +#elif (STM32_HSECLK < STM32_HSECLK_MIN) || (STM32_HSECLK > STM32_HSECLK_MAX) +#error "STM32_HSECLK outside acceptable range (STM32_HSECLK_MIN...STM32_HSECLK_MAX)" +#endif + +#else /* !STM32_HSE_ENABLED */ + +#if STM32_SW == STM32_SW_HSE +#error "HSE not enabled, required by STM32_SW" +#endif + +#if (STM32_SW == STM32_SW_PLL) && (STM32_PLLSRC == STM32_PLLSRC_HSE) +#error "HSE not enabled, required by STM32_SW and STM32_PLLSRC" +#endif + +#if (STM32_MCOSEL == STM32_MCOSEL_HSE) || \ + ((STM32_MCOSEL == STM32_MCOSEL_PLLDIV2) && \ + (STM32_PLLSRC == STM32_PLLSRC_HSE)) +#error "HSE not enabled, required by STM32_MCOSEL" +#endif + +#if STM32_RTCSEL == STM32_RTCSEL_HSEDIV +#error "HSE not enabled, required by STM32_RTCSEL" +#endif + +#endif /* !STM32_HSE_ENABLED */ + +/* + * LSI related checks. + */ +#if STM32_LSI_ENABLED +#else /* !STM32_LSI_ENABLED */ + +#if STM32_RTCSEL == STM32_RTCSEL_LSI +#error "LSI not enabled, required by STM32_RTCSEL" +#endif + +#endif /* !STM32_LSI_ENABLED */ + +/* + * LSE related checks. + */ +#if STM32_LSE_ENABLED + +#if !defined(STM32_LSECLK) || (STM32_LSECLK == 0) +#error "STM32_LSECLK not defined" +#endif + +#if (STM32_LSECLK < STM32_LSECLK_MIN) || (STM32_LSECLK > STM32_LSECLK_MAX) +#error "STM32_LSECLK outside acceptable range (STM32_LSECLK_MIN...STM32_LSECLK_MAX)" +#endif + +#if !defined(STM32_LSEDRV) +#error "STM32_LSEDRV not defined" +#endif + +#if (STM32_LSEDRV >> 3) > 3 +#error "STM32_LSEDRV outside acceptable range ((0<<3)...(3<<3))" +#endif + +#if STM32_USART1SW == STM32_USART1SW_LSE +#error "LSE not enabled, required by STM32_USART1SW" +#endif + +#if STM32_USART2SW == STM32_USART2SW_LSE +#error "LSE not enabled, required by STM32_USART2SW" +#endif + +#if STM32_USART3SW == STM32_USART3SW_LSE +#error "LSE not enabled, required by STM32_USART3SW" +#endif + +#if STM32_UART4SW == STM32_UART4SW_LSE +#error "LSE not enabled, required by STM32_UART4SW" +#endif + +#if STM32_UART5SW == STM32_UART5SW_LSE +#error "LSE not enabled, required by STM32_UART5SW" +#endif + +#else /* !STM32_LSE_ENABLED */ + +#if STM32_RTCSEL == STM32_RTCSEL_LSE +#error "LSE not enabled, required by STM32_RTCSEL" +#endif + +#endif /* !STM32_LSE_ENABLED */ + +/* PLL activation conditions.*/ +#if (STM32_SW == STM32_SW_PLL) || \ + (STM32_MCOSEL == STM32_MCOSEL_PLLDIV2) || \ + (STM32_TIM1SW == STM32_TIM1SW_PLLX2) || \ + (STM32_TIM8SW == STM32_TIM8SW_PLLX2) || \ + (STM32_ADC12PRES != STM32_ADC12PRES_NOCLOCK) || \ + (STM32_ADC34PRES != STM32_ADC34PRES_NOCLOCK) || \ + STM32_USB_CLOCK_REQUIRED || \ + defined(__DOXYGEN__) +/** + * @brief PLL activation flag. + */ +#define STM32_ACTIVATE_PLL TRUE +#else +#define STM32_ACTIVATE_PLL FALSE +#endif + +/* HSE prescaler setting check.*/ +#if ((STM32_PREDIV_VALUE >= 1) || (STM32_PREDIV_VALUE <= 16)) +#define STM32_PREDIV ((STM32_PREDIV_VALUE - 1) << 0) +#else +#error "invalid STM32_PREDIV value specified" +#endif + +/** + * @brief PLLMUL field. + */ +#if ((STM32_PLLMUL_VALUE >= 2) && (STM32_PLLMUL_VALUE <= 16)) || \ + defined(__DOXYGEN__) +#define STM32_PLLMUL ((STM32_PLLMUL_VALUE - 2) << 18) +#else +#error "invalid STM32_PLLMUL_VALUE value specified" +#endif + +/** + * @brief PLL input clock frequency. + */ +#if (STM32_PLLSRC == STM32_PLLSRC_HSE) || defined(__DOXYGEN__) +#define STM32_PLLCLKIN (STM32_HSECLK / STM32_PREDIV_VALUE) +#elif STM32_PLLSRC == STM32_PLLSRC_HSI +#define STM32_PLLCLKIN (STM32_HSICLK / 2) +#else +#error "invalid STM32_PLLSRC value specified" +#endif + +/* PLL input frequency range check.*/ +#if (STM32_PLLCLKIN < STM32_PLLIN_MIN) || (STM32_PLLCLKIN > STM32_PLLIN_MAX) +#error "STM32_PLLCLKIN outside acceptable range (STM32_PLLIN_MIN...STM32_PLLIN_MAX)" +#endif + +/** + * @brief PLL output clock frequency. + */ +#define STM32_PLLCLKOUT (STM32_PLLCLKIN * STM32_PLLMUL_VALUE) + +/* PLL output frequency range check.*/ +#if (STM32_PLLCLKOUT < STM32_PLLOUT_MIN) || (STM32_PLLCLKOUT > STM32_PLLOUT_MAX) +#error "STM32_PLLCLKOUT outside acceptable range (STM32_PLLOUT_MIN...STM32_PLLOUT_MAX)" +#endif + +/** + * @brief System clock source. + */ +#if (STM32_SW == STM32_SW_PLL) || defined(__DOXYGEN__) +#define STM32_SYSCLK STM32_PLLCLKOUT +#elif (STM32_SW == STM32_SW_HSI) +#define STM32_SYSCLK STM32_HSICLK +#elif (STM32_SW == STM32_SW_HSE) +#define STM32_SYSCLK STM32_HSECLK +#else +#error "invalid STM32_SW value specified" +#endif + +/* Check on the system clock.*/ +#if STM32_SYSCLK > STM32_SYSCLK_MAX +#error "STM32_SYSCLK above maximum rated frequency (STM32_SYSCLK_MAX)" +#endif + +/** + * @brief AHB frequency. + */ +#if (STM32_HPRE == STM32_HPRE_DIV1) || defined(__DOXYGEN__) +#define STM32_HCLK (STM32_SYSCLK / 1) +#elif STM32_HPRE == STM32_HPRE_DIV2 +#define STM32_HCLK (STM32_SYSCLK / 2) +#elif STM32_HPRE == STM32_HPRE_DIV4 +#define STM32_HCLK (STM32_SYSCLK / 4) +#elif STM32_HPRE == STM32_HPRE_DIV8 +#define STM32_HCLK (STM32_SYSCLK / 8) +#elif STM32_HPRE == STM32_HPRE_DIV16 +#define STM32_HCLK (STM32_SYSCLK / 16) +#elif STM32_HPRE == STM32_HPRE_DIV64 +#define STM32_HCLK (STM32_SYSCLK / 64) +#elif STM32_HPRE == STM32_HPRE_DIV128 +#define STM32_HCLK (STM32_SYSCLK / 128) +#elif STM32_HPRE == STM32_HPRE_DIV256 +#define STM32_HCLK (STM32_SYSCLK / 256) +#elif STM32_HPRE == STM32_HPRE_DIV512 +#define STM32_HCLK (STM32_SYSCLK / 512) +#else +#error "invalid STM32_HPRE value specified" +#endif + +/* AHB frequency check.*/ +#if STM32_HCLK > STM32_SYSCLK_MAX +#error "STM32_HCLK exceeding maximum frequency (STM32_SYSCLK_MAX)" +#endif + +/** + * @brief APB1 frequency. + */ +#if (STM32_PPRE1 == STM32_PPRE1_DIV1) || defined(__DOXYGEN__) +#define STM32_PCLK1 (STM32_HCLK / 1) +#elif STM32_PPRE1 == STM32_PPRE1_DIV2 +#define STM32_PCLK1 (STM32_HCLK / 2) +#elif STM32_PPRE1 == STM32_PPRE1_DIV4 +#define STM32_PCLK1 (STM32_HCLK / 4) +#elif STM32_PPRE1 == STM32_PPRE1_DIV8 +#define STM32_PCLK1 (STM32_HCLK / 8) +#elif STM32_PPRE1 == STM32_PPRE1_DIV16 +#define STM32_PCLK1 (STM32_HCLK / 16) +#else +#error "invalid STM32_PPRE1 value specified" +#endif + +/* APB1 frequency check.*/ +#if STM32_PCLK1 > STM32_PCLK1_MAX +#error "STM32_PCLK1 exceeding maximum frequency (STM32_PCLK1_MAX)" +#endif + +/** + * @brief APB2 frequency. + */ +#if (STM32_PPRE2 == STM32_PPRE2_DIV1) || defined(__DOXYGEN__) +#define STM32_PCLK2 (STM32_HCLK / 1) +#elif STM32_PPRE2 == STM32_PPRE2_DIV2 +#define STM32_PCLK2 (STM32_HCLK / 2) +#elif STM32_PPRE2 == STM32_PPRE2_DIV4 +#define STM32_PCLK2 (STM32_HCLK / 4) +#elif STM32_PPRE2 == STM32_PPRE2_DIV8 +#define STM32_PCLK2 (STM32_HCLK / 8) +#elif STM32_PPRE2 == STM32_PPRE2_DIV16 +#define STM32_PCLK2 (STM32_HCLK / 16) +#else +#error "invalid STM32_PPRE2 value specified" +#endif + +/* APB2 frequency check.*/ +#if STM32_PCLK2 > STM32_PCLK2_MAX +#error "STM32_PCLK2 exceeding maximum frequency (STM32_PCLK2_MAX)" +#endif + +/** + * @brief RTC clock. + */ +#if (STM32_RTCSEL == STM32_RTCSEL_LSE) || defined(__DOXYGEN__) +#define STM32_RTCCLK STM32_LSECLK +#elif STM32_RTCSEL == STM32_RTCSEL_LSI +#define STM32_RTCCLK STM32_LSICLK +#elif STM32_RTCSEL == STM32_RTCSEL_HSEDIV +#define STM32_RTCCLK (STM32_HSECLK / 32) +#elif STM32_RTCSEL == STM32_RTCSEL_NOCLOCK +#define STM32_RTCCLK 0 +#else +#error "invalid source selected for RTC clock" +#endif + +/** + * @brief ADC12 frequency. + */ +#if (STM32_ADC12PRES == STM32_ADC12PRES_NOCLOCK) || defined(__DOXYGEN__) +#define STM32_ADC12CLK 0 +#elif STM32_ADC12PRES == STM32_ADC12PRES_DIV1 +#define STM32_ADC12CLK (STM32_PLLCLKOUT / 1) +#elif STM32_ADC12PRES == STM32_ADC12PRES_DIV2 +#define STM32_ADC12CLK (STM32_PLLCLKOUT / 2) +#elif STM32_ADC12PRES == STM32_ADC12PRES_DIV4 +#define STM32_ADC12CLK (STM32_PLLCLKOUT / 4) +#elif STM32_ADC12PRES == STM32_ADC12PRES_DIV6 +#define STM32_ADC12CLK (STM32_PLLCLKOUT / 6) +#elif STM32_ADC12PRES == STM32_ADC12PRES_DIV8 +#define STM32_ADC12CLK (STM32_PLLCLKOUT / 8) +#elif STM32_ADC12PRES == STM32_ADC12PRES_DIV10 +#define STM32_ADC12CLK (STM32_PLLCLKOUT / 10) +#elif STM32_ADC12PRES == STM32_ADC12PRES_DIV12 +#define STM32_ADC12CLK (STM32_PLLCLKOUT / 12) +#elif STM32_ADC12PRES == STM32_ADC12PRES_DIV16 +#define STM32_ADC12CLK (STM32_PLLCLKOUT / 16) +#elif STM32_ADC12PRES == STM32_ADC12PRES_DIV32 +#define STM32_ADC12CLK (STM32_PLLCLKOUT / 32) +#elif STM32_ADC12PRES == STM32_ADC12PRES_DIV64 +#define STM32_ADC12CLK (STM32_PLLCLKOUT / 64) +#elif STM32_ADC12PRES == STM32_ADC12PRES_DIV128 +#define STM32_ADC12CLK (STM32_PLLCLKOUT / 128) +#elif STM32_ADC12PRES == STM32_ADC12PRES_DIV256 +#define STM32_ADC12CLK (STM32_PLLCLKOUT / 256) +#else +#error "invalid STM32_ADC12PRES value specified" +#endif + +/** + * @brief ADC34 frequency. + */ +#if (STM32_ADC43PRES == STM32_ADC34PRES_NOCLOCK) || defined(__DOXYGEN__) +#define STM32_ADC34CLK 0 +#elif STM32_ADC34PRES == STM32_ADC34PRES_DIV1 +#define STM32_ADC34CLK (STM32_PLLCLKOUT / 1) +#elif STM32_ADC34PRES == STM32_ADC34PRES_DIV2 +#define STM32_ADC34CLK (STM32_PLLCLKOUT / 2) +#elif STM32_ADC34PRES == STM32_ADC34PRES_DIV4 +#define STM32_ADC34CLK (STM32_PLLCLKOUT / 4) +#elif STM32_ADC34PRES == STM32_ADC34PRES_DIV6 +#define STM32_ADC34CLK (STM32_PLLCLKOUT / 6) +#elif STM32_ADC34PRES == STM32_ADC34PRES_DIV8 +#define STM32_ADC34CLK (STM32_PLLCLKOUT / 8) +#elif STM32_ADC34PRES == STM32_ADC34PRES_DIV10 +#define STM32_ADC34CLK (STM32_PLLCLKOUT / 10) +#elif STM32_ADC34PRES == STM32_ADC34PRES_DIV12 +#define STM32_ADC34CLK (STM32_PLLCLKOUT / 12) +#elif STM32_ADC34PRES == STM32_ADC34PRES_DIV16 +#define STM32_ADC34CLK (STM32_PLLCLKOUT / 16) +#elif STM32_ADC34PRES == STM32_ADC34PRES_DIV32 +#define STM32_ADC34CLK (STM32_PLLCLKOUT / 32) +#elif STM32_ADC34PRES == STM32_ADC34PRES_DIV64 +#define STM32_ADC34CLK (STM32_PLLCLKOUT / 64) +#elif STM32_ADC34PRES == STM32_ADC34PRES_DIV128 +#define STM32_ADC34CLK (STM32_PLLCLKOUT / 128) +#elif STM32_ADC34PRES == STM32_ADC34PRES_DIV256 +#define STM32_ADC34CLK (STM32_PLLCLKOUT / 256) +#else +#error "invalid STM32_ADC34PRES value specified" +#endif + +/* ADC12 frequency check.*/ +#if STM32_ADC12CLK > STM32_ADCCLK_MAX +#error "STM32_ADC12CLK exceeding maximum frequency (STM32_ADCCLK_MAX)" +#endif + +/* ADC34 frequency check.*/ +#if STM32_ADC34CLK > STM32_ADCCLK_MAX +#error "STM32_ADC34CLK exceeding maximum frequency (STM32_ADCCLK_MAX)" +#endif + +/** + * @brief I2C1 frequency. + */ +#if STM32_I2C1SW == STM32_I2C1SW_HSI +#define STM32_I2C1CLK STM32_HSICLK +#elif STM32_I2C1SW == STM32_I2C1SW_SYSCLK +#define STM32_I2C1CLK STM32_SYSCLK +#else +#error "invalid source selected for I2C1 clock" +#endif + +/** + * @brief I2C2 frequency. + */ +#if STM32_I2C2SW == STM32_I2C2SW_HSI +#define STM32_I2C2CLK STM32_HSICLK +#elif STM32_I2C2SW == STM32_I2C2SW_SYSCLK +#define STM32_I2C2CLK STM32_SYSCLK +#else +#error "invalid source selected for I2C2 clock" +#endif + +/** + * @brief USART1 frequency. + */ +#if STM32_USART1SW == STM32_USART1SW_PCLK +#define STM32_USART1CLK STM32_PCLK2 +#elif STM32_USART1SW == STM32_USART1SW_SYSCLK +#define STM32_USART1CLK STM32_SYSCLK +#elif STM32_USART1SW == STM32_USART1SW_LSECLK +#define STM32_USART1CLK STM32_LSECLK +#elif STM32_USART1SW == STM32_USART1SW_HSICLK +#define STM32_USART1CLK STM32_HSICLK +#else +#error "invalid source selected for USART1 clock" +#endif + +/** + * @brief USART2 frequency. + */ +#if STM32_USART2SW == STM32_USART2SW_PCLK +#define STM32_USART2CLK STM32_PCLK1 +#elif STM32_USART2SW == STM32_USART2SW_SYSCLK +#define STM32_USART2CLK STM32_SYSCLK +#elif STM32_USART2SW == STM32_USART2SW_LSECLK +#define STM32_USART2CLK STM32_LSECLK +#elif STM32_USART2SW == STM32_USART2SW_HSICLK +#define STM32_USART2CLK STM32_HSICLK +#else +#error "invalid source selected for USART2 clock" +#endif + +/** + * @brief USART3 frequency. + */ +#if STM32_USART3SW == STM32_USART3SW_PCLK +#define STM32_USART3CLK STM32_PCLK1 +#elif STM32_USART3SW == STM32_USART3SW_SYSCLK +#define STM32_USART3CLK STM32_SYSCLK +#elif STM32_USART3SW == STM32_USART3SW_LSECLK +#define STM32_USART3CLK STM32_LSECLK +#elif STM32_USART3SW == STM32_USART3SW_HSICLK +#define STM32_USART3CLK STM32_HSICLK +#else +#error "invalid source selected for USART3 clock" +#endif + +/** + * @brief UART4 frequency. + */ +#if STM32_UART4SW == STM32_UART4SW_PCLK +#define STM32_UART4CLK STM32_PCLK1 +#elif STM32_UART4SW == STM32_UART4SW_SYSCLK +#define STM32_UART4CLK STM32_SYSCLK +#elif STM32_UART4SW == STM32_UART4SW_LSECLK +#define STM32_UART4CLK STM32_LSECLK +#elif STM32_UART4SW == STM32_UART4SW_HSICLK +#define STM32_UART4CLK STM32_HSICLK +#else +#error "invalid source selected for UART4 clock" +#endif + +/** + * @brief UART5 frequency. + */ +#if STM32_UART5SW == STM32_UART5SW_PCLK +#define STM32_UART5CLK STM32_PCLK1 +#elif STM32_UART5SW == STM32_UART5SW_SYSCLK +#define STM32_UART5CLK STM32_SYSCLK +#elif STM32_UART5SW == STM32_UART5SW_LSECLK +#define STM32_UART5CLK STM32_LSECLK +#elif STM32_UART5SW == STM32_UART5SW_HSICLK +#define STM32_UART5CLK STM32_HSICLK +#else +#error "invalid source selected for UART5 clock" +#endif + +/** + * @brief TIM1 frequency. + */ +#if STM32_TIM1SW == STM32_TIM1SW_PCLK2 +#define STM32_TIM1CLK STM32_PCLK2 +#elif STM32_TIM1SW == STM32_TIM1SW_PLLX2 +#define STM32_TIM1CLK (STM32_PLLCLKOUT * 2) +#else +#error "invalid source selected for TIM1 clock" +#endif + +/** + * @brief TIM8 frequency. + */ +#if STM32_TIM8SW == STM32_TIM8SW_PCLK2 +#define STM32_TIM8CLK STM32_PCLK2 +#elif STM32_TIM8SW == STM32_TIM8SW_PLLX2 +#define STM32_TIM8CLK (STM32_PLLCLKOUT * 2) +#else +#error "invalid source selected for TIM8 clock" +#endif + +/** + * @brief Timers 2, 3, 4, 6, 7 frequency. + */ +#if (STM32_PPRE1 == STM32_PPRE1_DIV1) || defined(__DOXYGEN__) +#define STM32_TIMCLK1 (STM32_PCLK1 * 1) +#else +#define STM32_TIMCLK1 (STM32_PCLK1 * 2) +#endif + +/** + * @brief Timers 1, 8, 15, 16, 17 frequency. + */ +#if (STM32_PPRE2 == STM32_PPRE2_DIV1) || defined(__DOXYGEN__) +#define STM32_TIMCLK2 (STM32_PCLK2 * 1) +#else +#define STM32_TIMCLK2 (STM32_PCLK2 * 2) +#endif + +/** + * @brief USB frequency. + */ +#if (STM32_USBPRE == STM32_USBPRE_DIV1P5) || defined(__DOXYGEN__) +#define STM32_USBCLK ((STM32_PLLCLKOUT * 2) / 3) +#elif (STM32_USBPRE == STM32_USBPRE_DIV1) +#define STM32_USBCLK STM32_PLLCLKOUT +#else +#error "invalid STM32_USBPRE value specified" +#endif + +/** + * @brief Flash settings. + */ +#if (STM32_HCLK <= 24000000) || defined(__DOXYGEN__) +#define STM32_FLASHBITS 0x00000010 +#elif STM32_HCLK <= 48000000 +#define STM32_FLASHBITS 0x00000011 +#else +#define STM32_FLASHBITS 0x00000012 +#endif + +/*===========================================================================*/ +/* Driver data structures and types. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver macros. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +/* Various helpers.*/ +#include "nvic.h" +#include "stm32_isr.h" +#include "stm32_dma.h" +#include "stm32_rcc.h" + +#ifdef __cplusplus +extern "C" { +#endif + void hal_lld_init(void); + void stm32_clock_init(void); +#ifdef __cplusplus +} +#endif + +#endif /* _HAL_LLD_H_ */ + +/** @} */ diff --git a/os/hal/ports/STM32F30x/platform.mk b/os/hal/ports/STM32F30x/platform.mk new file mode 100644 index 000000000..09d7f1872 --- /dev/null +++ b/os/hal/ports/STM32F30x/platform.mk @@ -0,0 +1,31 @@ +# List of all the STM32F30x platform files. +PLATFORMSRC = ${CHIBIOS}/os/hal/platforms/common/ARMCMx/nvic.c \ + ${CHIBIOS}/os/hal/platforms/STM32F30x/stm32_dma.c \ + ${CHIBIOS}/os/hal/platforms/STM32F30x/hal_lld.c \ + ${CHIBIOS}/os/hal/platforms/STM32F30x/adc_lld.c \ + ${CHIBIOS}/os/hal/platforms/STM32F30x/ext_lld_isr.c \ + ${CHIBIOS}/os/hal/platforms/STM32/can_lld.c \ + ${CHIBIOS}/os/hal/platforms/STM32/ext_lld.c \ + ${CHIBIOS}/os/hal/platforms/STM32/GPIOv2/pal_lld.c \ + ${CHIBIOS}/os/hal/platforms/STM32/I2Cv2/i2c_lld.c \ + ${CHIBIOS}/os/hal/platforms/STM32/RTCv2/rtc_lld.c \ + ${CHIBIOS}/os/hal/platforms/STM32/SPIv2/spi_lld.c \ + ${CHIBIOS}/os/hal/platforms/STM32/TIMv1/gpt_lld.c \ + ${CHIBIOS}/os/hal/platforms/STM32/TIMv1/icu_lld.c \ + ${CHIBIOS}/os/hal/platforms/STM32/TIMv1/pwm_lld.c \ + ${CHIBIOS}/os/hal/platforms/STM32/TIMv1/st_lld.c \ + ${CHIBIOS}/os/hal/platforms/STM32/USARTv2/serial_lld.c \ + ${CHIBIOS}/os/hal/platforms/STM32/USARTv2/uart_lld.c \ + ${CHIBIOS}/os/hal/platforms/STM32/USBv1/usb_lld.c + +# Required include directories +PLATFORMINC = ${CHIBIOS}/os/hal/platforms/common/ARMCMx \ + ${CHIBIOS}/os/hal/platforms/STM32F30x \ + ${CHIBIOS}/os/hal/platforms/STM32 \ + ${CHIBIOS}/os/hal/platforms/STM32/GPIOv2 \ + ${CHIBIOS}/os/hal/platforms/STM32/I2Cv2 \ + ${CHIBIOS}/os/hal/platforms/STM32/RTCv2 \ + ${CHIBIOS}/os/hal/platforms/STM32/SPIv2 \ + ${CHIBIOS}/os/hal/platforms/STM32/TIMv1 \ + ${CHIBIOS}/os/hal/platforms/STM32/USARTv2 \ + ${CHIBIOS}/os/hal/platforms/STM32/USBv1 diff --git a/os/hal/ports/STM32F30x/stm32_dma.c b/os/hal/ports/STM32F30x/stm32_dma.c new file mode 100644 index 000000000..eb73f1b37 --- /dev/null +++ b/os/hal/ports/STM32F30x/stm32_dma.c @@ -0,0 +1,449 @@ +/* + ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file STM32F30x/stm32_dma.c + * @brief DMA helper driver code. + * + * @addtogroup STM32F30x_DMA + * @details DMA sharing helper driver. In the STM32 the DMA streams are a + * shared resource, this driver allows to allocate and free DMA + * streams at runtime in order to allow all the other device + * drivers to coordinate the access to the resource. + * @note The DMA ISR handlers are all declared into this module because + * sharing, the various device drivers can associate a callback to + * ISRs when allocating streams. + * @{ + */ + +#include "hal.h" + +/* The following macro is only defined if some driver requiring DMA services + has been enabled.*/ +#if defined(STM32_DMA_REQUIRED) || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver local definitions. */ +/*===========================================================================*/ + +/** + * @brief Mask of the DMA1 streams in @p dma_streams_mask. + */ +#define STM32_DMA1_STREAMS_MASK 0x0000007F + +/** + * @brief Mask of the DMA2 streams in @p dma_streams_mask. + */ +#define STM32_DMA2_STREAMS_MASK 0x00000F80 + +/** + * @brief Post-reset value of the stream CCR register. + */ +#define STM32_DMA_CCR_RESET_VALUE 0x00000000 + +/*===========================================================================*/ +/* Driver exported variables. */ +/*===========================================================================*/ + +/** + * @brief DMA streams descriptors. + * @details This table keeps the association between an unique stream + * identifier and the involved physical registers. + * @note Don't use this array directly, use the appropriate wrapper macros + * instead: @p STM32_DMA1_STREAM1, @p STM32_DMA1_STREAM2 etc. + */ +const stm32_dma_stream_t _stm32_dma_streams[STM32_DMA_STREAMS] = { + {DMA1_Channel1, &DMA1->IFCR, 0, 0, DMA1_Channel1_IRQn}, + {DMA1_Channel2, &DMA1->IFCR, 4, 1, DMA1_Channel2_IRQn}, + {DMA1_Channel3, &DMA1->IFCR, 8, 2, DMA1_Channel3_IRQn}, + {DMA1_Channel4, &DMA1->IFCR, 12, 3, DMA1_Channel4_IRQn}, + {DMA1_Channel5, &DMA1->IFCR, 16, 4, DMA1_Channel5_IRQn}, + {DMA1_Channel6, &DMA1->IFCR, 20, 5, DMA1_Channel6_IRQn}, + {DMA1_Channel7, &DMA1->IFCR, 24, 6, DMA1_Channel7_IRQn}, + {DMA2_Channel1, &DMA2->IFCR, 0, 7, DMA2_Channel1_IRQn}, + {DMA2_Channel2, &DMA2->IFCR, 4, 8, DMA2_Channel2_IRQn}, + {DMA2_Channel3, &DMA2->IFCR, 8, 9, DMA2_Channel3_IRQn}, + {DMA2_Channel4, &DMA2->IFCR, 12, 10, DMA2_Channel4_IRQn}, + {DMA2_Channel5, &DMA2->IFCR, 16, 11, DMA2_Channel5_IRQn}, +}; + +/*===========================================================================*/ +/* Driver local variables and types. */ +/*===========================================================================*/ + +/** + * @brief DMA ISR redirector type. + */ +typedef struct { + stm32_dmaisr_t dma_func; /**< @brief DMA callback function. */ + void *dma_param; /**< @brief DMA callback parameter. */ +} dma_isr_redir_t; + +/** + * @brief Mask of the allocated streams. + */ +static uint32_t dma_streams_mask; + +/** + * @brief DMA IRQ redirectors. + */ +static dma_isr_redir_t dma_isr_redir[STM32_DMA_STREAMS]; + +/*===========================================================================*/ +/* Driver local functions. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver interrupt handlers. */ +/*===========================================================================*/ + +/** + * @brief DMA1 stream 1 shared interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(Vector6C) { + uint32_t flags; + + OSAL_IRQ_PROLOGUE(); + + flags = (DMA1->ISR >> 0) & STM32_DMA_ISR_MASK; + DMA1->IFCR = STM32_DMA_ISR_MASK << 0; + if (dma_isr_redir[0].dma_func) + dma_isr_redir[0].dma_func(dma_isr_redir[0].dma_param, flags); + + OSAL_IRQ_EPILOGUE(); +} + +/** + * @brief DMA1 stream 2 shared interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(Vector70) { + uint32_t flags; + + OSAL_IRQ_PROLOGUE(); + + flags = (DMA1->ISR >> 4) & STM32_DMA_ISR_MASK; + DMA1->IFCR = STM32_DMA_ISR_MASK << 4; + if (dma_isr_redir[1].dma_func) + dma_isr_redir[1].dma_func(dma_isr_redir[1].dma_param, flags); + + OSAL_IRQ_EPILOGUE(); +} + +/** + * @brief DMA1 stream 3 shared interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(Vector74) { + uint32_t flags; + + OSAL_IRQ_PROLOGUE(); + + flags = (DMA1->ISR >> 8) & STM32_DMA_ISR_MASK; + DMA1->IFCR = STM32_DMA_ISR_MASK << 8; + if (dma_isr_redir[2].dma_func) + dma_isr_redir[2].dma_func(dma_isr_redir[2].dma_param, flags); + + OSAL_IRQ_EPILOGUE(); +} + +/** + * @brief DMA1 stream 4 shared interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(Vector78) { + uint32_t flags; + + OSAL_IRQ_PROLOGUE(); + + flags = (DMA1->ISR >> 12) & STM32_DMA_ISR_MASK; + DMA1->IFCR = STM32_DMA_ISR_MASK << 12; + if (dma_isr_redir[3].dma_func) + dma_isr_redir[3].dma_func(dma_isr_redir[3].dma_param, flags); + + OSAL_IRQ_EPILOGUE(); +} + +/** + * @brief DMA1 stream 5 shared interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(Vector7C) { + uint32_t flags; + + OSAL_IRQ_PROLOGUE(); + + flags = (DMA1->ISR >> 16) & STM32_DMA_ISR_MASK; + DMA1->IFCR = STM32_DMA_ISR_MASK << 16; + if (dma_isr_redir[4].dma_func) + dma_isr_redir[4].dma_func(dma_isr_redir[4].dma_param, flags); + + OSAL_IRQ_EPILOGUE(); +} + +/** + * @brief DMA1 stream 6 shared interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(Vector80) { + uint32_t flags; + + OSAL_IRQ_PROLOGUE(); + + flags = (DMA1->ISR >> 20) & STM32_DMA_ISR_MASK; + DMA1->IFCR = STM32_DMA_ISR_MASK << 20; + if (dma_isr_redir[5].dma_func) + dma_isr_redir[5].dma_func(dma_isr_redir[5].dma_param, flags); + + OSAL_IRQ_EPILOGUE(); +} + +/** + * @brief DMA1 stream 7 shared interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(Vector84) { + uint32_t flags; + + OSAL_IRQ_PROLOGUE(); + + flags = (DMA1->ISR >> 24) & STM32_DMA_ISR_MASK; + DMA1->IFCR = STM32_DMA_ISR_MASK << 24; + if (dma_isr_redir[6].dma_func) + dma_isr_redir[6].dma_func(dma_isr_redir[6].dma_param, flags); + + OSAL_IRQ_EPILOGUE(); +} + +/** + * @brief DMA2 stream 1 shared interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(Vector120) { + uint32_t flags; + + OSAL_IRQ_PROLOGUE(); + + flags = (DMA2->ISR >> 0) & STM32_DMA_ISR_MASK; + DMA2->IFCR = STM32_DMA_ISR_MASK << 0; + if (dma_isr_redir[7].dma_func) + dma_isr_redir[7].dma_func(dma_isr_redir[7].dma_param, flags); + + OSAL_IRQ_EPILOGUE(); +} + +/** + * @brief DMA2 stream 2 shared interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(Vector124) { + uint32_t flags; + + OSAL_IRQ_PROLOGUE(); + + flags = (DMA2->ISR >> 4) & STM32_DMA_ISR_MASK; + DMA2->IFCR = STM32_DMA_ISR_MASK << 4; + if (dma_isr_redir[8].dma_func) + dma_isr_redir[8].dma_func(dma_isr_redir[8].dma_param, flags); + + OSAL_IRQ_EPILOGUE(); +} + +/** + * @brief DMA2 stream 3 shared interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(Vector128) { + uint32_t flags; + + OSAL_IRQ_PROLOGUE(); + + flags = (DMA2->ISR >> 8) & STM32_DMA_ISR_MASK; + DMA2->IFCR = STM32_DMA_ISR_MASK << 8; + if (dma_isr_redir[9].dma_func) + dma_isr_redir[9].dma_func(dma_isr_redir[9].dma_param, flags); + + OSAL_IRQ_EPILOGUE(); +} + +/** + * @brief DMA2 stream 4 shared interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(Vector12C) { + uint32_t flags; + + OSAL_IRQ_PROLOGUE(); + + flags = (DMA2->ISR >> 12) & STM32_DMA_ISR_MASK; + DMA2->IFCR = STM32_DMA_ISR_MASK << 12; + if (dma_isr_redir[10].dma_func) + dma_isr_redir[10].dma_func(dma_isr_redir[10].dma_param, flags); + + OSAL_IRQ_EPILOGUE(); +} + +/** + * @brief DMA2 stream 5 shared interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(Vector130) { + uint32_t flags; + + OSAL_IRQ_PROLOGUE(); + + flags = (DMA2->ISR >> 16) & STM32_DMA_ISR_MASK; + DMA2->IFCR = STM32_DMA_ISR_MASK << 16; + if (dma_isr_redir[11].dma_func) + dma_isr_redir[11].dma_func(dma_isr_redir[11].dma_param, flags); + + OSAL_IRQ_EPILOGUE(); +} + +/*===========================================================================*/ +/* Driver exported functions. */ +/*===========================================================================*/ + +/** + * @brief STM32 DMA helper initialization. + * + * @init + */ +void dmaInit(void) { + int i; + + dma_streams_mask = 0; + for (i = 0; i < STM32_DMA_STREAMS; i++) { + _stm32_dma_streams[i].channel->CCR = 0; + dma_isr_redir[i].dma_func = NULL; + } + DMA1->IFCR = 0xFFFFFFFF; +#if STM32_HAS_DMA2 + DMA2->IFCR = 0xFFFFFFFF; +#endif +} + +/** + * @brief Allocates a DMA stream. + * @details The stream is allocated and, if required, the DMA clock enabled. + * The function also enables the IRQ vector associated to the stream + * and initializes its priority. + * @pre The stream must not be already in use or an error is returned. + * @post The stream is allocated and the default ISR handler redirected + * to the specified function. + * @post The stream ISR vector is enabled and its priority configured. + * @post The stream must be freed using @p dmaStreamRelease() before it can + * be reused with another peripheral. + * @post The stream is in its post-reset state. + * @note This function can be invoked in both ISR or thread context. + * + * @param[in] dmastp pointer to a stm32_dma_stream_t structure + * @param[in] priority IRQ priority mask for the DMA stream + * @param[in] func handling function pointer, can be @p NULL + * @param[in] param a parameter to be passed to the handling function + * @return The operation status. + * @retval FALSE no error, stream taken. + * @retval TRUE error, stream already taken. + * + * @special + */ +bool_t dmaStreamAllocate(const stm32_dma_stream_t *dmastp, + uint32_t priority, + stm32_dmaisr_t func, + void *param) { + + osalDbgCheck(dmastp != NULL); + + /* Checks if the stream is already taken.*/ + if ((dma_streams_mask & (1 << dmastp->selfindex)) != 0) + return TRUE; + + /* Marks the stream as allocated.*/ + dma_isr_redir[dmastp->selfindex].dma_func = func; + dma_isr_redir[dmastp->selfindex].dma_param = param; + dma_streams_mask |= (1 << dmastp->selfindex); + + /* Enabling DMA clocks required by the current streams set.*/ + if ((dma_streams_mask & STM32_DMA1_STREAMS_MASK) != 0) + rccEnableDMA1(FALSE); +#if STM32_HAS_DMA2 + if ((dma_streams_mask & STM32_DMA2_STREAMS_MASK) != 0) + rccEnableDMA2(FALSE); +#endif + + /* Putting the stream in a safe state.*/ + dmaStreamDisable(dmastp); + dmastp->channel->CCR = STM32_DMA_CCR_RESET_VALUE; + + /* Enables the associated IRQ vector if a callback is defined.*/ + if (func != NULL) + nvicEnableVector(dmastp->vector, priority); + + return FALSE; +} + +/** + * @brief Releases a DMA stream. + * @details The stream is freed and, if required, the DMA clock disabled. + * Trying to release a unallocated stream is an illegal operation + * and is trapped if assertions are enabled. + * @pre The stream must have been allocated using @p dmaStreamAllocate(). + * @post The stream is again available. + * @note This function can be invoked in both ISR or thread context. + * + * @param[in] dmastp pointer to a stm32_dma_stream_t structure + * + * @special + */ +void dmaStreamRelease(const stm32_dma_stream_t *dmastp) { + + osalDbgCheck(dmastp != NULL); + + /* Check if the streams is not taken.*/ + osalDbgAssert((dma_streams_mask & (1 << dmastp->selfindex)) != 0, + "not allocated"); + + /* Disables the associated IRQ vector.*/ + nvicDisableVector(dmastp->vector); + + /* Marks the stream as not allocated.*/ + dma_streams_mask &= ~(1 << dmastp->selfindex); + + /* Shutting down clocks that are no more required, if any.*/ + if ((dma_streams_mask & STM32_DMA1_STREAMS_MASK) == 0) + rccDisableDMA1(FALSE); +#if STM32_HAS_DMA2 + if ((dma_streams_mask & STM32_DMA2_STREAMS_MASK) == 0) + rccDisableDMA2(FALSE); +#endif +} + +#endif /* STM32_DMA_REQUIRED */ + +/** @} */ diff --git a/os/hal/ports/STM32F30x/stm32_dma.h b/os/hal/ports/STM32F30x/stm32_dma.h new file mode 100644 index 000000000..2415f00f2 --- /dev/null +++ b/os/hal/ports/STM32F30x/stm32_dma.h @@ -0,0 +1,406 @@ +/* + ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file STM32F30x/stm32_dma.h + * @brief DMA helper driver header. + * @note This file requires definitions from the ST header file stm32f30x.h. + * @note This driver uses the new naming convention used for the STM32F2xx + * so the "DMA channels" are referred as "DMA streams". + * + * @addtogroup STM32F30x_DMA + * @{ + */ + +#ifndef _STM32_DMA_H_ +#define _STM32_DMA_H_ + +/*===========================================================================*/ +/* Driver constants. */ +/*===========================================================================*/ + +/** + * @brief Total number of DMA streams. + * @note This is the total number of streams among all the DMA units. + */ +#if STM32_HAS_DMA2 || defined(__DOXYGEN__) +#define STM32_DMA_STREAMS 12 +#else +#define STM32_DMA_STREAMS 7 +#endif + +/** + * @brief Mask of the ISR bits passed to the DMA callback functions. + */ +#define STM32_DMA_ISR_MASK 0x0F + +/** + * @brief Returns the channel associated to the specified stream. + * + * @param[in] n the stream number (0...STM32_DMA_STREAMS-1) + * @param[in] c a stream/channel association word, one channel per + * nibble, not associated channels must be set to 0xF + * @return Always zero, in this platform there is no dynamic + * association between streams and channels. + */ +#define STM32_DMA_GETCHANNEL(n, c) 0 + +/** + * @brief Checks if a DMA priority is within the valid range. + * @param[in] prio DMA priority + * + * @retval The check result. + * @retval FALSE invalid DMA priority. + * @retval TRUE correct DMA priority. + */ +#define STM32_DMA_IS_VALID_PRIORITY(prio) (((prio) >= 0) && ((prio) <= 3)) + +/** + * @brief Returns an unique numeric identifier for a DMA stream. + * + * @param[in] dma the DMA unit number + * @param[in] stream the stream number + * @return An unique numeric stream identifier. + */ +#define STM32_DMA_STREAM_ID(dma, stream) ((((dma) - 1) * 7) + ((stream) - 1)) + +/** + * @brief Returns a DMA stream identifier mask. + * + * + * @param[in] dma the DMA unit number + * @param[in] stream the stream number + * @return A DMA stream identifier mask. + */ +#define STM32_DMA_STREAM_ID_MSK(dma, stream) \ + (1 << STM32_DMA_STREAM_ID(dma, stream)) + +/** + * @brief Checks if a DMA stream unique identifier belongs to a mask. + * @param[in] id the stream numeric identifier + * @param[in] mask the stream numeric identifiers mask + * + * @retval The check result. + * @retval FALSE id does not belong to the mask. + * @retval TRUE id belongs to the mask. + */ +#define STM32_DMA_IS_VALID_ID(id, mask) (((1 << (id)) & (mask))) + +/** + * @name DMA streams identifiers + * @{ + */ +/** + * @brief Returns a pointer to a stm32_dma_stream_t structure. + * + * @param[in] id the stream numeric identifier + * @return A pointer to the stm32_dma_stream_t constant structure + * associated to the DMA stream. + */ +#define STM32_DMA_STREAM(id) (&_stm32_dma_streams[id]) + +#define STM32_DMA1_STREAM1 STM32_DMA_STREAM(0) +#define STM32_DMA1_STREAM2 STM32_DMA_STREAM(1) +#define STM32_DMA1_STREAM3 STM32_DMA_STREAM(2) +#define STM32_DMA1_STREAM4 STM32_DMA_STREAM(3) +#define STM32_DMA1_STREAM5 STM32_DMA_STREAM(4) +#define STM32_DMA1_STREAM6 STM32_DMA_STREAM(5) +#define STM32_DMA1_STREAM7 STM32_DMA_STREAM(6) +#define STM32_DMA2_STREAM1 STM32_DMA_STREAM(7) +#define STM32_DMA2_STREAM2 STM32_DMA_STREAM(8) +#define STM32_DMA2_STREAM3 STM32_DMA_STREAM(9) +#define STM32_DMA2_STREAM4 STM32_DMA_STREAM(10) +#define STM32_DMA2_STREAM5 STM32_DMA_STREAM(11) +/** @} */ + +/** + * @name CR register constants common to all DMA types + * @{ + */ +#define STM32_DMA_CR_EN DMA_CCR_EN +#define STM32_DMA_CR_TEIE DMA_CCR_TEIE +#define STM32_DMA_CR_HTIE DMA_CCR_HTIE +#define STM32_DMA_CR_TCIE DMA_CCR_TCIE +#define STM32_DMA_CR_DIR_MASK (DMA_CCR_DIR | DMA_CCR_MEM2MEM) +#define STM32_DMA_CR_DIR_P2M 0 +#define STM32_DMA_CR_DIR_M2P DMA_CCR_DIR +#define STM32_DMA_CR_DIR_M2M DMA_CCR_MEM2MEM +#define STM32_DMA_CR_CIRC DMA_CCR_CIRC +#define STM32_DMA_CR_PINC DMA_CCR_PINC +#define STM32_DMA_CR_MINC DMA_CCR_MINC +#define STM32_DMA_CR_PSIZE_MASK DMA_CCR_PSIZE +#define STM32_DMA_CR_PSIZE_BYTE 0 +#define STM32_DMA_CR_PSIZE_HWORD DMA_CCR_PSIZE_0 +#define STM32_DMA_CR_PSIZE_WORD DMA_CCR_PSIZE_1 +#define STM32_DMA_CR_MSIZE_MASK DMA_CCR_MSIZE +#define STM32_DMA_CR_MSIZE_BYTE 0 +#define STM32_DMA_CR_MSIZE_HWORD DMA_CCR_MSIZE_0 +#define STM32_DMA_CR_MSIZE_WORD DMA_CCR_MSIZE_1 +#define STM32_DMA_CR_SIZE_MASK (STM32_DMA_CR_PSIZE_MASK | \ + STM32_DMA_CR_MSIZE_MASK) +#define STM32_DMA_CR_PL_MASK DMA_CCR_PL +#define STM32_DMA_CR_PL(n) ((n) << 12) +/** @} */ + +/** + * @name CR register constants only found in enhanced DMA + * @{ + */ +#define STM32_DMA_CR_DMEIE 0 /**< @brief Ignored by normal DMA. */ +#define STM32_DMA_CR_CHSEL_MASK 0 /**< @brief Ignored by normal DMA. */ +#define STM32_DMA_CR_CHSEL(n) 0 /**< @brief Ignored by normal DMA. */ +/** @} */ + +/** + * @name Status flags passed to the ISR callbacks + * @{ + */ +#define STM32_DMA_ISR_FEIF 0 +#define STM32_DMA_ISR_DMEIF 0 +#define STM32_DMA_ISR_TEIF DMA_ISR_TEIF1 +#define STM32_DMA_ISR_HTIF DMA_ISR_HTIF1 +#define STM32_DMA_ISR_TCIF DMA_ISR_TCIF1 +/** @} */ + +/*===========================================================================*/ +/* Driver pre-compile time settings. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Derived constants and error checks. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver data structures and types. */ +/*===========================================================================*/ + +/** + * @brief STM32 DMA stream descriptor structure. + */ +typedef struct { + DMA_Channel_TypeDef *channel; /**< @brief Associated DMA channel. */ + volatile uint32_t *ifcr; /**< @brief Associated IFCR reg. */ + uint8_t ishift; /**< @brief Bits offset in xIFCR + register. */ + uint8_t selfindex; /**< @brief Index to self in array. */ + uint8_t vector; /**< @brief Associated IRQ vector. */ +} stm32_dma_stream_t; + +/** + * @brief STM32 DMA ISR function type. + * + * @param[in] p parameter for the registered function + * @param[in] flags pre-shifted content of the ISR register, the bits + * are aligned to bit zero + */ +typedef void (*stm32_dmaisr_t)(void *p, uint32_t flags); + +/*===========================================================================*/ +/* Driver macros. */ +/*===========================================================================*/ + +/** + * @name Macro Functions + * @{ + */ +/** + * @brief Associates a peripheral data register to a DMA stream. + * @note This function can be invoked in both ISR or thread context. + * @pre The stream must have been allocated using @p dmaStreamAllocate(). + * @post After use the stream can be released using @p dmaStreamRelease(). + * + * @param[in] dmastp pointer to a stm32_dma_stream_t structure + * @param[in] addr value to be written in the CPAR register + * + * @special + */ +#define dmaStreamSetPeripheral(dmastp, addr) { \ + (dmastp)->channel->CPAR = (uint32_t)(addr); \ +} + +/** + * @brief Associates a memory destination to a DMA stream. + * @note This function can be invoked in both ISR or thread context. + * @pre The stream must have been allocated using @p dmaStreamAllocate(). + * @post After use the stream can be released using @p dmaStreamRelease(). + * + * @param[in] dmastp pointer to a stm32_dma_stream_t structure + * @param[in] addr value to be written in the CMAR register + * + * @special + */ +#define dmaStreamSetMemory0(dmastp, addr) { \ + (dmastp)->channel->CMAR = (uint32_t)(addr); \ +} + +/** + * @brief Sets the number of transfers to be performed. + * @note This function can be invoked in both ISR or thread context. + * @pre The stream must have been allocated using @p dmaStreamAllocate(). + * @post After use the stream can be released using @p dmaStreamRelease(). + * + * @param[in] dmastp pointer to a stm32_dma_stream_t structure + * @param[in] size value to be written in the CNDTR register + * + * @special + */ +#define dmaStreamSetTransactionSize(dmastp, size) { \ + (dmastp)->channel->CNDTR = (uint32_t)(size); \ +} + +/** + * @brief Returns the number of transfers to be performed. + * @note This function can be invoked in both ISR or thread context. + * @pre The stream must have been allocated using @p dmaStreamAllocate(). + * @post After use the stream can be released using @p dmaStreamRelease(). + * + * @param[in] dmastp pointer to a stm32_dma_stream_t structure + * @return The number of transfers to be performed. + * + * @special + */ +#define dmaStreamGetTransactionSize(dmastp) ((size_t)((dmastp)->channel->CNDTR)) + +/** + * @brief Programs the stream mode settings. + * @note This function can be invoked in both ISR or thread context. + * @pre The stream must have been allocated using @p dmaStreamAllocate(). + * @post After use the stream can be released using @p dmaStreamRelease(). + * + * @param[in] dmastp pointer to a stm32_dma_stream_t structure + * @param[in] mode value to be written in the CCR register + * + * @special + */ +#define dmaStreamSetMode(dmastp, mode) { \ + (dmastp)->channel->CCR = (uint32_t)(mode); \ +} + +/** + * @brief DMA stream enable. + * @note This function can be invoked in both ISR or thread context. + * @pre The stream must have been allocated using @p dmaStreamAllocate(). + * @post After use the stream can be released using @p dmaStreamRelease(). + * + * @param[in] dmastp pointer to a stm32_dma_stream_t structure + * + * @special + */ +#define dmaStreamEnable(dmastp) { \ + (dmastp)->channel->CCR |= STM32_DMA_CR_EN; \ +} + +/** + * @brief DMA stream disable. + * @details The function disables the specified stream and then clears any + * pending interrupt. + * @note This function can be invoked in both ISR or thread context. + * @note Interrupts enabling flags are set to zero after this call, see + * bug 3607518. + * @pre The stream must have been allocated using @p dmaStreamAllocate(). + * @post After use the stream can be released using @p dmaStreamRelease(). + * + * @param[in] dmastp pointer to a stm32_dma_stream_t structure + * + * @special + */ +#define dmaStreamDisable(dmastp) { \ + (dmastp)->channel->CCR &= ~(STM32_DMA_CR_TCIE | STM32_DMA_CR_HTIE | \ + STM32_DMA_CR_TEIE | STM32_DMA_CR_EN); \ + dmaStreamClearInterrupt(dmastp); \ +} + +/** + * @brief DMA stream interrupt sources clear. + * @note This function can be invoked in both ISR or thread context. + * @pre The stream must have been allocated using @p dmaStreamAllocate(). + * @post After use the stream can be released using @p dmaStreamRelease(). + * + * @param[in] dmastp pointer to a stm32_dma_stream_t structure + * + * @special + */ +#define dmaStreamClearInterrupt(dmastp) { \ + *(dmastp)->ifcr = STM32_DMA_ISR_MASK << (dmastp)->ishift; \ +} + +/** + * @brief Starts a memory to memory operation using the specified stream. + * @note The default transfer data mode is "byte to byte" but it can be + * changed by specifying extra options in the @p mode parameter. + * @pre The stream must have been allocated using @p dmaStreamAllocate(). + * @post After use the stream can be released using @p dmaStreamRelease(). + * + * @param[in] dmastp pointer to a stm32_dma_stream_t structure + * @param[in] mode value to be written in the CCR register, this value + * is implicitly ORed with: + * - @p STM32_DMA_CR_MINC + * - @p STM32_DMA_CR_PINC + * - @p STM32_DMA_CR_DIR_M2M + * - @p STM32_DMA_CR_EN + * . + * @param[in] src source address + * @param[in] dst destination address + * @param[in] n number of data units to copy + */ +#define dmaStartMemCopy(dmastp, mode, src, dst, n) { \ + dmaStreamSetPeripheral(dmastp, src); \ + dmaStreamSetMemory0(dmastp, dst); \ + dmaStreamSetTransactionSize(dmastp, n); \ + dmaStreamSetMode(dmastp, (mode) | \ + STM32_DMA_CR_MINC | STM32_DMA_CR_PINC | \ + STM32_DMA_CR_DIR_M2M | STM32_DMA_CR_EN); \ +} + +/** + * @brief Polled wait for DMA transfer end. + * @pre The stream must have been allocated using @p dmaStreamAllocate(). + * @post After use the stream can be released using @p dmaStreamRelease(). + * + * @param[in] dmastp pointer to a stm32_dma_stream_t structure + */ +#define dmaWaitCompletion(dmastp) { \ + while ((dmastp)->channel->CNDTR > 0) \ + ; \ + dmaStreamDisable(dmastp); \ +} + +/** @} */ + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +#if !defined(__DOXYGEN__) +extern const stm32_dma_stream_t _stm32_dma_streams[STM32_DMA_STREAMS]; +#endif + +#ifdef __cplusplus +extern "C" { +#endif + void dmaInit(void); + bool_t dmaStreamAllocate(const stm32_dma_stream_t *dmastp, + uint32_t priority, + stm32_dmaisr_t func, + void *param); + void dmaStreamRelease(const stm32_dma_stream_t *dmastp); +#ifdef __cplusplus +} +#endif + +#endif /* _STM32_DMA_H_ */ + +/** @} */ diff --git a/os/hal/ports/STM32F30x/stm32_isr.h b/os/hal/ports/STM32F30x/stm32_isr.h new file mode 100644 index 000000000..94b04b63e --- /dev/null +++ b/os/hal/ports/STM32F30x/stm32_isr.h @@ -0,0 +1,132 @@ +/* + ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file STM32F30x/stm32_isr.h + * @brief ISR remapper driver header. + * + * @addtogroup STM32F30x_ISR + * @{ + */ + +#ifndef _STM32_ISR_H_ +#define _STM32_ISR_H_ + +/*===========================================================================*/ +/* Driver constants. */ +/*===========================================================================*/ + +/** + * @name ISR names and numbers remapping + * @{ + */ +/* + * CAN units. + */ +#define STM32_CAN1_TX_HANDLER Vector8C +#define STM32_CAN1_RX0_HANDLER Vector90 +#define STM32_CAN1_RX1_HANDLER Vector94 +#define STM32_CAN1_SCE_HANDLER Vector98 + +#define STM32_CAN1_TX_NUMBER 19 +#define STM32_CAN1_RX0_NUMBER 20 +#define STM32_CAN1_RX1_NUMBER 21 +#define STM32_CAN1_SCE_NUMBER 22 + +/* + * I2C units. + */ +#define STM32_I2C1_EVENT_HANDLER VectorBC +#define STM32_I2C1_ERROR_HANDLER VectorC0 +#define STM32_I2C1_EVENT_NUMBER 31 +#define STM32_I2C1_ERROR_NUMBER 32 + +#define STM32_I2C2_EVENT_HANDLER VectorC4 +#define STM32_I2C2_ERROR_HANDLER VectorC8 +#define STM32_I2C2_EVENT_NUMBER 33 +#define STM32_I2C2_ERROR_NUMBER 34 + +/* + * TIM units. + */ +#define STM32_TIM1_UP_HANDLER VectorA4 +#define STM32_TIM1_CC_HANDLER VectorAC +#define STM32_TIM2_HANDLER VectorB0 +#define STM32_TIM3_HANDLER VectorB4 +#define STM32_TIM4_HANDLER VectorB8 +#define STM32_TIM6_HANDLER Vector118 +#define STM32_TIM7_HANDLER Vector11C +#define STM32_TIM8_UP_HANDLER VectorF0 +#define STM32_TIM8_CC_HANDLER VectorF8 + +#define STM32_TIM1_UP_NUMBER 25 +#define STM32_TIM1_CC_NUMBER 27 +#define STM32_TIM2_NUMBER 28 +#define STM32_TIM3_NUMBER 29 +#define STM32_TIM4_NUMBER 30 +#define STM32_TIM6_NUMBER 54 +#define STM32_TIM7_NUMBER 55 +#define STM32_TIM8_UP_NUMBER 44 +#define STM32_TIM8_CC_NUMBER 46 + +/* + * USART units. + */ +#define STM32_USART1_HANDLER VectorD4 +#define STM32_USART2_HANDLER VectorD8 +#define STM32_USART3_HANDLER VectorDC +#define STM32_UART4_HANDLER Vector110 +#define STM32_UART5_HANDLER Vector114 + +#define STM32_USART1_NUMBER 37 +#define STM32_USART2_NUMBER 38 +#define STM32_USART3_NUMBER 39 +#define STM32_UART4_NUMBER 52 +#define STM32_UART5_NUMBER 53 + +/* + * USB units. + */ +#define STM32_USB1_HP_HANDLER Vector168 +#define STM32_USB1_LP_HANDLER Vector16C + +#define STM32_USB1_HP_NUMBER 74 +#define STM32_USB1_LP_NUMBER 75 +/** @} */ + +/*===========================================================================*/ +/* Driver pre-compile time settings. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Derived constants and error checks. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver data structures and types. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver macros. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +#endif /* _STM32_ISR_H_ */ + +/** @} */ diff --git a/os/hal/ports/STM32F30x/stm32_rcc.h b/os/hal/ports/STM32F30x/stm32_rcc.h new file mode 100644 index 000000000..9cc2edf52 --- /dev/null +++ b/os/hal/ports/STM32F30x/stm32_rcc.h @@ -0,0 +1,835 @@ +/* + ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file STM32F30x/stm32_rcc.h + * @brief RCC helper driver header. + * @note This file requires definitions from the ST header file + * @p stm32f30x.h. + * + * @addtogroup STM32F30x_RCC + * @{ + */ + +#ifndef _STM32_RCC_ +#define _STM32_RCC_ + +/*===========================================================================*/ +/* Driver constants. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver pre-compile time settings. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Derived constants and error checks. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver data structures and types. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver macros. */ +/*===========================================================================*/ + +/** + * @name Generic RCC operations + * @{ + */ +/** + * @brief Enables the clock of one or more peripheral on the APB1 bus. + * + * @param[in] mask APB1 peripherals mask + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableAPB1(mask, lp) { \ + RCC->APB1ENR |= (mask); \ +} + +/** + * @brief Disables the clock of one or more peripheral on the APB1 bus. + * + * @param[in] mask APB1 peripherals mask + * @param[in] lp low power enable flag + * + * @api + */ +#define rccDisableAPB1(mask, lp) { \ + RCC->APB1ENR &= ~(mask); \ +} + +/** + * @brief Resets one or more peripheral on the APB1 bus. + * + * @param[in] mask APB1 peripherals mask + * + * @api + */ +#define rccResetAPB1(mask) { \ + RCC->APB1RSTR |= (mask); \ + RCC->APB1RSTR = 0; \ +} + +/** + * @brief Enables the clock of one or more peripheral on the APB2 bus. + * + * @param[in] mask APB2 peripherals mask + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableAPB2(mask, lp) { \ + RCC->APB2ENR |= (mask); \ +} + +/** + * @brief Disables the clock of one or more peripheral on the APB2 bus. + * + * @param[in] mask APB2 peripherals mask + * @param[in] lp low power enable flag + * + * @api + */ +#define rccDisableAPB2(mask, lp) { \ + RCC->APB2ENR &= ~(mask); \ +} + +/** + * @brief Resets one or more peripheral on the APB2 bus. + * + * @param[in] mask APB2 peripherals mask + * + * @api + */ +#define rccResetAPB2(mask) { \ + RCC->APB2RSTR |= (mask); \ + RCC->APB2RSTR = 0; \ +} + +/** + * @brief Enables the clock of one or more peripheral on the AHB bus. + * + * @param[in] mask AHB peripherals mask + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableAHB(mask, lp) { \ + RCC->AHBENR |= (mask); \ +} + +/** + * @brief Disables the clock of one or more peripheral on the AHB bus. + * + * @param[in] mask AHB peripherals mask + * @param[in] lp low power enable flag + * + * @api + */ +#define rccDisableAHB(mask, lp) { \ + RCC->AHBENR &= ~(mask); \ +} + +/** + * @brief Resets one or more peripheral on the AHB bus. + * + * @param[in] mask AHB peripherals mask + * + * @api + */ +#define rccResetAHB(mask) { \ + RCC->AHBRSTR |= (mask); \ + RCC->AHBRSTR = 0; \ +} +/** @} */ + +/** + * @name ADC peripherals specific RCC operations + * @{ + */ +/** + * @brief Enables the ADC1/ADC2 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableADC12(lp) rccEnableAHB(RCC_AHBENR_ADC12EN, lp) + +/** + * @brief Disables the ADC1/ADC2 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccDisableADC12(lp) rccDisableAHB(RCC_AHBENR_ADC12EN, lp) + +/** + * @brief Resets the ADC1/ADC2 peripheral. + * + * @api + */ +#define rccResetADC12() rccResetAHB(RCC_AHBRSTR_ADC12RST) + +/** + * @brief Enables the ADC3/ADC4 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableADC34(lp) rccEnableAHB(RCC_AHBENR_ADC34EN, lp) + +/** + * @brief Disables the ADC3/ADC4 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccDisableADC34(lp) rccDisableAHB(RCC_AHBENR_ADC34EN, lp) + +/** + * @brief Resets the ADC3/ADC4 peripheral. + * + * @api + */ +#define rccResetADC34() rccResetAHB(RCC_AHBRSTR_ADC34RST) +/** @} */ + +/** + * @name CAN peripherals specific RCC operations + * @{ + */ +/** + * @brief Enables the CAN1 peripheral clock. + * @note The @p lp parameter is ignored in this family. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableCAN1(lp) rccEnableAPB1(RCC_APB1ENR_CAN1EN, lp) + +/** + * @brief Disables the CAN1 peripheral clock. + * @note The @p lp parameter is ignored in this family. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccDisableCAN1(lp) rccDisableAPB1(RCC_APB1ENR_CAN1EN, lp) + +/** + * @brief Resets the CAN1 peripheral. + * + * @api + */ +#define rccResetCAN1() rccResetAPB1(RCC_APB1RSTR_CAN1RST) +/** @} */ + +/** + * @name DMA peripheral specific RCC operations + * @{ + */ +/** + * @brief Enables the DMA1 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableDMA1(lp) rccEnableAHB(RCC_AHBENR_DMA1EN, lp) + +/** + * @brief Disables the DMA1 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccDisableDMA1(lp) rccDisableAHB(RCC_AHBENR_DMA1EN, lp) + +/** + * @brief Resets the DMA1 peripheral. + * + * @api + */ +#define rccResetDMA1() rccResetAHB(RCC_AHBRSTR_DMA1RST) + +/** + * @brief Enables the DMA2 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableDMA2(lp) rccEnableAHB(RCC_AHBENR_DMA2EN, lp) + +/** + * @brief Disables the DMA2 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccDisableDMA2(lp) rccDisableAHB(RCC_AHBENR_DMA2EN, lp) + +/** + * @brief Resets the DMA2 peripheral. + * + * @api + */ +#define rccResetDMA2() rccResetAHB(RCC_AHBRSTR_DMA2RST) +/** @} */ + +/** + * @name PWR interface specific RCC operations + * @{ + */ +/** + * @brief Enables the PWR interface clock. + * @note The @p lp parameter is ignored in this family. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnablePWRInterface(lp) rccEnableAPB1(RCC_APB1ENR_PWREN, lp) + +/** + * @brief Disables PWR interface clock. + * @note The @p lp parameter is ignored in this family. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccDisablePWRInterface(lp) rccDisableAPB1(RCC_APB1ENR_PWREN, lp) + +/** + * @brief Resets the PWR interface. + * + * @api + */ +#define rccResetPWRInterface() rccResetAPB1(RCC_APB1RSTR_PWRRST) +/** @} */ + +/** + * @name I2C peripherals specific RCC operations + * @{ + */ +/** + * @brief Enables the I2C1 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableI2C1(lp) rccEnableAPB1(RCC_APB1ENR_I2C1EN, lp) + +/** + * @brief Disables the I2C1 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccDisableI2C1(lp) rccDisableAPB1(RCC_APB1ENR_I2C1EN, lp) + +/** + * @brief Resets the I2C1 peripheral. + * + * @api + */ +#define rccResetI2C1() rccResetAPB1(RCC_APB1RSTR_I2C1RST) + +/** + * @brief Enables the I2C2 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableI2C2(lp) rccEnableAPB1(RCC_APB1ENR_I2C2EN, lp) + +/** + * @brief Disables the I2C2 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccDisableI2C2(lp) rccDisableAPB1(RCC_APB1ENR_I2C2EN, lp) + +/** + * @brief Resets the I2C2 peripheral. + * + * @api + */ +#define rccResetI2C2() rccResetAPB1(RCC_APB1RSTR_I2C2RST) +/** @} */ + +/** + * @name SPI peripherals specific RCC operations + * @{ + */ +/** + * @brief Enables the SPI1 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableSPI1(lp) rccEnableAPB2(RCC_APB2ENR_SPI1EN, lp) + +/** + * @brief Disables the SPI1 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccDisableSPI1(lp) rccDisableAPB2(RCC_APB2ENR_SPI1EN, lp) + +/** + * @brief Resets the SPI1 peripheral. + * + * @api + */ +#define rccResetSPI1() rccResetAPB2(RCC_APB2RSTR_SPI1RST) + +/** + * @brief Enables the SPI2 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableSPI2(lp) rccEnableAPB1(RCC_APB1ENR_SPI2EN, lp) + +/** + * @brief Disables the SPI2 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccDisableSPI2(lp) rccDisableAPB1(RCC_APB1ENR_SPI2EN, lp) + +/** + * @brief Resets the SPI2 peripheral. + * + * @api + */ +#define rccResetSPI2() rccResetAPB1(RCC_APB1RSTR_SPI2RST) + +/** + * @brief Enables the SPI3 peripheral clock. + * @note The @p lp parameter is ignored in this family. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableSPI3(lp) rccEnableAPB1(RCC_APB1ENR_SPI3EN, lp) + +/** + * @brief Disables the SPI3 peripheral clock. + * @note The @p lp parameter is ignored in this family. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccDisableSPI3(lp) rccDisableAPB1(RCC_APB1ENR_SPI3EN, lp) + +/** + * @brief Resets the SPI3 peripheral. + * + * @api + */ +#define rccResetSPI3() rccResetAPB1(RCC_APB1RSTR_SPI3RST) +/** @} */ + +/** + * @name TIM peripherals specific RCC operations + * @{ + */ +/** + * @brief Enables the TIM1 peripheral clock. + * @note The @p lp parameter is ignored in this family. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableTIM1(lp) rccEnableAPB2(RCC_APB2ENR_TIM1EN, lp) + +/** + * @brief Disables the TIM1 peripheral clock. + * @note The @p lp parameter is ignored in this family. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccDisableTIM1(lp) rccDisableAPB2(RCC_APB2ENR_TIM1EN, lp) + +/** + * @brief Resets the TIM1 peripheral. + * + * @api + */ +#define rccResetTIM1() rccResetAPB2(RCC_APB2RSTR_TIM1RST) + +/** + * @brief Enables the TIM2 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableTIM2(lp) rccEnableAPB1(RCC_APB1ENR_TIM2EN, lp) + +/** + * @brief Disables the TIM2 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccDisableTIM2(lp) rccDisableAPB1(RCC_APB1ENR_TIM2EN, lp) + +/** + * @brief Resets the TIM2 peripheral. + * + * @api + */ +#define rccResetTIM2() rccResetAPB1(RCC_APB1RSTR_TIM2RST) + +/** + * @brief Enables the TIM3 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableTIM3(lp) rccEnableAPB1(RCC_APB1ENR_TIM3EN, lp) + +/** + * @brief Disables the TIM3 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccDisableTIM3(lp) rccDisableAPB1(RCC_APB1ENR_TIM3EN, lp) + +/** + * @brief Resets the TIM3 peripheral. + * + * @api + */ +#define rccResetTIM3() rccResetAPB1(RCC_APB1RSTR_TIM3RST) + +/** + * @brief Enables the TIM4 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableTIM4(lp) rccEnableAPB1(RCC_APB1ENR_TIM4EN, lp) + +/** + * @brief Disables the TIM4 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccDisableTIM4(lp) rccDisableAPB1(RCC_APB1ENR_TIM4EN, lp) + +/** + * @brief Resets the TIM4 peripheral. + * + * @api + */ +#define rccResetTIM4() rccResetAPB1(RCC_APB1RSTR_TIM4RST) + +/** + * @brief Enables the TIM6 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableTIM6(lp) rccEnableAPB1(RCC_APB1ENR_TIM6EN, lp) + +/** + * @brief Disables the TIM6 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccDisableTIM6(lp) rccDisableAPB1(RCC_APB1ENR_TIM6EN, lp) + +/** + * @brief Resets the TIM6 peripheral. + * + * @api + */ +#define rccResetTIM6() rccResetAPB1(RCC_APB1RSTR_TIM6RST) + +/** + * @brief Enables the TIM7 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableTIM7(lp) rccEnableAPB1(RCC_APB1ENR_TIM7EN, lp) + +/** + * @brief Disables the TIM7 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccDisableTIM7(lp) rccDisableAPB1(RCC_APB1ENR_TIM7EN, lp) + +/** + * @brief Resets the TIM7 peripheral. + * + * @api + */ +#define rccResetTIM7() rccResetAPB1(RCC_APB1RSTR_TIM7RST) + +/** + * @brief Enables the TIM8 peripheral clock. + * @note The @p lp parameter is ignored in this family. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableTIM8(lp) rccEnableAPB2(RCC_APB2ENR_TIM8EN, lp) + +/** + * @brief Disables the TIM8 peripheral clock. + * @note The @p lp parameter is ignored in this family. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccDisableTIM8(lp) rccDisableAPB2(RCC_APB2ENR_TIM8EN, lp) + +/** + * @brief Resets the TIM8 peripheral. + * + * @api + */ +#define rccResetTIM8() rccResetAPB2(RCC_APB2RSTR_TIM8RST) +/** @} */ + +/** + * @name USART/UART peripherals specific RCC operations + * @{ + */ +/** + * @brief Enables the USART1 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableUSART1(lp) rccEnableAPB2(RCC_APB2ENR_USART1EN, lp) + +/** + * @brief Disables the USART1 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccDisableUSART1(lp) rccDisableAPB2(RCC_APB2ENR_USART1EN, lp) + +/** + * @brief Resets the USART1 peripheral. + * + * @api + */ +#define rccResetUSART1() rccResetAPB2(RCC_APB2RSTR_USART1RST) + +/** + * @brief Enables the USART2 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableUSART2(lp) rccEnableAPB1(RCC_APB1ENR_USART2EN, lp) + +/** + * @brief Disables the USART2 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccDisableUSART2(lp) rccDisableAPB1(RCC_APB1ENR_USART2EN, lp) + +/** + * @brief Resets the USART2 peripheral. + * + * @api + */ +#define rccResetUSART2() rccResetAPB1(RCC_APB1RSTR_USART2RST) + +/** + * @brief Enables the USART3 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableUSART3(lp) rccEnableAPB1(RCC_APB1ENR_USART3EN, lp) + +/** + * @brief Disables the USART3 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccDisableUSART3(lp) rccDisableAPB1(RCC_APB1ENR_USART3EN, lp) + +/** + * @brief Resets the USART3 peripheral. + * + * @api + */ +#define rccResetUSART3() rccResetAPB1(RCC_APB1RSTR_USART3RST) + +/** + * @brief Enables the UART4 peripheral clock. + * @note The @p lp parameter is ignored in this family. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableUART4(lp) rccEnableAPB1(RCC_APB1ENR_UART4EN, lp) + +/** + * @brief Disables the UART4 peripheral clock. + * @note The @p lp parameter is ignored in this family. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccDisableUART4(lp) rccDisableAPB1(RCC_APB1ENR_UART4EN, lp) + +/** + * @brief Resets the UART4 peripheral. + * + * @api + */ +#define rccResetUART4() rccResetAPB1(RCC_APB1RSTR_UART4RST) + +/** + * @brief Enables the UART5 peripheral clock. + * @note The @p lp parameter is ignored in this family. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableUART5(lp) rccEnableAPB1(RCC_APB1ENR_UART5EN, lp) + +/** + * @brief Disables the UART5 peripheral clock. + * @note The @p lp parameter is ignored in this family. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccDisableUART5(lp) rccDisableAPB1(RCC_APB1ENR_UART5EN, lp) + +/** + * @brief Resets the UART5 peripheral. + * + * @api + */ +#define rccResetUART5() rccResetAPB1(RCC_APB1RSTR_UART5RST) +/** @} */ + +/** + * @name USB peripheral specific RCC operations + * @{ + */ +/** + * @brief Enables the USB peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableUSB(lp) rccEnableAPB1(RCC_APB1ENR_USBEN, lp) + +/** + * @brief Disables the USB peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccDisableUSB(lp) rccDisableAPB1(RCC_APB1ENR_USBEN, lp) + +/** + * @brief Resets the USB peripheral. + * + * @api + */ +#define rccResetUSB() rccResetAPB1(RCC_APB1RSTR_USBRST) +/** @} */ + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +#ifdef __cplusplus +extern "C" { +#endif +#ifdef __cplusplus +} +#endif + +#endif /* _STM32_RCC_ */ + +/** @} */ diff --git a/os/hal/ports/STM32F30x/stm32_registry.h b/os/hal/ports/STM32F30x/stm32_registry.h new file mode 100644 index 000000000..7487620ef --- /dev/null +++ b/os/hal/ports/STM32F30x/stm32_registry.h @@ -0,0 +1,194 @@ +/* + ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file STM32F30x/stm32_registry.h + * @brief STM32F30x capabilities registry. + * + * @addtogroup HAL + * @{ + */ + +#ifndef _STM32_REGISTRY_H_ +#define _STM32_REGISTRY_H_ + +/*===========================================================================*/ +/* Platform capabilities. */ +/*===========================================================================*/ + +/** + * @name STM32F30x capabilities + * @{ + */ +/* ADC attributes.*/ +#define STM32_HAS_ADC1 TRUE + +#define STM32_HAS_ADC2 TRUE + +#define STM32_HAS_ADC3 TRUE + +#define STM32_HAS_ADC4 TRUE + +#define STM32_HAS_SDADC1 FALSE +#define STM32_HAS_SDADC2 FALSE +#define STM32_HAS_SDADC3 FALSE + +/* CAN attributes.*/ +#define STM32_HAS_CAN1 TRUE +#define STM32_HAS_CAN2 FALSE +#define STM32_CAN_MAX_FILTERS 14 + +/* DAC attributes.*/ +#define STM32_HAS_DAC1 TRUE +#define STM32_HAS_DAC2 TRUE + +/* DMA attributes.*/ +#define STM32_ADVANCED_DMA FALSE +#define STM32_HAS_DMA1 TRUE +#define STM32_HAS_DMA2 TRUE + +/* ETH attributes.*/ +#define STM32_HAS_ETH FALSE + +/* EXTI attributes.*/ +#define STM32_EXTI_NUM_CHANNELS 34 + +/* GPIO attributes.*/ +#define STM32_HAS_GPIOA TRUE +#define STM32_HAS_GPIOB TRUE +#define STM32_HAS_GPIOC TRUE +#define STM32_HAS_GPIOD TRUE +#define STM32_HAS_GPIOE TRUE +#define STM32_HAS_GPIOF TRUE +#define STM32_HAS_GPIOG FALSE +#define STM32_HAS_GPIOH FALSE +#define STM32_HAS_GPIOI FALSE + +/* I2C attributes.*/ +#define STM32_HAS_I2C1 TRUE +#define STM32_I2C_I2C1_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7) +#define STM32_I2C_I2C1_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 6) + +#define STM32_HAS_I2C2 TRUE +#define STM32_I2C_I2C2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 5) +#define STM32_I2C_I2C2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) + +#define STM32_HAS_I2C3 FALSE + +/* RTC attributes.*/ +#define STM32_HAS_RTC TRUE +#define STM32_RTC_HAS_SUBSECONDS TRUE +#define STM32_RTC_IS_CALENDAR TRUE + +/* SDIO attributes.*/ +#define STM32_HAS_SDIO FALSE + +/* SPI attributes.*/ +#define STM32_HAS_SPI1 TRUE +#define STM32_SPI_SPI1_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2) +#define STM32_SPI_SPI1_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 3) + +#define STM32_HAS_SPI2 TRUE +#define STM32_SPI_SPI2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) +#define STM32_SPI_SPI2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 5) + +#define STM32_HAS_SPI3 TRUE +#define STM32_SPI_SPI3_RX_DMA_STREAM STM32_DMA_STREAM_ID(2, 1) +#define STM32_SPI_SPI3_TX_DMA_STREAM STM32_DMA_STREAM_ID(2, 2) + +/* TIM attributes.*/ +#define STM32_TIM_MAX_CHANNELS 6 + +#define STM32_HAS_TIM1 TRUE +#define STM32_TIM1_IS_32BITS FALSE +#define STM32_TIM1_CHANNELS 6 + +#define STM32_HAS_TIM2 TRUE +#define STM32_TIM2_IS_32BITS TRUE +#define STM32_TIM2_CHANNELS 4 + +#define STM32_HAS_TIM3 TRUE +#define STM32_TIM3_IS_32BITS FALSE +#define STM32_TIM3_CHANNELS 4 + +#define STM32_HAS_TIM4 TRUE +#define STM32_TIM4_IS_32BITS FALSE +#define STM32_TIM4_CHANNELS 4 + +#define STM32_HAS_TIM6 TRUE +#define STM32_TIM6_IS_32BITS FALSE +#define STM32_TIM6_CHANNELS 0 + +#define STM32_HAS_TIM7 TRUE +#define STM32_TIM7_IS_32BITS FALSE +#define STM32_TIM7_CHANNELS 0 + +#define STM32_HAS_TIM8 TRUE +#define STM32_TIM8_IS_32BITS FALSE +#define STM32_TIM8_CHANNELS 6 + +#define STM32_HAS_TIM15 TRUE +#define STM32_TIM15_IS_32BITS FALSE +#define STM32_TIM15_CHANNELS 2 + +#define STM32_HAS_TIM16 TRUE +#define STM32_TIM16_IS_32BITS FALSE +#define STM32_TIM16_CHANNELS 2 + +#define STM32_HAS_TIM17 TRUE +#define STM32_TIM17_IS_32BITS FALSE +#define STM32_TIM17_CHANNELS 2 + +#define STM32_HAS_TIM5 FALSE +#define STM32_HAS_TIM9 FALSE +#define STM32_HAS_TIM10 FALSE +#define STM32_HAS_TIM11 FALSE +#define STM32_HAS_TIM12 FALSE +#define STM32_HAS_TIM13 FALSE +#define STM32_HAS_TIM14 FALSE +#define STM32_HAS_TIM18 FALSE +#define STM32_HAS_TIM19 FALSE + +/* USART attributes.*/ +#define STM32_HAS_USART1 TRUE +#define STM32_UART_USART1_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 5) +#define STM32_UART_USART1_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) + +#define STM32_HAS_USART2 TRUE +#define STM32_UART_USART2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 6) +#define STM32_UART_USART2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7) + +#define STM32_HAS_USART3 TRUE +#define STM32_UART_USART3_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 3) +#define STM32_UART_USART3_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2) + +#define STM32_HAS_UART4 TRUE +#define STM32_UART_UART4_RX_DMA_STREAM STM32_DMA_STREAM_ID(2, 3) +#define STM32_UART_UART4_TX_DMA_STREAM STM32_DMA_STREAM_ID(2, 5) + +#define STM32_HAS_UART5 TRUE + +#define STM32_HAS_USART6 FALSE + +/* USB attributes.*/ +#define STM32_HAS_USB TRUE +#define STM32_HAS_OTG1 FALSE +#define STM32_HAS_OTG2 FALSE +/** @} */ + +#endif /* _STM32_REGISTRY_H_ */ + +/** @} */ diff --git a/os/hal/ports/STM32F4xx/adc_lld.c b/os/hal/ports/STM32F4xx/adc_lld.c new file mode 100644 index 000000000..724dc2938 --- /dev/null +++ b/os/hal/ports/STM32F4xx/adc_lld.c @@ -0,0 +1,418 @@ +/* + ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file STM32F4xx/adc_lld.c + * @brief STM32F4xx/STM32F2xx ADC subsystem low level driver source. + * + * @addtogroup ADC + * @{ + */ + +#include "hal.h" + +#if HAL_USE_ADC || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver local definitions. */ +/*===========================================================================*/ + +#define ADC1_DMA_CHANNEL \ + STM32_DMA_GETCHANNEL(STM32_ADC_ADC1_DMA_STREAM, STM32_ADC1_DMA_CHN) + +#define ADC2_DMA_CHANNEL \ + STM32_DMA_GETCHANNEL(STM32_ADC_ADC2_DMA_STREAM, STM32_ADC2_DMA_CHN) + +#define ADC3_DMA_CHANNEL \ + STM32_DMA_GETCHANNEL(STM32_ADC_ADC3_DMA_STREAM, STM32_ADC3_DMA_CHN) + +/*===========================================================================*/ +/* Driver exported variables. */ +/*===========================================================================*/ + +/** @brief ADC1 driver identifier.*/ +#if STM32_ADC_USE_ADC1 || defined(__DOXYGEN__) +ADCDriver ADCD1; +#endif + +/** @brief ADC2 driver identifier.*/ +#if STM32_ADC_USE_ADC2 || defined(__DOXYGEN__) +ADCDriver ADCD2; +#endif + +/** @brief ADC3 driver identifier.*/ +#if STM32_ADC_USE_ADC3 || defined(__DOXYGEN__) +ADCDriver ADCD3; +#endif + +/*===========================================================================*/ +/* Driver local variables and types. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local functions. */ +/*===========================================================================*/ + +/** + * @brief ADC DMA ISR service routine. + * + * @param[in] adcp pointer to the @p ADCDriver object + * @param[in] flags pre-shifted content of the ISR register + */ +static void adc_lld_serve_rx_interrupt(ADCDriver *adcp, uint32_t flags) { + + /* DMA errors handling.*/ + if ((flags & (STM32_DMA_ISR_TEIF | STM32_DMA_ISR_DMEIF)) != 0) { + /* DMA, this could help only if the DMA tries to access an unmapped + address space or violates alignment rules.*/ + _adc_isr_error_code(adcp, ADC_ERR_DMAFAILURE); + } + else { + /* It is possible that the conversion group has already be reset by the + ADC error handler, in this case this interrupt is spurious.*/ + if (adcp->grpp != NULL) { + if ((flags & STM32_DMA_ISR_HTIF) != 0) { + /* Half transfer processing.*/ + _adc_isr_half_code(adcp); + } + if ((flags & STM32_DMA_ISR_TCIF) != 0) { + /* Transfer complete processing.*/ + _adc_isr_full_code(adcp); + } + } + } +} + +/*===========================================================================*/ +/* Driver interrupt handlers. */ +/*===========================================================================*/ + +#if STM32_ADC_USE_ADC1 || STM32_ADC_USE_ADC2 || STM32_ADC_USE_ADC3 || \ + defined(__DOXYGEN__) +/** + * @brief ADC interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(ADC1_2_3_IRQHandler) { + uint32_t sr; + + OSAL_IRQ_PROLOGUE(); + +#if STM32_ADC_USE_ADC1 + sr = ADC1->SR; + ADC1->SR = 0; + /* Note, an overflow may occur after the conversion ended before the driver + is able to stop the ADC, this is why the DMA channel is checked too.*/ + if ((sr & ADC_SR_OVR) && (dmaStreamGetTransactionSize(ADCD1.dmastp) > 0)) { + /* ADC overflow condition, this could happen only if the DMA is unable + to read data fast enough.*/ + if (ADCD1.grpp != NULL) + _adc_isr_error_code(&ADCD1, ADC_ERR_OVERFLOW); + } + /* TODO: Add here analog watchdog handling.*/ +#endif /* STM32_ADC_USE_ADC1 */ + +#if STM32_ADC_USE_ADC2 + sr = ADC2->SR; + ADC2->SR = 0; + /* Note, an overflow may occur after the conversion ended before the driver + is able to stop the ADC, this is why the DMA channel is checked too.*/ + if ((sr & ADC_SR_OVR) && (dmaStreamGetTransactionSize(ADCD2.dmastp) > 0)) { + /* ADC overflow condition, this could happen only if the DMA is unable + to read data fast enough.*/ + if (ADCD2.grpp != NULL) + _adc_isr_error_code(&ADCD2, ADC_ERR_OVERFLOW); + } + /* TODO: Add here analog watchdog handling.*/ +#endif /* STM32_ADC_USE_ADC2 */ + +#if STM32_ADC_USE_ADC3 + sr = ADC3->SR; + ADC3->SR = 0; + /* Note, an overflow may occur after the conversion ended before the driver + is able to stop the ADC, this is why the DMA channel is checked too.*/ + if ((sr & ADC_SR_OVR) && (dmaStreamGetTransactionSize(ADCD3.dmastp) > 0)) { + /* ADC overflow condition, this could happen only if the DMA is unable + to read data fast enough.*/ + if (ADCD3.grpp != NULL) + _adc_isr_error_code(&ADCD3, ADC_ERR_OVERFLOW); + } + /* TODO: Add here analog watchdog handling.*/ +#endif /* STM32_ADC_USE_ADC3 */ + + OSAL_IRQ_EPILOGUE(); +} +#endif + +/*===========================================================================*/ +/* Driver exported functions. */ +/*===========================================================================*/ + +/** + * @brief Low level ADC driver initialization. + * + * @notapi + */ +void adc_lld_init(void) { + +#if STM32_ADC_USE_ADC1 + /* Driver initialization.*/ + adcObjectInit(&ADCD1); + ADCD1.adc = ADC1; + ADCD1.dmastp = STM32_DMA_STREAM(STM32_ADC_ADC1_DMA_STREAM); + ADCD1.dmamode = STM32_DMA_CR_CHSEL(ADC1_DMA_CHANNEL) | + STM32_DMA_CR_PL(STM32_ADC_ADC1_DMA_PRIORITY) | + STM32_DMA_CR_DIR_P2M | + STM32_DMA_CR_MSIZE_HWORD | STM32_DMA_CR_PSIZE_HWORD | + STM32_DMA_CR_MINC | STM32_DMA_CR_TCIE | + STM32_DMA_CR_DMEIE | STM32_DMA_CR_TEIE; +#endif + +#if STM32_ADC_USE_ADC2 + /* Driver initialization.*/ + adcObjectInit(&ADCD2); + ADCD2.adc = ADC2; + ADCD2.dmastp = STM32_DMA_STREAM(STM32_ADC_ADC2_DMA_STREAM); + ADCD2.dmamode = STM32_DMA_CR_CHSEL(ADC2_DMA_CHANNEL) | + STM32_DMA_CR_PL(STM32_ADC_ADC2_DMA_PRIORITY) | + STM32_DMA_CR_DIR_P2M | + STM32_DMA_CR_MSIZE_HWORD | STM32_DMA_CR_PSIZE_HWORD | + STM32_DMA_CR_MINC | STM32_DMA_CR_TCIE | + STM32_DMA_CR_DMEIE | STM32_DMA_CR_TEIE; +#endif + +#if STM32_ADC_USE_ADC3 + /* Driver initialization.*/ + adcObjectInit(&ADCD3); + ADCD3.adc = ADC3; + ADCD3.dmastp = STM32_DMA_STREAM(STM32_ADC_ADC3_DMA_STREAM); + ADCD3.dmamode = STM32_DMA_CR_CHSEL(ADC3_DMA_CHANNEL) | + STM32_DMA_CR_PL(STM32_ADC_ADC3_DMA_PRIORITY) | + STM32_DMA_CR_DIR_P2M | + STM32_DMA_CR_MSIZE_HWORD | STM32_DMA_CR_PSIZE_HWORD | + STM32_DMA_CR_MINC | STM32_DMA_CR_TCIE | + STM32_DMA_CR_DMEIE | STM32_DMA_CR_TEIE; +#endif + + /* The shared vector is initialized on driver initialization and never + disabled.*/ + nvicEnableVector(ADC_IRQn, STM32_ADC_IRQ_PRIORITY); +} + +/** + * @brief Configures and activates the ADC peripheral. + * + * @param[in] adcp pointer to the @p ADCDriver object + * + * @notapi + */ +void adc_lld_start(ADCDriver *adcp) { + + /* If in stopped state then enables the ADC and DMA clocks.*/ + if (adcp->state == ADC_STOP) { +#if STM32_ADC_USE_ADC1 + if (&ADCD1 == adcp) { + bool b; + b = dmaStreamAllocate(adcp->dmastp, + STM32_ADC_ADC1_DMA_IRQ_PRIORITY, + (stm32_dmaisr_t)adc_lld_serve_rx_interrupt, + (void *)adcp); + osalDbgAssert(!b, "stream already allocated"); + dmaStreamSetPeripheral(adcp->dmastp, &ADC1->DR); + rccEnableADC1(FALSE); + } +#endif /* STM32_ADC_USE_ADC1 */ + +#if STM32_ADC_USE_ADC2 + if (&ADCD2 == adcp) { + bool b; + b = dmaStreamAllocate(adcp->dmastp, + STM32_ADC_ADC2_DMA_IRQ_PRIORITY, + (stm32_dmaisr_t)adc_lld_serve_rx_interrupt, + (void *)adcp); + osalDbgAssert(!b, "stream already allocated"); + dmaStreamSetPeripheral(adcp->dmastp, &ADC2->DR); + rccEnableADC2(FALSE); + } +#endif /* STM32_ADC_USE_ADC2 */ + +#if STM32_ADC_USE_ADC3 + if (&ADCD3 == adcp) { + bool b; + b = dmaStreamAllocate(adcp->dmastp, + STM32_ADC_ADC3_DMA_IRQ_PRIORITY, + (stm32_dmaisr_t)adc_lld_serve_rx_interrupt, + (void *)adcp); + osalDbgAssert(!b, "stream already allocated"); + dmaStreamSetPeripheral(adcp->dmastp, &ADC3->DR); + rccEnableADC3(FALSE); + } +#endif /* STM32_ADC_USE_ADC3 */ + + /* This is a common register but apparently it requires that at least one + of the ADCs is clocked in order to allow writing, see bug 3575297.*/ + ADC->CCR = (ADC->CCR & (ADC_CCR_TSVREFE | ADC_CCR_VBATE)) | + (STM32_ADC_ADCPRE << 16); + + /* ADC initial setup, starting the analog part here in order to reduce + the latency when starting a conversion.*/ + adcp->adc->CR1 = 0; + adcp->adc->CR2 = 0; + adcp->adc->CR2 = ADC_CR2_ADON; + } +} + +/** + * @brief Deactivates the ADC peripheral. + * + * @param[in] adcp pointer to the @p ADCDriver object + * + * @notapi + */ +void adc_lld_stop(ADCDriver *adcp) { + + /* If in ready state then disables the ADC clock.*/ + if (adcp->state == ADC_READY) { + dmaStreamRelease(adcp->dmastp); + adcp->adc->CR1 = 0; + adcp->adc->CR2 = 0; + +#if STM32_ADC_USE_ADC1 + if (&ADCD1 == adcp) + rccDisableADC1(FALSE); +#endif + +#if STM32_ADC_USE_ADC2 + if (&ADCD2 == adcp) + rccDisableADC2(FALSE); +#endif + +#if STM32_ADC_USE_ADC3 + if (&ADCD3 == adcp) + rccDisableADC3(FALSE); +#endif + } +} + +/** + * @brief Starts an ADC conversion. + * + * @param[in] adcp pointer to the @p ADCDriver object + * + * @notapi + */ +void adc_lld_start_conversion(ADCDriver *adcp) { + uint32_t mode; + const ADCConversionGroup *grpp = adcp->grpp; + + /* DMA setup.*/ + mode = adcp->dmamode; + if (grpp->circular) { + mode |= STM32_DMA_CR_CIRC; + } + if (adcp->depth > 1) { + /* If the buffer depth is greater than one then the half transfer interrupt + interrupt is enabled in order to allows streaming processing.*/ + mode |= STM32_DMA_CR_HTIE; + } + dmaStreamSetMemory0(adcp->dmastp, adcp->samples); + dmaStreamSetTransactionSize(adcp->dmastp, (uint32_t)grpp->num_channels * + (uint32_t)adcp->depth); + dmaStreamSetMode(adcp->dmastp, mode); + dmaStreamEnable(adcp->dmastp); + + /* ADC setup.*/ + adcp->adc->SR = 0; + adcp->adc->SMPR1 = grpp->smpr1; + adcp->adc->SMPR2 = grpp->smpr2; + adcp->adc->SQR1 = grpp->sqr1; + adcp->adc->SQR2 = grpp->sqr2; + adcp->adc->SQR3 = grpp->sqr3; + + /* ADC configuration and start, the start is performed using the method + specified in the CR2 configuration, usually ADC_CR2_SWSTART.*/ + adcp->adc->CR1 = grpp->cr1 | ADC_CR1_OVRIE | ADC_CR1_SCAN; + if ((grpp->cr2 & ADC_CR2_SWSTART) != 0) + adcp->adc->CR2 = grpp->cr2 | ADC_CR2_CONT | ADC_CR2_DMA | + ADC_CR2_DDS | ADC_CR2_ADON; + else + adcp->adc->CR2 = grpp->cr2 | ADC_CR2_DMA | + ADC_CR2_DDS | ADC_CR2_ADON; +} + +/** + * @brief Stops an ongoing conversion. + * + * @param[in] adcp pointer to the @p ADCDriver object + * + * @notapi + */ +void adc_lld_stop_conversion(ADCDriver *adcp) { + + dmaStreamDisable(adcp->dmastp); + adcp->adc->CR1 = 0; + adcp->adc->CR2 = 0; + adcp->adc->CR2 = ADC_CR2_ADON; +} + +/** + * @brief Enables the TSVREFE bit. + * @details The TSVREFE bit is required in order to sample the internal + * temperature sensor and internal reference voltage. + * @note This is an STM32-only functionality. + */ +void adcSTM32EnableTSVREFE(void) { + + ADC->CCR |= ADC_CCR_TSVREFE; +} + +/** + * @brief Disables the TSVREFE bit. + * @details The TSVREFE bit is required in order to sample the internal + * temperature sensor and internal reference voltage. + * @note This is an STM32-only functionality. + */ +void adcSTM32DisableTSVREFE(void) { + + ADC->CCR &= ~ADC_CCR_TSVREFE; +} + +/** + * @brief Enables the VBATE bit. + * @details The VBATE bit is required in order to sample the VBAT channel. + * @note This is an STM32-only functionality. + * @note This function is meant to be called after @p adcStart(). + */ +void adcSTM32EnableVBATE(void) { + + ADC->CCR |= ADC_CCR_VBATE; +} + +/** + * @brief Disables the VBATE bit. + * @details The VBATE bit is required in order to sample the VBAT channel. + * @note This is an STM32-only functionality. + * @note This function is meant to be called after @p adcStart(). + */ +void adcSTM32DisableVBATE(void) { + + ADC->CCR &= ~ADC_CCR_VBATE; +} + +#endif /* HAL_USE_ADC */ + +/** @} */ diff --git a/os/hal/ports/STM32F4xx/adc_lld.h b/os/hal/ports/STM32F4xx/adc_lld.h new file mode 100644 index 000000000..c8f0570eb --- /dev/null +++ b/os/hal/ports/STM32F4xx/adc_lld.h @@ -0,0 +1,563 @@ +/* + ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file STM32F4xx/adc_lld.h + * @brief STM32F4xx/STM32F2xx ADC subsystem low level driver header. + * + * @addtogroup ADC + * @{ + */ + +#ifndef _ADC_LLD_H_ +#define _ADC_LLD_H_ + +#if HAL_USE_ADC || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver constants. */ +/*===========================================================================*/ + +/** + * @name Absolute Maximum Ratings + * @{ + */ +/** + * @brief Minimum ADC clock frequency. + */ +#define STM32_ADCCLK_MIN 600000 + +/** + * @brief Maximum ADC clock frequency. + */ +#if defined(STM32F4XX) || defined(__DOXYGEN__) +#define STM32_ADCCLK_MAX 36000000 +#else +#define STM32_ADCCLK_MAX 30000000 +#endif +/** @} */ + +/** + * @name Triggers selection + * @{ + */ +#define ADC_CR2_EXTSEL_SRC(n) ((n) << 24) /**< @brief Trigger source. */ +/** @} */ + +/** + * @name ADC clock divider settings + * @{ + */ +#define ADC_CCR_ADCPRE_DIV2 0 +#define ADC_CCR_ADCPRE_DIV4 1 +#define ADC_CCR_ADCPRE_DIV6 2 +#define ADC_CCR_ADCPRE_DIV8 3 +/** @} */ + +/** + * @name Available analog channels + * @{ + */ +#define ADC_CHANNEL_IN0 0 /**< @brief External analog input 0. */ +#define ADC_CHANNEL_IN1 1 /**< @brief External analog input 1. */ +#define ADC_CHANNEL_IN2 2 /**< @brief External analog input 2. */ +#define ADC_CHANNEL_IN3 3 /**< @brief External analog input 3. */ +#define ADC_CHANNEL_IN4 4 /**< @brief External analog input 4. */ +#define ADC_CHANNEL_IN5 5 /**< @brief External analog input 5. */ +#define ADC_CHANNEL_IN6 6 /**< @brief External analog input 6. */ +#define ADC_CHANNEL_IN7 7 /**< @brief External analog input 7. */ +#define ADC_CHANNEL_IN8 8 /**< @brief External analog input 8. */ +#define ADC_CHANNEL_IN9 9 /**< @brief External analog input 9. */ +#define ADC_CHANNEL_IN10 10 /**< @brief External analog input 10. */ +#define ADC_CHANNEL_IN11 11 /**< @brief External analog input 11. */ +#define ADC_CHANNEL_IN12 12 /**< @brief External analog input 12. */ +#define ADC_CHANNEL_IN13 13 /**< @brief External analog input 13. */ +#define ADC_CHANNEL_IN14 14 /**< @brief External analog input 14. */ +#define ADC_CHANNEL_IN15 15 /**< @brief External analog input 15. */ +#define ADC_CHANNEL_SENSOR 16 /**< @brief Internal temperature sensor. + @note Available onADC1 only. */ +#define ADC_CHANNEL_VREFINT 17 /**< @brief Internal reference. + @note Available onADC1 only. */ +#define ADC_CHANNEL_VBAT 18 /**< @brief VBAT. + @note Available onADC1 only. */ +/** @} */ + +/** + * @name Sampling rates + * @{ + */ +#define ADC_SAMPLE_3 0 /**< @brief 3 cycles sampling time. */ +#define ADC_SAMPLE_15 1 /**< @brief 15 cycles sampling time. */ +#define ADC_SAMPLE_28 2 /**< @brief 28 cycles sampling time. */ +#define ADC_SAMPLE_56 3 /**< @brief 56 cycles sampling time. */ +#define ADC_SAMPLE_84 4 /**< @brief 84 cycles sampling time. */ +#define ADC_SAMPLE_112 5 /**< @brief 112 cycles sampling time. */ +#define ADC_SAMPLE_144 6 /**< @brief 144 cycles sampling time. */ +#define ADC_SAMPLE_480 7 /**< @brief 480 cycles sampling time. */ +/** @} */ + +/*===========================================================================*/ +/* Driver pre-compile time settings. */ +/*===========================================================================*/ + +/** + * @name Configuration options + * @{ + */ +/** + * @brief ADC common clock divider. + * @note This setting is influenced by the VDDA voltage and other + * external conditions, please refer to the datasheet for more + * info.
+ * See section 5.3.20 "12-bit ADC characteristics". + */ +#if !defined(STM32_ADC_ADCPRE) || defined(__DOXYGEN__) +#define STM32_ADC_ADCPRE ADC_CCR_ADCPRE_DIV2 +#endif + +/** + * @brief ADC1 driver enable switch. + * @details If set to @p TRUE the support for ADC1 is included. + * @note The default is @p TRUE. + */ +#if !defined(STM32_ADC_USE_ADC1) || defined(__DOXYGEN__) +#define STM32_ADC_USE_ADC1 FALSE +#endif + +/** + * @brief ADC2 driver enable switch. + * @details If set to @p TRUE the support for ADC2 is included. + * @note The default is @p TRUE. + */ +#if !defined(STM32_ADC_USE_ADC2) || defined(__DOXYGEN__) +#define STM32_ADC_USE_ADC2 FALSE +#endif + +/** + * @brief ADC3 driver enable switch. + * @details If set to @p TRUE the support for ADC3 is included. + * @note The default is @p TRUE. + */ +#if !defined(STM32_ADC_USE_ADC3) || defined(__DOXYGEN__) +#define STM32_ADC_USE_ADC3 FALSE +#endif + +/** + * @brief DMA stream used for ADC1 operations. + */ +#if !defined(STM32_ADC_ADC1_DMA_STREAM) || defined(__DOXYGEN__) +#define STM32_ADC_ADC1_DMA_STREAM STM32_DMA_STREAM_ID(2, 4) +#endif + +/** + * @brief DMA stream used for ADC2 operations. + */ +#if !defined(STM32_ADC_ADC2_DMA_STREAM) || defined(__DOXYGEN__) +#define STM32_ADC_ADC2_DMA_STREAM STM32_DMA_STREAM_ID(2, 2) +#endif + +/** + * @brief DMA stream used for ADC3 operations. + */ +#if !defined(STM32_ADC_ADC3_DMA_STREAM) || defined(__DOXYGEN__) +#define STM32_ADC_ADC3_DMA_STREAM STM32_DMA_STREAM_ID(2, 1) +#endif + +/** + * @brief ADC1 DMA priority (0..3|lowest..highest). + */ +#if !defined(STM32_ADC_ADC1_DMA_PRIORITY) || defined(__DOXYGEN__) +#define STM32_ADC_ADC1_DMA_PRIORITY 2 +#endif + +/** + * @brief ADC2 DMA priority (0..3|lowest..highest). + */ +#if !defined(STM32_ADC_ADC2_DMA_PRIORITY) || defined(__DOXYGEN__) +#define STM32_ADC_ADC2_DMA_PRIORITY 2 +#endif + +/** + * @brief ADC3 DMA priority (0..3|lowest..highest). + */ +#if !defined(STM32_ADC_ADC3_DMA_PRIORITY) || defined(__DOXYGEN__) +#define STM32_ADC_ADC3_DMA_PRIORITY 2 +#endif + +/** + * @brief ADC interrupt priority level setting. + * @note This setting is shared among ADC1, ADC2 and ADC3 because + * all ADCs share the same vector. + */ +#if !defined(STM32_ADC_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_ADC_IRQ_PRIORITY 5 +#endif + +/** + * @brief ADC1 DMA interrupt priority level setting. + */ +#if !defined(STM32_ADC_ADC1_DMA_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_ADC_ADC1_DMA_IRQ_PRIORITY 5 +#endif + +/** + * @brief ADC2 DMA interrupt priority level setting. + */ +#if !defined(STM32_ADC_ADC2_DMA_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_ADC_ADC2_DMA_IRQ_PRIORITY 5 +#endif + +/** + * @brief ADC3 DMA interrupt priority level setting. + */ +#if !defined(STM32_ADC_ADC3_DMA_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_ADC_ADC3_DMA_IRQ_PRIORITY 5 +#endif + +/** @} */ + +/*===========================================================================*/ +/* Derived constants and error checks. */ +/*===========================================================================*/ + +#if STM32_ADC_USE_ADC1 && !STM32_HAS_ADC1 +#error "ADC1 not present in the selected device" +#endif + +#if STM32_ADC_USE_ADC2 && !STM32_HAS_ADC2 +#error "ADC2 not present in the selected device" +#endif + +#if STM32_ADC_USE_ADC3 && !STM32_HAS_ADC3 +#error "ADC3 not present in the selected device" +#endif + +#if !STM32_ADC_USE_ADC1 && !STM32_ADC_USE_ADC2 && !STM32_ADC_USE_ADC3 +#error "ADC driver activated but no ADC peripheral assigned" +#endif + +#if STM32_ADC_USE_ADC1 && \ + !STM32_DMA_IS_VALID_ID(STM32_ADC_ADC1_DMA_STREAM, STM32_ADC1_DMA_MSK) +#error "invalid DMA stream associated to ADC1" +#endif + +#if STM32_ADC_USE_ADC2 && \ + !STM32_DMA_IS_VALID_ID(STM32_ADC_ADC2_DMA_STREAM, STM32_ADC2_DMA_MSK) +#error "invalid DMA stream associated to ADC2" +#endif + +#if STM32_ADC_USE_ADC3 && \ + !STM32_DMA_IS_VALID_ID(STM32_ADC_ADC3_DMA_STREAM, STM32_ADC3_DMA_MSK) +#error "invalid DMA stream associated to ADC3" +#endif + +/* ADC clock related settings and checks.*/ +#if STM32_ADC_ADCPRE == ADC_CCR_ADCPRE_DIV2 +#define STM32_ADCCLK (STM32_PCLK2 / 2) +#elif STM32_ADC_ADCPRE == ADC_CCR_ADCPRE_DIV4 +#define STM32_ADCCLK (STM32_PCLK2 / 4) +#elif STM32_ADC_ADCPRE == ADC_CCR_ADCPRE_DIV6 +#define STM32_ADCCLK (STM32_PCLK2 / 6) +#elif STM32_ADC_ADCPRE == ADC_CCR_ADCPRE_DIV8 +#define STM32_ADCCLK (STM32_PCLK2 / 8) +#else +#error "invalid STM32_ADC_ADCPRE value specified" +#endif + +#if (STM32_ADCCLK < STM32_ADCCLK_MIN) || (STM32_ADCCLK > STM32_ADCCLK_MAX) +#error "STM32_ADCCLK outside acceptable range (STM32_ADCCLK_MIN...STM32_ADCCLK_MAX)" +#endif + +#if !defined(STM32_DMA_REQUIRED) +#define STM32_DMA_REQUIRED +#endif + +/*===========================================================================*/ +/* Driver data structures and types. */ +/*===========================================================================*/ + +/** + * @brief ADC sample data type. + */ +typedef uint16_t adcsample_t; + +/** + * @brief Channels number in a conversion group. + */ +typedef uint16_t adc_channels_num_t; + +/** + * @brief Possible ADC failure causes. + * @note Error codes are architecture dependent and should not relied + * upon. + */ +typedef enum { + ADC_ERR_DMAFAILURE = 0, /**< DMA operations failure. */ + ADC_ERR_OVERFLOW = 1 /**< ADC overflow condition. */ +} adcerror_t; + +/** + * @brief Type of a structure representing an ADC driver. + */ +typedef struct ADCDriver ADCDriver; + +/** + * @brief ADC notification callback type. + * + * @param[in] adcp pointer to the @p ADCDriver object triggering the + * callback + * @param[in] buffer pointer to the most recent samples data + * @param[in] n number of buffer rows available starting from @p buffer + */ +typedef void (*adccallback_t)(ADCDriver *adcp, adcsample_t *buffer, size_t n); + +/** + * @brief ADC error callback type. + * + * @param[in] adcp pointer to the @p ADCDriver object triggering the + * callback + * @param[in] err ADC error code + */ +typedef void (*adcerrorcallback_t)(ADCDriver *adcp, adcerror_t err); + +/** + * @brief Conversion group configuration structure. + * @details This implementation-dependent structure describes a conversion + * operation. + * @note The use of this configuration structure requires knowledge of + * STM32 ADC cell registers interface, please refer to the STM32 + * reference manual for details. + */ +typedef struct { + /** + * @brief Enables the circular buffer mode for the group. + */ + bool_t circular; + /** + * @brief Number of the analog channels belonging to the conversion group. + */ + adc_channels_num_t num_channels; + /** + * @brief Callback function associated to the group or @p NULL. + */ + adccallback_t end_cb; + /** + * @brief Error callback or @p NULL. + */ + adcerrorcallback_t error_cb; + /* End of the mandatory fields.*/ + /** + * @brief ADC CR1 register initialization data. + * @note All the required bits must be defined into this field except + * @p ADC_CR1_SCAN that is enforced inside the driver. + */ + uint32_t cr1; + /** + * @brief ADC CR2 register initialization data. + * @note All the required bits must be defined into this field except + * @p ADC_CR2_DMA, @p ADC_CR2_CONT and @p ADC_CR2_ADON that are + * enforced inside the driver. + */ + uint32_t cr2; + /** + * @brief ADC SMPR1 register initialization data. + * @details In this field must be specified the sample times for channels + * 10...18. + */ + uint32_t smpr1; + /** + * @brief ADC SMPR2 register initialization data. + * @details In this field must be specified the sample times for channels + * 0...9. + */ + uint32_t smpr2; + /** + * @brief ADC SQR1 register initialization data. + * @details Conversion group sequence 13...16 + sequence length. + */ + uint32_t sqr1; + /** + * @brief ADC SQR2 register initialization data. + * @details Conversion group sequence 7...12. + */ + uint32_t sqr2; + /** + * @brief ADC SQR3 register initialization data. + * @details Conversion group sequence 1...6. + */ + uint32_t sqr3; +} ADCConversionGroup; + +/** + * @brief Driver configuration structure. + * @note It could be empty on some architectures. + */ +typedef struct { + uint32_t dummy; +} ADCConfig; + +/** + * @brief Structure representing an ADC driver. + */ +struct ADCDriver { + /** + * @brief Driver state. + */ + adcstate_t state; + /** + * @brief Current configuration data. + */ + const ADCConfig *config; + /** + * @brief Current samples buffer pointer or @p NULL. + */ + adcsample_t *samples; + /** + * @brief Current samples buffer depth or @p 0. + */ + size_t depth; + /** + * @brief Current conversion group pointer or @p NULL. + */ + const ADCConversionGroup *grpp; +#if ADC_USE_WAIT || defined(__DOXYGEN__) + /** + * @brief Waiting thread. + */ + thread_reference_t thread; +#endif +#if ADC_USE_MUTUAL_EXCLUSION || defined(__DOXYGEN__) + /** + * @brief Mutex protecting the peripheral. + */ + mutex_t mutex; +#endif /* ADC_USE_MUTUAL_EXCLUSION */ +#if defined(ADC_DRIVER_EXT_FIELDS) + ADC_DRIVER_EXT_FIELDS +#endif + /* End of the mandatory fields.*/ + /** + * @brief Pointer to the ADCx registers block. + */ + ADC_TypeDef *adc; + /** + * @brief Pointer to associated DMA channel. + */ + const stm32_dma_stream_t *dmastp; + /** + * @brief DMA mode bit mask. + */ + uint32_t dmamode; +}; + +/*===========================================================================*/ +/* Driver macros. */ +/*===========================================================================*/ + +/** + * @name Sequences building helper macros + * @{ + */ +/** + * @brief Number of channels in a conversion sequence. + */ +#define ADC_SQR1_NUM_CH(n) (((n) - 1) << 20) + +#define ADC_SQR3_SQ1_N(n) ((n) << 0) /**< @brief 1st channel in seq. */ +#define ADC_SQR3_SQ2_N(n) ((n) << 5) /**< @brief 2nd channel in seq. */ +#define ADC_SQR3_SQ3_N(n) ((n) << 10) /**< @brief 3rd channel in seq. */ +#define ADC_SQR3_SQ4_N(n) ((n) << 15) /**< @brief 4th channel in seq. */ +#define ADC_SQR3_SQ5_N(n) ((n) << 20) /**< @brief 5th channel in seq. */ +#define ADC_SQR3_SQ6_N(n) ((n) << 25) /**< @brief 6th channel in seq. */ + +#define ADC_SQR2_SQ7_N(n) ((n) << 0) /**< @brief 7th channel in seq. */ +#define ADC_SQR2_SQ8_N(n) ((n) << 5) /**< @brief 8th channel in seq. */ +#define ADC_SQR2_SQ9_N(n) ((n) << 10) /**< @brief 9th channel in seq. */ +#define ADC_SQR2_SQ10_N(n) ((n) << 15) /**< @brief 10th channel in seq.*/ +#define ADC_SQR2_SQ11_N(n) ((n) << 20) /**< @brief 11th channel in seq.*/ +#define ADC_SQR2_SQ12_N(n) ((n) << 25) /**< @brief 12th channel in seq.*/ + +#define ADC_SQR1_SQ13_N(n) ((n) << 0) /**< @brief 13th channel in seq.*/ +#define ADC_SQR1_SQ14_N(n) ((n) << 5) /**< @brief 14th channel in seq.*/ +#define ADC_SQR1_SQ15_N(n) ((n) << 10) /**< @brief 15th channel in seq.*/ +#define ADC_SQR1_SQ16_N(n) ((n) << 15) /**< @brief 16th channel in seq.*/ +/** @} */ + +/** + * @name Sampling rate settings helper macros + * @{ + */ +#define ADC_SMPR2_SMP_AN0(n) ((n) << 0) /**< @brief AN0 sampling time. */ +#define ADC_SMPR2_SMP_AN1(n) ((n) << 3) /**< @brief AN1 sampling time. */ +#define ADC_SMPR2_SMP_AN2(n) ((n) << 6) /**< @brief AN2 sampling time. */ +#define ADC_SMPR2_SMP_AN3(n) ((n) << 9) /**< @brief AN3 sampling time. */ +#define ADC_SMPR2_SMP_AN4(n) ((n) << 12) /**< @brief AN4 sampling time. */ +#define ADC_SMPR2_SMP_AN5(n) ((n) << 15) /**< @brief AN5 sampling time. */ +#define ADC_SMPR2_SMP_AN6(n) ((n) << 18) /**< @brief AN6 sampling time. */ +#define ADC_SMPR2_SMP_AN7(n) ((n) << 21) /**< @brief AN7 sampling time. */ +#define ADC_SMPR2_SMP_AN8(n) ((n) << 24) /**< @brief AN8 sampling time. */ +#define ADC_SMPR2_SMP_AN9(n) ((n) << 27) /**< @brief AN9 sampling time. */ + +#define ADC_SMPR1_SMP_AN10(n) ((n) << 0) /**< @brief AN10 sampling time. */ +#define ADC_SMPR1_SMP_AN11(n) ((n) << 3) /**< @brief AN11 sampling time. */ +#define ADC_SMPR1_SMP_AN12(n) ((n) << 6) /**< @brief AN12 sampling time. */ +#define ADC_SMPR1_SMP_AN13(n) ((n) << 9) /**< @brief AN13 sampling time. */ +#define ADC_SMPR1_SMP_AN14(n) ((n) << 12) /**< @brief AN14 sampling time. */ +#define ADC_SMPR1_SMP_AN15(n) ((n) << 15) /**< @brief AN15 sampling time. */ +#define ADC_SMPR1_SMP_SENSOR(n) ((n) << 18) /**< @brief Temperature Sensor + sampling time. */ +#define ADC_SMPR1_SMP_VREF(n) ((n) << 21) /**< @brief Voltage Reference + sampling time. */ +#define ADC_SMPR1_SMP_VBAT(n) ((n) << 24) /**< @brief VBAT sampling time. */ +/** @} */ + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +#if STM32_ADC_USE_ADC1 && !defined(__DOXYGEN__) +extern ADCDriver ADCD1; +#endif + +#if STM32_ADC_USE_ADC2 && !defined(__DOXYGEN__) +extern ADCDriver ADCD2; +#endif + +#if STM32_ADC_USE_ADC3 && !defined(__DOXYGEN__) +extern ADCDriver ADCD3; +#endif + +#ifdef __cplusplus +extern "C" { +#endif + void adc_lld_init(void); + void adc_lld_start(ADCDriver *adcp); + void adc_lld_stop(ADCDriver *adcp); + void adc_lld_start_conversion(ADCDriver *adcp); + void adc_lld_stop_conversion(ADCDriver *adcp); + void adcSTM32EnableTSVREFE(void); + void adcSTM32DisableTSVREFE(void); + void adcSTM32EnableVBATE(void); + void adcSTM32DisableVBATE(void); +#ifdef __cplusplus +} +#endif + +#endif /* HAL_USE_ADC */ + +#endif /* _ADC_LLD_H_ */ + +/** @} */ diff --git a/os/hal/ports/STM32F4xx/ext_lld_isr.c b/os/hal/ports/STM32F4xx/ext_lld_isr.c new file mode 100644 index 000000000..dd1491557 --- /dev/null +++ b/os/hal/ports/STM32F4xx/ext_lld_isr.c @@ -0,0 +1,338 @@ +/* + ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file STM32F4xx/ext_lld_isr.c + * @brief STM32F4xx/STM32F2xx EXT subsystem low level driver ISR code. + * + * @addtogroup EXT + * @{ + */ + +#include "hal.h" + +#if HAL_USE_EXT || defined(__DOXYGEN__) + +#include "ext_lld_isr.h" + +/*===========================================================================*/ +/* Driver local definitions. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver exported variables. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local variables. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local functions. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver interrupt handlers. */ +/*===========================================================================*/ + +/** + * @brief EXTI[0] interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(Vector58) { + + OSAL_IRQ_PROLOGUE(); + + EXTI->PR = (1 << 0); + EXTD1.config->channels[0].cb(&EXTD1, 0); + + OSAL_IRQ_EPILOGUE(); +} + +/** + * @brief EXTI[1] interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(Vector5C) { + + OSAL_IRQ_PROLOGUE(); + + EXTI->PR = (1 << 1); + EXTD1.config->channels[1].cb(&EXTD1, 1); + + OSAL_IRQ_EPILOGUE(); +} + +/** + * @brief EXTI[2] interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(Vector60) { + + OSAL_IRQ_PROLOGUE(); + + EXTI->PR = (1 << 2); + EXTD1.config->channels[2].cb(&EXTD1, 2); + + OSAL_IRQ_EPILOGUE(); +} + +/** + * @brief EXTI[3] interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(Vector64) { + + OSAL_IRQ_PROLOGUE(); + + EXTI->PR = (1 << 3); + EXTD1.config->channels[3].cb(&EXTD1, 3); + + OSAL_IRQ_EPILOGUE(); +} + +/** + * @brief EXTI[4] interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(Vector68) { + + OSAL_IRQ_PROLOGUE(); + + EXTI->PR = (1 << 4); + EXTD1.config->channels[4].cb(&EXTD1, 4); + + OSAL_IRQ_EPILOGUE(); +} + +/** + * @brief EXTI[5]...EXTI[9] interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(Vector9C) { + uint32_t pr; + + OSAL_IRQ_PROLOGUE(); + + pr = EXTI->PR & ((1 << 5) | (1 << 6) | (1 << 7) | (1 << 8) | (1 << 9)); + EXTI->PR = pr; + if (pr & (1 << 5)) + EXTD1.config->channels[5].cb(&EXTD1, 5); + if (pr & (1 << 6)) + EXTD1.config->channels[6].cb(&EXTD1, 6); + if (pr & (1 << 7)) + EXTD1.config->channels[7].cb(&EXTD1, 7); + if (pr & (1 << 8)) + EXTD1.config->channels[8].cb(&EXTD1, 8); + if (pr & (1 << 9)) + EXTD1.config->channels[9].cb(&EXTD1, 9); + + OSAL_IRQ_EPILOGUE(); +} + +/** + * @brief EXTI[10]...EXTI[15] interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(VectorE0) { + uint32_t pr; + + OSAL_IRQ_PROLOGUE(); + + pr = EXTI->PR & ((1 << 10) | (1 << 11) | (1 << 12) | (1 << 13) | (1 << 14) | + (1 << 15)); + EXTI->PR = pr; + if (pr & (1 << 10)) + EXTD1.config->channels[10].cb(&EXTD1, 10); + if (pr & (1 << 11)) + EXTD1.config->channels[11].cb(&EXTD1, 11); + if (pr & (1 << 12)) + EXTD1.config->channels[12].cb(&EXTD1, 12); + if (pr & (1 << 13)) + EXTD1.config->channels[13].cb(&EXTD1, 13); + if (pr & (1 << 14)) + EXTD1.config->channels[14].cb(&EXTD1, 14); + if (pr & (1 << 15)) + EXTD1.config->channels[15].cb(&EXTD1, 15); + + OSAL_IRQ_EPILOGUE(); +} + +/** + * @brief EXTI[16] interrupt handler (PVD). + * + * @isr + */ +OSAL_IRQ_HANDLER(Vector44) { + + OSAL_IRQ_PROLOGUE(); + + EXTI->PR = (1 << 16); + EXTD1.config->channels[16].cb(&EXTD1, 16); + + OSAL_IRQ_EPILOGUE(); +} + +/** + * @brief EXTI[17] interrupt handler (RTC_ALARM). + * + * @isr + */ +OSAL_IRQ_HANDLER(VectorE4) { + + OSAL_IRQ_PROLOGUE(); + + EXTI->PR = (1 << 17); + EXTD1.config->channels[17].cb(&EXTD1, 17); + + OSAL_IRQ_EPILOGUE(); +} + +/** + * @brief EXTI[18] interrupt handler (OTG_FS_WKUP). + * + * @isr + */ +OSAL_IRQ_HANDLER(VectorE8) { + + OSAL_IRQ_PROLOGUE(); + + EXTI->PR = (1 << 18); + EXTD1.config->channels[18].cb(&EXTD1, 18); + + OSAL_IRQ_EPILOGUE(); +} + +/** + * @brief EXTI[19] interrupt handler (ETH_WKUP). + * + * @isr + */ +OSAL_IRQ_HANDLER(Vector138) { + + OSAL_IRQ_PROLOGUE(); + + EXTI->PR = (1 << 19); + EXTD1.config->channels[19].cb(&EXTD1, 19); + + OSAL_IRQ_EPILOGUE(); +} + +/** + * @brief EXTI[20] interrupt handler (OTG_HS_WKUP). + * + * @isr + */ +OSAL_IRQ_HANDLER(Vector170) { + + OSAL_IRQ_PROLOGUE(); + + EXTI->PR = (1 << 20); + EXTD1.config->channels[20].cb(&EXTD1, 20); + + OSAL_IRQ_EPILOGUE(); +} + +/** + * @brief EXTI[21] interrupt handler (TAMPER_STAMP). + * + * @isr + */ +OSAL_IRQ_HANDLER(Vector48) { + + OSAL_IRQ_PROLOGUE(); + + EXTI->PR = (1 << 21); + EXTD1.config->channels[21].cb(&EXTD1, 21); + + OSAL_IRQ_EPILOGUE(); +} + +/** + * @brief EXTI[22] interrupt handler (RTC_WKUP). + * + * @isr + */ +OSAL_IRQ_HANDLER(Vector4C) { + + OSAL_IRQ_PROLOGUE(); + + EXTI->PR = (1 << 22); + EXTD1.config->channels[22].cb(&EXTD1, 22); + + OSAL_IRQ_EPILOGUE(); +} + +/*===========================================================================*/ +/* Driver exported functions. */ +/*===========================================================================*/ + +/** + * @brief Enables EXTI IRQ sources. + * + * @notapi + */ +void ext_lld_exti_irq_enable(void) { + + nvicEnableVector(EXTI0_IRQn, STM32_EXT_EXTI0_IRQ_PRIORITY); + nvicEnableVector(EXTI1_IRQn, STM32_EXT_EXTI1_IRQ_PRIORITY); + nvicEnableVector(EXTI2_IRQn, STM32_EXT_EXTI2_IRQ_PRIORITY); + nvicEnableVector(EXTI3_IRQn, STM32_EXT_EXTI3_IRQ_PRIORITY); + nvicEnableVector(EXTI4_IRQn, STM32_EXT_EXTI4_IRQ_PRIORITY); + nvicEnableVector(EXTI9_5_IRQn, STM32_EXT_EXTI5_9_IRQ_PRIORITY); + nvicEnableVector(EXTI15_10_IRQn, STM32_EXT_EXTI10_15_IRQ_PRIORITY); + nvicEnableVector(PVD_IRQn, STM32_EXT_EXTI16_IRQ_PRIORITY); + nvicEnableVector(RTC_Alarm_IRQn, STM32_EXT_EXTI17_IRQ_PRIORITY); + nvicEnableVector(OTG_FS_WKUP_IRQn, STM32_EXT_EXTI18_IRQ_PRIORITY); + nvicEnableVector(ETH_WKUP_IRQn, STM32_EXT_EXTI19_IRQ_PRIORITY); + nvicEnableVector(OTG_HS_WKUP_IRQn, STM32_EXT_EXTI20_IRQ_PRIORITY); + nvicEnableVector(TAMP_STAMP_IRQn, STM32_EXT_EXTI21_IRQ_PRIORITY); + nvicEnableVector(RTC_WKUP_IRQn, STM32_EXT_EXTI22_IRQ_PRIORITY); +} + +/** + * @brief Disables EXTI IRQ sources. + * + * @notapi + */ +void ext_lld_exti_irq_disable(void) { + + nvicDisableVector(EXTI0_IRQn); + nvicDisableVector(EXTI1_IRQn); + nvicDisableVector(EXTI2_IRQn); + nvicDisableVector(EXTI3_IRQn); + nvicDisableVector(EXTI4_IRQn); + nvicDisableVector(EXTI9_5_IRQn); + nvicDisableVector(EXTI15_10_IRQn); + nvicDisableVector(PVD_IRQn); + nvicDisableVector(RTC_Alarm_IRQn); + nvicDisableVector(OTG_FS_WKUP_IRQn); + nvicDisableVector(ETH_WKUP_IRQn); + nvicDisableVector(OTG_HS_WKUP_IRQn); + nvicDisableVector(TAMP_STAMP_IRQn); + nvicDisableVector(RTC_WKUP_IRQn); +} + +#endif /* HAL_USE_EXT */ + +/** @} */ diff --git a/os/hal/ports/STM32F4xx/ext_lld_isr.h b/os/hal/ports/STM32F4xx/ext_lld_isr.h new file mode 100644 index 000000000..33e8e0be1 --- /dev/null +++ b/os/hal/ports/STM32F4xx/ext_lld_isr.h @@ -0,0 +1,170 @@ +/* + ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file STM32F4xx/ext_lld_isr.h + * @brief STM32F4xx/STM32F2xx EXT subsystem low level driver ISR header. + * + * @addtogroup EXT + * @{ + */ + +#ifndef _EXT_LLD_ISR_H_ +#define _EXT_LLD_ISR_H_ + +#if HAL_USE_EXT || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver constants. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver pre-compile time settings. */ +/*===========================================================================*/ + +/** + * @name Configuration options + * @{ + */ +/** + * @brief EXTI0 interrupt priority level setting. + */ +#if !defined(STM32_EXT_EXTI0_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_EXT_EXTI0_IRQ_PRIORITY 6 +#endif + +/** + * @brief EXTI1 interrupt priority level setting. + */ +#if !defined(STM32_EXT_EXTI1_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_EXT_EXTI1_IRQ_PRIORITY 6 +#endif + +/** + * @brief EXTI2 interrupt priority level setting. + */ +#if !defined(STM32_EXT_EXTI2_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_EXT_EXTI2_IRQ_PRIORITY 6 +#endif + +/** + * @brief EXTI3 interrupt priority level setting. + */ +#if !defined(STM32_EXT_EXTI3_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_EXT_EXTI3_IRQ_PRIORITY 6 +#endif + +/** + * @brief EXTI4 interrupt priority level setting. + */ +#if !defined(STM32_EXT_EXTI4_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_EXT_EXTI4_IRQ_PRIORITY 6 +#endif + +/** + * @brief EXTI9..5 interrupt priority level setting. + */ +#if !defined(STM32_EXT_EXTI5_9_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_EXT_EXTI5_9_IRQ_PRIORITY 6 +#endif + +/** + * @brief EXTI15..10 interrupt priority level setting. + */ +#if !defined(STM32_EXT_EXTI10_15_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_EXT_EXTI10_15_IRQ_PRIORITY 6 +#endif + +/** + * @brief EXTI16 interrupt priority level setting. + */ +#if !defined(STM32_EXT_EXTI16_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_EXT_EXTI16_IRQ_PRIORITY 6 +#endif + +/** + * @brief EXTI17 interrupt priority level setting. + */ +#if !defined(STM32_EXT_EXTI17_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_EXT_EXTI17_IRQ_PRIORITY 6 +#endif + +/** + * @brief EXTI18 interrupt priority level setting. + */ +#if !defined(STM32_EXT_EXTI18_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_EXT_EXTI18_IRQ_PRIORITY 6 +#endif + +/** + * @brief EXTI19 interrupt priority level setting. + */ +#if !defined(STM32_EXT_EXTI19_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_EXT_EXTI19_IRQ_PRIORITY 6 +#endif + +/** + * @brief EXTI20 interrupt priority level setting. + */ +#if !defined(STM32_EXT_EXTI20_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_EXT_EXTI20_IRQ_PRIORITY 6 +#endif + +/** + * @brief EXTI21 interrupt priority level setting. + */ +#if !defined(STM32_EXT_EXTI21_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_EXT_EXTI21_IRQ_PRIORITY 6 +#endif + +/** + * @brief EXTI22 interrupt priority level setting. + */ +#if !defined(STM32_EXT_EXTI22_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_EXT_EXTI22_IRQ_PRIORITY 6 +#endif +/** @} */ + +/*===========================================================================*/ +/* Derived constants and error checks. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver data structures and types. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver macros. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +#ifdef __cplusplus +extern "C" { +#endif + void ext_lld_exti_irq_enable(void); + void ext_lld_exti_irq_disable(void); +#ifdef __cplusplus +} +#endif + +#endif /* HAL_USE_EXT */ + +#endif /* _EXT_LLD_ISR_H_ */ + +/** @} */ diff --git a/os/hal/ports/STM32F4xx/hal_lld.c b/os/hal/ports/STM32F4xx/hal_lld.c new file mode 100644 index 000000000..e414043cc --- /dev/null +++ b/os/hal/ports/STM32F4xx/hal_lld.c @@ -0,0 +1,225 @@ +/* + ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file STM32F4xx/hal_lld.c + * @brief STM32F4xx/STM32F2xx HAL subsystem low level driver source. + * + * @addtogroup HAL + * @{ + */ + +/* TODO: LSEBYP like in F3.*/ + +#include "hal.h" + +/*===========================================================================*/ +/* Driver local definitions. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver exported variables. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local variables and types. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local functions. */ +/*===========================================================================*/ + +/** + * @brief Initializes the backup domain. + * @note WARNING! Changing clock source impossible without resetting + * of the whole BKP domain. + */ +static void hal_lld_backup_domain_init(void) { + + /* Backup domain access enabled and left open.*/ + PWR->CR |= PWR_CR_DBP; + + /* Reset BKP domain if different clock source selected.*/ + if ((RCC->BDCR & STM32_RTCSEL_MASK) != STM32_RTCSEL) { + /* Backup domain reset.*/ + RCC->BDCR = RCC_BDCR_BDRST; + RCC->BDCR = 0; + } + +#if STM32_LSE_ENABLED + RCC->BDCR |= RCC_BDCR_LSEON; + while ((RCC->BDCR & RCC_BDCR_LSERDY) == 0) + ; /* Waits until LSE is stable. */ +#endif + +#if HAL_USE_RTC + /* If the backup domain hasn't been initialized yet then proceed with + initialization.*/ + if ((RCC->BDCR & RCC_BDCR_RTCEN) == 0) { + /* Selects clock source.*/ + RCC->BDCR |= STM32_RTCSEL; + + /* RTC clock enabled.*/ + RCC->BDCR |= RCC_BDCR_RTCEN; + } +#endif /* HAL_USE_RTC */ + +#if STM32_BKPRAM_ENABLE + rccEnableBKPSRAM(false); + + PWR->CSR |= PWR_CSR_BRE; + while ((PWR->CSR & PWR_CSR_BRR) == 0) + ; /* Waits until the regulator is stable */ +#else + PWR->CSR &= ~PWR_CSR_BRE; +#endif /* STM32_BKPRAM_ENABLE */ +} + +/*===========================================================================*/ +/* Driver interrupt handlers. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver exported functions. */ +/*===========================================================================*/ + +/** + * @brief Low level HAL driver initialization. + * + * @notapi + */ +void hal_lld_init(void) { + + /* Reset of all peripherals. AHB3 is not reseted because it could have + been initialized in the board initialization file (board.c).*/ + rccResetAHB1(~0); + rccResetAHB2(~0); + rccResetAPB1(~RCC_APB1RSTR_PWRRST); + rccResetAPB2(~0); + + /* PWR clock enabled.*/ + rccEnablePWRInterface(FALSE); + + /* Initializes the backup domain.*/ + hal_lld_backup_domain_init(); + +#if defined(STM32_DMA_REQUIRED) + dmaInit(); +#endif + + /* Programmable voltage detector enable.*/ +#if STM32_PVD_ENABLE + PWR->CR |= PWR_CR_PVDE | (STM32_PLS & STM32_PLS_MASK); +#endif /* STM32_PVD_ENABLE */ +} + +/** + * @brief STM32F2xx clocks and PLL initialization. + * @note All the involved constants come from the file @p board.h. + * @note This function should be invoked just after the system reset. + * + * @special + */ +void stm32_clock_init(void) { + +#if !STM32_NO_INIT + /* PWR clock enable.*/ + RCC->APB1ENR = RCC_APB1ENR_PWREN; + + /* PWR initialization.*/ +#if defined(STM32F4XX) || defined(__DOXYGEN__) + PWR->CR = STM32_VOS; + while ((PWR->CSR & PWR_CSR_VOSRDY) == 0) + ; /* Waits until power regulator is stable. */ +#else + PWR->CR = 0; +#endif + + /* Initial clocks setup and wait for HSI stabilization, the MSI clock is + always enabled because it is the fallback clock when PLL the fails.*/ + RCC->CR |= RCC_CR_HSION; + while ((RCC->CR & RCC_CR_HSIRDY) == 0) + ; /* Waits until HSI is stable. */ + +#if STM32_HSE_ENABLED + /* HSE activation.*/ +#if defined(STM32_HSE_BYPASS) + /* HSE Bypass.*/ + RCC->CR |= RCC_CR_HSEON | RCC_CR_HSEBYP; +#else + /* No HSE Bypass.*/ + RCC->CR |= RCC_CR_HSEON; +#endif + while ((RCC->CR & RCC_CR_HSERDY) == 0) + ; /* Waits until HSE is stable. */ +#endif + +#if STM32_LSI_ENABLED + /* LSI activation.*/ + RCC->CSR |= RCC_CSR_LSION; + while ((RCC->CSR & RCC_CSR_LSIRDY) == 0) + ; /* Waits until LSI is stable. */ +#endif + +#if STM32_ACTIVATE_PLL + /* PLL activation.*/ + RCC->PLLCFGR = STM32_PLLQ | STM32_PLLSRC | STM32_PLLP | STM32_PLLN | + STM32_PLLM; + RCC->CR |= RCC_CR_PLLON; + while (!(RCC->CR & RCC_CR_PLLRDY)) + ; /* Waits until PLL is stable. */ +#endif + +#if STM32_ACTIVATE_PLLI2S + /* PLLI2S activation.*/ + RCC->PLLI2SCFGR = STM32_PLLI2SR | STM32_PLLI2SN; + RCC->CR |= RCC_CR_PLLI2SON; + while (!(RCC->CR & RCC_CR_PLLI2SRDY)) + ; /* Waits until PLLI2S is stable. */ +#endif + + /* Other clock-related settings (dividers, MCO etc).*/ + RCC->CFGR |= STM32_MCO2PRE | STM32_MCO2SEL | STM32_MCO1PRE | STM32_MCO1SEL | + STM32_RTCPRE | STM32_PPRE2 | STM32_PPRE1 | STM32_HPRE; + + /* Flash setup.*/ +#if defined(STM32_USE_REVISION_A_FIX) + /* Some old revisions of F4x MCUs randomly crashes with compiler + optimizations enabled AND flash caches enabled. */ + if ((DBGMCU->IDCODE == 0x20006411) && (SCB->CPUID == 0x410FC241)) + FLASH->ACR = FLASH_ACR_PRFTEN | STM32_FLASHBITS; + else + FLASH->ACR = FLASH_ACR_PRFTEN | FLASH_ACR_ICEN | + FLASH_ACR_DCEN | STM32_FLASHBITS; +#else + FLASH->ACR = FLASH_ACR_PRFTEN | FLASH_ACR_ICEN | + FLASH_ACR_DCEN | STM32_FLASHBITS; +#endif + + /* Switching to the configured clock source if it is different from MSI.*/ +#if (STM32_SW != STM32_SW_HSI) + RCC->CFGR |= STM32_SW; /* Switches on the selected clock source. */ + while ((RCC->CFGR & RCC_CFGR_SWS) != (STM32_SW << 2)) + ; +#endif +#endif /* STM32_NO_INIT */ + + /* SYSCFG clock enabled here because it is a multi-functional unit shared + among multiple drivers.*/ + rccEnableAPB2(RCC_APB2ENR_SYSCFGEN, TRUE); +} + +/** @} */ diff --git a/os/hal/ports/STM32F4xx/hal_lld.h b/os/hal/ports/STM32F4xx/hal_lld.h new file mode 100644 index 000000000..ae5378c23 --- /dev/null +++ b/os/hal/ports/STM32F4xx/hal_lld.h @@ -0,0 +1,1232 @@ +/* + ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file STM32F4xx/hal_lld.h + * @brief STM32F4xx/STM32F2xx HAL subsystem low level driver header. + * @pre This module requires the following macros to be defined in the + * @p board.h file: + * - STM32_LSECLK. + * - STM32_HSECLK. + * - STM32_HSE_BYPASS (optionally). + * - STM32_VDD (as hundredths of Volt). + * . + * One of the following macros must also be defined: + * - STM32F2XX for High-performance STM32 F-2 devices. + * - STM32F4XX for High-performance STM32 F-4 devices. + * . + * + * @addtogroup HAL + * @{ + */ + +#ifndef _HAL_LLD_H_ +#define _HAL_LLD_H_ + +#include "stm32.h" +#include "stm32_registry.h" + +/*===========================================================================*/ +/* Driver constants. */ +/*===========================================================================*/ + +/** + * @brief Defines the support for realtime counters in the HAL. + */ +#define HAL_IMPLEMENTS_COUNTERS TRUE + +/** + * @name Platform identification + * @{ + */ +#if defined(STM32F4XX) || defined(__DOXYGEN__) +#define PLATFORM_NAME "STM32F4xx High Performance" +#else /* !defined(STM32F4XX) */ +#define PLATFORM_NAME "STM32F2xx High Performance" +#endif /* !defined(STM32F4XX) */ +/** @} */ + +/** + * @name Absolute Maximum Ratings + * @{ + */ +#if defined(STM32F4XX) || defined(__DOXYGEN__) +/** + * @brief Maximum HSE clock frequency. + */ +#define STM32_HSECLK_MAX 26000000 + +/** + * @brief Minimum HSE clock frequency. + */ +#define STM32_HSECLK_MIN 1000000 + +/** + * @brief Maximum LSE clock frequency. + */ +#define STM32_LSECLK_MAX 1000000 + +/** + * @brief Minimum LSE clock frequency. + */ +#define STM32_LSECLK_MIN 32768 + +/** + * @brief Maximum PLLs input clock frequency. + */ +#define STM32_PLLIN_MAX 2000000 + +/** + * @brief Minimum PLLs input clock frequency. + */ +#define STM32_PLLIN_MIN 950000 + +/** + * @brief Maximum PLLs VCO clock frequency. + */ +#define STM32_PLLVCO_MAX 432000000 + +/** + * @brief Maximum PLLs VCO clock frequency. + */ +#define STM32_PLLVCO_MIN 192000000 + +/** + * @brief Maximum PLL output clock frequency. + */ +#define STM32_PLLOUT_MAX 168000000 + +/** + * @brief Minimum PLL output clock frequency. + */ +#define STM32_PLLOUT_MIN 24000000 + +/** + * @brief Maximum APB1 clock frequency. + */ +#define STM32_PCLK1_MAX 42000000 + +/** + * @brief Maximum APB2 clock frequency. + */ +#define STM32_PCLK2_MAX 84000000 + +/** + * @brief Maximum SPI/I2S clock frequency. + */ +#define STM32_SPII2S_MAX 37500000 + +#else /* !defined(STM32F4XX) */ +#define STM32_SYSCLK_MAX 120000000 +#define STM32_HSECLK_MAX 26000000 +#define STM32_HSECLK_MIN 1000000 +#define STM32_LSECLK_MAX 1000000 +#define STM32_LSECLK_MIN 32768 +#define STM32_PLLIN_MAX 2000000 +#define STM32_PLLIN_MIN 950000 +#define STM32_PLLVCO_MAX 432000000 +#define STM32_PLLVCO_MIN 192000000 +#define STM32_PLLOUT_MAX 120000000 +#define STM32_PLLOUT_MIN 24000000 +#define STM32_PCLK1_MAX 30000000 +#define STM32_PCLK2_MAX 60000000 +#define STM32_SPII2S_MAX 37500000 +#endif /* !defined(STM32F4XX) */ +/** @} */ + +/** + * @name Internal clock sources + * @{ + */ +#define STM32_HSICLK 16000000 /**< High speed internal clock. */ +#define STM32_LSICLK 32000 /**< Low speed internal clock. */ +/** @} */ + +/** + * @name PWR_CR register bits definitions + * @{ + */ +#if defined(STM32F4XX) || defined(__DOXYGEN__) +#define STM32_VOS_MASK (1 << 14) /**< Core voltage mask. */ +#define STM32_VOS_LOW (0 << 14) /**< Core voltage set to low. */ +#define STM32_VOS_HIGH (1 << 14) /**< Core voltage set to high. */ +#endif +#define STM32_PLS_MASK (7 << 5) /**< PLS bits mask. */ +#define STM32_PLS_LEV0 (0 << 5) /**< PVD level 0. */ +#define STM32_PLS_LEV1 (1 << 5) /**< PVD level 1. */ +#define STM32_PLS_LEV2 (2 << 5) /**< PVD level 2. */ +#define STM32_PLS_LEV3 (3 << 5) /**< PVD level 3. */ +#define STM32_PLS_LEV4 (4 << 5) /**< PVD level 4. */ +#define STM32_PLS_LEV5 (5 << 5) /**< PVD level 5. */ +#define STM32_PLS_LEV6 (6 << 5) /**< PVD level 6. */ +#define STM32_PLS_LEV7 (7 << 5) /**< PVD level 7. */ +/** @} */ + +/** + * @name RCC_PLLCFGR register bits definitions + * @{ + */ +#define STM32_PLLP_MASK (3 << 16) /**< PLLP mask. */ +#define STM32_PLLP_DIV2 (0 << 16) /**< PLL clock divided by 2. */ +#define STM32_PLLP_DIV4 (1 << 16) /**< PLL clock divided by 4. */ +#define STM32_PLLP_DIV6 (2 << 16) /**< PLL clock divided by 6. */ +#define STM32_PLLP_DIV8 (3 << 16) /**< PLL clock divided by 8. */ + +#define STM32_PLLSRC_HSI (0 << 22) /**< PLL clock source is HSI. */ +#define STM32_PLLSRC_HSE (1 << 22) /**< PLL clock source is HSE. */ +/** @} */ + +/** + * @name RCC_CFGR register bits definitions + * @{ + */ +#define STM32_SW_MASK (3 << 0) /**< SW mask. */ +#define STM32_SW_HSI (0 << 0) /**< SYSCLK source is HSI. */ +#define STM32_SW_HSE (1 << 0) /**< SYSCLK source is HSE. */ +#define STM32_SW_PLL (2 << 0) /**< SYSCLK source is PLL. */ + +#define STM32_HPRE_MASK (15 << 4) /**< HPRE mask. */ +#define STM32_HPRE_DIV1 (0 << 4) /**< SYSCLK divided by 1. */ +#define STM32_HPRE_DIV2 (8 << 4) /**< SYSCLK divided by 2. */ +#define STM32_HPRE_DIV4 (9 << 4) /**< SYSCLK divided by 4. */ +#define STM32_HPRE_DIV8 (10 << 4) /**< SYSCLK divided by 8. */ +#define STM32_HPRE_DIV16 (11 << 4) /**< SYSCLK divided by 16. */ +#define STM32_HPRE_DIV64 (12 << 4) /**< SYSCLK divided by 64. */ +#define STM32_HPRE_DIV128 (13 << 4) /**< SYSCLK divided by 128. */ +#define STM32_HPRE_DIV256 (14 << 4) /**< SYSCLK divided by 256. */ +#define STM32_HPRE_DIV512 (15 << 4) /**< SYSCLK divided by 512. */ + +#define STM32_PPRE1_MASK (7 << 10) /**< PPRE1 mask. */ +#define STM32_PPRE1_DIV1 (0 << 10) /**< HCLK divided by 1. */ +#define STM32_PPRE1_DIV2 (4 << 10) /**< HCLK divided by 2. */ +#define STM32_PPRE1_DIV4 (5 << 10) /**< HCLK divided by 4. */ +#define STM32_PPRE1_DIV8 (6 << 10) /**< HCLK divided by 8. */ +#define STM32_PPRE1_DIV16 (7 << 10) /**< HCLK divided by 16. */ + +#define STM32_PPRE2_MASK (7 << 13) /**< PPRE2 mask. */ +#define STM32_PPRE2_DIV1 (0 << 13) /**< HCLK divided by 1. */ +#define STM32_PPRE2_DIV2 (4 << 13) /**< HCLK divided by 2. */ +#define STM32_PPRE2_DIV4 (5 << 13) /**< HCLK divided by 4. */ +#define STM32_PPRE2_DIV8 (6 << 13) /**< HCLK divided by 8. */ +#define STM32_PPRE2_DIV16 (7 << 13) /**< HCLK divided by 16. */ + +#define STM32_RTCPRE_MASK (31 << 16) /**< RTCPRE mask. */ + +#define STM32_MCO1SEL_MASK (3 << 21) /**< MCO1 mask. */ +#define STM32_MCO1SEL_HSI (0 << 21) /**< HSI clock on MCO1 pin. */ +#define STM32_MCO1SEL_LSE (1 << 21) /**< LSE clock on MCO1 pin. */ +#define STM32_MCO1SEL_HSE (2 << 21) /**< HSE clock on MCO1 pin. */ +#define STM32_MCO1SEL_PLL (3 << 21) /**< PLL clock on MCO1 pin. */ + +#define STM32_I2SSRC_MASK (1 << 23) /**< I2CSRC mask. */ +#define STM32_I2SSRC_PLLI2S (0 << 23) /**< I2SSRC is PLLI2S. */ +#define STM32_I2SSRC_CKIN (1 << 23) /**< I2S_CKIN is PLLI2S. */ + +#define STM32_MCO1PRE_MASK (7 << 24) /**< MCO1PRE mask. */ +#define STM32_MCO1PRE_DIV1 (0 << 24) /**< MCO1 divided by 1. */ +#define STM32_MCO1PRE_DIV2 (4 << 24) /**< MCO1 divided by 2. */ +#define STM32_MCO1PRE_DIV3 (5 << 24) /**< MCO1 divided by 3. */ +#define STM32_MCO1PRE_DIV4 (6 << 24) /**< MCO1 divided by 4. */ +#define STM32_MCO1PRE_DIV5 (7 << 24) /**< MCO1 divided by 5. */ + +#define STM32_MCO2PRE_MASK (7 << 27) /**< MCO2PRE mask. */ +#define STM32_MCO2PRE_DIV1 (0 << 27) /**< MCO2 divided by 1. */ +#define STM32_MCO2PRE_DIV2 (4 << 27) /**< MCO2 divided by 2. */ +#define STM32_MCO2PRE_DIV3 (5 << 27) /**< MCO2 divided by 3. */ +#define STM32_MCO2PRE_DIV4 (6 << 27) /**< MCO2 divided by 4. */ +#define STM32_MCO2PRE_DIV5 (7 << 27) /**< MCO2 divided by 5. */ + +#define STM32_MCO2SEL_MASK (3U << 30) /**< MCO2 mask. */ +#define STM32_MCO2SEL_SYSCLK (0U << 30) /**< SYSCLK clock on MCO2 pin. */ +#define STM32_MCO2SEL_PLLI2S (1U << 30) /**< PLLI2S clock on MCO2 pin. */ +#define STM32_MCO2SEL_HSE (2U << 30) /**< HSE clock on MCO2 pin. */ +#define STM32_MCO2SEL_PLL (3U << 30) /**< PLL clock on MCO2 pin. */ + +#define STM32_RTC_NOCLOCK (0 << 8) /**< No clock. */ +#define STM32_RTC_LSE (1 << 8) /**< LSE used as RTC clock. */ +#define STM32_RTC_LSI (2 << 8) /**< LSI used as RTC clock. */ +#define STM32_RTC_HSE (3 << 8) /**< HSE divided by programmable + prescaler used as RTC clock*/ + +/** + * @name RCC_PLLI2SCFGR register bits definitions + * @{ + */ +#define STM32_PLLI2SN_MASK (511 << 6) /**< PLLI2SN mask. */ +#define STM32_PLLI2SR_MASK (7 << 28) /**< PLLI2SR mask. */ +/** @} */ + +/** + * @name RCC_BDCR register bits definitions + * @{ + */ +#define STM32_RTCSEL_MASK (3 << 8) /**< RTC source mask. */ +#define STM32_RTCSEL_NOCLOCK (0 << 8) /**< No RTC source. */ +#define STM32_RTCSEL_LSE (1 << 8) /**< RTC source is LSE. */ +#define STM32_RTCSEL_LSI (2 << 8) /**< RTC source is LSI. */ +#define STM32_RTCSEL_HSEDIV (3 << 8) /**< RTC source is HSE divided. */ +/** @} */ + +/*===========================================================================*/ +/* Driver pre-compile time settings. */ +/*===========================================================================*/ + +/** + * @name Configuration options + * @{ + */ +/** + * @brief Disables the PWR/RCC initialization in the HAL. + */ +#if !defined(STM32_NO_INIT) || defined(__DOXYGEN__) +#define STM32_NO_INIT FALSE +#endif + +/** + * @brief Enables or disables the programmable voltage detector. + */ +#if !defined(STM32_PVD_ENABLE) || defined(__DOXYGEN__) +#define STM32_PVD_ENABLE FALSE +#endif + +/** + * @brief Sets voltage level for programmable voltage detector. + */ +#if !defined(STM32_PLS) || defined(__DOXYGEN__) +#define STM32_PLS STM32_PLS_LEV0 +#endif + +/** + * @brief Enables or disables the HSI clock source. + */ +#if !defined(STM32_HSI_ENABLED) || defined(__DOXYGEN__) +#define STM32_HSI_ENABLED TRUE +#endif + +/** + * @brief Enables or disables the LSI clock source. + */ +#if !defined(STM32_LSI_ENABLED) || defined(__DOXYGEN__) +#define STM32_LSI_ENABLED FALSE +#endif + +/** + * @brief Enables or disables the HSE clock source. + */ +#if !defined(STM32_HSE_ENABLED) || defined(__DOXYGEN__) +#define STM32_HSE_ENABLED TRUE +#endif + +/** + * @brief Enables or disables the LSE clock source. + */ +#if !defined(STM32_LSE_ENABLED) || defined(__DOXYGEN__) +#define STM32_LSE_ENABLED FALSE +#endif + +/** + * @brief USB/SDIO clock setting. + */ +#if !defined(STM32_CLOCK48_REQUIRED) || defined(__DOXYGEN__) +#define STM32_CLOCK48_REQUIRED TRUE +#endif + +/** + * @brief Main clock source selection. + * @note If the selected clock source is not the PLL then the PLL is not + * initialized and started. + * @note The default value is calculated for a 168MHz system clock from + * an external 8MHz HSE clock. + */ +#if !defined(STM32_SW) || defined(__DOXYGEN__) +#define STM32_SW STM32_SW_PLL +#endif + +#if defined(STM32F4XX) || defined(__DOXYGEN__) +/** + * @brief Core voltage selection. + * @note This setting affects all the performance and clock related + * settings, the maximum performance is only obtainable selecting + * the maximum voltage. + */ +#if !defined(STM32_VOS) || defined(__DOXYGEN__) +#define STM32_VOS STM32_VOS_HIGH +#endif + +/** + * @brief Clock source for the PLLs. + * @note This setting has only effect if the PLL is selected as the + * system clock source. + * @note The default value is calculated for a 168MHz system clock from + * an external 8MHz HSE clock. + */ +#if !defined(STM32_PLLSRC) || defined(__DOXYGEN__) +#define STM32_PLLSRC STM32_PLLSRC_HSE +#endif + +/** + * @brief PLLM divider value. + * @note The allowed values are 2..63. + * @note The default value is calculated for a 168MHz system clock from + * an external 8MHz HSE clock. + */ +#if !defined(STM32_PLLM_VALUE) || defined(__DOXYGEN__) +#define STM32_PLLM_VALUE 8 +#endif + +/** + * @brief PLLN multiplier value. + * @note The allowed values are 192..432. + * @note The default value is calculated for a 168MHz system clock from + * an external 8MHz HSE clock. + */ +#if !defined(STM32_PLLN_VALUE) || defined(__DOXYGEN__) +#define STM32_PLLN_VALUE 336 +#endif + +/** + * @brief PLLP divider value. + * @note The allowed values are 2, 4, 6, 8. + * @note The default value is calculated for a 168MHz system clock from + * an external 8MHz HSE clock. + */ +#if !defined(STM32_PLLP_VALUE) || defined(__DOXYGEN__) +#define STM32_PLLP_VALUE 2 +#endif + +/** + * @brief PLLQ multiplier value. + * @note The allowed values are 2..15. + * @note The default value is calculated for a 168MHz system clock from + * an external 8MHz HSE clock. + */ +#if !defined(STM32_PLLQ_VALUE) || defined(__DOXYGEN__) +#define STM32_PLLQ_VALUE 7 +#endif + +#else /* !defined(STM32F4XX) */ +/** + * @brief Clock source for the PLLs. + * @note This setting has only effect if the PLL is selected as the + * system clock source. + * @note The default value is calculated for a 120MHz system clock from + * an external 8MHz HSE clock. + */ +#if !defined(STM32_PLLSRC) || defined(__DOXYGEN__) +#define STM32_PLLSRC STM32_PLLSRC_HSE +#endif + +/** + * @brief PLLM divider value. + * @note The allowed values are 2..63. + * @note The default value is calculated for a 120MHz system clock from + * an external 8MHz HSE clock. + */ +#if !defined(STM32_PLLM_VALUE) || defined(__DOXYGEN__) +#define STM32_PLLM_VALUE 8 +#endif + +/** + * @brief PLLN multiplier value. + * @note The allowed values are 192..432. + * @note The default value is calculated for a 120MHz system clock from + * an external 8MHz HSE clock. + */ +#if !defined(STM32_PLLN_VALUE) || defined(__DOXYGEN__) +#define STM32_PLLN_VALUE 240 +#endif + +/** + * @brief PLLP divider value. + * @note The allowed values are 2, 4, 6, 8. + * @note The default value is calculated for a 120MHz system clock from + * an external 8MHz HSE clock. + */ +#if !defined(STM32_PLLP_VALUE) || defined(__DOXYGEN__) +#define STM32_PLLP_VALUE 2 +#endif + +/** + * @brief PLLQ multiplier value. + * @note The allowed values are 2..15. + * @note The default value is calculated for a 120MHz system clock from + * an external 8MHz HSE clock. + */ +#if !defined(STM32_PLLQ_VALUE) || defined(__DOXYGEN__) +#define STM32_PLLQ_VALUE 5 +#endif +#endif /* !defined(STM32F4XX) */ + +/** + * @brief AHB prescaler value. + */ +#if !defined(STM32_HPRE) || defined(__DOXYGEN__) +#define STM32_HPRE STM32_HPRE_DIV1 +#endif + +/** + * @brief APB1 prescaler value. + */ +#if !defined(STM32_PPRE1) || defined(__DOXYGEN__) +#define STM32_PPRE1 STM32_PPRE1_DIV4 +#endif + +/** + * @brief APB2 prescaler value. + */ +#if !defined(STM32_PPRE2) || defined(__DOXYGEN__) +#define STM32_PPRE2 STM32_PPRE2_DIV2 +#endif + +/** + * @brief RTC clock source. + */ +#if !defined(STM32_RTCSEL) || defined(__DOXYGEN__) +#define STM32_RTCSEL STM32_RTCSEL_LSE +#endif + +/** + * @brief RTC HSE prescaler value. + */ +#if !defined(STM32_RTCPRE_VALUE) || defined(__DOXYGEN__) +#define STM32_RTCPRE_VALUE 8 +#endif + +/** + * @brief MC01 clock source value. + * @note The default value outputs HSI clock on MC01 pin. + */ +#if !defined(STM32_MCO1SEL) || defined(__DOXYGEN__) +#define STM32_MCO1SEL STM32_MCO1SEL_HSI +#endif + +/** + * @brief MC01 prescaler value. + * @note The default value outputs HSI clock on MC01 pin. + */ +#if !defined(STM32_MCO1PRE) || defined(__DOXYGEN__) +#define STM32_MCO1PRE STM32_MCO1PRE_DIV1 +#endif + +/** + * @brief MC02 clock source value. + * @note The default value outputs SYSCLK / 5 on MC02 pin. + */ +#if !defined(STM32_MCO2SEL) || defined(__DOXYGEN__) +#define STM32_MCO2SEL STM32_MCO2SEL_SYSCLK +#endif + +/** + * @brief MC02 prescaler value. + * @note The default value outputs SYSCLK / 5 on MC02 pin. + */ +#if !defined(STM32_MCO2PRE) || defined(__DOXYGEN__) +#define STM32_MCO2PRE STM32_MCO2PRE_DIV5 +#endif + +/** + * @brief I2S clock source. + */ +#if !defined(STM32_I2SSRC) || defined(__DOXYGEN__) +#define STM32_I2SSRC STM32_I2SSRC_CKIN +#endif + +/** + * @brief PLLI2SN multiplier value. + * @note The allowed values are 192..432. + */ +#if !defined(STM32_PLLI2SN_VALUE) || defined(__DOXYGEN__) +#define STM32_PLLI2SN_VALUE 192 +#endif + +/** + * @brief PLLI2SR multiplier value. + * @note The allowed values are 2..7. + */ +#if !defined(STM32_PLLI2SR_VALUE) || defined(__DOXYGEN__) +#define STM32_PLLI2SR_VALUE 5 +#endif +/** @} */ + +/*===========================================================================*/ +/* Derived constants and error checks. */ +/*===========================================================================*/ + +#if defined(STM32F4XX) || defined(__DOXYGEN__) +/* + * Configuration-related checks. + */ +#if !defined(STM32F4xx_MCUCONF) +#error "Using a wrong mcuconf.h file, STM32F4xx_MCUCONF not defined" +#endif + +/** + * @brief Maximum SYSCLK. + * @note It is a function of the core voltage setting. + */ +#if (STM32_VOS == STM32_VOS_HIGH) || defined(__DOXYGEN__) +#define STM32_SYSCLK_MAX 168000000 +#else +#define STM32_SYSCLK_MAX 144000000 +#endif + +#else /* !defined(STM32F4XX) */ +/* + * Configuration-related checks. + */ +#if !defined(STM32F2xx_MCUCONF) +#error "Using a wrong mcuconf.h file, STM32F2xx_MCUCONF not defined" +#endif +#endif /* !defined(STM32F4XX) */ + +/** + * @brief Maximum frequency thresholds and wait states for flash access. + * @note The values are valid for 2.7V to 3.6V supply range. + */ +#if defined(STM32F4XX) || defined(__DOXYGEN__) +#if ((STM32_VDD >= 270) && (STM32_VDD <= 360)) || defined(__DOXYGEN__) +#define STM32_0WS_THRESHOLD 30000000 +#define STM32_1WS_THRESHOLD 60000000 +#define STM32_2WS_THRESHOLD 90000000 +#define STM32_3WS_THRESHOLD 120000000 +#define STM32_4WS_THRESHOLD 150000000 +#define STM32_5WS_THRESHOLD 168000000 +#define STM32_6WS_THRESHOLD 0 +#define STM32_7WS_THRESHOLD 0 +#elif (STM32_VDD >= 240) && (STM32_VDD < 270) +#define STM32_0WS_THRESHOLD 24000000 +#define STM32_1WS_THRESHOLD 48000000 +#define STM32_2WS_THRESHOLD 72000000 +#define STM32_3WS_THRESHOLD 96000000 +#define STM32_4WS_THRESHOLD 120000000 +#define STM32_5WS_THRESHOLD 144000000 +#define STM32_6WS_THRESHOLD 168000000 +#define STM32_7WS_THRESHOLD 0 +#elif (STM32_VDD >= 210) && (STM32_VDD < 240) +#define STM32_0WS_THRESHOLD 18000000 +#define STM32_1WS_THRESHOLD 36000000 +#define STM32_2WS_THRESHOLD 54000000 +#define STM32_3WS_THRESHOLD 72000000 +#define STM32_4WS_THRESHOLD 90000000 +#define STM32_5WS_THRESHOLD 108000000 +#define STM32_6WS_THRESHOLD 120000000 +#define STM32_7WS_THRESHOLD 138000000 +#elif (STM32_VDD >= 180) && (STM32_VDD < 210) +#define STM32_0WS_THRESHOLD 16000000 +#define STM32_1WS_THRESHOLD 32000000 +#define STM32_2WS_THRESHOLD 48000000 +#define STM32_3WS_THRESHOLD 64000000 +#define STM32_4WS_THRESHOLD 80000000 +#define STM32_5WS_THRESHOLD 96000000 +#define STM32_6WS_THRESHOLD 112000000 +#define STM32_7WS_THRESHOLD 128000000 +#else +#error "invalid VDD voltage specified" +#endif + +#else /* !defined(STM32F4XX) */ +#if ((STM32_VDD >= 270) && (STM32_VDD <= 360)) || defined(__DOXYGEN__) +#define STM32_0WS_THRESHOLD 30000000 +#define STM32_1WS_THRESHOLD 60000000 +#define STM32_2WS_THRESHOLD 90000000 +#define STM32_3WS_THRESHOLD 120000000 +#define STM32_4WS_THRESHOLD 0 +#define STM32_5WS_THRESHOLD 0 +#define STM32_6WS_THRESHOLD 0 +#define STM32_7WS_THRESHOLD 0 +#elif (STM32_VDD >= 240) && (STM32_VDD < 270) +#define STM32_0WS_THRESHOLD 24000000 +#define STM32_1WS_THRESHOLD 48000000 +#define STM32_2WS_THRESHOLD 72000000 +#define STM32_3WS_THRESHOLD 96000000 +#define STM32_4WS_THRESHOLD 120000000 +#define STM32_5WS_THRESHOLD 0 +#define STM32_6WS_THRESHOLD 0 +#define STM32_7WS_THRESHOLD 0 +#elif (STM32_VDD >= 210) && (STM32_VDD < 240) +#define STM32_0WS_THRESHOLD 18000000 +#define STM32_1WS_THRESHOLD 36000000 +#define STM32_2WS_THRESHOLD 54000000 +#define STM32_3WS_THRESHOLD 72000000 +#define STM32_4WS_THRESHOLD 90000000 +#define STM32_5WS_THRESHOLD 108000000 +#define STM32_6WS_THRESHOLD 120000000 +#define STM32_7WS_THRESHOLD 0 +#elif (STM32_VDD >= 180) && (STM32_VDD < 210) +#define STM32_0WS_THRESHOLD 16000000 +#define STM32_1WS_THRESHOLD 32000000 +#define STM32_2WS_THRESHOLD 48000000 +#define STM32_3WS_THRESHOLD 64000000 +#define STM32_4WS_THRESHOLD 80000000 +#define STM32_5WS_THRESHOLD 96000000 +#define STM32_6WS_THRESHOLD 112000000 +#define STM32_7WS_THRESHOLD 120000000 +#else +#error "invalid VDD voltage specified" +#endif +#endif /* !defined(STM32F4XX) */ + +/* + * HSI related checks. + */ +#if STM32_HSI_ENABLED +#else /* !STM32_HSI_ENABLED */ + +#if STM32_SW == STM32_SW_HSI +#error "HSI not enabled, required by STM32_SW" +#endif + +#if (STM32_SW == STM32_SW_PLL) && (STM32_PLLSRC == STM32_PLLSRC_HSI) +#error "HSI not enabled, required by STM32_SW and STM32_PLLSRC" +#endif + +#if (STM32_MCO1SEL == STM32_MCO1SEL_HSI) || \ + ((STM32_MCO1SEL == STM32_MCO1SEL_PLL) && \ + (STM32_PLLSRC == STM32_PLLSRC_HSI)) +#error "HSI not enabled, required by STM32_MCO1SEL" +#endif + +#if (STM32_MCO2SEL == STM32_MCO2SEL_HSI) || \ + ((STM32_MCO2SEL == STM32_MCO2SEL_PLL) && \ + (STM32_PLLSRC == STM32_PLLSRC_HSI)) +#error "HSI not enabled, required by STM32_MCO2SEL" +#endif + +#if (STM32_I2SSRC == STM32_I2SSRC_PLLI2S) && \ + (STM32_PLLSRC == STM32_PLLSRC_HSI) +#error "HSI not enabled, required by STM32_I2SSRC" +#endif + +#endif /* !STM32_HSI_ENABLED */ + +/* + * HSE related checks. + */ +#if STM32_HSE_ENABLED + +#if STM32_HSECLK == 0 +#error "HSE frequency not defined" +#elif (STM32_HSECLK < STM32_HSECLK_MIN) || (STM32_HSECLK > STM32_HSECLK_MAX) +#error "STM32_HSECLK outside acceptable range (STM32_HSECLK_MIN...STM32_HSECLK_MAX)" +#endif + +#else /* !STM32_HSE_ENABLED */ + +#if STM32_SW == STM32_SW_HSE +#error "HSE not enabled, required by STM32_SW" +#endif + +#if (STM32_SW == STM32_SW_PLL) && (STM32_PLLSRC == STM32_PLLSRC_HSE) +#error "HSE not enabled, required by STM32_SW and STM32_PLLSRC" +#endif + +#if (STM32_MCO1SEL == STM32_MCO1SEL_HSE) || \ + ((STM32_MCO1SEL == STM32_MCO1SEL_PLL) && \ + (STM32_PLLSRC == STM32_PLLSRC_HSE)) +#error "HSE not enabled, required by STM32_MCO1SEL" +#endif + +#if (STM32_MCO2SEL == STM32_MCO2SEL_HSE) || \ + ((STM32_MCO2SEL == STM32_MCO2SEL_PLL) && \ + (STM32_PLLSRC == STM32_PLLSRC_HSE)) +#error "HSE not enabled, required by STM32_MCO2SEL" +#endif + +#if (STM32_I2SSRC == STM32_I2SSRC_PLLI2S) && \ + (STM32_PLLSRC == STM32_PLLSRC_HSE) +#error "HSE not enabled, required by STM32_I2SSRC" +#endif + +#if STM32_RTCSEL == STM32_RTCSEL_HSEDIV +#error "HSE not enabled, required by STM32_RTCSEL" +#endif + +#endif /* !STM32_HSE_ENABLED */ + +/* + * LSI related checks. + */ +#if STM32_LSI_ENABLED +#else /* !STM32_LSI_ENABLED */ + +#if STM32_RTCSEL == STM32_RTCSEL_LSI +#error "LSI not enabled, required by STM32_RTCSEL" +#endif + +#endif /* !STM32_LSI_ENABLED */ + +/* + * LSE related checks. + */ +#if STM32_LSE_ENABLED + +#if (STM32_LSECLK == 0) +#error "LSE frequency not defined" +#endif + +#if (STM32_LSECLK < STM32_LSECLK_MIN) || (STM32_LSECLK > STM32_LSECLK_MAX) +#error "STM32_LSECLK outside acceptable range (STM32_LSECLK_MIN...STM32_LSECLK_MAX)" +#endif + +#else /* !STM32_LSE_ENABLED */ + +#if STM32_RTCSEL == STM32_RTCSEL_LSE +#error "LSE not enabled, required by STM32_RTCSEL" +#endif + +#endif /* !STM32_LSE_ENABLED */ + +/** + * @brief STM32_PLLM field. + */ +#if ((STM32_PLLM_VALUE >= 2) && (STM32_PLLM_VALUE <= 63)) || \ + defined(__DOXYGEN__) +#define STM32_PLLM (STM32_PLLM_VALUE << 0) +#else +#error "invalid STM32_PLLM_VALUE value specified" +#endif + +/** + * @brief PLLs input clock frequency. + */ +#if (STM32_PLLSRC == STM32_PLLSRC_HSE) || defined(__DOXYGEN__) +#define STM32_PLLCLKIN (STM32_HSECLK / STM32_PLLM_VALUE) +#elif STM32_PLLSRC == STM32_PLLSRC_HSI +#define STM32_PLLCLKIN (STM32_HSICLK / STM32_PLLM_VALUE) +#else +#error "invalid STM32_PLLSRC value specified" +#endif + +/* + * PLLs input frequency range check. + */ +#if (STM32_PLLCLKIN < STM32_PLLIN_MIN) || (STM32_PLLCLKIN > STM32_PLLIN_MAX) +#error "STM32_PLLCLKIN outside acceptable range (STM32_PLLIN_MIN...STM32_PLLIN_MAX)" +#endif + +/* + * PLL enable check. + */ +#if STM32_CLOCK48_REQUIRED || \ + (STM32_SW == STM32_SW_PLL) || \ + (STM32_MCO1SEL == STM32_MCO1SEL_PLL) || \ + (STM32_MCO2SEL == STM32_MCO2SEL_PLL) || \ + defined(__DOXYGEN__) +/** + * @brief PLL activation flag. + */ +#define STM32_ACTIVATE_PLL TRUE +#else +#define STM32_ACTIVATE_PLL FALSE +#endif + +/** + * @brief STM32_PLLN field. + */ +#if ((STM32_PLLN_VALUE >= 64) && (STM32_PLLN_VALUE <= 432)) || \ + defined(__DOXYGEN__) +#define STM32_PLLN (STM32_PLLN_VALUE << 6) +#else +#error "invalid STM32_PLLN_VALUE value specified" +#endif + +/** + * @brief STM32_PLLP field. + */ +#if (STM32_PLLP_VALUE == 2) || defined(__DOXYGEN__) +#define STM32_PLLP (0 << 16) +#elif STM32_PLLP_VALUE == 4 +#define STM32_PLLP (1 << 16) +#elif STM32_PLLP_VALUE == 6 +#define STM32_PLLP (2 << 16) +#elif STM32_PLLP_VALUE == 8 +#define STM32_PLLP (3 << 16) +#else +#error "invalid STM32_PLLP_VALUE value specified" +#endif + +/** + * @brief STM32_PLLQ field. + */ +#if ((STM32_PLLQ_VALUE >= 2) && (STM32_PLLQ_VALUE <= 15)) || \ + defined(__DOXYGEN__) +#define STM32_PLLQ (STM32_PLLQ_VALUE << 24) +#else +#error "invalid STM32_PLLQ_VALUE value specified" +#endif + +/** + * @brief PLL VCO frequency. + */ +#define STM32_PLLVCO (STM32_PLLCLKIN * STM32_PLLN_VALUE) + +/* + * PLL VCO frequency range check. + */ +#if (STM32_PLLVCO < STM32_PLLVCO_MIN) || (STM32_PLLVCO > STM32_PLLVCO_MAX) +#error "STM32_PLLVCO outside acceptable range (STM32_PLLVCO_MIN...STM32_PLLVCO_MAX)" +#endif + +/** + * @brief PLL output clock frequency. + */ +#define STM32_PLLCLKOUT (STM32_PLLVCO / STM32_PLLP_VALUE) + +/* + * PLL output frequency range check. + */ +#if (STM32_PLLCLKOUT < STM32_PLLOUT_MIN) || (STM32_PLLCLKOUT > STM32_PLLOUT_MAX) +#error "STM32_PLLCLKOUT outside acceptable range (STM32_PLLOUT_MIN...STM32_PLLOUT_MAX)" +#endif + +/** + * @brief System clock source. + */ +#if STM32_NO_INIT || defined(__DOXYGEN__) +#define STM32_SYSCLK STM32_HSICLK +#elif (STM32_SW == STM32_SW_HSI) +#define STM32_SYSCLK STM32_HSICLK +#elif (STM32_SW == STM32_SW_HSE) +#define STM32_SYSCLK STM32_HSECLK +#elif (STM32_SW == STM32_SW_PLL) +#define STM32_SYSCLK STM32_PLLCLKOUT +#else +#error "invalid STM32_SW value specified" +#endif + +/* Check on the system clock.*/ +#if STM32_SYSCLK > STM32_SYSCLK_MAX +#error "STM32_SYSCLK above maximum rated frequency (STM32_SYSCLK_MAX)" +#endif + +/** + * @brief AHB frequency. + */ +#if (STM32_HPRE == STM32_HPRE_DIV1) || defined(__DOXYGEN__) +#define STM32_HCLK (STM32_SYSCLK / 1) +#elif STM32_HPRE == STM32_HPRE_DIV2 +#define STM32_HCLK (STM32_SYSCLK / 2) +#elif STM32_HPRE == STM32_HPRE_DIV4 +#define STM32_HCLK (STM32_SYSCLK / 4) +#elif STM32_HPRE == STM32_HPRE_DIV8 +#define STM32_HCLK (STM32_SYSCLK / 8) +#elif STM32_HPRE == STM32_HPRE_DIV16 +#define STM32_HCLK (STM32_SYSCLK / 16) +#elif STM32_HPRE == STM32_HPRE_DIV64 +#define STM32_HCLK (STM32_SYSCLK / 64) +#elif STM32_HPRE == STM32_HPRE_DIV128 +#define STM32_HCLK (STM32_SYSCLK / 128) +#elif STM32_HPRE == STM32_HPRE_DIV256 +#define STM32_HCLK (STM32_SYSCLK / 256) +#elif STM32_HPRE == STM32_HPRE_DIV512 +#define STM32_HCLK (STM32_SYSCLK / 512) +#else +#error "invalid STM32_HPRE value specified" +#endif + +/* + * AHB frequency check. + */ +#if STM32_HCLK > STM32_SYSCLK_MAX +#error "STM32_HCLK exceeding maximum frequency (STM32_SYSCLK_MAX)" +#endif + +/** + * @brief APB1 frequency. + */ +#if (STM32_PPRE1 == STM32_PPRE1_DIV1) || defined(__DOXYGEN__) +#define STM32_PCLK1 (STM32_HCLK / 1) +#elif STM32_PPRE1 == STM32_PPRE1_DIV2 +#define STM32_PCLK1 (STM32_HCLK / 2) +#elif STM32_PPRE1 == STM32_PPRE1_DIV4 +#define STM32_PCLK1 (STM32_HCLK / 4) +#elif STM32_PPRE1 == STM32_PPRE1_DIV8 +#define STM32_PCLK1 (STM32_HCLK / 8) +#elif STM32_PPRE1 == STM32_PPRE1_DIV16 +#define STM32_PCLK1 (STM32_HCLK / 16) +#else +#error "invalid STM32_PPRE1 value specified" +#endif + +/* + * APB1 frequency check. + */ +#if STM32_PCLK1 > STM32_PCLK1_MAX +#error "STM32_PCLK1 exceeding maximum frequency (STM32_PCLK1_MAX)" +#endif + +/** + * @brief APB2 frequency. + */ +#if (STM32_PPRE2 == STM32_PPRE2_DIV1) || defined(__DOXYGEN__) +#define STM32_PCLK2 (STM32_HCLK / 1) +#elif STM32_PPRE2 == STM32_PPRE2_DIV2 +#define STM32_PCLK2 (STM32_HCLK / 2) +#elif STM32_PPRE2 == STM32_PPRE2_DIV4 +#define STM32_PCLK2 (STM32_HCLK / 4) +#elif STM32_PPRE2 == STM32_PPRE2_DIV8 +#define STM32_PCLK2 (STM32_HCLK / 8) +#elif STM32_PPRE2 == STM32_PPRE2_DIV16 +#define STM32_PCLK2 (STM32_HCLK / 16) +#else +#error "invalid STM32_PPRE2 value specified" +#endif + +/* + * APB2 frequency check. + */ +#if STM32_PCLK2 > STM32_PCLK2_MAX +#error "STM32_PCLK2 exceeding maximum frequency (STM32_PCLK2_MAX)" +#endif + +/* + * PLLI2S enable check. + */ +#if (STM32_I2SSRC == STM32_I2SSRC_PLLI2S) || defined(__DOXYGEN__) +/** + * @brief PLL activation flag. + */ +#define STM32_ACTIVATE_PLLI2S TRUE +#else +#define STM32_ACTIVATE_PLLI2S FALSE +#endif + +/** + * @brief STM32_PLLI2SN field. + */ +#if ((STM32_PLLI2SN_VALUE >= 192) && (STM32_PLLI2SN_VALUE <= 432)) || \ + defined(__DOXYGEN__) +#define STM32_PLLI2SN (STM32_PLLI2SN_VALUE << 6) +#else +#error "invalid STM32_PLLI2SN_VALUE value specified" +#endif + +/** + * @brief STM32_PLLI2SR field. + */ +#if ((STM32_PLLI2SR_VALUE >= 2) && (STM32_PLLI2SR_VALUE <= 7)) || \ + defined(__DOXYGEN__) +#define STM32_PLLI2SR (STM32_PLLI2SR_VALUE << 28) +#else +#error "invalid STM32_PLLI2SR_VALUE value specified" +#endif + +/** + * @brief PLL VCO frequency. + */ +#define STM32_PLLI2SVCO (STM32_PLLCLKIN * STM32_PLLI2SN_VALUE) + +/* + * PLLI2S VCO frequency range check. + */ +#if (STM32_PLLI2SVCO < STM32_PLLVCO_MIN) || \ + (STM32_PLLI2SVCO > STM32_PLLVCO_MAX) +#error "STM32_PLLI2SVCO outside acceptable range (STM32_PLLVCO_MIN...STM32_PLLVCO_MAX)" +#endif + +/** + * @brief PLLI2S output clock frequency. + */ +#define STM32_PLLI2SCLKOUT (STM32_PLLI2SVCO / STM32_PLLI2SR_VALUE) + +/** + * @brief MCO1 divider clock. + */ +#if (STM32_MCO1SEL == STM32_MCO1SEL_HSI) || defined(__DOXYGEN__) +#define STM32_MCO1DIVCLK STM32_HSICLK +#elif STM32_MCO1SEL == STM32_MCO1SEL_LSE +#define STM32_MCO1DIVCLK STM32_LSECLK +#elif STM32_MCO1SEL == STM32_MCO1SEL_HSE +#define STM32_MCO1DIVCLK STM32_HSECLK +#elif STM32_MCO1SEL == STM32_MCO1SEL_PLL +#define STM32_MCO1DIVCLK STM32_PLLCLKOUT +#else +#error "invalid STM32_MCO1SEL value specified" +#endif + +/** + * @brief MCO1 output pin clock. + */ +#if (STM32_MCO1PRE == STM32_MCO1PRE_DIV1) || defined(__DOXYGEN__) +#define STM32_MCO1CLK STM32_MCO1DIVCLK +#elif STM32_MCO1PRE == STM32_MCO1PRE_DIV2 +#define STM32_MCO1CLK (STM32_MCO1DIVCLK / 2) +#elif STM32_MCO1PRE == STM32_MCO1PRE_DIV3 +#define STM32_MCO1CLK (STM32_MCO1DIVCLK / 3) +#elif STM32_MCO1PRE == STM32_MCO1PRE_DIV4 +#define STM32_MCO1CLK (STM32_MCO1DIVCLK / 4) +#elif STM32_MCO1PRE == STM32_MCO1PRE_DIV5 +#define STM32_MCO1CLK (STM32_MCO1DIVCLK / 5) +#else +#error "invalid STM32_MCO1PRE value specified" +#endif + +/** + * @brief MCO2 divider clock. + */ +#if (STM32_MCO2SEL == STM32_MCO2SEL_HSE) || defined(__DOXYGEN__) +#define STM32_MCO2DIVCLK STM32_HSECLK +#elif STM32_MCO2SEL == STM32_MCO2SEL_PLL +#define STM32_MCO2DIVCLK STM32_PLLCLKOUT +#elif STM32_MCO2SEL == STM32_MCO2SEL_SYSCLK +#define STM32_MCO2DIVCLK STM32_SYSCLK +#elif STM32_MCO2SEL == STM32_MCO2SEL_PLLI2S +#define STM32_MCO2DIVCLK STM32_PLLI2S +#else +#error "invalid STM32_MCO2SEL value specified" +#endif + +/** + * @brief MCO2 output pin clock. + */ +#if (STM32_MCO2PRE == STM32_MCO2PRE_DIV1) || defined(__DOXYGEN__) +#define STM32_MCO2CLK STM32_MCO2DIVCLK +#elif STM32_MCO2PRE == STM32_MCO2PRE_DIV2 +#define STM32_MCO2CLK (STM32_MCO2DIVCLK / 2) +#elif STM32_MCO2PRE == STM32_MCO2PRE_DIV3 +#define STM32_MCO2CLK (STM32_MCO2DIVCLK / 3) +#elif STM32_MCO2PRE == STM32_MCO2PRE_DIV4 +#define STM32_MCO2CLK (STM32_MCO2DIVCLK / 4) +#elif STM32_MCO2PRE == STM32_MCO2PRE_DIV5 +#define STM32_MCO2CLK (STM32_MCO2DIVCLK / 5) +#else +#error "invalid STM32_MCO2PRE value specified" +#endif + +/** + * @brief RTC HSE divider setting. + */ +#if ((STM32_RTCPRE_VALUE >= 2) && (STM32_RTCPRE_VALUE <= 31)) || \ + defined(__DOXYGEN__) +#define STM32_RTCPRE (STM32_RTCPRE_VALUE << 16) +#else +#error "invalid STM32_RTCPRE value specified" +#endif + +/** + * @brief HSE divider toward RTC clock. + */ +#if ((STM32_RTCPRE_VALUE >= 2) && (STM32_RTCPRE_VALUE <= 31)) || \ + defined(__DOXYGEN__) +#define STM32_HSEDIVCLK (STM32_HSECLK / STM32_RTCPRE_VALUE) +#else +#error "invalid STM32_RTCPRE value specified" +#endif + +/** + * @brief RTC clock. + */ +#if (STM32_RTCSEL == STM32_RTCSEL_NOCLOCK) || defined(__DOXYGEN__) +#define STM32_RTCCLK 0 +#elif STM32_RTCSEL == STM32_RTCSEL_LSE +#define STM32_RTCCLK STM32_LSECLK +#elif STM32_RTCSEL == STM32_RTCSEL_LSI +#define STM32_RTCCLK STM32_LSICLK +#elif STM32_RTCSEL == STM32_RTCSEL_HSEDIV +#define STM32_RTCCLK STM32_HSEDIVCLK +#else +#error "invalid STM32_RTCSEL value specified" +#endif + +/** + * @brief 48MHz frequency. + */ +#if STM32_CLOCK48_REQUIRED || defined(__DOXYGEN__) +#define STM32_PLL48CLK (STM32_PLLVCO / STM32_PLLQ_VALUE) +#else +#define STM32_PLL48CLK 0 +#endif + +/** + * @brief Timers 2, 3, 4, 5, 6, 7, 9, 10, 11, 12, 13, 14 clock. + */ +#if (STM32_PPRE1 == STM32_PPRE1_DIV1) || defined(__DOXYGEN__) +#define STM32_TIMCLK1 (STM32_PCLK1 * 1) +#else +#define STM32_TIMCLK1 (STM32_PCLK1 * 2) +#endif + +/** + * @brief Timers 1, 8 clock. + */ +#if (STM32_PPRE2 == STM32_PPRE2_DIV1) || defined(__DOXYGEN__) +#define STM32_TIMCLK2 (STM32_PCLK2 * 1) +#else +#define STM32_TIMCLK2 (STM32_PCLK2 * 2) +#endif + +/** + * @brief Flash settings. + */ +#if (STM32_HCLK <= STM32_0WS_THRESHOLD) || defined(__DOXYGEN__) +#define STM32_FLASHBITS 0x00000000 +#elif STM32_HCLK <= STM32_1WS_THRESHOLD +#define STM32_FLASHBITS 0x00000001 +#elif STM32_HCLK <= STM32_2WS_THRESHOLD +#define STM32_FLASHBITS 0x00000002 +#elif STM32_HCLK <= STM32_3WS_THRESHOLD +#define STM32_FLASHBITS 0x00000003 +#elif STM32_HCLK <= STM32_4WS_THRESHOLD +#define STM32_FLASHBITS 0x00000004 +#elif STM32_HCLK <= STM32_5WS_THRESHOLD +#define STM32_FLASHBITS 0x00000005 +#elif STM32_HCLK <= STM32_6WS_THRESHOLD +#define STM32_FLASHBITS 0x00000006 +#else +#define STM32_FLASHBITS 0x00000007 +#endif + +/* There are differences in vector names in the various sub-families, + normalizing.*/ +#if 0 +#define TIM1_BRK_IRQn TIM1_BRK_TIM9_IRQn +#define TIM1_UP_IRQn TIM1_UP_TIM10_IRQn +#define TIM1_TRG_COM_IRQn TIM1_TRG_COM_TIM11_IRQn +#define TIM8_BRK_IRQn TIM8_BRK_TIM12_IRQn +#define TIM8_UP_IRQn TIM8_UP_TIM13_IRQn +#define TIM8_TRG_COM_IRQn TIM8_TRG_COM_TIM14_IRQn +#endif + +/*===========================================================================*/ +/* Driver data structures and types. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver macros. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +/* Various helpers.*/ +#include "nvic.h" +#include "stm32_isr.h" +#include "stm32_dma.h" +#include "stm32_rcc.h" + +#ifdef __cplusplus +extern "C" { +#endif + void hal_lld_init(void); + void stm32_clock_init(void); +#ifdef __cplusplus +} +#endif + +#endif /* _HAL_LLD_H_ */ + +/** @} */ diff --git a/os/hal/ports/STM32F4xx/platform.mk b/os/hal/ports/STM32F4xx/platform.mk new file mode 100644 index 000000000..fdd725faf --- /dev/null +++ b/os/hal/ports/STM32F4xx/platform.mk @@ -0,0 +1,33 @@ +# List of all the STM32F2xx/STM32F4xx platform files. +PLATFORMSRC = ${CHIBIOS}/os/hal/platforms/common/ARMCMx/nvic.c \ + ${CHIBIOS}/os/hal/platforms/STM32F4xx/stm32_dma.c \ + ${CHIBIOS}/os/hal/platforms/STM32F4xx/hal_lld.c \ + ${CHIBIOS}/os/hal/platforms/STM32F4xx/adc_lld.c \ + ${CHIBIOS}/os/hal/platforms/STM32F4xx/ext_lld_isr.c \ + ${CHIBIOS}/os/hal/platforms/STM32/can_lld.c \ + ${CHIBIOS}/os/hal/platforms/STM32/ext_lld.c \ + ${CHIBIOS}/os/hal/platforms/STM32/mac_lld.c \ + ${CHIBIOS}/os/hal/platforms/STM32/sdc_lld.c \ + ${CHIBIOS}/os/hal/platforms/STM32/GPIOv2/pal_lld.c \ + ${CHIBIOS}/os/hal/platforms/STM32/I2Cv1/i2c_lld.c \ + ${CHIBIOS}/os/hal/platforms/STM32/OTGv1/usb_lld.c \ + ${CHIBIOS}/os/hal/platforms/STM32/RTCv2/rtc_lld.c \ + ${CHIBIOS}/os/hal/platforms/STM32/SPIv1/spi_lld.c \ + ${CHIBIOS}/os/hal/platforms/STM32/TIMv1/gpt_lld.c \ + ${CHIBIOS}/os/hal/platforms/STM32/TIMv1/icu_lld.c \ + ${CHIBIOS}/os/hal/platforms/STM32/TIMv1/pwm_lld.c \ + ${CHIBIOS}/os/hal/platforms/STM32/TIMv1/st_lld.c \ + ${CHIBIOS}/os/hal/platforms/STM32/USARTv1/serial_lld.c \ + ${CHIBIOS}/os/hal/platforms/STM32/USARTv1/uart_lld.c + +# Required include directories +PLATFORMINC = ${CHIBIOS}/os/hal/platforms/common/ARMCMx \ + ${CHIBIOS}/os/hal/platforms/STM32F4xx \ + ${CHIBIOS}/os/hal/platforms/STM32 \ + ${CHIBIOS}/os/hal/platforms/STM32/GPIOv2 \ + ${CHIBIOS}/os/hal/platforms/STM32/I2Cv1 \ + ${CHIBIOS}/os/hal/platforms/STM32/OTGv1 \ + ${CHIBIOS}/os/hal/platforms/STM32/RTCv2 \ + ${CHIBIOS}/os/hal/platforms/STM32/SPIv1 \ + ${CHIBIOS}/os/hal/platforms/STM32/TIMv1 \ + ${CHIBIOS}/os/hal/platforms/STM32/USARTv1 diff --git a/os/hal/ports/STM32F4xx/stm32_dma.c b/os/hal/ports/STM32F4xx/stm32_dma.c new file mode 100644 index 000000000..a3bb26b0d --- /dev/null +++ b/os/hal/ports/STM32F4xx/stm32_dma.c @@ -0,0 +1,527 @@ +/* + ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file STM32F4xx/stm32_dma.c + * @brief Enhanced DMA helper driver code. + * + * @addtogroup STM32F4xx_DMA + * @details DMA sharing helper driver. In the STM32 the DMA streams are a + * shared resource, this driver allows to allocate and free DMA + * streams at runtime in order to allow all the other device + * drivers to coordinate the access to the resource. + * @note The DMA ISR handlers are all declared into this module because + * sharing, the various device drivers can associate a callback to + * ISRs when allocating streams. + * @{ + */ + +#include "hal.h" + +/* The following macro is only defined if some driver requiring DMA services + has been enabled.*/ +#if defined(STM32_DMA_REQUIRED) || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver local definitions. */ +/*===========================================================================*/ + +/** + * @brief Mask of the DMA1 streams in @p dma_streams_mask. + */ +#define STM32_DMA1_STREAMS_MASK 0x000000FF + +/** + * @brief Mask of the DMA2 streams in @p dma_streams_mask. + */ +#define STM32_DMA2_STREAMS_MASK 0x0000FF00 + +/** + * @brief Post-reset value of the stream CR register. + */ +#define STM32_DMA_CR_RESET_VALUE 0x00000000 + +/** + * @brief Post-reset value of the stream FCR register. + */ +#define STM32_DMA_FCR_RESET_VALUE 0x00000021 + +/*===========================================================================*/ +/* Driver exported variables. */ +/*===========================================================================*/ + +/** + * @brief DMA streams descriptors. + * @details This table keeps the association between an unique stream + * identifier and the involved physical registers. + * @note Don't use this array directly, use the appropriate wrapper macros + * instead: @p STM32_DMA1_STREAM0, @p STM32_DMA1_STREAM1 etc. + */ +const stm32_dma_stream_t _stm32_dma_streams[STM32_DMA_STREAMS] = { + {DMA1_Stream0, &DMA1->LIFCR, 0, 0, DMA1_Stream0_IRQn}, + {DMA1_Stream1, &DMA1->LIFCR, 6, 1, DMA1_Stream1_IRQn}, + {DMA1_Stream2, &DMA1->LIFCR, 16, 2, DMA1_Stream2_IRQn}, + {DMA1_Stream3, &DMA1->LIFCR, 22, 3, DMA1_Stream3_IRQn}, + {DMA1_Stream4, &DMA1->HIFCR, 0, 4, DMA1_Stream4_IRQn}, + {DMA1_Stream5, &DMA1->HIFCR, 6, 5, DMA1_Stream5_IRQn}, + {DMA1_Stream6, &DMA1->HIFCR, 16, 6, DMA1_Stream6_IRQn}, + {DMA1_Stream7, &DMA1->HIFCR, 22, 7, DMA1_Stream7_IRQn}, + {DMA2_Stream0, &DMA2->LIFCR, 0, 8, DMA2_Stream0_IRQn}, + {DMA2_Stream1, &DMA2->LIFCR, 6, 9, DMA2_Stream1_IRQn}, + {DMA2_Stream2, &DMA2->LIFCR, 16, 10, DMA2_Stream2_IRQn}, + {DMA2_Stream3, &DMA2->LIFCR, 22, 11, DMA2_Stream3_IRQn}, + {DMA2_Stream4, &DMA2->HIFCR, 0, 12, DMA2_Stream4_IRQn}, + {DMA2_Stream5, &DMA2->HIFCR, 6, 13, DMA2_Stream5_IRQn}, + {DMA2_Stream6, &DMA2->HIFCR, 16, 14, DMA2_Stream6_IRQn}, + {DMA2_Stream7, &DMA2->HIFCR, 22, 15, DMA2_Stream7_IRQn}, +}; + +/*===========================================================================*/ +/* Driver local variables and types. */ +/*===========================================================================*/ + +/** + * @brief DMA ISR redirector type. + */ +typedef struct { + stm32_dmaisr_t dma_func; /**< @brief DMA callback function. */ + void *dma_param; /**< @brief DMA callback parameter. */ +} dma_isr_redir_t; + +/** + * @brief Mask of the allocated streams. + */ +static uint32_t dma_streams_mask; + +/** + * @brief DMA IRQ redirectors. + */ +static dma_isr_redir_t dma_isr_redir[STM32_DMA_STREAMS]; + +/*===========================================================================*/ +/* Driver local functions. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver interrupt handlers. */ +/*===========================================================================*/ + +/** + * @brief DMA1 stream 0 shared interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(Vector6C) { + uint32_t flags; + + OSAL_IRQ_PROLOGUE(); + + flags = (DMA1->LISR >> 0) & STM32_DMA_ISR_MASK; + DMA1->LIFCR = STM32_DMA_ISR_MASK << 0; + if (dma_isr_redir[0].dma_func) + dma_isr_redir[0].dma_func(dma_isr_redir[0].dma_param, flags); + + OSAL_IRQ_EPILOGUE(); +} + +/** + * @brief DMA1 stream 1 shared interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(Vector70) { + uint32_t flags; + + OSAL_IRQ_PROLOGUE(); + + flags = (DMA1->LISR >> 6) & STM32_DMA_ISR_MASK; + DMA1->LIFCR = STM32_DMA_ISR_MASK << 6; + if (dma_isr_redir[1].dma_func) + dma_isr_redir[1].dma_func(dma_isr_redir[1].dma_param, flags); + + OSAL_IRQ_EPILOGUE(); +} + +/** + * @brief DMA1 stream 2 shared interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(Vector74) { + uint32_t flags; + + OSAL_IRQ_PROLOGUE(); + + flags = (DMA1->LISR >> 16) & STM32_DMA_ISR_MASK; + DMA1->LIFCR = STM32_DMA_ISR_MASK << 16; + if (dma_isr_redir[2].dma_func) + dma_isr_redir[2].dma_func(dma_isr_redir[2].dma_param, flags); + + OSAL_IRQ_EPILOGUE(); +} + +/** + * @brief DMA1 stream 3 shared interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(Vector78) { + uint32_t flags; + + OSAL_IRQ_PROLOGUE(); + + flags = (DMA1->LISR >> 22) & STM32_DMA_ISR_MASK; + DMA1->LIFCR = STM32_DMA_ISR_MASK << 22; + if (dma_isr_redir[3].dma_func) + dma_isr_redir[3].dma_func(dma_isr_redir[3].dma_param, flags); + + OSAL_IRQ_EPILOGUE(); +} + +/** + * @brief DMA1 stream 4 shared interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(Vector7C) { + uint32_t flags; + + OSAL_IRQ_PROLOGUE(); + + flags = (DMA1->HISR >> 0) & STM32_DMA_ISR_MASK; + DMA1->HIFCR = STM32_DMA_ISR_MASK << 0; + if (dma_isr_redir[4].dma_func) + dma_isr_redir[4].dma_func(dma_isr_redir[4].dma_param, flags); + + OSAL_IRQ_EPILOGUE(); +} + +/** + * @brief DMA1 stream 5 shared interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(Vector80) { + uint32_t flags; + + OSAL_IRQ_PROLOGUE(); + + flags = (DMA1->HISR >> 6) & STM32_DMA_ISR_MASK; + DMA1->HIFCR = STM32_DMA_ISR_MASK << 6; + if (dma_isr_redir[5].dma_func) + dma_isr_redir[5].dma_func(dma_isr_redir[5].dma_param, flags); + + OSAL_IRQ_EPILOGUE(); +} + +/** + * @brief DMA1 stream 6 shared interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(Vector84) { + uint32_t flags; + + OSAL_IRQ_PROLOGUE(); + + flags = (DMA1->HISR >> 16) & STM32_DMA_ISR_MASK; + DMA1->HIFCR = STM32_DMA_ISR_MASK << 16; + if (dma_isr_redir[6].dma_func) + dma_isr_redir[6].dma_func(dma_isr_redir[6].dma_param, flags); + + OSAL_IRQ_EPILOGUE(); +} + +/** + * @brief DMA1 stream 7 shared interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(VectorFC) { + uint32_t flags; + + OSAL_IRQ_PROLOGUE(); + + flags = (DMA1->HISR >> 22) & STM32_DMA_ISR_MASK; + DMA1->HIFCR = STM32_DMA_ISR_MASK << 22; + if (dma_isr_redir[7].dma_func) + dma_isr_redir[7].dma_func(dma_isr_redir[7].dma_param, flags); + + OSAL_IRQ_EPILOGUE(); +} + +/** + * @brief DMA2 stream 0 shared interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(Vector120) { + uint32_t flags; + + OSAL_IRQ_PROLOGUE(); + + flags = (DMA2->LISR >> 0) & STM32_DMA_ISR_MASK; + DMA2->LIFCR = STM32_DMA_ISR_MASK << 0; + if (dma_isr_redir[8].dma_func) + dma_isr_redir[8].dma_func(dma_isr_redir[8].dma_param, flags); + + OSAL_IRQ_EPILOGUE(); +} + +/** + * @brief DMA2 stream 1 shared interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(Vector124) { + uint32_t flags; + + OSAL_IRQ_PROLOGUE(); + + flags = (DMA2->LISR >> 6) & STM32_DMA_ISR_MASK; + DMA2->LIFCR = STM32_DMA_ISR_MASK << 6; + if (dma_isr_redir[9].dma_func) + dma_isr_redir[9].dma_func(dma_isr_redir[9].dma_param, flags); + + OSAL_IRQ_EPILOGUE(); +} + +/** + * @brief DMA2 stream 2 shared interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(Vector128) { + uint32_t flags; + + OSAL_IRQ_PROLOGUE(); + + flags = (DMA2->LISR >> 16) & STM32_DMA_ISR_MASK; + DMA2->LIFCR = STM32_DMA_ISR_MASK << 16; + if (dma_isr_redir[10].dma_func) + dma_isr_redir[10].dma_func(dma_isr_redir[10].dma_param, flags); + + OSAL_IRQ_EPILOGUE(); +} + +/** + * @brief DMA2 stream 3 shared interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(Vector12C) { + uint32_t flags; + + OSAL_IRQ_PROLOGUE(); + + flags = (DMA2->LISR >> 22) & STM32_DMA_ISR_MASK; + DMA2->LIFCR = STM32_DMA_ISR_MASK << 22; + if (dma_isr_redir[11].dma_func) + dma_isr_redir[11].dma_func(dma_isr_redir[11].dma_param, flags); + + OSAL_IRQ_EPILOGUE(); +} + +/** + * @brief DMA2 stream 4 shared interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(Vector130) { + uint32_t flags; + + OSAL_IRQ_PROLOGUE(); + + flags = (DMA2->HISR >> 0) & STM32_DMA_ISR_MASK; + DMA2->HIFCR = STM32_DMA_ISR_MASK << 0; + if (dma_isr_redir[12].dma_func) + dma_isr_redir[12].dma_func(dma_isr_redir[12].dma_param, flags); + + OSAL_IRQ_EPILOGUE(); +} + +/** + * @brief DMA2 stream 5 shared interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(Vector150) { + uint32_t flags; + + OSAL_IRQ_PROLOGUE(); + + flags = (DMA2->HISR >> 6) & STM32_DMA_ISR_MASK; + DMA2->HIFCR = STM32_DMA_ISR_MASK << 6; + if (dma_isr_redir[13].dma_func) + dma_isr_redir[13].dma_func(dma_isr_redir[13].dma_param, flags); + + OSAL_IRQ_EPILOGUE(); +} + +/** + * @brief DMA2 stream 6 shared interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(Vector154) { + uint32_t flags; + + OSAL_IRQ_PROLOGUE(); + + flags = (DMA2->HISR >> 16) & STM32_DMA_ISR_MASK; + DMA2->HIFCR = STM32_DMA_ISR_MASK << 16; + if (dma_isr_redir[14].dma_func) + dma_isr_redir[14].dma_func(dma_isr_redir[14].dma_param, flags); + + OSAL_IRQ_EPILOGUE(); +} + +/** + * @brief DMA2 stream 7 shared interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(Vector158) { + uint32_t flags; + + OSAL_IRQ_PROLOGUE(); + + flags = (DMA2->HISR >> 22) & STM32_DMA_ISR_MASK; + DMA2->HIFCR = STM32_DMA_ISR_MASK << 22; + if (dma_isr_redir[15].dma_func) + dma_isr_redir[15].dma_func(dma_isr_redir[15].dma_param, flags); + + OSAL_IRQ_EPILOGUE(); +} + +/*===========================================================================*/ +/* Driver exported functions. */ +/*===========================================================================*/ + +/** + * @brief STM32 DMA helper initialization. + * + * @init + */ +void dmaInit(void) { + int i; + + dma_streams_mask = 0; + for (i = 0; i < STM32_DMA_STREAMS; i++) { + _stm32_dma_streams[i].stream->CR = 0; + dma_isr_redir[i].dma_func = NULL; + } + DMA1->LIFCR = 0xFFFFFFFF; + DMA1->HIFCR = 0xFFFFFFFF; + DMA2->LIFCR = 0xFFFFFFFF; + DMA2->HIFCR = 0xFFFFFFFF; +} + +/** + * @brief Allocates a DMA stream. + * @details The stream is allocated and, if required, the DMA clock enabled. + * The function also enables the IRQ vector associated to the stream + * and initializes its priority. + * @pre The stream must not be already in use or an error is returned. + * @post The stream is allocated and the default ISR handler redirected + * to the specified function. + * @post The stream ISR vector is enabled and its priority configured. + * @post The stream must be freed using @p dmaStreamRelease() before it can + * be reused with another peripheral. + * @post The stream is in its post-reset state. + * @note This function can be invoked in both ISR or thread context. + * + * @param[in] dmastp pointer to a stm32_dma_stream_t structure + * @param[in] priority IRQ priority mask for the DMA stream + * @param[in] func handling function pointer, can be @p NULL + * @param[in] param a parameter to be passed to the handling function + * @return The operation status. + * @retval FALSE no error, stream taken. + * @retval TRUE error, stream already taken. + * + * @special + */ +bool_t dmaStreamAllocate(const stm32_dma_stream_t *dmastp, + uint32_t priority, + stm32_dmaisr_t func, + void *param) { + + osalDbgCheck(dmastp != NULL); + + /* Checks if the stream is already taken.*/ + if ((dma_streams_mask & (1 << dmastp->selfindex)) != 0) + return TRUE; + + /* Marks the stream as allocated.*/ + dma_isr_redir[dmastp->selfindex].dma_func = func; + dma_isr_redir[dmastp->selfindex].dma_param = param; + dma_streams_mask |= (1 << dmastp->selfindex); + + /* Enabling DMA clocks required by the current streams set.*/ + if ((dma_streams_mask & STM32_DMA1_STREAMS_MASK) != 0) + rccEnableDMA1(FALSE); + if ((dma_streams_mask & STM32_DMA2_STREAMS_MASK) != 0) + rccEnableDMA2(FALSE); + + /* Putting the stream in a safe state.*/ + dmaStreamDisable(dmastp); + dmastp->stream->CR = STM32_DMA_CR_RESET_VALUE; + dmastp->stream->FCR = STM32_DMA_FCR_RESET_VALUE; + + /* Enables the associated IRQ vector if a callback is defined.*/ + if (func != NULL) + nvicEnableVector(dmastp->vector, priority); + + return FALSE; +} + +/** + * @brief Releases a DMA stream. + * @details The stream is freed and, if required, the DMA clock disabled. + * Trying to release a unallocated stream is an illegal operation + * and is trapped if assertions are enabled. + * @pre The stream must have been allocated using @p dmaStreamAllocate(). + * @post The stream is again available. + * @note This function can be invoked in both ISR or thread context. + * + * @param[in] dmastp pointer to a stm32_dma_stream_t structure + * + * @special + */ +void dmaStreamRelease(const stm32_dma_stream_t *dmastp) { + + osalDbgCheck(dmastp != NULL); + + /* Check if the streams is not taken.*/ + osalDbgAssert((dma_streams_mask & (1 << dmastp->selfindex)) != 0, + "not allocated"); + + /* Disables the associated IRQ vector.*/ + nvicDisableVector(dmastp->vector); + + /* Marks the stream as not allocated.*/ + dma_streams_mask &= ~(1 << dmastp->selfindex); + + /* Shutting down clocks that are no more required, if any.*/ + if ((dma_streams_mask & STM32_DMA1_STREAMS_MASK) == 0) + rccDisableDMA1(FALSE); + if ((dma_streams_mask & STM32_DMA2_STREAMS_MASK) == 0) + rccDisableDMA2(FALSE); +} + +#endif /* STM32_DMA_REQUIRED */ + +/** @} */ diff --git a/os/hal/ports/STM32F4xx/stm32_dma.h b/os/hal/ports/STM32F4xx/stm32_dma.h new file mode 100644 index 000000000..62b0fbd43 --- /dev/null +++ b/os/hal/ports/STM32F4xx/stm32_dma.h @@ -0,0 +1,461 @@ +/* + ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file STM32F4xx/stm32_dma.h + * @brief Enhanced-DMA helper driver header. + * @note This file requires definitions from the ST STM32F4xx header file + * stm32f4xx.h. + * + * @addtogroup STM32F4xx_DMA + * @{ + */ + +#ifndef _STM32_DMA_H_ +#define _STM32_DMA_H_ + +/*===========================================================================*/ +/* Driver constants. */ +/*===========================================================================*/ + +/** + * @brief Total number of DMA streams. + * @note This is the total number of streams among all the DMA units. + */ +#define STM32_DMA_STREAMS 16 + +/** + * @brief Mask of the ISR bits passed to the DMA callback functions. + */ +#define STM32_DMA_ISR_MASK 0x3D + +/** + * @brief Returns the channel associated to the specified stream. + * + * @param[in] id the unique numeric stream identifier + * @param[in] c a stream/channel association word, one channel per + * nibble + * @return Returns the channel associated to the stream. + */ +#define STM32_DMA_GETCHANNEL(id, c) (((c) >> (((id) & 7) * 4)) & 7) + +/** + * @brief Checks if a DMA priority is within the valid range. + * @param[in] prio DMA priority + * + * @retval The check result. + * @retval FALSE invalid DMA priority. + * @retval TRUE correct DMA priority. + */ +#define STM32_DMA_IS_VALID_PRIORITY(prio) (((prio) >= 0) && ((prio) <= 3)) + +/** + * @brief Returns an unique numeric identifier for a DMA stream. + * + * @param[in] dma the DMA unit number + * @param[in] stream the stream number + * @return An unique numeric stream identifier. + */ +#define STM32_DMA_STREAM_ID(dma, stream) ((((dma) - 1) * 8) + (stream)) + +/** + * @brief Returns a DMA stream identifier mask. + * + * + * @param[in] dma the DMA unit number + * @param[in] stream the stream number + * @return A DMA stream identifier mask. + */ +#define STM32_DMA_STREAM_ID_MSK(dma, stream) \ + (1 << STM32_DMA_STREAM_ID(dma, stream)) + +/** + * @brief Checks if a DMA stream unique identifier belongs to a mask. + * @param[in] id the stream numeric identifier + * @param[in] mask the stream numeric identifiers mask + * + * @retval The check result. + * @retval FALSE id does not belong to the mask. + * @retval TRUE id belongs to the mask. + */ +#define STM32_DMA_IS_VALID_ID(id, mask) (((1 << (id)) & (mask))) + +/** + * @name DMA streams identifiers + * @{ + */ +/** + * @brief Returns a pointer to a stm32_dma_stream_t structure. + * + * @param[in] id the stream numeric identifier + * @return A pointer to the stm32_dma_stream_t constant structure + * associated to the DMA stream. + */ +#define STM32_DMA_STREAM(id) (&_stm32_dma_streams[id]) + +#define STM32_DMA1_STREAM0 STM32_DMA_STREAM(0) +#define STM32_DMA1_STREAM1 STM32_DMA_STREAM(1) +#define STM32_DMA1_STREAM2 STM32_DMA_STREAM(2) +#define STM32_DMA1_STREAM3 STM32_DMA_STREAM(3) +#define STM32_DMA1_STREAM4 STM32_DMA_STREAM(4) +#define STM32_DMA1_STREAM5 STM32_DMA_STREAM(5) +#define STM32_DMA1_STREAM6 STM32_DMA_STREAM(6) +#define STM32_DMA1_STREAM7 STM32_DMA_STREAM(7) +#define STM32_DMA2_STREAM0 STM32_DMA_STREAM(8) +#define STM32_DMA2_STREAM1 STM32_DMA_STREAM(9) +#define STM32_DMA2_STREAM2 STM32_DMA_STREAM(10) +#define STM32_DMA2_STREAM3 STM32_DMA_STREAM(11) +#define STM32_DMA2_STREAM4 STM32_DMA_STREAM(12) +#define STM32_DMA2_STREAM5 STM32_DMA_STREAM(13) +#define STM32_DMA2_STREAM6 STM32_DMA_STREAM(14) +#define STM32_DMA2_STREAM7 STM32_DMA_STREAM(15) +/** @} */ + +/** + * @name CR register constants common to all DMA types + * @{ + */ +#define STM32_DMA_CR_EN DMA_SxCR_EN +#define STM32_DMA_CR_TEIE DMA_SxCR_TEIE +#define STM32_DMA_CR_HTIE DMA_SxCR_HTIE +#define STM32_DMA_CR_TCIE DMA_SxCR_TCIE +#define STM32_DMA_CR_DIR_MASK DMA_SxCR_DIR +#define STM32_DMA_CR_DIR_P2M 0 +#define STM32_DMA_CR_DIR_M2P DMA_SxCR_DIR_0 +#define STM32_DMA_CR_DIR_M2M DMA_SxCR_DIR_1 +#define STM32_DMA_CR_CIRC DMA_SxCR_CIRC +#define STM32_DMA_CR_PINC DMA_SxCR_PINC +#define STM32_DMA_CR_MINC DMA_SxCR_MINC +#define STM32_DMA_CR_PSIZE_MASK DMA_SxCR_PSIZE +#define STM32_DMA_CR_PSIZE_BYTE 0 +#define STM32_DMA_CR_PSIZE_HWORD DMA_SxCR_PSIZE_0 +#define STM32_DMA_CR_PSIZE_WORD DMA_SxCR_PSIZE_1 +#define STM32_DMA_CR_MSIZE_MASK DMA_SxCR_MSIZE +#define STM32_DMA_CR_MSIZE_BYTE 0 +#define STM32_DMA_CR_MSIZE_HWORD DMA_SxCR_MSIZE_0 +#define STM32_DMA_CR_MSIZE_WORD DMA_SxCR_MSIZE_1 +#define STM32_DMA_CR_SIZE_MASK (STM32_DMA_CR_PSIZE_MASK | \ + STM32_DMA_CR_MSIZE_MASK) +#define STM32_DMA_CR_PL_MASK DMA_SxCR_PL +#define STM32_DMA_CR_PL(n) ((n) << 16) +/** @} */ + +/** + * @name CR register constants only found in STM32F2xx/STM32F4xx + * @{ + */ +#define STM32_DMA_CR_DMEIE DMA_SxCR_DMEIE +#define STM32_DMA_CR_PFCTRL DMA_SxCR_PFCTRL +#define STM32_DMA_CR_PINCOS DMA_SxCR_PINCOS +#define STM32_DMA_CR_DBM DMA_SxCR_DBM +#define STM32_DMA_CR_CT DMA_SxCR_CT +#define STM32_DMA_CR_PBURST_MASK DMA_SxCR_PBURST +#define STM32_DMA_CR_PBURST_SINGLE 0 +#define STM32_DMA_CR_PBURST_INCR4 DMA_SxCR_PBURST_0 +#define STM32_DMA_CR_PBURST_INCR8 DMA_SxCR_PBURST_1 +#define STM32_DMA_CR_PBURST_INCR16 (DMA_SxCR_PBURST_0 | DMA_SxCR_PBURST_1) +#define STM32_DMA_CR_MBURST_MASK DMA_SxCR_MBURST +#define STM32_DMA_CR_MBURST_SINGLE 0 +#define STM32_DMA_CR_MBURST_INCR4 DMA_SxCR_MBURST_0 +#define STM32_DMA_CR_MBURST_INCR8 DMA_SxCR_MBURST_1 +#define STM32_DMA_CR_MBURST_INCR16 (DMA_SxCR_MBURST_0 | DMA_SxCR_MBURST_1) +#define STM32_DMA_CR_CHSEL_MASK DMA_SxCR_CHSEL +#define STM32_DMA_CR_CHSEL(n) ((n) << 25) +/** @} */ + +/** + * @name FCR register constants only found in STM32F2xx/STM32F4xx + * @{ + */ +#define STM32_DMA_FCR_FEIE DMA_SxFCR_FEIE +#define STM32_DMA_FCR_FS_MASK DMA_SxFCR_FS +#define STM32_DMA_FCR_DMDIS DMA_SxFCR_DMDIS +#define STM32_DMA_FCR_FTH_MASK DMA_SxFCR_FTH +#define STM32_DMA_FCR_FTH_1Q 0 +#define STM32_DMA_FCR_FTH_HALF DMA_SxFCR_FTH_0 +#define STM32_DMA_FCR_FTH_3Q DMA_SxFCR_FTH_1 +#define STM32_DMA_FCR_FTH_FULL (DMA_SxFCR_FTH_0 | DMA_SxFCR_FTH_1) +/** @} */ + +/** + * @name Status flags passed to the ISR callbacks + */ +#define STM32_DMA_ISR_FEIF DMA_LISR_FEIF0 +#define STM32_DMA_ISR_DMEIF DMA_LISR_DMEIF0 +#define STM32_DMA_ISR_TEIF DMA_LISR_TEIF0 +#define STM32_DMA_ISR_HTIF DMA_LISR_HTIF0 +#define STM32_DMA_ISR_TCIF DMA_LISR_TCIF0 +/** @} */ + +/*===========================================================================*/ +/* Driver pre-compile time settings. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Derived constants and error checks. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver data structures and types. */ +/*===========================================================================*/ + +/** + * @brief STM32 DMA stream descriptor structure. + */ +typedef struct { + DMA_Stream_TypeDef *stream; /**< @brief Associated DMA stream. */ + volatile uint32_t *ifcr; /**< @brief Associated IFCR reg. */ + uint8_t ishift; /**< @brief Bits offset in xIFCR + register. */ + uint8_t selfindex; /**< @brief Index to self in array. */ + uint8_t vector; /**< @brief Associated IRQ vector. */ +} stm32_dma_stream_t; + +/** + * @brief STM32 DMA ISR function type. + * + * @param[in] p parameter for the registered function + * @param[in] flags pre-shifted content of the xISR register, the bits + * are aligned to bit zero + */ +typedef void (*stm32_dmaisr_t)(void *p, uint32_t flags); + +/*===========================================================================*/ +/* Driver macros. */ +/*===========================================================================*/ + +/** + * @name Macro Functions + * @{ + */ +/** + * @brief Associates a peripheral data register to a DMA stream. + * @note This function can be invoked in both ISR or thread context. + * @pre The stream must have been allocated using @p dmaStreamAllocate(). + * @post After use the stream can be released using @p dmaStreamRelease(). + * + * @param[in] dmastp pointer to a stm32_dma_stream_t structure + * @param[in] addr value to be written in the PAR register + * + * @special + */ +#define dmaStreamSetPeripheral(dmastp, addr) { \ + (dmastp)->stream->PAR = (uint32_t)(addr); \ +} + +/** + * @brief Associates a memory destination to a DMA stream. + * @note This function can be invoked in both ISR or thread context. + * @pre The stream must have been allocated using @p dmaStreamAllocate(). + * @post After use the stream can be released using @p dmaStreamRelease(). + * + * @param[in] dmastp pointer to a stm32_dma_stream_t structure + * @param[in] addr value to be written in the M0AR register + * + * @special + */ +#define dmaStreamSetMemory0(dmastp, addr) { \ + (dmastp)->stream->M0AR = (uint32_t)(addr); \ +} + +/** + * @brief Associates an alternate memory destination to a DMA stream. + * @note This function can be invoked in both ISR or thread context. + * + * @param[in] dmastp pointer to a stm32_dma_stream_t structure + * @param[in] addr value to be written in the M1AR register + * + * @special + */ +#define dmaStreamSetMemory1(dmastp, addr) { \ + (dmastp)->stream->M1AR = (uint32_t)(addr); \ +} + +/** + * @brief Sets the number of transfers to be performed. + * @note This function can be invoked in both ISR or thread context. + * @pre The stream must have been allocated using @p dmaStreamAllocate(). + * @post After use the stream can be released using @p dmaStreamRelease(). + * + * @param[in] dmastp pointer to a stm32_dma_stream_t structure + * @param[in] size value to be written in the CNDTR register + * + * @special + */ +#define dmaStreamSetTransactionSize(dmastp, size) { \ + (dmastp)->stream->NDTR = (uint32_t)(size); \ +} + +/** + * @brief Returns the number of transfers to be performed. + * @note This function can be invoked in both ISR or thread context. + * @pre The stream must have been allocated using @p dmaStreamAllocate(). + * @post After use the stream can be released using @p dmaStreamRelease(). + * + * @param[in] dmastp pointer to a stm32_dma_stream_t structure + * @return The number of transfers to be performed. + * + * @special + */ +#define dmaStreamGetTransactionSize(dmastp) ((size_t)((dmastp)->stream->NDTR)) + +/** + * @brief Programs the stream mode settings. + * @note This function can be invoked in both ISR or thread context. + * @pre The stream must have been allocated using @p dmaStreamAllocate(). + * @post After use the stream can be released using @p dmaStreamRelease(). + * + * @param[in] dmastp pointer to a stm32_dma_stream_t structure + * @param[in] mode value to be written in the CR register + * + * @special + */ +#define dmaStreamSetMode(dmastp, mode) { \ + (dmastp)->stream->CR = (uint32_t)(mode); \ +} + +/** + * @brief Programs the stream FIFO settings. + * @note This function can be invoked in both ISR or thread context. + * @pre The stream must have been allocated using @p dmaStreamAllocate(). + * @post After use the stream can be released using @p dmaStreamRelease(). + * + * @param[in] dmastp pointer to a stm32_dma_stream_t structure + * @param[in] mode value to be written in the FCR register + * + * @special + */ +#define dmaStreamSetFIFO(dmastp, mode) { \ + (dmastp)->stream->FCR = (uint32_t)(mode); \ +} + +/** + * @brief DMA stream enable. + * @note This function can be invoked in both ISR or thread context. + * @pre The stream must have been allocated using @p dmaStreamAllocate(). + * @post After use the stream can be released using @p dmaStreamRelease(). + * + * @param[in] dmastp pointer to a stm32_dma_stream_t structure + * + * @special + */ +#define dmaStreamEnable(dmastp) { \ + (dmastp)->stream->CR |= STM32_DMA_CR_EN; \ +} + +/** + * @brief DMA stream disable. + * @details The function disables the specified stream, waits for the disable + * operation to complete and then clears any pending interrupt. + * @note This function can be invoked in both ISR or thread context. + * @note Interrupts enabling flags are set to zero after this call, see + * bug 3607518. + * @pre The stream must have been allocated using @p dmaStreamAllocate(). + * @post After use the stream can be released using @p dmaStreamRelease(). + * + * @param[in] dmastp pointer to a stm32_dma_stream_t structure + * + * @special + */ +#define dmaStreamDisable(dmastp) { \ + (dmastp)->stream->CR &= ~(STM32_DMA_CR_TCIE | STM32_DMA_CR_HTIE | \ + STM32_DMA_CR_TEIE | STM32_DMA_CR_DMEIE | \ + STM32_DMA_CR_EN); \ + while (((dmastp)->stream->CR & STM32_DMA_CR_EN) != 0) \ + ; \ + dmaStreamClearInterrupt(dmastp); \ +} + +/** + * @brief DMA stream interrupt sources clear. + * @note This function can be invoked in both ISR or thread context. + * @pre The stream must have been allocated using @p dmaStreamAllocate(). + * @post After use the stream can be released using @p dmaStreamRelease(). + * + * @param[in] dmastp pointer to a stm32_dma_stream_t structure + * + * @special + */ +#define dmaStreamClearInterrupt(dmastp) { \ + *(dmastp)->ifcr = STM32_DMA_ISR_MASK << (dmastp)->ishift; \ +} + +/** + * @brief Starts a memory to memory operation using the specified stream. + * @note The default transfer data mode is "byte to byte" but it can be + * changed by specifying extra options in the @p mode parameter. + * @pre The stream must have been allocated using @p dmaStreamAllocate(). + * @post After use the stream can be released using @p dmaStreamRelease(). + * + * @param[in] dmastp pointer to a stm32_dma_stream_t structure + * @param[in] mode value to be written in the CCR register, this value + * is implicitly ORed with: + * - @p STM32_DMA_CR_MINC + * - @p STM32_DMA_CR_PINC + * - @p STM32_DMA_CR_DIR_M2M + * - @p STM32_DMA_CR_EN + * . + * @param[in] src source address + * @param[in] dst destination address + * @param[in] n number of data units to copy + */ +#define dmaStartMemCopy(dmastp, mode, src, dst, n) { \ + dmaStreamSetPeripheral(dmastp, src); \ + dmaStreamSetMemory0(dmastp, dst); \ + dmaStreamSetTransactionSize(dmastp, n); \ + dmaStreamSetMode(dmastp, (mode) | \ + STM32_DMA_CR_MINC | STM32_DMA_CR_PINC | \ + STM32_DMA_CR_DIR_M2M | STM32_DMA_CR_EN); \ +} + +/** + * @brief Polled wait for DMA transfer end. + * @pre The stream must have been allocated using @p dmaStreamAllocate(). + * @post After use the stream can be released using @p dmaStreamRelease(). + * + * @param[in] dmastp pointer to a stm32_dma_stream_t structure + */ +#define dmaWaitCompletion(dmastp) { \ + while ((dmastp)->stream->NDTR > 0) \ + ; \ + dmaStreamDisable(dmastp); \ +} +/** @} */ + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +#if !defined(__DOXYGEN__) +extern const stm32_dma_stream_t _stm32_dma_streams[STM32_DMA_STREAMS]; +#endif + +#ifdef __cplusplus +extern "C" { +#endif + void dmaInit(void); + bool_t dmaStreamAllocate(const stm32_dma_stream_t *dmastp, + uint32_t priority, + stm32_dmaisr_t func, + void *param); + void dmaStreamRelease(const stm32_dma_stream_t *dmastp); +#ifdef __cplusplus +} +#endif + +#endif /* _STM32_DMA_H_ */ + +/** @} */ diff --git a/os/hal/ports/STM32F4xx/stm32_isr.h b/os/hal/ports/STM32F4xx/stm32_isr.h new file mode 100644 index 000000000..0e936b3d6 --- /dev/null +++ b/os/hal/ports/STM32F4xx/stm32_isr.h @@ -0,0 +1,150 @@ +/* + ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file STM32F4xx/stm32_isr.h + * @brief ISR remapper driver header. + * + * @addtogroup STM32F4xx_ISR + * @{ + */ + +#ifndef _STM32_ISR_H_ +#define _STM32_ISR_H_ + +/*===========================================================================*/ +/* Driver constants. */ +/*===========================================================================*/ + +/** + * @name ISR names and numbers remapping + * @{ + */ +/* + * CAN units. + */ +#define STM32_CAN1_TX_HANDLER Vector8C +#define STM32_CAN1_RX0_HANDLER Vector90 +#define STM32_CAN1_RX1_HANDLER Vector94 +#define STM32_CAN1_SCE_HANDLER Vector98 +#define STM32_CAN2_TX_HANDLER Vector13C +#define STM32_CAN2_RX0_HANDLER Vector140 +#define STM32_CAN2_RX1_HANDLER Vector144 +#define STM32_CAN2_SCE_HANDLER Vector148 + +#define STM32_CAN1_TX_NUMBER 19 +#define STM32_CAN1_RX0_NUMBER 20 +#define STM32_CAN1_RX1_NUMBER 21 +#define STM32_CAN1_SCE_NUMBER 22 +#define STM32_CAN2_TX_NUMBER 63 +#define STM32_CAN2_RX0_NUMBER 64 +#define STM32_CAN2_RX1_NUMBER 65 +#define STM32_CAN2_SCE_NUMBER 66 + +/* + * OTG units. + */ +#define STM32_OTG1_HANDLER Vector14C +#define STM32_OTG2_HANDLER Vector174 +#define STM32_OTG2_EP1OUT_HANDLER Vector168 +#define STM32_OTG2_EP1IN_HANDLER Vector16C + +#define STM32_OTG1_NUMBER 67 +#define STM32_OTG2_NUMBER 77 +#define STM32_OTG2_EP1OUT_NUMBER 74 +#define STM32_OTG2_EP1IN_NUMBER 75 + +/* + * SDIO unit. + */ +#define STM32_SDIO_HANDLER Vector104 + +#define STM32_SDIO_NUMBER 49 + +/* + * TIM units. + */ +#define STM32_TIM1_UP_HANDLER VectorA4 +#define STM32_TIM1_CC_HANDLER VectorAC +#define STM32_TIM2_HANDLER VectorB0 +#define STM32_TIM3_HANDLER VectorB4 +#define STM32_TIM4_HANDLER VectorB8 +#define STM32_TIM5_HANDLER Vector108 +#define STM32_TIM6_HANDLER Vector118 +#define STM32_TIM7_HANDLER Vector11C +#define STM32_TIM8_UP_HANDLER VectorF0 +#define STM32_TIM8_CC_HANDLER VectorF8 +#define STM32_TIM9_HANDLER VectorA0 +#define STM32_TIM11_HANDLER VectorA8 +#define STM32_TIM12_HANDLER VectorEC +#define STM32_TIM14_HANDLER VectorF4 + +#define STM32_TIM1_UP_NUMBER 25 +#define STM32_TIM1_CC_NUMBER 27 +#define STM32_TIM2_NUMBER 28 +#define STM32_TIM3_NUMBER 29 +#define STM32_TIM4_NUMBER 30 +#define STM32_TIM5_NUMBER 50 +#define STM32_TIM6_NUMBER 54 +#define STM32_TIM7_NUMBER 55 +#define STM32_TIM8_UP_NUMBER 44 +#define STM32_TIM8_CC_NUMBER 46 +#define STM32_TIM9_NUMBER 24 +#define STM32_TIM11_NUMBER 26 +#define STM32_TIM12_NUMBER 43 +#define STM32_TIM14_NUMBER 45 + +/* + * USART units. + */ +#define STM32_USART1_HANDLER VectorD4 +#define STM32_USART2_HANDLER VectorD8 +#define STM32_USART3_HANDLER VectorDC +#define STM32_UART4_HANDLER Vector110 +#define STM32_UART5_HANDLER Vector114 +#define STM32_USART6_HANDLER Vector15C + +#define STM32_USART1_NUMBER 37 +#define STM32_USART2_NUMBER 38 +#define STM32_USART3_NUMBER 39 +#define STM32_UART4_NUMBER 52 +#define STM32_UART5_NUMBER 53 +#define STM32_USART6_NUMBER 71 +/** @} */ + +/*===========================================================================*/ +/* Driver pre-compile time settings. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Derived constants and error checks. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver data structures and types. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver macros. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +#endif /* _STM32_ISR_H_ */ + +/** @} */ diff --git a/os/hal/ports/STM32F4xx/stm32_rcc.h b/os/hal/ports/STM32F4xx/stm32_rcc.h new file mode 100644 index 000000000..25a9bb037 --- /dev/null +++ b/os/hal/ports/STM32F4xx/stm32_rcc.h @@ -0,0 +1,1254 @@ +/* + ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file STM32F4xx/stm32_rcc.h + * @brief RCC helper driver header. + * @note This file requires definitions from the ST header file + * @p stm32f4xx.h. + * + * @addtogroup STM32F4xx_RCC + * @{ + */ +#ifndef _STM32_RCC_ +#define _STM32_RCC_ + +/*===========================================================================*/ +/* Driver constants. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver pre-compile time settings. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Derived constants and error checks. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver data structures and types. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver macros. */ +/*===========================================================================*/ + +/** + * @name Generic RCC operations + * @{ + */ +/** + * @brief Enables the clock of one or more peripheral on the APB1 bus. + * + * @param[in] mask APB1 peripherals mask + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableAPB1(mask, lp) { \ + RCC->APB1ENR |= (mask); \ + if (lp) \ + RCC->APB1LPENR |= (mask); \ +} + +/** + * @brief Disables the clock of one or more peripheral on the APB1 bus. + * + * @param[in] mask APB1 peripherals mask + * @param[in] lp low power enable flag + * + * @api + */ +#define rccDisableAPB1(mask, lp) { \ + RCC->APB1ENR &= ~(mask); \ + if (lp) \ + RCC->APB1LPENR &= ~(mask); \ +} + +/** + * @brief Resets one or more peripheral on the APB1 bus. + * + * @param[in] mask APB1 peripherals mask + * + * @api + */ +#define rccResetAPB1(mask) { \ + RCC->APB1RSTR |= (mask); \ + RCC->APB1RSTR = 0; \ +} + +/** + * @brief Enables the clock of one or more peripheral on the APB2 bus. + * + * @param[in] mask APB2 peripherals mask + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableAPB2(mask, lp) { \ + RCC->APB2ENR |= (mask); \ + if (lp) \ + RCC->APB2LPENR |= (mask); \ +} + +/** + * @brief Disables the clock of one or more peripheral on the APB2 bus. + * + * @param[in] mask APB2 peripherals mask + * @param[in] lp low power enable flag + * + * @api + */ +#define rccDisableAPB2(mask, lp) { \ + RCC->APB2ENR &= ~(mask); \ + if (lp) \ + RCC->APB2LPENR &= ~(mask); \ +} + +/** + * @brief Resets one or more peripheral on the APB2 bus. + * + * @param[in] mask APB2 peripherals mask + * + * @api + */ +#define rccResetAPB2(mask) { \ + RCC->APB2RSTR |= (mask); \ + RCC->APB2RSTR = 0; \ +} + +/** + * @brief Enables the clock of one or more peripheral on the AHB1 bus. + * + * @param[in] mask AHB1 peripherals mask + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableAHB1(mask, lp) { \ + RCC->AHB1ENR |= (mask); \ + if (lp) \ + RCC->AHB1LPENR |= (mask); \ +} + +/** + * @brief Disables the clock of one or more peripheral on the AHB1 bus. + * + * @param[in] mask AHB1 peripherals mask + * @param[in] lp low power enable flag + * + * @api + */ +#define rccDisableAHB1(mask, lp) { \ + RCC->AHB1ENR &= ~(mask); \ + if (lp) \ + RCC->AHB1LPENR &= ~(mask); \ +} + +/** + * @brief Resets one or more peripheral on the AHB1 bus. + * + * @param[in] mask AHB1 peripherals mask + * + * @api + */ +#define rccResetAHB1(mask) { \ + RCC->AHB1RSTR |= (mask); \ + RCC->AHB1RSTR = 0; \ +} + +/** + * @brief Enables the clock of one or more peripheral on the AHB2 bus. + * + * @param[in] mask AHB2 peripherals mask + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableAHB2(mask, lp) { \ + RCC->AHB2ENR |= (mask); \ + if (lp) \ + RCC->AHB2LPENR |= (mask); \ +} + +/** + * @brief Disables the clock of one or more peripheral on the AHB2 bus. + * + * @param[in] mask AHB2 peripherals mask + * @param[in] lp low power enable flag + * + * @api + */ +#define rccDisableAHB2(mask, lp) { \ + RCC->AHB2ENR &= ~(mask); \ + if (lp) \ + RCC->AHB2LPENR &= ~(mask); \ +} + +/** + * @brief Resets one or more peripheral on the AHB2 bus. + * + * @param[in] mask AHB2 peripherals mask + * + * @api + */ +#define rccResetAHB2(mask) { \ + RCC->AHB2RSTR |= (mask); \ + RCC->AHB2RSTR = 0; \ +} + +/** + * @brief Enables the clock of one or more peripheral on the AHB3 (FSMC) bus. + * + * @param[in] mask AHB3 peripherals mask + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableAHB3(mask, lp) { \ + RCC->AHB3ENR |= (mask); \ + if (lp) \ + RCC->AHB3LPENR |= (mask); \ +} + +/** + * @brief Disables the clock of one or more peripheral on the AHB3 (FSMC) bus. + * + * @param[in] mask AHB3 peripherals mask + * @param[in] lp low power enable flag + * + * @api + */ +#define rccDisableAHB3(mask, lp) { \ + RCC->AHB3ENR &= ~(mask); \ + if (lp) \ + RCC->AHB3LPENR &= ~(mask); \ +} + +/** + * @brief Resets one or more peripheral on the AHB3 (FSMC) bus. + * + * @param[in] mask AHB3 peripherals mask + * + * @api + */ +#define rccResetAHB3(mask) { \ + RCC->AHB3RSTR |= (mask); \ + RCC->AHB3RSTR = 0; \ +} +/** @} */ + +/** + * @name ADC peripherals specific RCC operations + * @{ + */ +/** + * @brief Enables the ADC1 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableADC1(lp) rccEnableAPB2(RCC_APB2ENR_ADC1EN, lp) + +/** + * @brief Disables the ADC1 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccDisableADC1(lp) rccDisableAPB2(RCC_APB2ENR_ADC1EN, lp) + +/** + * @brief Resets the ADC1 peripheral. + * + * @api + */ +#define rccResetADC1() rccResetAPB2(RCC_APB2RSTR_ADC1RST) + +/** + * @brief Enables the ADC2 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableADC2(lp) rccEnableAPB2(RCC_APB2ENR_ADC2EN, lp) + +/** + * @brief Disables the ADC2 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccDisableADC2(lp) rccDisableAPB2(RCC_APB2ENR_ADC2EN, lp) + +/** + * @brief Resets the ADC2 peripheral. + * + * @api + */ +#define rccResetADC2() rccResetAPB2(RCC_APB2RSTR_ADC2RST) + +/** + * @brief Enables the ADC3 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableADC3(lp) rccEnableAPB2(RCC_APB2ENR_ADC3EN, lp) + +/** + * @brief Disables the ADC3 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccDisableADC3(lp) rccDisableAPB2(RCC_APB2ENR_ADC3EN, lp) + +/** + * @brief Resets the ADC3 peripheral. + * + * @api + */ +#define rccResetADC3() rccResetAPB2(RCC_APB2RSTR_ADC3RST) +/** @} */ + +/** + * @name DMA peripheral specific RCC operations + * @{ + */ +/** + * @brief Enables the DMA1 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableDMA1(lp) rccEnableAHB1(RCC_AHB1ENR_DMA1EN, lp) + +/** + * @brief Disables the DMA1 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccDisableDMA1(lp) rccDisableAHB1(RCC_AHB1ENR_DMA1EN, lp) + +/** + * @brief Resets the DMA1 peripheral. + * + * @api + */ +#define rccResetDMA1() rccResetAHB1(RCC_AHB1RSTR_DMA1RST) + +/** + * @brief Enables the DMA2 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableDMA2(lp) rccEnableAHB1(RCC_AHB1ENR_DMA2EN, lp) + +/** + * @brief Disables the DMA2 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccDisableDMA2(lp) rccDisableAHB1(RCC_AHB1ENR_DMA2EN, lp) + +/** + * @brief Resets the DMA2 peripheral. + * + * @api + */ +#define rccResetDMA2() rccResetAHB1(RCC_AHB1RSTR_DMA2RST) +/** @} */ + +/** + * @name PWR interface specific RCC operations + * @{ + */ +/** + * @brief Enables the PWR interface clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnablePWRInterface(lp) rccEnableAPB1(RCC_APB1ENR_PWREN, lp) + +/** + * @brief Disables PWR interface clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccDisablePWRInterface(lp) rccDisableAPB1(RCC_APB1ENR_PWREN, lp) + +/** + * @brief Resets the PWR interface. + * + * @api + */ +#define rccResetPWRInterface() rccResetAPB1(RCC_APB1RSTR_PWRRST) +/** @} */ + + +/** + * @name CAN peripherals specific RCC operations + * @{ + */ +/** + * @brief Enables the CAN1 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableCAN1(lp) rccEnableAPB1(RCC_APB1ENR_CAN1EN, lp) + +/** + * @brief Disables the CAN1 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccDisableCAN1(lp) rccDisableAPB1(RCC_APB1ENR_CAN1EN, lp) + +/** + * @brief Resets the CAN1 peripheral. + * + * @api + */ +#define rccResetCAN1() rccResetAPB1(RCC_APB1RSTR_CAN1RST) + +/** + * @brief Enables the CAN2 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableCAN2(lp) rccEnableAPB1(RCC_APB1ENR_CAN2EN, lp) + +/** + * @brief Disables the CAN2 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccDisableCAN2(lp) rccDisableAPB1(RCC_APB1ENR_CAN2EN, lp) + +/** + * @brief Resets the CAN2 peripheral. + * + * @api + */ +#define rccResetCAN2() rccResetAPB1(RCC_APB1RSTR_CAN2RST) +/** @} */ + +/** + * @name ETH peripheral specific RCC operations + * @{ + */ +/** + * @brief Enables the ETH peripheral clock. + * @note The @p lp parameter is ignored in this family. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableETH(lp) rccEnableAHB1(RCC_AHB1ENR_ETHMACEN | \ + RCC_AHB1ENR_ETHMACTXEN | \ + RCC_AHB1ENR_ETHMACRXEN, lp) + +/** + * @brief Disables the ETH peripheral clock. + * @note The @p lp parameter is ignored in this family. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccDisableETH(lp) rccDisableAHB1(RCC_AHB1ENR_ETHMACEN | \ + RCC_AHB1ENR_ETHMACTXEN | \ + RCC_AHB1ENR_ETHMACRXEN, lp) + +/** + * @brief Resets the ETH peripheral. + * + * @api + */ +#define rccResetETH() rccResetAHB1(RCC_AHB1RSTR_ETHMACRST) +/** @} */ + +/** + * @name I2C peripherals specific RCC operations + * @{ + */ +/** + * @brief Enables the I2C1 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableI2C1(lp) rccEnableAPB1(RCC_APB1ENR_I2C1EN, lp) + +/** + * @brief Disables the I2C1 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccDisableI2C1(lp) rccDisableAPB1(RCC_APB1ENR_I2C1EN, lp) + +/** + * @brief Resets the I2C1 peripheral. + * + * @api + */ +#define rccResetI2C1() rccResetAPB1(RCC_APB1RSTR_I2C1RST) + +/** + * @brief Enables the I2C2 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableI2C2(lp) rccEnableAPB1(RCC_APB1ENR_I2C2EN, lp) + +/** + * @brief Disables the I2C2 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccDisableI2C2(lp) rccDisableAPB1(RCC_APB1ENR_I2C2EN, lp) + +/** + * @brief Resets the I2C2 peripheral. + * + * @api + */ +#define rccResetI2C2() rccResetAPB1(RCC_APB1RSTR_I2C2RST) + +/** + * @brief Enables the I2C3 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableI2C3(lp) rccEnableAPB1(RCC_APB1ENR_I2C3EN, lp) + +/** + * @brief Disables the I2C3 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccDisableI2C3(lp) rccDisableAPB1(RCC_APB1ENR_I2C3EN, lp) + +/** + * @brief Resets the I2C3 peripheral. + * + * @api + */ +#define rccResetI2C3() rccResetAPB1(RCC_APB1RSTR_I2C3RST) +/** @} */ + +/** + * @name OTG peripherals specific RCC operations + * @{ + */ +/** + * @brief Enables the OTG_FS peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableOTG_FS(lp) rccEnableAHB2(RCC_AHB2ENR_OTGFSEN, lp) + +/** + * @brief Disables the OTG_FS peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccDisableOTG_FS(lp) rccDisableAHB2(RCC_AHB2ENR_OTGFSEN, lp) + +/** + * @brief Resets the OTG_FS peripheral. + * + * @api + */ +#define rccResetOTG_FS() rccResetAHB2(RCC_AHB2RSTR_OTGFSRST) + +/** + * @brief Enables the OTG_HS peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableOTG_HS(lp) rccEnableAHB1(RCC_AHB1ENR_OTGHSEN, lp) + +/** + * @brief Disables the OTG_HS peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccDisableOTG_HS(lp) rccDisableAHB1(RCC_AHB1ENR_OTGHSEN, lp) + +/** + * @brief Resets the OTG_HS peripheral. + * + * @api + */ +#define rccResetOTG_HS() rccResetAHB1(RCC_AHB1RSTR_OTGHSRST) +/** @} */ + +/** + * @name SDIO peripheral specific RCC operations + * @{ + */ +/** + * @brief Enables the SDIO peripheral clock. + * @note The @p lp parameter is ignored in this family. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableSDIO(lp) rccEnableAPB2(RCC_APB2ENR_SDIOEN, lp) + +/** + * @brief Disables the SDIO peripheral clock. + * @note The @p lp parameter is ignored in this family. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccDisableSDIO(lp) rccDisableAPB2(RCC_APB2ENR_SDIOEN, lp) + +/** + * @brief Resets the SDIO peripheral. + * @note Not supported in this family, does nothing. + * + * @api + */ +#define rccResetSDIO() rccResetAPB2(RCC_APB2RSTR_SDIORST) +/** @} */ + +/** + * @name SPI peripherals specific RCC operations + * @{ + */ +/** + * @brief Enables the SPI1 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableSPI1(lp) rccEnableAPB2(RCC_APB2ENR_SPI1EN, lp) + +/** + * @brief Disables the SPI1 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccDisableSPI1(lp) rccDisableAPB2(RCC_APB2ENR_SPI1EN, lp) + +/** + * @brief Resets the SPI1 peripheral. + * + * @api + */ +#define rccResetSPI1() rccResetAPB2(RCC_APB2RSTR_SPI1RST) + +/** + * @brief Enables the SPI2 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableSPI2(lp) rccEnableAPB1(RCC_APB1ENR_SPI2EN, lp) + +/** + * @brief Disables the SPI2 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccDisableSPI2(lp) rccDisableAPB1(RCC_APB1ENR_SPI2EN, lp) + +/** + * @brief Resets the SPI2 peripheral. + * + * @api + */ +#define rccResetSPI2() rccResetAPB1(RCC_APB1RSTR_SPI2RST) + +/** + * @brief Enables the SPI3 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableSPI3(lp) rccEnableAPB1(RCC_APB1ENR_SPI3EN, lp) + +/** + * @brief Disables the SPI3 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccDisableSPI3(lp) rccDisableAPB1(RCC_APB1ENR_SPI3EN, lp) + +/** + * @brief Resets the SPI3 peripheral. + * + * @api + */ +#define rccResetSPI3() rccResetAPB1(RCC_APB1RSTR_SPI3RST) +/** @} */ + +/** + * @name TIM peripherals specific RCC operations + * @{ + */ +/** + * @brief Enables the TIM1 peripheral clock. + * @note The @p lp parameter is ignored in this family. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableTIM1(lp) rccEnableAPB2(RCC_APB2ENR_TIM1EN, lp) + +/** + * @brief Disables the TIM1 peripheral clock. + * @note The @p lp parameter is ignored in this family. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccDisableTIM1(lp) rccDisableAPB2(RCC_APB2ENR_TIM1EN, lp) + +/** + * @brief Resets the TIM1 peripheral. + * + * @api + */ +#define rccResetTIM1() rccResetAPB2(RCC_APB2RSTR_TIM1RST) + +/** + * @brief Enables the TIM2 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableTIM2(lp) rccEnableAPB1(RCC_APB1ENR_TIM2EN, lp) + +/** + * @brief Disables the TIM2 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccDisableTIM2(lp) rccDisableAPB1(RCC_APB1ENR_TIM2EN, lp) + +/** + * @brief Resets the TIM2 peripheral. + * + * @api + */ +#define rccResetTIM2() rccResetAPB1(RCC_APB1RSTR_TIM2RST) + +/** + * @brief Enables the TIM3 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableTIM3(lp) rccEnableAPB1(RCC_APB1ENR_TIM3EN, lp) + +/** + * @brief Disables the TIM3 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccDisableTIM3(lp) rccDisableAPB1(RCC_APB1ENR_TIM3EN, lp) + +/** + * @brief Resets the TIM3 peripheral. + * + * @api + */ +#define rccResetTIM3() rccResetAPB1(RCC_APB1RSTR_TIM3RST) + +/** + * @brief Enables the TIM4 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableTIM4(lp) rccEnableAPB1(RCC_APB1ENR_TIM4EN, lp) + +/** + * @brief Disables the TIM4 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccDisableTIM4(lp) rccDisableAPB1(RCC_APB1ENR_TIM4EN, lp) + +/** + * @brief Resets the TIM4 peripheral. + * + * @api + */ +#define rccResetTIM4() rccResetAPB1(RCC_APB1RSTR_TIM4RST) + +/** + * @brief Enables the TIM5 peripheral clock. + * @note The @p lp parameter is ignored in this family. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableTIM5(lp) rccEnableAPB1(RCC_APB1ENR_TIM5EN, lp) + +/** + * @brief Disables the TIM5 peripheral clock. + * @note The @p lp parameter is ignored in this family. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccDisableTIM5(lp) rccDisableAPB1(RCC_APB1ENR_TIM5EN, lp) + +/** + * @brief Resets the TIM5 peripheral. + * + * @api + */ +#define rccResetTIM5() rccResetAPB1(RCC_APB1RSTR_TIM5RST) + +/** + * @brief Enables the TIM6 peripheral clock. + * @note The @p lp parameter is ignored in this family. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableTIM6(lp) rccEnableAPB1(RCC_APB1ENR_TIM6EN, lp) + +/** + * @brief Disables the TIM6 peripheral clock. + * @note The @p lp parameter is ignored in this family. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccDisableTIM6(lp) rccDisableAPB1(RCC_APB1ENR_TIM6EN, lp) + +/** + * @brief Resets the TIM6 peripheral. + * + * @api + */ +#define rccResetTIM6() rccResetAPB1(RCC_APB1RSTR_TIM6RST) + +/** + * @brief Enables the TIM7 peripheral clock. + * @note The @p lp parameter is ignored in this family. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableTIM7(lp) rccEnableAPB1(RCC_APB1ENR_TIM7EN, lp) + +/** + * @brief Disables the TIM7 peripheral clock. + * @note The @p lp parameter is ignored in this family. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccDisableTIM7(lp) rccDisableAPB1(RCC_APB1ENR_TIM7EN, lp) + +/** + * @brief Resets the TIM7 peripheral. + * + * @api + */ +#define rccResetTIM7() rccResetAPB1(RCC_APB1RSTR_TIM7RST) + +/** + * @brief Enables the TIM8 peripheral clock. + * @note The @p lp parameter is ignored in this family. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableTIM8(lp) rccEnableAPB2(RCC_APB2ENR_TIM8EN, lp) + +/** + * @brief Disables the TIM8 peripheral clock. + * @note The @p lp parameter is ignored in this family. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccDisableTIM8(lp) rccDisableAPB2(RCC_APB2ENR_TIM8EN, lp) + +/** + * @brief Resets the TIM8 peripheral. + * + * @api + */ +#define rccResetTIM8() rccResetAPB2(RCC_APB2RSTR_TIM8RST) + +/** + * @brief Enables the TIM9peripheral clock. + * @note The @p lp parameter is ignored in this family. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableTIM9(lp) rccEnableAPB2(RCC_APB2ENR_TIM9EN, lp) + +/** + * @brief Disables the TIM9 peripheral clock. + * @note The @p lp parameter is ignored in this family. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccDisableTIM9(lp) rccDisableAPB2(RCC_APB2ENR_TIM9EN, lp) + +/** + * @brief Resets the TIM9 peripheral. + * + * @api + */ +#define rccResetTIM9() rccResetAPB2(RCC_APB2RSTR_TIM9RST) + +/** + * @brief Enables the TIM11 peripheral clock. + * @note The @p lp parameter is ignored in this family. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableTIM11(lp) rccEnableAPB2(RCC_APB2ENR_TIM11EN, lp) + +/** + * @brief Disables the TIM11 peripheral clock. + * @note The @p lp parameter is ignored in this family. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccDisableTIM11(lp) rccDisableAPB2(RCC_APB2ENR_TIM11EN, lp) + +/** + * @brief Resets the TIM11 peripheral. + * + * @api + */ +#define rccResetTIM11() rccResetAPB2(RCC_APB2RSTR_TIM11RST) + +/** + * @brief Enables the TIM12 peripheral clock. + * @note The @p lp parameter is ignored in this family. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableTIM12(lp) rccEnableAPB1(RCC_APB1ENR_TIM12EN, lp) + +/** + * @brief Disables the TIM12 peripheral clock. + * @note The @p lp parameter is ignored in this family. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccDisableTIM12(lp) rccDisableAPB1(RCC_APB1ENR_TIM12EN, lp) + +/** + * @brief Resets the TIM12 peripheral. + * + * @api + */ +#define rccResetTIM12() rccResetAPB1(RCC_APB1RSTR_TIM12RST) + +/** + * @brief Enables the TIM14 peripheral clock. + * @note The @p lp parameter is ignored in this family. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableTIM14(lp) rccEnableAPB1(RCC_APB1ENR_TIM14EN, lp) + +/** + * @brief Disables the TIM14 peripheral clock. + * @note The @p lp parameter is ignored in this family. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccDisableTIM14(lp) rccDisableAPB1(RCC_APB1ENR_TIM14EN, lp) + +/** + * @brief Resets the TIM14 peripheral. + * + * @api + */ +#define rccResetTIM14() rccResetAPB1(RCC_APB1RSTR_TIM14RST) +/** @} */ + +/** + * @name USART/UART peripherals specific RCC operations + * @{ + */ +/** + * @brief Enables the USART1 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableUSART1(lp) rccEnableAPB2(RCC_APB2ENR_USART1EN, lp) + +/** + * @brief Disables the USART1 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccDisableUSART1(lp) rccDisableAPB2(RCC_APB2ENR_USART1EN, lp) + +/** + * @brief Resets the USART1 peripheral. + * + * @api + */ +#define rccResetUSART1() rccResetAPB2(RCC_APB2RSTR_USART1RST) + +/** + * @brief Enables the USART2 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableUSART2(lp) rccEnableAPB1(RCC_APB1ENR_USART2EN, lp) + +/** + * @brief Disables the USART2 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccDisableUSART2(lp) rccDisableAPB1(RCC_APB1ENR_USART2EN, lp) + +/** + * @brief Resets the USART2 peripheral. + * + * @api + */ +#define rccResetUSART2() rccResetAPB1(RCC_APB1RSTR_USART2RST) + +/** + * @brief Enables the USART3 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableUSART3(lp) rccEnableAPB1(RCC_APB1ENR_USART3EN, lp) + +/** + * @brief Disables the USART3 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccDisableUSART3(lp) rccDisableAPB1(RCC_APB1ENR_USART3EN, lp) + +/** + * @brief Resets the USART3 peripheral. + * + * @api + */ +#define rccResetUSART3() rccResetAPB1(RCC_APB1RSTR_USART3RST) + +/** + * @brief Enables the USART6 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableUSART6(lp) rccEnableAPB2(RCC_APB2ENR_USART6EN, lp) + +/** + * @brief Disables the USART6 peripheral clock. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccDisableUSART6(lp) rccDisableAPB2(RCC_APB2ENR_USART6EN, lp) + +/** + * @brief Enables the UART4 peripheral clock. + * @note The @p lp parameter is ignored in this family. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableUART4(lp) rccEnableAPB1(RCC_APB1ENR_UART4EN, lp) + +/** + * @brief Disables the UART4 peripheral clock. + * @note The @p lp parameter is ignored in this family. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccDisableUART4(lp) rccDisableAPB1(RCC_APB1ENR_UART4EN, lp) + +/** + * @brief Resets the UART4 peripheral. + * + * @api + */ +#define rccResetUART4() rccResetAPB1(RCC_APB1RSTR_UART4RST) + +/** + * @brief Enables the UART5 peripheral clock. + * @note The @p lp parameter is ignored in this family. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccEnableUART5(lp) rccEnableAPB1(RCC_APB1ENR_UART5EN, lp) + +/** + * @brief Disables the UART5 peripheral clock. + * @note The @p lp parameter is ignored in this family. + * + * @param[in] lp low power enable flag + * + * @api + */ +#define rccDisableUART5(lp) rccDisableAPB1(RCC_APB1ENR_UART5EN, lp) + +/** + * @brief Resets the UART5 peripheral. + * + * @api + */ +#define rccResetUART5() rccResetAPB1(RCC_APB1RSTR_UART5RST) + +/** + * @brief Resets the USART6 peripheral. + * + * @api + */ +#define rccResetUSART6() rccResetAPB2(RCC_APB2RSTR_USART6RST) +/** @} */ + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +#ifdef __cplusplus +extern "C" { +#endif +#ifdef __cplusplus +} +#endif + +#endif /* _STM32_RCC_ */ + +/** @} */ diff --git a/os/hal/ports/STM32F4xx/stm32_registry.h b/os/hal/ports/STM32F4xx/stm32_registry.h new file mode 100644 index 000000000..ba462175c --- /dev/null +++ b/os/hal/ports/STM32F4xx/stm32_registry.h @@ -0,0 +1,265 @@ +/* + ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file STM32F4xx/stm32_registry.h + * @brief STM32F4xx capabilities registry. + * + * @addtogroup HAL + * @{ + */ + +#ifndef _STM32_REGISTRY_H_ +#define _STM32_REGISTRY_H_ + +#if defined(STM32F40XX) || defined(STM32F427X) +#define STM32F4XX +#endif + +/*===========================================================================*/ +/* Platform capabilities. */ +/*===========================================================================*/ + +/** + * @name STM32F30x capabilities + * @{ + */ +/* ADC attributes.*/ +#define STM32_HAS_ADC1 TRUE +#define STM32_ADC1_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 0) |\ + STM32_DMA_STREAM_ID_MSK(2, 4)) +#define STM32_ADC1_DMA_CHN 0x00000000 + +#define STM32_HAS_ADC2 TRUE +#define STM32_ADC2_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 2) |\ + STM32_DMA_STREAM_ID_MSK(2, 3)) +#define STM32_ADC2_DMA_CHN 0x00001100 + +#define STM32_HAS_ADC3 TRUE +#define STM32_ADC3_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 0) |\ + STM32_DMA_STREAM_ID_MSK(2, 1)) +#define STM32_ADC3_DMA_CHN 0x00000022 + +#define STM32_HAS_ADC4 FALSE + +#define STM32_HAS_SDADC1 FALSE +#define STM32_HAS_SDADC2 FALSE +#define STM32_HAS_SDADC3 FALSE + +/* CAN attributes.*/ +#define STM32_HAS_CAN1 TRUE +#define STM32_HAS_CAN2 TRUE +#define STM32_CAN_MAX_FILTERS 28 + +/* DAC attributes.*/ +#define STM32_HAS_DAC1 TRUE +#define STM32_HAS_DAC2 FALSE + +/* DMA attributes.*/ +#define STM32_ADVANCED_DMA TRUE +#define STM32_HAS_DMA1 TRUE +#define STM32_HAS_DMA2 TRUE + +/* ETH attributes.*/ +#define STM32_HAS_ETH TRUE + +/* EXTI attributes.*/ +#define STM32_EXTI_NUM_CHANNELS 23 + +/* GPIO attributes.*/ +#define STM32_HAS_GPIOA TRUE +#define STM32_HAS_GPIOB TRUE +#define STM32_HAS_GPIOC TRUE +#define STM32_HAS_GPIOD TRUE +#define STM32_HAS_GPIOE TRUE +#define STM32_HAS_GPIOF TRUE +#define STM32_HAS_GPIOG TRUE +#define STM32_HAS_GPIOH TRUE +#define STM32_HAS_GPIOI TRUE + +/* I2C attributes.*/ +#define STM32_HAS_I2C1 TRUE +#define STM32_I2C1_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 0) |\ + STM32_DMA_STREAM_ID_MSK(1, 5)) +#define STM32_I2C1_RX_DMA_CHN 0x00100001 +#define STM32_I2C1_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 7) |\ + STM32_DMA_STREAM_ID_MSK(1, 6)) +#define STM32_I2C1_TX_DMA_CHN 0x11000000 + +#define STM32_HAS_I2C2 TRUE +#define STM32_I2C2_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 2) |\ + STM32_DMA_STREAM_ID_MSK(1, 3)) +#define STM32_I2C2_RX_DMA_CHN 0x00007700 +#define STM32_I2C2_TX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 7) +#define STM32_I2C2_TX_DMA_CHN 0x70000000 + +#define STM32_HAS_I2C3 TRUE +#define STM32_I2C3_RX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 2) +#define STM32_I2C3_RX_DMA_CHN 0x00000300 +#define STM32_I2C3_TX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 4) +#define STM32_I2C3_TX_DMA_CHN 0x00030000 + +/* RTC attributes.*/ +#define STM32_HAS_RTC TRUE +#if defined(STM32F4XX) || defined(__DOXYGEN__) +#define STM32_RTC_HAS_SUBSECONDS TRUE +#else +#define STM32_RTC_HAS_SUBSECONDS FALSE +#endif +#define STM32_RTC_IS_CALENDAR TRUE + +/* SDIO attributes.*/ +#define STM32_HAS_SDIO TRUE +#define STM32_SDC_SDIO_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 3) |\ + STM32_DMA_STREAM_ID_MSK(2, 6)) +#define STM32_SDC_SDIO_DMA_CHN 0x04004000 + +/* SPI attributes.*/ +#define STM32_HAS_SPI1 TRUE +#define STM32_SPI1_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 0) |\ + STM32_DMA_STREAM_ID_MSK(2, 2)) +#define STM32_SPI1_RX_DMA_CHN 0x00000303 +#define STM32_SPI1_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 3) |\ + STM32_DMA_STREAM_ID_MSK(2, 5)) +#define STM32_SPI1_TX_DMA_CHN 0x00303000 + +#define STM32_HAS_SPI2 TRUE +#define STM32_SPI2_RX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 3) +#define STM32_SPI2_RX_DMA_CHN 0x00000000 +#define STM32_SPI2_TX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 4) +#define STM32_SPI2_TX_DMA_CHN 0x00000000 + +#define STM32_HAS_SPI3 TRUE +#define STM32_SPI3_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 0) |\ + STM32_DMA_STREAM_ID_MSK(1, 2)) +#define STM32_SPI3_RX_DMA_CHN 0x00000000 +#define STM32_SPI3_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 5) |\ + STM32_DMA_STREAM_ID_MSK(1, 7)) +#define STM32_SPI3_TX_DMA_CHN 0x00000000 + +/* TIM attributes.*/ +#define STM32_HAS_TIM1 TRUE +#define STM32_TIM1_IS_32BITS FALSE +#define STM32_TIM1_CHANNELS 4 + +#define STM32_HAS_TIM2 TRUE +#define STM32_TIM2_IS_32BITS TRUE +#define STM32_TIM2_CHANNELS 4 + +#define STM32_HAS_TIM3 TRUE +#define STM32_TIM3_IS_32BITS FALSE +#define STM32_TIM3_CHANNELS 4 + +#define STM32_HAS_TIM4 TRUE +#define STM32_TIM4_IS_32BITS FALSE +#define STM32_TIM4_CHANNELS 4 + +#define STM32_HAS_TIM5 TRUE +#define STM32_TIM5_IS_32BITS TRUE +#define STM32_TIM5_CHANNELS 4 + +#define STM32_HAS_TIM6 TRUE +#define STM32_TIM6_IS_32BITS FALSE +#define STM32_TIM6_CHANNELS 0 + +#define STM32_HAS_TIM7 TRUE +#define STM32_TIM7_IS_32BITS FALSE +#define STM32_TIM7_CHANNELS 0 + +#define STM32_HAS_TIM8 TRUE +#define STM32_TIM8_IS_32BITS FALSE +#define STM32_TIM8_CHANNELS 6 + +#define STM32_HAS_TIM9 TRUE +#define STM32_TIM9_IS_32BITS FALSE +#define STM32_TIM9_CHANNELS 2 + +#define STM32_HAS_TIM10 TRUE +#define STM32_TIM10_IS_32BITS FALSE +#define STM32_TIM10_CHANNELS 2 + +#define STM32_HAS_TIM11 TRUE +#define STM32_TIM11_IS_32BITS FALSE +#define STM32_TIM11_CHANNELS 2 + +#define STM32_HAS_TIM12 TRUE +#define STM32_TIM12_IS_32BITS FALSE +#define STM32_TIM12_CHANNELS 2 + +#define STM32_HAS_TIM13 TRUE +#define STM32_TIM13_IS_32BITS FALSE +#define STM32_TIM13_CHANNELS 2 + +#define STM32_HAS_TIM14 TRUE +#define STM32_TIM14_IS_32BITS FALSE +#define STM32_TIM14_CHANNELS 2 + +#define STM32_HAS_TIM15 FALSE +#define STM32_HAS_TIM16 FALSE +#define STM32_HAS_TIM17 FALSE +#define STM32_HAS_TIM18 FALSE +#define STM32_HAS_TIM19 FALSE + +/* USART attributes.*/ +#define STM32_HAS_USART1 TRUE +#define STM32_USART1_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 2) |\ + STM32_DMA_STREAM_ID_MSK(2, 5)) +#define STM32_USART1_RX_DMA_CHN 0x00400400 +#define STM32_USART1_TX_DMA_MSK STM32_DMA_STREAM_ID_MSK(2, 7) +#define STM32_USART1_TX_DMA_CHN 0x40000000 + +#define STM32_HAS_USART2 TRUE +#define STM32_USART2_RX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 5) +#define STM32_USART2_RX_DMA_CHN 0x00400000 +#define STM32_USART2_TX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 6) +#define STM32_USART2_TX_DMA_CHN 0x04000000 + +#define STM32_HAS_USART3 TRUE +#define STM32_USART3_RX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 1) +#define STM32_USART3_RX_DMA_CHN 0x00000040 +#define STM32_USART3_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 3) |\ + STM32_DMA_STREAM_ID_MSK(1, 4)) +#define STM32_USART3_TX_DMA_CHN 0x00074000 + +#define STM32_HAS_UART4 TRUE +#define STM32_UART4_RX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 2) +#define STM32_UART4_RX_DMA_CHN 0x00000400 +#define STM32_UART4_TX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 4) +#define STM32_UART4_TX_DMA_CHN 0x00040000 + +#define STM32_HAS_UART5 TRUE +#define STM32_UART5_RX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 0) +#define STM32_UART5_RX_DMA_CHN 0x00000004 +#define STM32_UART5_TX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 7) +#define STM32_UART5_TX_DMA_CHN 0x40000000 + +#define STM32_HAS_USART6 TRUE +#define STM32_USART6_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 1) |\ + STM32_DMA_STREAM_ID_MSK(2, 2)) +#define STM32_USART6_RX_DMA_CHN 0x00000550 +#define STM32_USART6_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 6) |\ + STM32_DMA_STREAM_ID_MSK(2, 7)) +#define STM32_USART6_TX_DMA_CHN 0x55000000 + +/* USB attributes.*/ +#define STM32_HAS_USB FALSE +#define STM32_HAS_OTG1 TRUE +#define STM32_HAS_OTG2 TRUE +/** @} */ + +#endif /* _STM32_REGISTRY_H_ */ + +/** @} */ diff --git a/os/hal/ports/common/ARMCMx/nvic.c b/os/hal/ports/common/ARMCMx/nvic.c new file mode 100644 index 000000000..c45366396 --- /dev/null +++ b/os/hal/ports/common/ARMCMx/nvic.c @@ -0,0 +1,89 @@ +/* + ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file common/ARMCMx/nvic.c + * @brief Cortex-Mx NVIC support code. + * + * @addtogroup COMMON_ARMCMx_NVIC + * @{ + */ + +#include "hal.h" + +/*===========================================================================*/ +/* Driver local definitions. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver exported variables. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local types. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local variables. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local functions. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver exported functions. */ +/*===========================================================================*/ + +/** + * @brief Sets the priority of an interrupt handler and enables it. + * @note The parameters are not tested for correctness. + * + * @param[in] n the interrupt number + * @param[in] prio the interrupt priority mask + */ +void nvicEnableVector(IRQn_Type n, uint32_t prio) { + + NVIC->IP[n] = NVIC_PRIORITY_MASK(prio); + NVIC->ICPR[n >> 5] = 1 << (n & 0x1F); + NVIC->ISER[n >> 5] = 1 << (n & 0x1F); +} + +/** + * @brief Disables an interrupt handler. + * @note The parameters are not tested for correctness. + * + * @param[in] n the interrupt number + */ +void nvicDisableVector(IRQn_Type n) { + + NVIC->ICER[n >> 5] = 1 << (n & 0x1F); + NVIC->IP[n] = 0; +} + +/** + * @brief Changes the priority of a system handler. + * @note The parameters are not tested for correctness. + * + * @param[in] handler the system handler number + * @param[in] prio the system handler priority mask + */ +void nvicSetSystemHandlerPriority(IRQn_Type handler, uint32_t prio) { + + SCB->SHP[((uint32_t)(handler) & 15) - 4] = NVIC_PRIORITY_MASK(prio); +} + +/** @} */ diff --git a/os/hal/ports/common/ARMCMx/nvic.h b/os/hal/ports/common/ARMCMx/nvic.h new file mode 100644 index 000000000..82fde801c --- /dev/null +++ b/os/hal/ports/common/ARMCMx/nvic.h @@ -0,0 +1,69 @@ +/* + ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file common/ARMCMx/nvic.h + * @brief Cortex-Mx NVIC support macros and structures. + * + * @addtogroup COMMON_ARMCMx_NVIC + * @{ + */ + +#ifndef _NVIC_H_ +#define _NVIC_H_ + +/*===========================================================================*/ +/* Driver constants. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver pre-compile time settings. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Derived constants and error checks. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver data structures and types. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver macros. */ +/*===========================================================================*/ + +/** + * @brief Priority level to priority mask conversion macro. + */ +#define NVIC_PRIORITY_MASK(prio) ((prio) << (8 - __NVIC_PRIO_BITS)) + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +#ifdef __cplusplus +extern "C" { +#endif + void nvicEnableVector(IRQn_Type n, uint32_t prio); + void nvicDisableVector(IRQn_Type n); + void nvicSetSystemHandlerPriority(IRQn_Type handler, uint32_t prio); +#ifdef __cplusplus +} +#endif + +#endif /* _NVIC_H_ */ + +/** @} */ -- cgit v1.2.3