diff options
| -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  | 
