*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
~(STM_MODER_MASK << STM_MODER_SHIFT(pin))) |
value << STM_MODER_SHIFT(pin));
}
-
-static inline vuint32_t
+
+static inline uint32_t
+stm_spread_mask(uint16_t mask) {
+ uint32_t m = mask;
+
+ /* 0000000000000000mmmmmmmmmmmmmmmm */
+ m = (m & 0xff) | ((m & 0xff00) << 8);
+ /* 00000000mmmmmmmm00000000mmmmmmmm */
+ m = (m & 0x000f000f) | ((m & 0x00f000f0) << 4);
+ /* 0000mmmm0000mmmm0000mmmm0000mmmm */
+ m = (m & 0x03030303) | ((m & 0x0c0c0c0c) << 2);
+ /* 00mm00mm00mm00mm00mm00mm00mm00mm */
+ m = (m & 0x11111111) | ((m & 0x22222222) << 2);
+ /* 0m0m0m0m0m0m0m0m0m0m0m0m0m0m0m0m */
+ return m;
+}
+
+static inline void
+stm_moder_set_mask(struct stm_gpio *gpio, uint16_t mask, uint32_t value) {
+ uint32_t bits32 = stm_spread_mask(mask);
+ uint32_t mask32 = 3 * bits32;
+ uint32_t value32 = (value & 3) * bits32;
+
+ gpio->moder = ((gpio->moder & ~mask32) | value32);
+}
+
+static inline uint32_t
stm_moder_get(struct stm_gpio *gpio, int pin) {
return (gpio->moder >> STM_MODER_SHIFT(pin)) & STM_MODER_MASK;
}
~(STM_OTYPER_MASK << STM_OTYPER_SHIFT(pin))) |
value << STM_OTYPER_SHIFT(pin));
}
-
-static inline vuint32_t
+
+static inline uint32_t
stm_otyper_get(struct stm_gpio *gpio, int pin) {
return (gpio->otyper >> STM_OTYPER_SHIFT(pin)) & STM_OTYPER_MASK;
}
#define STM_OSPEEDR_40MHz 3
static inline void
-stm_ospeedr_set(struct stm_gpio *gpio, int pin, vuint32_t value) {
+stm_ospeedr_set(struct stm_gpio *gpio, int pin, uint32_t value) {
gpio->ospeedr = ((gpio->ospeedr &
~(STM_OSPEEDR_MASK << STM_OSPEEDR_SHIFT(pin))) |
value << STM_OSPEEDR_SHIFT(pin));
}
-
-static inline vuint32_t
+
+static inline void
+stm_ospeedr_set_mask(struct stm_gpio *gpio, uint16_t mask, uint32_t value) {
+ uint32_t bits32 = stm_spread_mask(mask);
+ uint32_t mask32 = 3 * bits32;
+ uint32_t value32 = (value & 3) * bits32;
+
+ gpio->ospeedr = ((gpio->ospeedr & ~mask32) | value32);
+}
+
+static inline uint32_t
stm_ospeedr_get(struct stm_gpio *gpio, int pin) {
return (gpio->ospeedr >> STM_OSPEEDR_SHIFT(pin)) & STM_OSPEEDR_MASK;
}
~(STM_PUPDR_MASK << STM_PUPDR_SHIFT(pin))) |
value << STM_PUPDR_SHIFT(pin));
}
-
+
+static inline void
+stm_pupdr_set_mask(struct stm_gpio *gpio, uint16_t mask, uint32_t value) {
+ uint32_t bits32 = stm_spread_mask(mask);
+ uint32_t mask32 = 3 * bits32;
+ uint32_t value32 = (value & 3) * bits32;
+
+ gpio->pupdr = (gpio->pupdr & ~mask32) | value32;
+}
+
static inline uint32_t
stm_pupdr_get(struct stm_gpio *gpio, int pin) {
return (gpio->pupdr >> STM_PUPDR_SHIFT(pin)) & STM_PUPDR_MASK;
gpio->bsrr = ((uint32_t) (value ^ 1) << (pin + 16)) | ((uint32_t) value << pin);
}
+static inline void
+stm_gpio_set_mask(struct stm_gpio *gpio, uint16_t bits, uint16_t mask) {
+ /* Use the bit set/reset register to do this atomically */
+ gpio->bsrr = ((uint32_t) (~bits & mask) << 16) | ((uint32_t) (bits & mask));
+}
+
+static inline void
+stm_gpio_set_bits(struct stm_gpio *gpio, uint16_t bits) {
+ gpio->bsrr = bits;
+}
+
+static inline void
+stm_gpio_clr_bits(struct stm_gpio *gpio, uint16_t bits) {
+ gpio->bsrr = ((uint32_t) bits) << 16;
+}
+
static inline uint8_t
stm_gpio_get(struct stm_gpio *gpio, int pin) {
return (gpio->idr >> pin) & 1;
}
+static inline uint16_t
+stm_gpio_get_all(struct stm_gpio *gpio) {
+ return gpio->idr;
+}
+
+/*
+ * We can't define these in registers.ld or our fancy
+ * ao_enable_gpio macro will expand into a huge pile of code
+ * as the compiler won't do correct constant folding and
+ * dead-code elimination
+ */
+
extern struct stm_gpio stm_gpioa;
extern struct stm_gpio stm_gpiob;
extern struct stm_gpio stm_gpioc;
extern struct stm_gpio stm_gpioe;
extern struct stm_gpio stm_gpioh;
+#define stm_gpioh (*((struct stm_gpio *) 0x40021400))
+#define stm_gpioe (*((struct stm_gpio *) 0x40021000))
+#define stm_gpiod (*((struct stm_gpio *) 0x40020c00))
+#define stm_gpioc (*((struct stm_gpio *) 0x40020800))
+#define stm_gpiob (*((struct stm_gpio *) 0x40020400))
+#define stm_gpioa (*((struct stm_gpio *) 0x40020000))
+
struct stm_usart {
vuint32_t sr; /* status register */
vuint32_t dr; /* data register */
#define STM_FLASH_PEKEYR_PEKEY1 0x89ABCDEF
#define STM_FLASH_PEKEYR_PEKEY2 0x02030405
+#define STM_FLASH_PRGKEYR_PRGKEY1 0x8C9DAEBF
+#define STM_FLASH_PRGKEYR_PRGKEY2 0x13141516
+
struct stm_rcc {
vuint32_t cr;
vuint32_t icscr;
#define STM_RCC_CFGR_MCOPRE_DIV_4 2
#define STM_RCC_CFGR_MCOPRE_DIV_8 3
#define STM_RCC_CFGR_MCOPRE_DIV_16 4
-#define STM_RCC_CFGR_MCOPRE_DIV_MASK 7
+#define STM_RCC_CFGR_MCOPRE_MASK 7
#define STM_RCC_CFGR_MCOSEL (24)
#define STM_RCC_CFGR_MCOSEL_DISABLE 0
#define STM_LCD_CLR_UDDC (3)
#define STM_LCD_CLR_SOFC (1)
+/* The SYSTICK starts at 0xe000e010 */
+
+struct stm_systick {
+ vuint32_t csr;
+ vuint32_t rvr;
+ vuint32_t cvr;
+ vuint32_t calib;
+};
+
+extern struct stm_systick stm_systick;
+
+#define STM_SYSTICK_CSR_ENABLE 0
+#define STM_SYSTICK_CSR_TICKINT 1
+#define STM_SYSTICK_CSR_CLKSOURCE 2
+#define STM_SYSTICK_CSR_CLKSOURCE_HCLK_8 0
+#define STM_SYSTICK_CSR_CLKSOURCE_HCLK 1
+#define STM_SYSTICK_CSR_COUNTFLAG 16
+
+/* The NVIC starts at 0xe000e100, so add that to the offsets to find the absolute address */
+
struct stm_nvic {
- vuint32_t iser[3]; /* 0x000 */
+ vuint32_t iser[8]; /* 0x000 0xe000e100 Set Enable Register */
- uint8_t _unused00c[0x080 - 0x00c];
+ uint8_t _unused020[0x080 - 0x020];
- vuint32_t icer[3]; /* 0x080 */
+ vuint32_t icer[8]; /* 0x080 0xe000e180 Clear Enable Register */
- uint8_t _unused08c[0x100 - 0x08c];
+ uint8_t _unused0a0[0x100 - 0x0a0];
- vuint32_t ispr[3]; /* 0x100 */
+ vuint32_t ispr[8]; /* 0x100 0xe000e200 Set Pending Register */
- uint8_t _unused10c[0x180 - 0x10c];
+ uint8_t _unused120[0x180 - 0x120];
- vuint32_t icpr[3]; /* 0x180 */
+ vuint32_t icpr[8]; /* 0x180 0xe000e280 Clear Pending Register */
- uint8_t _unused18c[0x200 - 0x18c];
+ uint8_t _unused1a0[0x200 - 0x1a0];
- vuint32_t iabr[3]; /* 0x200 */
+ vuint32_t iabr[8]; /* 0x200 0xe000e300 Active Bit Register */
- uint8_t _unused20c[0x300 - 0x20c];
+ uint8_t _unused220[0x300 - 0x220];
- vuint32_t ipr[21]; /* 0x300 */
+ vuint32_t ipr[60]; /* 0x300 0xe000e400 Priority Register */
- uint8_t _unused324[0xe00 - 0x324];
+ uint8_t _unused3f0[0xc00 - 0x3f0];
+
+ vuint32_t cpuid_base; /* 0xc00 0xe000ed00 CPUID Base Register */
+ vuint32_t ics; /* 0xc04 0xe000ed04 Interrupt Control State Register */
+ vuint32_t vto; /* 0xc08 0xe000ed08 Vector Table Offset Register */
+ vuint32_t ai_rc; /* 0xc0c 0xe000ed0c Application Interrupt/Reset Control Register */
+ vuint32_t sc; /* 0xc10 0xe000ed10 System Control Register */
+ vuint32_t cc; /* 0xc14 0xe000ed14 Configuration Control Register */
+
+ vuint32_t shpr7_4; /* 0xc18 0xe000ed18 System Hander Priority Registers */
+ vuint32_t shpr11_8; /* 0xc1c */
+ vuint32_t shpr15_12; /* 0xc20 */
+
+ uint8_t _unusedc18[0xe00 - 0xc24];
vuint32_t stir; /* 0xe00 */
};
return (stm_nvic.ipr[IRQ_PRIO_REG(irq)] >> IRQ_PRIO_BIT(irq)) & IRQ_PRIO_MASK(0);
}
-#define isr(name) void stm_ ## name ## _isr(void);
-
-isr(nmi)
-isr(hardfault)
-isr(memmanage)
-isr(busfault)
-isr(usagefault)
-isr(svc)
-isr(debugmon)
-isr(pendsv)
-isr(systick)
-isr(wwdg)
-isr(pvd)
-isr(tamper_stamp)
-isr(rtc_wkup)
-isr(flash)
-isr(rcc)
-isr(exti0)
-isr(exti1)
-isr(exti2)
-isr(exti3)
-isr(exti4)
-isr(dma1_channel1)
-isr(dma1_channel2)
-isr(dma1_channel3)
-isr(dma1_channel4)
-isr(dma1_channel5)
-isr(dma1_channel6)
-isr(dma1_channel7)
-isr(adc1)
-isr(usb_hp)
-isr(usb_lp)
-isr(dac)
-isr(comp)
-isr(exti9_5)
-isr(lcd)
-isr(tim9)
-isr(tim10)
-isr(tim11)
-isr(tim2)
-isr(tim3)
-isr(tim4)
-isr(i2c1_ev)
-isr(i2c1_er)
-isr(i2c2_ev)
-isr(i2c2_er)
-isr(spi1)
-isr(spi2)
-isr(usart1)
-isr(usart2)
-isr(usart3)
-isr(exti15_10)
-isr(rtc_alarm)
-isr(usb_fs_wkup)
-isr(tim6)
-isr(tim7)
-
-#undef isr
+struct stm_scb {
+ vuint32_t cpuid;
+ vuint32_t icsr;
+ vuint32_t vtor;
+ vuint32_t aircr;
+
+ vuint32_t scr;
+ vuint32_t ccr;
+ vuint32_t shpr1;
+ vuint32_t shpr2;
+
+ vuint32_t shpr3;
+ vuint32_t shcrs;
+ vuint32_t cfsr;
+ vuint32_t hfsr;
+
+ uint32_t unused_30;
+ vuint32_t mmfar;
+ vuint32_t bfar;
+};
+
+extern struct stm_scb stm_scb;
+
+#define STM_SCB_AIRCR_VECTKEY 16
+#define STM_SCB_AIRCR_VECTKEY_KEY 0x05fa
+#define STM_SCB_AIRCR_PRIGROUP 8
+#define STM_SCB_AIRCR_SYSRESETREQ 2
+#define STM_SCB_AIRCR_VECTCLRACTIVE 1
+#define STM_SCB_AIRCR_VECTRESET 0
+
+struct stm_mpu {
+ vuint32_t typer;
+ vuint32_t cr;
+ vuint32_t rnr;
+ vuint32_t rbar;
+
+ vuint32_t rasr;
+ vuint32_t rbar_a1;
+ vuint32_t rasr_a1;
+ vuint32_t rbar_a2;
+ vuint32_t rasr_a2;
+ vuint32_t rbar_a3;
+ vuint32_t rasr_a3;
+};
+
+extern struct stm_mpu stm_mpu;
+
+#define STM_MPU_TYPER_IREGION 16
+#define STM_MPU_TYPER_IREGION_MASK 0xff
+#define STM_MPU_TYPER_DREGION 8
+#define STM_MPU_TYPER_DREGION_MASK 0xff
+#define STM_MPU_TYPER_SEPARATE 0
+
+#define STM_MPU_CR_PRIVDEFENA 2
+#define STM_MPU_CR_HFNMIENA 1
+#define STM_MPU_CR_ENABLE 0
+
+#define STM_MPU_RNR_REGION 0
+#define STM_MPU_RNR_REGION_MASK 0xff
+
+#define STM_MPU_RBAR_ADDR 5
+#define STM_MPU_RBAR_ADDR_MASK 0x7ffffff
+
+#define STM_MPU_RBAR_VALID 4
+#define STM_MPU_RBAR_REGION 0
+#define STM_MPU_RBAR_REGION_MASK 0xf
+
+#define STM_MPU_RASR_XN 28
+#define STM_MPU_RASR_AP 24
+#define STM_MPU_RASR_AP_NONE_NONE 0
+#define STM_MPU_RASR_AP_RW_NONE 1
+#define STM_MPU_RASR_AP_RW_RO 2
+#define STM_MPU_RASR_AP_RW_RW 3
+#define STM_MPU_RASR_AP_RO_NONE 5
+#define STM_MPU_RASR_AP_RO_RO 6
+#define STM_MPU_RASR_AP_MASK 7
+#define STM_MPU_RASR_TEX 19
+#define STM_MPU_RASR_TEX_MASK 7
+#define STM_MPU_RASR_S 18
+#define STM_MPU_RASR_C 17
+#define STM_MPU_RASR_B 16
+#define STM_MPU_RASR_SRD 8
+#define STM_MPU_RASR_SRD_MASK 0xff
+#define STM_MPU_RASR_SIZE 1
+#define STM_MPU_RASR_SIZE_MASK 0x1f
+#define STM_MPU_RASR_ENABLE 0
+
+#define isr_decl(name) void stm_ ## name ## _isr(void)
+
+isr_decl(halt);
+isr_decl(ignore);
+
+isr_decl(nmi);
+isr_decl(hardfault);
+isr_decl(memmanage);
+isr_decl(busfault);
+isr_decl(usagefault);
+isr_decl(svc);
+isr_decl(debugmon);
+isr_decl(pendsv);
+isr_decl(systick);
+isr_decl(wwdg);
+isr_decl(pvd);
+isr_decl(tamper_stamp);
+isr_decl(rtc_wkup);
+isr_decl(flash);
+isr_decl(rcc);
+isr_decl(exti0);
+isr_decl(exti1);
+isr_decl(exti2);
+isr_decl(exti3);
+isr_decl(exti4);
+isr_decl(dma1_channel1);
+isr_decl(dma1_channel2);
+isr_decl(dma1_channel3);
+isr_decl(dma1_channel4);
+isr_decl(dma1_channel5);
+isr_decl(dma1_channel6);
+isr_decl(dma1_channel7);
+isr_decl(adc1);
+isr_decl(usb_hp);
+isr_decl(usb_lp);
+isr_decl(dac);
+isr_decl(comp);
+isr_decl(exti9_5);
+isr_decl(lcd);
+isr_decl(tim9);
+isr_decl(tim10);
+isr_decl(tim11);
+isr_decl(tim2);
+isr_decl(tim3);
+isr_decl(tim4);
+isr_decl(i2c1_ev);
+isr_decl(i2c1_er);
+isr_decl(i2c2_ev);
+isr_decl(i2c2_er);
+isr_decl(spi1);
+isr_decl(spi2);
+isr_decl(usart1);
+isr_decl(usart2);
+isr_decl(usart3);
+isr_decl(exti15_10);
+isr_decl(rtc_alarm);
+isr_decl(usb_fs_wkup);
+isr_decl(tim6);
+isr_decl(tim7);
+
+#undef isr_decl
#define STM_ISR_WWDG_POS 0
#define STM_ISR_PVD_POS 1
#define STM_SPI_CR2_TXDMAEN 1
#define STM_SPI_CR2_RXDMAEN 0
+#define STM_SPI_SR_FRE 8
#define STM_SPI_SR_BSY 7
#define STM_SPI_SR_OVR 6
#define STM_SPI_SR_MODF 5
#define STM_SPI_SR_CRCERR 4
+#define STM_SPI_SR_UDR 3
+#define STM_SPI_SR_CHSIDE 2
#define STM_SPI_SR_TXE 1
#define STM_SPI_SR_RXNE 0
extern struct stm_adc stm_adc;
+#define STM_ADC_SQ_TEMP 16
+#define STM_ADC_SQ_V_REF 17
+
#define STM_ADC_SR_JCNR 9
#define STM_ADC_SR_RCNR 8
#define STM_ADC_SR_ADONS 6
#define stm_temp_cal_cold 25
#define stm_temp_cal_hot 110
+struct stm_dbg_mcu {
+ uint32_t idcode;
+};
+
+extern struct stm_dbg_mcu stm_dbg_mcu;
+
+static inline uint16_t
+stm_dev_id(void) {
+ return stm_dbg_mcu.idcode & 0xfff;
+}
+
+struct stm_flash_size {
+ uint16_t f_size;
+};
+
+extern struct stm_flash_size stm_flash_size_medium;
+extern struct stm_flash_size stm_flash_size_large;
+
+/* Returns flash size in bytes */
+extern uint32_t
+stm_flash_size(void);
+
+struct stm_device_id {
+ uint32_t u_id0;
+ uint32_t u_id1;
+ uint32_t u_id2;
+};
+
+extern struct stm_device_id stm_device_id;
+
#define STM_NUM_I2C 2
#define STM_I2C_INDEX(channel) ((channel) - 1)
#define STM_I2C_CR2_FREQ_4_MHZ 4
#define STM_I2C_CR2_FREQ_8_MHZ 8
#define STM_I2C_CR2_FREQ_16_MHZ 16
+#define STM_I2C_CR2_FREQ_24_MHZ 24
#define STM_I2C_CR2_FREQ_32_MHZ 32
#define STM_I2C_CR2_FREQ_MASK 0x3f
#define STM_TIM234_SMCR_SMS_EXTERNAL_CLOCK 7
#define STM_TIM234_SMCR_SMS_MASK 7
+#define STM_TIM234_DIER_CC4IE 4
+#define STM_TIM234_DIER_CC3IE 3
+#define STM_TIM234_DIER_CC2IE 2
+#define STM_TIM234_DIER_CC1IE 1
+#define STM_TIM234_DIER_UIE 0
+
#define STM_TIM234_SR_CC4OF 12
#define STM_TIM234_SR_CC3OF 11
#define STM_TIM234_SR_CC2OF 10
#define STM_TIM234_SR_CC1IF 1
#define STM_TIM234_SR_UIF 0
+#define STM_TIM234_EGR_TG 6
+#define STM_TIM234_EGR_CC4G 4
+#define STM_TIM234_EGR_CC3G 3
+#define STM_TIM234_EGR_CC2G 2
+#define STM_TIM234_EGR_CC1G 1
+#define STM_TIM234_EGR_UG 0
+
#define STM_TIM234_CCMR1_OC2CE 15
#define STM_TIM234_CCMR1_OC2M 12
#define STM_TIM234_CCMR1_OC2M_FROZEN 0
#define STM_TIM234_CCMR1_OC1M_PWM_MODE_1 6
#define STM_TIM234_CCMR1_OC1M_PWM_MODE_2 7
#define STM_TIM234_CCMR1_OC1M_MASK 7
-#define STM_TIM234_CCMR1_OC1PE 11
+#define STM_TIM234_CCMR1_OC1PE 3
#define STM_TIM234_CCMR1_OC1FE 2
#define STM_TIM234_CCMR1_CC1S 0
#define STM_TIM234_CCMR1_CC1S_OUTPUT 0
#define STM_TIM234_CCMR1_CC1S_INPUT_TRC 3
#define STM_TIM234_CCMR1_CC1S_MASK 3
-#define STM_TIM234_CCMR2_OC2CE 15
+#define STM_TIM234_CCMR2_OC4CE 15
#define STM_TIM234_CCMR2_OC4M 12
#define STM_TIM234_CCMR2_OC4M_FROZEN 0
#define STM_TIM234_CCMR2_OC4M_SET_HIGH_ON_MATCH 1
#define STM_TIM234_CCMR2_OC3M_PWM_MODE_1 6
#define STM_TIM234_CCMR2_OC3M_PWM_MODE_2 7
#define STM_TIM234_CCMR2_OC3M_MASK 7
-#define STM_TIM234_CCMR2_OC3PE 11
+#define STM_TIM234_CCMR2_OC3PE 3
#define STM_TIM234_CCMR2_OC3FE 2
#define STM_TIM234_CCMR2_CC3S 0
#define STM_TIM234_CCMR2_CC3S_OUTPUT 0
#define STM_TIM234_CCER_CC4NP 15
#define STM_TIM234_CCER_CC4P 13
+#define STM_TIM234_CCER_CC4P_ACTIVE_HIGH 0
+#define STM_TIM234_CCER_CC4P_ACTIVE_LOW 1
#define STM_TIM234_CCER_CC4E 12
#define STM_TIM234_CCER_CC3NP 11
#define STM_TIM234_CCER_CC3P 9
+#define STM_TIM234_CCER_CC3P_ACTIVE_HIGH 0
+#define STM_TIM234_CCER_CC3P_ACTIVE_LOW 1
#define STM_TIM234_CCER_CC3E 8
#define STM_TIM234_CCER_CC2NP 7
#define STM_TIM234_CCER_CC2P 5
+#define STM_TIM234_CCER_CC2P_ACTIVE_HIGH 0
+#define STM_TIM234_CCER_CC2P_ACTIVE_LOW 1
#define STM_TIM234_CCER_CC2E 4
#define STM_TIM234_CCER_CC1NP 3
#define STM_TIM234_CCER_CC1P 1
+#define STM_TIM234_CCER_CC1P_ACTIVE_HIGH 0
+#define STM_TIM234_CCER_CC1P_ACTIVE_LOW 1
#define STM_TIM234_CCER_CC1E 0
struct stm_usb {
#define STM_USB_BDT_SIZE 8
-extern uint8_t stm_usb_sram[];
+extern uint8_t stm_usb_sram[] __attribute__ ((aligned(4)));
struct stm_exti {
vuint32_t imr;