summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNicolas Schodet2016-08-01 15:19:00 +0200
committerNicolas Schodet2019-10-09 23:05:50 +0200
commit3e4d6ce0beb81b99bcba9192e3855e1753599733 (patch)
treecd3c68303f561588378e2319a9289a520560128f
parent23950b079fa441e7ace347a82898f45ef10b0578 (diff)
ucoo: add support for STM32F4[67]9
m---------lib/cmsis0
-rw-r--r--ucoo/arch/interrupt.stm32f4.hh6
-rw-r--r--ucoo/arch/rcc.stm32f4.cc37
-rw-r--r--ucoo/arch/rcc.stm32f4.hh15
-rw-r--r--ucoo/arch/reg.stm32.hh9
-rw-r--r--ucoo/arch/reg.stm32f4.hh47
-rw-r--r--ucoo/arch/vector.stm32f4.hh24
-rw-r--r--ucoo/hal/usb/usb_dwc_otg.stm32.cc43
8 files changed, 172 insertions, 9 deletions
diff --git a/lib/cmsis b/lib/cmsis
-Subproject 1b9674a239ca7ff155b4b870af689eb6d3160a0
+Subproject c3f1b388fe087aec0ce5698504d505f43aa9126
diff --git a/ucoo/arch/interrupt.stm32f4.hh b/ucoo/arch/interrupt.stm32f4.hh
index ffd3912..ee58dd7 100644
--- a/ucoo/arch/interrupt.stm32f4.hh
+++ b/ucoo/arch/interrupt.stm32f4.hh
@@ -119,6 +119,12 @@ enum class Irq
LTDC,
LTDC_ER,
DMA2D,
+#ifdef QSPI_R_BASE
+ QUADSPI,
+#endif
+#ifdef DSI_BASE
+ DSI,
+#endif
COUNT
};
diff --git a/ucoo/arch/rcc.stm32f4.cc b/ucoo/arch/rcc.stm32f4.cc
index 36e31b6..37aaaa1 100644
--- a/ucoo/arch/rcc.stm32f4.cc
+++ b/ucoo/arch/rcc.stm32f4.cc
@@ -36,6 +36,7 @@ int rcc_apb2_freq_hz = hsi_freq_hz;
int rcc_apb1_timer_freq_hz = hsi_freq_hz;
int rcc_apb2_timer_freq_hz = hsi_freq_hz;
int rcc_pll48_freq_hz = 0;
+int rcc_lcd_freq_hz = 0;
void
rcc_sys_clock_setup_pll (int sys_freq_hz, int hse_freq_hz,
@@ -95,7 +96,8 @@ rcc_sys_clock_setup_pll (int sys_freq_hz, int hse_freq_hz,
| pllm << RCC_PLLCFGR_PLLM_Pos
| plln << RCC_PLLCFGR_PLLN_Pos
| (pllp / 2 - 1) << RCC_PLLCFGR_PLLP_Pos
- | pllq << RCC_PLLCFGR_PLLQ_Pos;
+ | pllq << RCC_PLLCFGR_PLLQ_Pos
+ | (reg::RCC->PLLCFGR & RCC_PLLCFGR_PLLR);
reg::RCC->CR |= RCC_CR_PLLON;
while (!(reg::RCC->CR & RCC_CR_PLLRDY))
;
@@ -122,4 +124,37 @@ rcc_sys_clock_setup_pll (int sys_freq_hz, int hse_freq_hz,
rcc_pll48_freq_hz = pll_in_freq_hz / pllm * plln / pllq;
}
+void
+rcc_sai_pll_setup (int hse_freq_hz,
+ int pllm, int plln, int pllp, int pllq, int pllq_div,
+ int pllr, int pllr_div)
+{
+ // Stop PLL.
+ reg::RCC->CR &= ~RCC_CR_PLLSAION;
+ while (reg::RCC->CR & RCC_CR_PLLSAIRDY)
+ ;
+ // Start PLL.
+ static const LookupTable<int, uint32_t> pllr_div_table[] =
+ {
+ { 2, RCC_DCKCFGR_PLLSAIDIVR_Div2 },
+ { 4, RCC_DCKCFGR_PLLSAIDIVR_Div4 },
+ { 8, RCC_DCKCFGR_PLLSAIDIVR_Div8 },
+ { 16, RCC_DCKCFGR_PLLSAIDIVR_Div16 },
+ };
+ reg::RCC->PLLSAICFGR =
+ plln * RCC_PLLSAICFGR_PLLSAIN_0
+ | (pllp / 2 - 1) * RCC_PLLSAICFGR_PLLSAIP_0
+ | pllq * RCC_PLLSAICFGR_PLLSAIQ_0
+ | pllr * RCC_PLLSAICFGR_PLLSAIR_0;
+ reg::RCC->DCKCFGR =
+ (pllq_div - 1) << RCC_DCKCFGR_PLLSAIDIVQ_Pos
+ | simple_table_lookup (pllr_div_table, pllr_div);
+ ucoo::reg::RCC->CR |= RCC_CR_PLLSAION;
+ while (!(ucoo::reg::RCC->CR & RCC_CR_PLLSAIRDY))
+ ;
+ // Update frequencies.
+ int vco_out = hse_freq_hz / pllm * plln;
+ rcc_lcd_freq_hz = vco_out / pllr / pllr_div;
+}
+
} // namespace ucoo
diff --git a/ucoo/arch/rcc.stm32f4.hh b/ucoo/arch/rcc.stm32f4.hh
index 9e49277..45b452b 100644
--- a/ucoo/arch/rcc.stm32f4.hh
+++ b/ucoo/arch/rcc.stm32f4.hh
@@ -94,6 +94,9 @@ enum class Rcc
RNG = details::rcc_enum (Bus::AHB2, RCC_AHB2ENR_RNGEN),
OTGFS = details::rcc_enum (Bus::AHB2, RCC_AHB2ENR_OTGFSEN),
FMC = details::rcc_enum (Bus::AHB3, RCC_AHB3ENR_FMCEN),
+#ifdef RCC_AHB3ENR_QSPIEN
+ QUADSPI = details::rcc_enum (Bus::AHB3, RCC_AHB3ENR_QSPIEN),
+#endif
TIM2 = details::rcc_enum (Bus::APB1, RCC_APB1ENR_TIM2EN),
TIM3 = details::rcc_enum (Bus::APB1, RCC_APB1ENR_TIM3EN),
TIM4 = details::rcc_enum (Bus::APB1, RCC_APB1ENR_TIM4EN),
@@ -137,6 +140,9 @@ enum class Rcc
SPI6 = details::rcc_enum (Bus::APB2, RCC_APB2ENR_SPI6EN),
SAI1 = details::rcc_enum (Bus::APB2, RCC_APB2ENR_SAI1EN),
LTDC = details::rcc_enum (Bus::APB2, RCC_APB2ENR_LTDCEN),
+#ifdef RCC_APB2ENR_DSIEN
+ DSI = details::rcc_enum (Bus::APB2, RCC_APB2ENR_DSIEN),
+#endif
};
/// Enable clock for given peripheral.
@@ -180,6 +186,9 @@ extern int rcc_apb2_timer_freq_hz;
/// Frequency of the should-be-48-MHz clock (used for USB, RNG & SDIO).
extern int rcc_pll48_freq_hz;
+/// Frequency of LCD clock;
+extern int rcc_lcd_freq_hz;
+
/// Setup system clock using PLL, from HSE clock if not 0, else HSI clock.
/// Also setup flash access and voltage regulator scale.
void
@@ -188,6 +197,12 @@ rcc_sys_clock_setup_pll (int sys_freq_hz, int hse_freq_hz,
int apb1_pre, int apb2_pre,
SupplyRange vrange);
+/// Setup SAI PLL.
+void
+rcc_sai_pll_setup (int hse_freq_hz,
+ int pllm, int plln, int pllp, int pllq, int pllq_div,
+ int pllr, int pllr_div);
+
} // namespace ucoo
#endif // ucoo_arch_rcc_stm32f4_hh
diff --git a/ucoo/arch/reg.stm32.hh b/ucoo/arch/reg.stm32.hh
index 4d46354..016453e 100644
--- a/ucoo/arch/reg.stm32.hh
+++ b/ucoo/arch/reg.stm32.hh
@@ -40,6 +40,15 @@
#define USART_CR2_STOP_Bits_2 USART_CR2_STOP_1
#define USART_CR2_STOP_Bits_1_5 (USART_CR2_STOP_1 | USART_CR2_STOP_0)
+#ifndef USB_OTG_GCCFG_VBUSBSEN
+// OTG version 0x1100
+# define USB_OTG_GCCFG_VBUSBSEN (1 << 19)
+#endif
+#ifndef USB_OTG_GCCFG_VBDEN
+// OTG version 0x2000
+# define USB_OTG_GCCFG_VBDEN (1 << 21)
+#endif
+
#define USB_OTG_GRXSTSP_PKTSTS_GlobalOutNak (1 << 17)
#define USB_OTG_GRXSTSP_PKTSTS_Out (2 << 17)
#define USB_OTG_GRXSTSP_PKTSTS_OutCompleted (3 << 17)
diff --git a/ucoo/arch/reg.stm32f4.hh b/ucoo/arch/reg.stm32f4.hh
index 31ad39d..1f5f2cf 100644
--- a/ucoo/arch/reg.stm32f4.hh
+++ b/ucoo/arch/reg.stm32f4.hh
@@ -24,7 +24,7 @@
//
// }}}
// Use a superset of all supported chips.
-#include "ST/STM32F4xx/Include/stm32f439xx.h"
+#include "ST/STM32F4xx/Include/stm32f479xx.h"
#include "ucoo/arch/reg.stm32.hh"
#define SCB_CPACR_CP10_Pos 20
@@ -47,6 +47,15 @@
#define RCC_PLLCFGR_PLLN_Pos 6
#define RCC_PLLCFGR_PLLP_Pos 16
#define RCC_PLLCFGR_PLLQ_Pos 24
+#ifdef RCC_PLLCFGR_PLLR
+# define RCC_PLLCFGR_PLLR_Pos 28
+#endif
+
+#define RCC_DCKCFGR_PLLSAIDIVQ_Pos 8
+#define RCC_DCKCFGR_PLLSAIDIVR_Div2 0
+#define RCC_DCKCFGR_PLLSAIDIVR_Div4 (1 << 16)
+#define RCC_DCKCFGR_PLLSAIDIVR_Div8 (2 << 16)
+#define RCC_DCKCFGR_PLLSAIDIVR_Div16 (3 << 16)
#define GPIO_MODER_Input 0
#define GPIO_MODER_Output 1
@@ -119,6 +128,30 @@
#define DESIG_FLASH_SIZE_BASE 0x1fff7a22
#define DESIG_UNIQUE_ID_BASE 0x1fff7a10
+#ifdef DSI_BASE
+# define DSI_VMCR_VMT_NonBurstSyncPulses 0
+# define DSI_VMCR_VMT_NonBurstSyncEvents 1
+# define DSI_VMCR_VMT_Burst 2
+# define DSI_LCOLCR_COLC_16BitConf1 0
+# define DSI_LCOLCR_COLC_16BitConf2 DSI_LCOLCR_COLC0
+# define DSI_LCOLCR_COLC_16BitConf3 DSI_LCOLCR_COLC1
+# define DSI_LCOLCR_COLC_18BitConf1 (DSI_LCOLCR_COLC1 | DSI_LCOLCR_COLC0)
+# define DSI_LCOLCR_COLC_18BitConf2 DSI_LCOLCR_COLC2
+# define DSI_LCOLCR_COLC_24Bit (DSI_LCOLCR_COLC2 | DSI_LCOLCR_COLC0)
+# define DSI_WCFGR_COLMUX_16BitConf1 0
+# define DSI_WCFGR_COLMUX_16BitConf2 DSI_WCFGR_COLMUX0
+# define DSI_WCFGR_COLMUX_16BitConf3 DSI_WCFGR_COLMUX1
+# define DSI_WCFGR_COLMUX_18BitConf1 (DSI_WCFGR_COLMUX1 | DSI_WCFGR_COLMUX0)
+# define DSI_WCFGR_COLMUX_18BitConf2 DSI_WCFGR_COLMUX2
+# define DSI_WCFGR_COLMUX_24Bit (DSI_WCFGR_COLMUX2 | DSI_WCFGR_COLMUX0)
+# define DSI_WRPCR_PLL_NDIV_Pos 2
+# define DSI_WRPCR_PLL_IDF_Pos 11
+# define DSI_WRPCR_PLL_ODF_Div1 0
+# define DSI_WRPCR_PLL_ODF_Div2 DSI_WRPCR_PLL_ODF0
+# define DSI_WRPCR_PLL_ODF_Div4 DSI_WRPCR_PLL_ODF1
+# define DSI_WRPCR_PLL_ODF_Div8 (DSI_WRPCR_PLL_ODF1 | DSI_WRPCR_PLL_ODF0)
+#endif
+
struct DESIG_TypeDef
{
__IO uint32_t U_ID[3];
@@ -183,6 +216,7 @@ struct DESIG_TypeDef
#undef LTDC
#undef LTDC_Layer1
#undef LTDC_Layer2
+#undef DSI
#undef GPIOA
#undef GPIOB
#undef GPIOC
@@ -227,6 +261,7 @@ struct DESIG_TypeDef
#undef FMC_Bank2_3
#undef FMC_Bank4
#undef FMC_Bank5_6
+#undef QUADSPI
#undef DBGMCU
#undef USB_OTG_FS
#undef USB_OTG_HS
@@ -291,6 +326,9 @@ constexpr auto SAI1_Block_B = reinterpret_cast<SAI_Block_TypeDef *> (SAI1_Block_
constexpr auto LTDC = reinterpret_cast<LTDC_TypeDef *> (LTDC_BASE);
constexpr auto LTDC_Layer1 = reinterpret_cast<LTDC_Layer_TypeDef *> (LTDC_Layer1_BASE);
constexpr auto LTDC_Layer2 = reinterpret_cast<LTDC_Layer_TypeDef *> (LTDC_Layer2_BASE);
+#ifdef DSI_BASE
+constexpr auto DSI = reinterpret_cast<DSI_TypeDef *> (DSI_BASE);
+#endif
constexpr auto GPIOA = reinterpret_cast<GPIO_TypeDef *> (GPIOA_BASE);
constexpr auto GPIOB = reinterpret_cast<GPIO_TypeDef *> (GPIOB_BASE);
constexpr auto GPIOC = reinterpret_cast<GPIO_TypeDef *> (GPIOC_BASE);
@@ -332,9 +370,16 @@ constexpr auto HASH_DIGEST = reinterpret_cast<HASH_DIGEST_TypeDef *> (HASH_DIGES
constexpr auto RNG = reinterpret_cast<RNG_TypeDef *> (RNG_BASE);
constexpr auto FMC_Bank1 = reinterpret_cast<FMC_Bank1_TypeDef *> (FMC_Bank1_R_BASE);
constexpr auto FMC_Bank1E = reinterpret_cast<FMC_Bank1E_TypeDef *> (FMC_Bank1E_R_BASE);
+#ifdef FMC_Bank2_3_R_BASE
constexpr auto FMC_Bank2_3 = reinterpret_cast<FMC_Bank2_3_TypeDef *> (FMC_Bank2_3_R_BASE);
+#endif
+#ifdef FMC_Bank4_R_BASE
constexpr auto FMC_Bank4 = reinterpret_cast<FMC_Bank4_TypeDef *> (FMC_Bank4_R_BASE);
+#endif
constexpr auto FMC_Bank5_6 = reinterpret_cast<FMC_Bank5_6_TypeDef *> (FMC_Bank5_6_R_BASE);
+#ifdef QSPI_R_BASE
+constexpr auto QUADSPI = reinterpret_cast<QUADSPI_TypeDef *> (QSPI_R_BASE);
+#endif
constexpr auto DBGMCU = reinterpret_cast<DBGMCU_TypeDef *> (DBGMCU_BASE);
constexpr auto USB_OTG_FS = reinterpret_cast<USB_OTG_TypeDef *> (USB_OTG_FS_PERIPH_BASE);
constexpr auto USB_OTG_HS = reinterpret_cast<USB_OTG_TypeDef *> (USB_OTG_HS_PERIPH_BASE);
diff --git a/ucoo/arch/vector.stm32f4.hh b/ucoo/arch/vector.stm32f4.hh
index 5fe1bae..7015eeb 100644
--- a/ucoo/arch/vector.stm32f4.hh
+++ b/ucoo/arch/vector.stm32f4.hh
@@ -115,7 +115,21 @@
interrupt<Irq::SAI1>, \
interrupt<Irq::LTDC>, \
interrupt<Irq::LTDC_ER>, \
- interrupt<Irq::DMA2D>
+ interrupt<Irq::DMA2D>, \
+ UCOO_VECTOR_IRQ_QUADSPI \
+ UCOO_VECTOR_IRQ_DSI
+
+#ifdef QSPI_R_BASE
+# define UCOO_VECTOR_IRQ_QUADSPI interrupt<Irq::QUADSPI>,
+#else
+# define UCOO_VECTOR_IRQ_QUADSPI
+#endif
+
+#ifdef DSI_BASE
+# define UCOO_VECTOR_IRQ_DSI interrupt<Irq::DSI>,
+#else
+# define UCOO_VECTOR_IRQ_DSI
+#endif
namespace ucoo {
@@ -301,6 +315,14 @@ template<> void interrupt<Irq::LTDC_ER> ()
__attribute__ ((weak, alias ("undefined_handler")));
template<> void interrupt<Irq::DMA2D> ()
__attribute__ ((weak, alias ("undefined_handler")));
+#ifdef QSPI_R_BASE
+template<> void interrupt<Irq::QUADSPI> ()
+ __attribute__ ((weak, alias ("undefined_handler")));
+#endif
+#ifdef DSI_BASE
+template<> void interrupt<Irq::DSI> ()
+ __attribute__ ((weak, alias ("undefined_handler")));
+#endif
} // namespace ucoo
diff --git a/ucoo/hal/usb/usb_dwc_otg.stm32.cc b/ucoo/hal/usb/usb_dwc_otg.stm32.cc
index a19fca7..76f1b24 100644
--- a/ucoo/hal/usb/usb_dwc_otg.stm32.cc
+++ b/ucoo/hal/usb/usb_dwc_otg.stm32.cc
@@ -117,13 +117,17 @@ UsbDriverDwcOtg::enable ()
| USB_OTG_GINTMSK_USBSUSPM | USB_OTG_GINTMSK_USBRST
| USB_OTG_GINTMSK_ENUMDNEM | USB_OTG_GINTMSK_IEPINT
| USB_OTG_GINTMSK_SRQIM /* ? */
+ // TODO: OTGINT for SEDDET.
| USB_OTG_GINTMSK_WUIM;
- // TODO: USB_OTG_GCCFG_VBDEN for F479.
- hard.base->global.GCCFG |= USB_OTG_GCCFG_VBUSBSEN | USB_OTG_GCCFG_PWRDWN;
+ if (hard.base->global.CID == 0x2000)
+ hard.base->global.GCCFG |= USB_OTG_GCCFG_VBDEN | USB_OTG_GCCFG_PWRDWN;
+ else
+ hard.base->global.GCCFG |= USB_OTG_GCCFG_VBUSBSEN | USB_OTG_GCCFG_PWRDWN;
hard.base->device.DCFG |= USB_OTG_DCFG_NZLSOHSK | USB_OTG_DCFG_DSPD;
hard.base->device.DCTL = 0;
hard.base->device.DIEPMSK = USB_OTG_DIEPMSK_XFRCM;
- hard.base->device.DAINTMSK = USB_OTG_DAINTMSK_IEPM;
+ hard.base->device.DOEPMSK = USB_OTG_DOEPMSK_XFRCM | USB_OTG_DOEPMSK_STUPM;
+ hard.base->device.DAINTMSK = USB_OTG_DAINTMSK_OEPM | USB_OTG_DAINTMSK_IEPM;
// Enable interrupts.
interrupt_enable (hard.irq);
}
@@ -348,9 +352,35 @@ UsbDriverDwcOtg::isr ()
{
if (daint & (1 << i))
{
- usb_trace ("isr in xfrc %d", i);
- ep_handle_in (i ? 0x80 | i : 0);
- hard.base->ep_in[i].DIEPINT = USB_OTG_DIEPINT_XFRC;
+ uint32_t diepint = hard.base->ep_in[i].DIEPINT;
+ if (diepint & USB_OTG_DIEPINT_XFRC)
+ {
+ usb_trace ("isr in xfrc %d", i);
+ ep_handle_in (i ? 0x80 | i : 0);
+ hard.base->ep_in[i].DIEPINT = USB_OTG_DIEPINT_XFRC;
+ }
+ }
+ }
+ }
+ if (gintsts & USB_OTG_GINTSTS_OEPINT)
+ {
+ /* OUT end point interrupt. */
+ uint32_t daint = hard.base->device.DAINT;
+ for (int i = 0; i < END_POINT_NB; i++)
+ {
+ if (daint & ((1 << 16) << i))
+ {
+ uint32_t doepint = hard.base->ep_out[i].DOEPINT;
+ if (doepint & USB_OTG_DOEPINT_XFRC)
+ {
+ usb_trace ("isr out xfrc %d", i);
+ hard.base->ep_out[i].DOEPINT = USB_OTG_DOEPINT_XFRC;
+ }
+ if (doepint & USB_OTG_DOEPINT_STUP)
+ {
+ usb_trace ("isr out stup %d", i);
+ hard.base->ep_out[i].DOEPINT = USB_OTG_DOEPINT_STUP;
+ }
}
}
}
@@ -388,6 +418,7 @@ UsbDriverDwcOtg::isr_rx_fifo ()
assert (ep == 0 && bcnt == 8);
setup_buf_[0] = hard.base->fifo[0].FIFO;
setup_buf_[1] = hard.base->fifo[0].FIFO;
+ hard.base->ep_out[0].DOEPTSIZ |= USB_OTG_DOEPTSIZ_STUPCNT;
}
else if (pkt_status == USB_OTG_GRXSTSP_PKTSTS_SetupCompleted)
{