diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/stmf0/ao_arch_funcs.h | 62 | ||||
-rw-r--r-- | src/stmf0/ao_timer.c | 94 | ||||
-rw-r--r-- | src/stmf0/ao_usb_stm.c | 58 |
3 files changed, 145 insertions, 69 deletions
diff --git a/src/stmf0/ao_arch_funcs.h b/src/stmf0/ao_arch_funcs.h index 3db96be2..8d585f80 100644 --- a/src/stmf0/ao_arch_funcs.h +++ b/src/stmf0/ao_arch_funcs.h @@ -18,6 +18,8 @@ #ifndef _AO_ARCH_FUNCS_H_ #define _AO_ARCH_FUNCS_H_ +#include <ao_power.h> + /* ao_spi_stm.c */ @@ -118,27 +120,44 @@ ao_spi_try_get_mask(struct stm_gpio *reg, uint16_t mask, uint8_t bus, uint32_t s #define ao_spi_get_bit(reg,bit,pin,bus,speed) ao_spi_get_mask(reg,(1<<bit),bus,speed) #define ao_spi_put_bit(reg,bit,pin,bus) ao_spi_put_mask(reg,(1<<bit),bus) -#define ao_enable_port(port) do { \ - if ((port) == &stm_gpioa) \ - stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_IOPAEN); \ - else if ((port) == &stm_gpiob) \ - stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_IOPBEN); \ - else if ((port) == &stm_gpioc) \ - stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_IOPCEN); \ - else if ((port) == &stm_gpiof) \ - stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_IOPFEN); \ - } while (0) +extern struct ao_power ao_power_gpioa; +extern struct ao_power ao_power_gpiob; +extern struct ao_power ao_power_gpioc; +extern struct ao_power ao_power_gpiof; -#define ao_disable_port(port) do { \ - if ((port) == &stm_gpioa) \ - stm_rcc.ahbenr &= ~(1 << STM_RCC_AHBENR_IOPAEN); \ - else if ((port) == &stm_gpiob) \ - stm_rcc.ahbenr &= ~(1 << STM_RCC_AHBENR_IOPBEN); \ - else if ((port) == &stm_gpioc) \ - stm_rcc.ahbenr &= ~(1 << STM_RCC_AHBENR_IOPCEN); \ - else if ((port) == &stm_gpiof) \ - stm_rcc.ahbenr &= ~(1 << STM_RCC_AHBENR_IOPFEN); \ - } while (0) +static inline void ao_enable_port(struct stm_gpio *port) +{ + if ((port) == &stm_gpioa) { + stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_IOPAEN); + ao_power_register(&ao_power_gpioa); + } else if ((port) == &stm_gpiob) { + stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_IOPBEN); + ao_power_register(&ao_power_gpiob); + } else if ((port) == &stm_gpioc) { + stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_IOPCEN); + ao_power_register(&ao_power_gpioc); + } else if ((port) == &stm_gpiof) { + stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_IOPFEN); + ao_power_register(&ao_power_gpiof); + } +} + +static inline void ao_disable_port(struct stm_gpio *port) +{ + if ((port) == &stm_gpioa) { + stm_rcc.ahbenr &= ~(1 << STM_RCC_AHBENR_IOPAEN); + ao_power_unregister(&ao_power_gpioa); + } else if ((port) == &stm_gpiob) { + stm_rcc.ahbenr &= ~(1 << STM_RCC_AHBENR_IOPBEN); + ao_power_unregister(&ao_power_gpiob); + } else if ((port) == &stm_gpioc) { + stm_rcc.ahbenr &= ~(1 << STM_RCC_AHBENR_IOPCEN); + ao_power_unregister(&ao_power_gpioc); + } else if ((port) == &stm_gpiof) { + stm_rcc.ahbenr &= ~(1 << STM_RCC_AHBENR_IOPFEN); + ao_power_unregister(&ao_power_gpiof); + } +} #define ao_gpio_set(port, bit, pin, v) stm_gpio_set(port, bit, v) @@ -166,8 +185,7 @@ ao_spi_try_get_mask(struct stm_gpio *reg, uint16_t mask, uint8_t bus, uint32_t s } while (0) #define ao_enable_cs(port,bit) do { \ - stm_gpio_set((port), bit, 1); \ - stm_moder_set((port), bit, STM_MODER_OUTPUT); \ + ao_enable_output(port, bit, pin, 1); \ } while (0) #define ao_spi_init_cs(port, mask) do { \ diff --git a/src/stmf0/ao_timer.c b/src/stmf0/ao_timer.c index 7d96542b..d3542a57 100644 --- a/src/stmf0/ao_timer.c +++ b/src/stmf0/ao_timer.c @@ -129,12 +129,9 @@ ao_clock_enable_crs(void) (0 << STM_CRS_CR_SYNCOKIE)); } -void -ao_clock_init(void) +static void +ao_clock_hsi(void) { - uint32_t cfgr; - - /* Switch to HSI while messing about */ stm_rcc.cr |= (1 << STM_RCC_CR_HSION); while (!(stm_rcc.cr & (1 << STM_RCC_CR_HSIRDY))) ao_arch_nop(); @@ -152,10 +149,11 @@ ao_clock_init(void) /* reset PLLON, CSSON, HSEBYP, HSEON */ stm_rcc.cr &= 0x0000ffff; +} - /* Disable all interrupts */ - stm_rcc.cir = 0; - +static void +ao_clock_normal_start(void) +{ #if AO_HSE #define STM_RCC_CFGR_SWS_TARGET_CLOCK STM_RCC_CFGR_SWS_HSE #define STM_RCC_CFGR_SW_TARGET_CLOCK STM_RCC_CFGR_SW_HSE @@ -171,6 +169,11 @@ ao_clock_init(void) stm_rcc.cr |= (1 << STM_RCC_CR_HSEON); while (!(stm_rcc.cr & (1 << STM_RCC_CR_HSERDY))) asm("nop"); + +#ifdef STM_PLLSRC +#error No code for PLL initialization yet +#endif + #endif @@ -195,10 +198,46 @@ ao_clock_init(void) #define STM_PLLSRC STM_HSI #define STM_RCC_CFGR_PLLSRC_TARGET_CLOCK 0 #endif +} -#ifdef STM_PLLSRC -#error No code for PLL initialization yet +static void +ao_clock_normal_switch(void) +{ + uint32_t cfgr; + + cfgr = stm_rcc.cfgr; + cfgr &= ~(STM_RCC_CFGR_SW_MASK << STM_RCC_CFGR_SW); + cfgr |= (STM_RCC_CFGR_SW_TARGET_CLOCK << STM_RCC_CFGR_SW); + stm_rcc.cfgr = cfgr; + for (;;) { + uint32_t c, part, mask, val; + + c = stm_rcc.cfgr; + mask = (STM_RCC_CFGR_SWS_MASK << STM_RCC_CFGR_SWS); + val = (STM_RCC_CFGR_SWS_TARGET_CLOCK << STM_RCC_CFGR_SWS); + part = c & mask; + if (part == val) + break; + } +#if !AO_HSI && !AO_NEED_HSI + /* Turn off the HSI clock */ + stm_rcc.cr &= ~(1 << STM_RCC_CR_HSION); #endif +} + +void +ao_clock_init(void) +{ + uint32_t cfgr; + + /* Switch to HSI while messing about */ + ao_clock_hsi(); + + /* Disable all interrupts */ + stm_rcc.cir = 0; + + /* Start high speed clock */ + ao_clock_normal_start(); /* Set flash latency to tolerate 48MHz SYSCLK -> 1 wait state */ @@ -227,29 +266,11 @@ ao_clock_init(void) stm_rcc.cfgr = cfgr; /* Switch to the desired system clock */ - - cfgr = stm_rcc.cfgr; - cfgr &= ~(STM_RCC_CFGR_SW_MASK << STM_RCC_CFGR_SW); - cfgr |= (STM_RCC_CFGR_SW_TARGET_CLOCK << STM_RCC_CFGR_SW); - stm_rcc.cfgr = cfgr; - for (;;) { - uint32_t c, part, mask, val; - - c = stm_rcc.cfgr; - mask = (STM_RCC_CFGR_SWS_MASK << STM_RCC_CFGR_SWS); - val = (STM_RCC_CFGR_SWS_TARGET_CLOCK << STM_RCC_CFGR_SWS); - part = c & mask; - if (part == val) - break; - } + ao_clock_normal_switch(); /* Clear reset flags */ stm_rcc.csr |= (1 << STM_RCC_CSR_RMVF); -#if !AO_HSI && !AO_NEED_HSI - /* Turn off the HSI clock */ - stm_rcc.cr &= ~(1 << STM_RCC_CR_HSION); -#endif #if DEBUG_THE_CLOCK /* Output SYSCLK on PA8 for measurments */ @@ -263,3 +284,18 @@ ao_clock_init(void) stm_rcc.cfgr |= (STM_RCC_CFGR_MCOSEL_HSE << STM_RCC_CFGR_MCOSEL); #endif } + +#if AO_POWER_MANAGEMENT +void +ao_clock_suspend(void) +{ + ao_clock_hsi(); +} + +void +ao_clock_resume(void) +{ + ao_clock_normal_start(); + ao_clock_normal_switch(); +} +#endif diff --git a/src/stmf0/ao_usb_stm.c b/src/stmf0/ao_usb_stm.c index b8146c21..691c2d56 100644 --- a/src/stmf0/ao_usb_stm.c +++ b/src/stmf0/ao_usb_stm.c @@ -18,8 +18,10 @@ #include "ao.h" #include "ao_usb.h" #include "ao_product.h" +#include "ao_power.h" #define USB_DEBUG 0 +#define USB_STATUS 0 #define USB_DEBUG_DATA 0 #define USB_ECHO 0 @@ -129,10 +131,9 @@ static uint8_t ao_usb_out_avail; uint8_t ao_usb_running; static uint8_t ao_usb_configuration; -#define AO_USB_EP0_GOT_RESET 1 -#define AO_USB_EP0_GOT_SETUP 2 -#define AO_USB_EP0_GOT_RX_DATA 4 -#define AO_USB_EP0_GOT_TX_ACK 8 +#define AO_USB_EP0_GOT_SETUP 1 +#define AO_USB_EP0_GOT_RX_DATA 2 +#define AO_USB_EP0_GOT_TX_ACK 4 static uint8_t ao_usb_ep0_receive; static uint8_t ao_usb_address; @@ -438,6 +439,7 @@ static uint16_t int_count; static uint16_t in_count; static uint16_t out_count; static uint16_t reset_count; +static uint16_t suspend_count; /* The USB memory must be accessed in 16-bit units */ @@ -686,11 +688,6 @@ static void ao_usb_ep0_handle(uint8_t receive) { ao_usb_ep0_receive = 0; - if (receive & AO_USB_EP0_GOT_RESET) { - debug ("\treset\n"); - ao_usb_set_ep0(); - return; - } if (receive & AO_USB_EP0_GOT_SETUP) { debug ("\tsetup\n"); ao_usb_ep0_setup(); @@ -722,6 +719,23 @@ ao_usb_ep0_handle(uint8_t receive) } void +ao_usb_suspend(void) +{ + stm_usb.cntr |= (1 << STM_USB_CNTR_FSUSP); + ao_power_suspend(); + stm_usb.cntr |= (1 << STM_USB_CNTR_LP_MODE); + ao_clock_suspend(); +} + +void +ao_usb_wakeup(void) +{ + ao_clock_resume(); + stm_usb.cntr &= ~(1 << STM_USB_CNTR_FSUSP); + ao_power_resume(); +} + +void stm_usb_isr(void) { uint32_t istr = stm_usb.istr; @@ -784,10 +798,18 @@ stm_usb_isr(void) if (istr & (1 << STM_USB_ISTR_RESET)) { ++reset_count; - ao_usb_ep0_receive |= AO_USB_EP0_GOT_RESET; - ao_usb_ep0_handle(ao_usb_ep0_receive); + debug ("\treset\n"); + ao_usb_set_ep0(); + } + if (istr & (1 << STM_USB_ISTR_SUSP)) { + ++suspend_count; + debug ("\tsuspend\n"); + ao_usb_suspend(); + } + if (istr & (1 << STM_USB_ISTR_WKUP)) { + debug ("\twakeup\n"); + ao_usb_wakeup(); } - } /* Queue the current IN buffer for transmission */ @@ -1050,8 +1072,8 @@ ao_usb_enable(void) stm_usb.cntr = ((1 << STM_USB_CNTR_CTRM) | (0 << STM_USB_CNTR_PMAOVRM) | (0 << STM_USB_CNTR_ERRM) | - (0 << STM_USB_CNTR_WKUPM) | - (0 << STM_USB_CNTR_SUSPM) | + (1 << STM_USB_CNTR_WKUPM) | + (1 << STM_USB_CNTR_SUSPM) | (1 << STM_USB_CNTR_RESETM) | (0 << STM_USB_CNTR_SOFM) | (0 << STM_USB_CNTR_ESOFM) | @@ -1086,12 +1108,12 @@ ao_usb_echo(void) } #endif -#if USB_DEBUG +#if USB_STATUS static void ao_usb_irq(void) { - printf ("control: %d out: %d in: %d int: %d reset: %d\n", - control_count, out_count, in_count, int_count, reset_count); + printf ("control: %d out: %d in: %d int: %d reset: %d suspend %d\n", + control_count, out_count, in_count, int_count, reset_count, suspend_count); } __code struct ao_cmds ao_usb_cmds[] = { @@ -1119,7 +1141,7 @@ ao_usb_init(void) #if USB_ECHO ao_add_task(&ao_usb_echo_task, ao_usb_echo, "usb echo"); #endif -#if USB_DEBUG +#if USB_STATUS ao_cmd_register(&ao_usb_cmds[0]); #endif #if !USB_ECHO |