diff options
| author | Bdale Garbee <bdale@gag.com> | 2016-05-06 18:13:12 -0600 | 
|---|---|---|
| committer | Bdale Garbee <bdale@gag.com> | 2016-05-06 18:13:12 -0600 | 
| commit | 4c20fdfa543059739b756171b991d430789cded1 (patch) | |
| tree | f39e6c729364211bf0570c459c37b576ecf9faa9 /src | |
| parent | e58dd78bcb749315f84168c83a74cf80851bf815 (diff) | |
| parent | 2f0c977c747824d0798550ac64eceb1d66c50efd (diff) | |
Merge branch 'branch-1.6' into debian
Diffstat (limited to 'src')
101 files changed, 5006 insertions, 446 deletions
| diff --git a/src/Makefile b/src/Makefile index ebe1df9c..ecba2fbd 100644 --- a/src/Makefile +++ b/src/Makefile @@ -39,11 +39,14 @@ ARMM3DIRS=\  	telescience-v0.2 telescience-v0.2/flash-loader \  	teledongle-v3.0 teledongle-v3.0/flash-loader \  	teleballoon-v2.0 \ -	telebt-v3.0 telebt-v3.0/flash-loader +	telebt-v3.0 telebt-v3.0/flash-loader \ +	telelcotwo-v0.1 telelcotwo-v0.1/flash-loader \ +	telefiretwo-v0.1 telefiretwo-v0.1/flash-loader \  ARMM0DIRS=\  	easymini-v1.0 easymini-v1.0/flash-loader \ -	chaoskey-v0.1 chaoskey-v0.1/flash-loader +	chaoskey-v0.1 chaoskey-v0.1/flash-loader \ +	chaoskey-v1.0 chaoskey-v1.0/flash-loader  AVRDIRS=\  	telescience-v0.1 telescience-pwm micropeak nanopeak-v0.1 microkite diff --git a/src/cc1111/ao_arch_funcs.h b/src/cc1111/ao_arch_funcs.h index ea340dfd..1eb506cd 100644 --- a/src/cc1111/ao_arch_funcs.h +++ b/src/cc1111/ao_arch_funcs.h @@ -146,4 +146,6 @@ ao_spi_init(void);  #define ao_enable_output(port,bit,pin,v) cc1111_enable_output(port,token_evaluator(port,DIR), token_evaluator(port,SEL), pin, bit, v)  #define ao_gpio_set(port, bit, pin, v) ((pin) = (v))  #define ao_gpio_get(port, bit, pin) (pin) - +#define ao_gpio_get_bits(port) (port) +#define ao_gpio_set_bits(port, bits) ((port) |= bits) +#define ao_gpio_clr_bits(port, bits) ((port) &= ~bits) diff --git a/src/chaoskey-v0.1/Makefile b/src/chaoskey-v0.1/Makefile index ac4a6788..85392280 100644 --- a/src/chaoskey-v0.1/Makefile +++ b/src/chaoskey-v0.1/Makefile @@ -13,6 +13,7 @@ INC = \  	ao_product.h \  	ao_task.h \  	ao_adc_fast.h \ +	ao_power.h \  	stm32f0.h  # @@ -33,9 +34,11 @@ ALTOS_SRC = \  	ao_usb_stm.c \  	ao_trng_send.c \  	ao_task.c \ +	ao_power.c \ +	ao_gpio.c \  	ao_product.c -PRODUCT=ChaosKey-v0.1 +PRODUCT=ChaosKey-hw-0.3-sw-$(VERSION)  PRODUCT_DEF=-DCHAOSKEY_V_0_1  IDVENDOR=0x1d50  IDPRODUCT=0x60c6 diff --git a/src/chaoskey-v0.1/ao_pins.h b/src/chaoskey-v0.1/ao_pins.h index 72963dba..73f76307 100644 --- a/src/chaoskey-v0.1/ao_pins.h +++ b/src/chaoskey-v0.1/ao_pins.h @@ -27,6 +27,9 @@  #define LEDS_AVAILABLE	(AO_LED_RED | AO_LED_GREEN) +#define AO_POWER_MANAGEMENT	1 +#define AO_LED_POWER		AO_LED_RED +  #define HAS_BEEP	0  /* 48MHz clock based on USB */ @@ -40,10 +43,18 @@  #define AO_APB_PRESCALER	1  #define AO_RCC_CFGR_PPRE_DIV	STM_RCC_CFGR_PPRE_DIV_1 -#define HAS_USB			1 -#define AO_USB_DIRECTIO		1 -#define AO_PA11_PA12_RMP	0 -#define AO_USB_INTERFACE_CLASS	0xff +#define HAS_USB				1 +#define AO_USB_DIRECTIO			1 +#define AO_PA11_PA12_RMP		0 +#define AO_USB_DEVICE_CLASS		0xff +#define AO_USB_INTERFACE_CLASS_DATA	0xff +#define AO_USB_HAS_OUT			0 +#define AO_USB_HAS_IN			1 +#define AO_USB_HAS_IN2			1 +#define AO_USB_HAS_INT			0 +#define USE_USB_STDIO			0 +#define AO_USB_SELF_POWER		0 +#define AO_USB_DEVICE_ID_SERIAL		1  #define IS_FLASH_LOADER	0 @@ -57,11 +68,21 @@  #define AO_NUM_ADC		1 +/* TRNG enable */ + +#define AO_TRNG_ENABLE_PORT	(&stm_gpioa) +#define AO_TRNG_ENABLE_BIT	8 +  /* CRC */  #define AO_CRC_WIDTH	32  #define AO_CRC_INIT	0xffffffff  /* TRNG */ -#define AO_LED_TRNG_ACTIVE	AO_LED_GREEN +#define AO_LED_TRNG_COOKED	AO_LED_GREEN +#define AO_LED_TRNG_RAW		AO_LED_GREEN + +/* Mode pin */ +#define AO_RAW_PORT		(&stm_gpioa) +#define AO_RAW_BIT		15  #endif /* _AO_PINS_H_ */ diff --git a/src/chaoskey-v1.0/.gitignore b/src/chaoskey-v1.0/.gitignore new file mode 100644 index 00000000..b0adba26 --- /dev/null +++ b/src/chaoskey-v1.0/.gitignore @@ -0,0 +1,2 @@ +ao_product.h +chaoskey-* diff --git a/src/chaoskey-v1.0/Makefile b/src/chaoskey-v1.0/Makefile new file mode 100644 index 00000000..d9944a12 --- /dev/null +++ b/src/chaoskey-v1.0/Makefile @@ -0,0 +1,73 @@ +# +# AltOS build +# +# + +include ../stmf0/Makefile.defs + +INC = \ +	ao.h \ +	ao_arch.h \ +	ao_arch_funcs.h \ +	ao_pins.h \ +	ao_product.h \ +	ao_task.h \ +	ao_adc_fast.h \ +	ao_power.h \ +	stm32f0.h + +# +# Common AltOS sources +# +ALTOS_SRC = \ +	ao_interrupt.c \ +	ao_timer.c \ +	ao_panic.c \ +	ao_mutex.c \ +	ao_dma_stm.c \ +	ao_adc_fast.c \ +	ao_crc_stm.c \ +	ao_stdio.c \ +	ao_led.c \ +	ao_romconfig.c \ +	ao_boot_chain.c \ +	ao_usb_stm.c \ +	ao_trng_send.c \ +	ao_task.c \ +	ao_power.c \ +	ao_gpio.c \ +	ao_product.c + +PRODUCT=ChaosKey-hw-1.0-sw-$(VERSION) +PRODUCT_DEF=-DCHAOSKEY_V_1_0 +IDVENDOR=0x1d50 +IDPRODUCT=0x60c6 + +CFLAGS = $(PRODUCT_DEF) $(STMF0_CFLAGS) -g -Os + +PROGNAME=chaoskey-v1.0 +PROG=$(PROGNAME)-$(VERSION).elf +HEX=$(PROGNAME)-$(VERSION).ihx + +SRC=$(ALTOS_SRC) ao_chaoskey.c +OBJ=$(SRC:.c=.o) + +all: $(PROG) $(HEX) + +$(PROG): Makefile $(OBJ) altos.ld +	$(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(OBJ) $(LIBS) + +ao_product.h: ao-make-product.5c ../Version +	$(call quiet,NICKLE,$<) $< -m altusmetrum.org -V $(IDVENDOR) -i $(IDPRODUCT) -p $(PRODUCT) -v $(VERSION) -o $@ + +$(OBJ): $(INC) + +distclean:	clean + +clean: +	rm -f *.o $(PROGNAME)-*.elf $(PROGNAME)-*.ihx +	rm -f ao_product.h + +install: + +uninstall: diff --git a/src/chaoskey-v1.0/ao_chaoskey.c b/src/chaoskey-v1.0/ao_chaoskey.c new file mode 100644 index 00000000..f887e601 --- /dev/null +++ b/src/chaoskey-v1.0/ao_chaoskey.c @@ -0,0 +1,38 @@ +/* + * Copyright © 2014 Keith Packard <keithp@keithp.com> + * + * 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. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include <ao.h> +#include <ao_adc_fast.h> +#include <ao_crc.h> +#include <ao_trng_send.h> + +void main(void) +{ +	ao_led_init(LEDS_AVAILABLE); +	ao_clock_init(); +	ao_task_init(); +	ao_timer_init(); +	ao_dma_init(); +	ao_adc_init(); +	ao_crc_init(); + +	ao_usb_init(); + +	ao_trng_send_init(); + +	ao_start_scheduler(); +} diff --git a/src/chaoskey-v1.0/ao_pins.h b/src/chaoskey-v1.0/ao_pins.h new file mode 100644 index 00000000..89a2cb08 --- /dev/null +++ b/src/chaoskey-v1.0/ao_pins.h @@ -0,0 +1,83 @@ +/* + * Copyright © 2015 Keith Packard <keithp@keithp.com> + * + * 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. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#ifndef _AO_PINS_H_ +#define _AO_PINS_H_ + +#define LED_PORT_ENABLE	STM_RCC_AHBENR_IOPBEN +#define LED_PORT	(&stm_gpiob) +#define LED_PIN_RED	4 +#define AO_LED_RED	(1 << LED_PIN_RED) + +#define LEDS_AVAILABLE	(AO_LED_RED) + +#define AO_POWER_MANAGEMENT	1 +#define AO_LED_POWER		AO_LED_RED + +#define HAS_BEEP	0 + +/* 48MHz clock based on USB */ +#define AO_HSI48	1 + +/* HCLK = 48MHz */ +#define AO_AHB_PRESCALER	1 +#define AO_RCC_CFGR_HPRE_DIV	STM_RCC_CFGR_HPRE_DIV_1 + +/* APB = 48MHz */ +#define AO_APB_PRESCALER	1 +#define AO_RCC_CFGR_PPRE_DIV	STM_RCC_CFGR_PPRE_DIV_1 + +#define HAS_USB				1 +#define AO_USB_DIRECTIO			1 +#define AO_PA11_PA12_RMP		1 +#define AO_USB_DEVICE_CLASS		0xff +#define AO_USB_INTERFACE_CLASS_DATA	0xff +#define AO_USB_HAS_OUT			0 +#define AO_USB_HAS_IN			1 +#define AO_USB_HAS_IN2			1 +#define AO_USB_HAS_INT			0 +#define AO_USB_SELF_POWER		0 +#define AO_USB_DEVICE_ID_SERIAL		1 +#define AO_USB_START_DISABLED		1 +#define USE_USB_STDIO			0 + +#define IS_FLASH_LOADER	0 + +/* ADC */ + +#define AO_ADC_PIN0_PORT	(&stm_gpioa) +#define AO_ADC_PIN0_PIN		0 +#define AO_ADC_PIN0_CH		0 + +#define AO_ADC_RCC_AHBENR	((1 << STM_RCC_AHBENR_IOPAEN)) + +#define AO_NUM_ADC		1 + +/* TRNG enable */ + +#define AO_TRNG_ENABLE_PORT	(&stm_gpioa) +#define AO_TRNG_ENABLE_BIT	1 + +/* CRC */ +#define AO_CRC_WIDTH	32 +#define AO_CRC_INIT	0xffffffff + +/* Mode pin */ +#define AO_RAW_PORT		(&stm_gpioa) +#define AO_RAW_BIT		15 + +#endif /* _AO_PINS_H_ */ diff --git a/src/chaoskey-v1.0/flash-loader/.gitignore b/src/chaoskey-v1.0/flash-loader/.gitignore new file mode 100644 index 00000000..a60a4945 --- /dev/null +++ b/src/chaoskey-v1.0/flash-loader/.gitignore @@ -0,0 +1,2 @@ +ao_product.h +chaoskey* diff --git a/src/chaoskey-v1.0/flash-loader/Makefile b/src/chaoskey-v1.0/flash-loader/Makefile new file mode 100644 index 00000000..4f84014a --- /dev/null +++ b/src/chaoskey-v1.0/flash-loader/Makefile @@ -0,0 +1,8 @@ +# +# AltOS flash loader build +# +# + +TOPDIR=../.. +HARDWARE=chaoskey-v1.0 +include $(TOPDIR)/stmf0/Makefile-flash.defs diff --git a/src/chaoskey-v1.0/flash-loader/ao_pins.h b/src/chaoskey-v1.0/flash-loader/ao_pins.h new file mode 100644 index 00000000..570800ca --- /dev/null +++ b/src/chaoskey-v1.0/flash-loader/ao_pins.h @@ -0,0 +1,36 @@ +/* + * Copyright © 2013 Keith Packard <keithp@keithp.com> + * + * 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. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#ifndef _AO_PINS_H_ +#define _AO_PINS_H_ + +#include <ao_flash_stm_pins.h> + +/* Pin 5 on debug connector */ + +#define AO_BOOT_PIN			1 +#define AO_BOOT_APPLICATION_GPIO	stm_gpioa +#define AO_BOOT_APPLICATION_PIN		15 +#define AO_BOOT_APPLICATION_VALUE	1 +#define AO_BOOT_APPLICATION_MODE	AO_EXTI_MODE_PULL_UP + +/* USB */ +#define HAS_USB			1 +#define AO_USB_DIRECTIO		0 +#define AO_PA11_PA12_RMP	1 + +#endif /* _AO_PINS_H_ */ diff --git a/src/detherm/.gitignore b/src/detherm/.gitignore new file mode 100644 index 00000000..4f11d9a0 --- /dev/null +++ b/src/detherm/.gitignore @@ -0,0 +1,2 @@ +ao_product.h +detherm-* diff --git a/src/detherm/Makefile b/src/detherm/Makefile new file mode 100644 index 00000000..6b0e0bf8 --- /dev/null +++ b/src/detherm/Makefile @@ -0,0 +1,82 @@ +# +# AltOS build +# +# + +include ../stmf0/Makefile.defs + +INC = \ +	ao.h \ +	ao_arch.h \ +	ao_arch_funcs.h \ +	ao_pins.h \ +	ao_product.h \ +	ao_task.h \ +	stm32f0.h + +# +# Common AltOS sources +# +ALTOS_SRC = \ +	ao_interrupt.c \ +	ao_timer.c \ +	ao_panic.c \ +	ao_mutex.c \ +	ao_dma_stm.c \ +	ao_usb_stm.c \ +	ao_spi_stm.c \ +	ao_exti_stm.c \ +	ao_stdio.c \ +	ao_led.c \ +	ao_log.c \ +	ao_log_mini.c \ +	ao_sample.c \ +	ao_data.c \ +	ao_kalman.c \ +	ao_flight.c \ +	ao_report.c \ +	ao_storage.c \ +	ao_m25.c \ +	ao_romconfig.c \ +	ao_boot_chain.c \ +	ao_ms5607.c \ +	ao_convert_pa.c \ +	ao_pwm.c \ +	ao_servo.c \ +	ao_task.c \ +	ao_config.c \ +	ao_cmd.c \ +	ao_product.c + +PRODUCT=Detherm-v1.0 +PRODUCT_DEF=-DDETHERM_V_1_0 +IDPRODUCT=0x0013 + +CFLAGS = $(PRODUCT_DEF) $(STMF0_CFLAGS) -g -Os + +PROGNAME=detherm-v1.0 +PROG=$(PROGNAME)-$(VERSION).elf +HEX=$(PROGNAME)-$(VERSION).ihx + +SRC=$(ALTOS_SRC) ao_detherm.c +OBJ=$(SRC:.c=.o) + +all: $(PROG) $(HEX) + +$(PROG): Makefile $(OBJ) altos.ld +	$(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(OBJ) $(LIBS) + +ao_product.h: ao-make-product.5c ../Version +	$(call quiet,NICKLE,$<) $< -m altusmetrum.org -i $(IDPRODUCT) -p $(PRODUCT) -v $(VERSION) -o $@ + +$(OBJ): $(INC) + +distclean:	clean + +clean: +	rm -f *.o $(PROGNAME)-*.elf $(PROGNAME)-*.ihx +	rm -f ao_product.h + +install: + +uninstall: diff --git a/src/detherm/ao_detherm.c b/src/detherm/ao_detherm.c new file mode 100644 index 00000000..fba9195e --- /dev/null +++ b/src/detherm/ao_detherm.c @@ -0,0 +1,50 @@ +/* + * Copyright © 2014 Keith Packard <keithp@keithp.com> + * + * 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. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include <ao.h> +#include <ao_exti.h> +#include <ao_pwm.h> +#include <ao_servo.h> + +void main(void) +{ +	ao_led_init(LEDS_AVAILABLE); + +	ao_led_on(AO_LED_RED); + +	ao_clock_init(); +	ao_task_init(); +	ao_timer_init(); +	ao_exti_init(); + +	ao_dma_init(); +	ao_spi_init(); +	ao_usb_init(); + +	ao_storage_init(); +	ao_ms5607_init(); +//	ao_flight_init(); +	ao_pwm_init(); +	ao_servo_init(); +	ao_log_init(); +	ao_report_init(); +	ao_config_init(); + +	ao_cmd_init(); + +	ao_start_scheduler(); +} diff --git a/src/detherm/ao_pins.h b/src/detherm/ao_pins.h new file mode 100644 index 00000000..1c577b6e --- /dev/null +++ b/src/detherm/ao_pins.h @@ -0,0 +1,115 @@ +/* + * Copyright © 2015 Keith Packard <keithp@keithp.com> + * + * 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. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#ifndef _AO_PINS_H_ +#define _AO_PINS_H_ + +#define LED_PORT_ENABLE	STM_RCC_AHBENR_IOPAEN +#define LED_PORT	(&stm_gpioa) +#define LED_PIN_RED	3 +#define AO_LED_RED	(1 << LED_PIN_RED) + +#define LEDS_AVAILABLE	(AO_LED_RED) + +#define HAS_BEEP	0 + +/* 48MHz clock based on USB */ +//#define AO_HSI48	1 +#define AO_HSE			16000000 +#define AO_RCC_CFGR_PLLMUL	STM_RCC_CFGR_PLLMUL_3 +#define AO_PLLMUL		3 +#define AO_PLLDIV		1 + +/* HCLK = 48MHz */ +#define AO_AHB_PRESCALER	1 +#define AO_RCC_CFGR_HPRE_DIV	STM_RCC_CFGR_HPRE_DIV_1 + +/* APB = 48MHz */ +#define AO_APB_PRESCALER	1 +#define AO_RCC_CFGR_PPRE_DIV	STM_RCC_CFGR_PPRE_DIV_1 + +#define HAS_USB				1 +#define AO_USB_DIRECTIO			0 +#define AO_PA11_PA12_RMP		1 + +#define IS_FLASH_LOADER	0 + +#define AO_DATA_RING	16 + +#define HAS_ADC		0 +#define HAS_ACCEL	0 +#define HAS_GPS		0 +#define HAS_RADIO	0 +#define HAS_FLIGHT	1 +#define HAS_EEPROM	1 +#define HAS_LOG		1 + +#define AO_LOG_FORMAT		AO_LOG_FORMAT_DETHERM + +#define USE_INTERNAL_FLASH	0 + +/* SPI */ +#define HAS_SPI_1		1 +#define HAS_SPI_2		0 +#define SPI_1_PA5_PA6_PA7	1 +#define SPI_1_PB3_PB4_PB5	1 +#define SPI_1_OSPEEDR		STM_OSPEEDR_HIGH + +/* MS5607 */ +#define HAS_MS5607		1 + +#define AO_MS5607_CS_PORT	(&stm_gpioa) +#define AO_MS5607_CS_PIN	0 +#define AO_MS5607_SPI_INDEX	AO_SPI_1_PB3_PB4_PB5 +#define AO_MS5607_MISO_PORT	(&stm_gpiob) +#define AO_MS5607_MISO_PIN	4 +#define AO_MS5607_PRIVATE_PINS	1 +#define AO_MS5607_SPI_SPEED	AO_SPI_SPEED_6MHz + +/* Flash */ + +#define M25_MAX_CHIPS		1 +#define AO_M25_SPI_CS_PORT	(&stm_gpioa) +#define AO_M25_SPI_CS_MASK	(1 << 4) +#define AO_M25_SPI_BUS		AO_SPI_1_PA5_PA6_PA7 + +/* PWM */ + +#define NUM_PWM			1 +#define AO_PWM_TIMER		(&stm_tim3) +#define AO_PWM_0_GPIO		(&stm_gpiob) +#define AO_PWM_0_PIN		1 +#define AO_PWM_0_CH		4 +#define PWM_MAX			20000 +#define AO_PWM_TIMER_ENABLE	STM_RCC_APB1ENR_TIM3EN +#define AO_PWM_TIMER_SCALE	32 + +/* Servo */ + +#define AO_SERVO_DIR_PORT	(&stm_gpiob) +#define AO_SERVO_DIR_BIT	0 +#define AO_SERVO_SPEED_PWM	0 + +/* limit 2 */ +#define AO_SERVO_LIMIT_FORE_PORT	(&stm_gpiob) +#define AO_SERVO_LIMIT_FORE_BIT		6 + +/* limit 1 */ +#define AO_SERVO_LIMIT_BACK_PORT	(&stm_gpiob) +#define AO_SERVO_LIMIT_BACK_BIT		7 + +#endif /* _AO_PINS_H_ */ diff --git a/src/detherm/flash-loader/.gitignore b/src/detherm/flash-loader/.gitignore new file mode 100644 index 00000000..d0d4657e --- /dev/null +++ b/src/detherm/flash-loader/.gitignore @@ -0,0 +1,2 @@ +ao_product.h +detherm* diff --git a/src/detherm/flash-loader/Makefile b/src/detherm/flash-loader/Makefile new file mode 100644 index 00000000..5210aa09 --- /dev/null +++ b/src/detherm/flash-loader/Makefile @@ -0,0 +1,8 @@ +# +# AltOS flash loader build +# +# + +TOPDIR=../.. +HARDWARE=detherm-v1.0 +include $(TOPDIR)/stmf0/Makefile-flash.defs diff --git a/src/detherm/flash-loader/ao_pins.h b/src/detherm/flash-loader/ao_pins.h new file mode 100644 index 00000000..570800ca --- /dev/null +++ b/src/detherm/flash-loader/ao_pins.h @@ -0,0 +1,36 @@ +/* + * Copyright © 2013 Keith Packard <keithp@keithp.com> + * + * 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. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#ifndef _AO_PINS_H_ +#define _AO_PINS_H_ + +#include <ao_flash_stm_pins.h> + +/* Pin 5 on debug connector */ + +#define AO_BOOT_PIN			1 +#define AO_BOOT_APPLICATION_GPIO	stm_gpioa +#define AO_BOOT_APPLICATION_PIN		15 +#define AO_BOOT_APPLICATION_VALUE	1 +#define AO_BOOT_APPLICATION_MODE	AO_EXTI_MODE_PULL_UP + +/* USB */ +#define HAS_USB			1 +#define AO_USB_DIRECTIO		0 +#define AO_PA11_PA12_RMP	1 + +#endif /* _AO_PINS_H_ */ diff --git a/src/drivers/ao_button.c b/src/drivers/ao_button.c index cdf07352..8e7dead7 100644 --- a/src/drivers/ao_button.c +++ b/src/drivers/ao_button.c @@ -18,7 +18,6 @@  #include <ao.h>  #include <ao_button.h>  #include <ao_exti.h> -#include <ao_debounce.h>  #if AO_EVENT  #include <ao_event.h>  #define ao_button_queue(b,v)	ao_event_put_isr(AO_EVENT_BUTTON, b, v) @@ -26,9 +25,14 @@  #define ao_button_queue(b,v)  #endif -#define AO_BUTTON_DEBOUNCE_HOLD	10 +#define AO_BUTTON_DEBOUNCE_INTERVAL	AO_MS_TO_TICKS(50) -static struct ao_debounce	ao_button_debounce[AO_BUTTON_COUNT]; +struct ao_button_state { +	AO_TICK_TYPE	time; +	uint8_t		value; +}; + +static struct ao_button_state	ao_button_state[AO_BUTTON_COUNT];  #define port(q)	AO_BUTTON_ ## q ## _PORT  #define bit(q) AO_BUTTON_ ## q @@ -38,10 +42,8 @@ static struct ao_debounce	ao_button_debounce[AO_BUTTON_COUNT];  #define ao_button_value(b)	!ao_gpio_get(port(b), bit(b), pin(b))  static uint8_t -_ao_button_get(struct ao_debounce *debounce) +_ao_button_get(uint8_t b)  { -	uint8_t	b = debounce - ao_button_debounce; -  	switch (b) {  #if AO_BUTTON_COUNT > 0  	case 0: return ao_button_value(0); @@ -63,22 +65,31 @@ _ao_button_get(struct ao_debounce *debounce)  }  static void -_ao_button_set(struct ao_debounce *debounce, uint8_t value) +_ao_button_check(uint8_t b)  { -	uint8_t b = debounce - ao_button_debounce; - -	ao_button_queue(b, value); -} +	uint8_t	value = _ao_button_get(b); +	if (value != ao_button_state[b].value) { +		AO_TICK_TYPE	now = ao_time(); -#define ao_button_update(b)	ao_button_do(b, ao_gpio_get(port(b), bit(b), pin(b))) +		if ((now - ao_button_state[b].time) >= AO_BUTTON_DEBOUNCE_INTERVAL) { +			ao_button_state[b].value = value; +			ao_button_queue(b, value); +		} +		ao_button_state[b].time = now; +	} +}  static void -ao_button_debounce_init(struct ao_debounce *debounce) { -	ao_debounce_config(debounce, -			   _ao_button_get, -			   _ao_button_set, -			   AO_BUTTON_DEBOUNCE_HOLD); +_ao_button_init(uint8_t b) +{ +	uint8_t	m = ao_arch_irqsave(); +	uint8_t value = _ao_button_get(b); +	ao_button_state[b].value = value; +	ao_button_state[b].time = ao_time(); +	ao_button_queue(b, value); +	ao_arch_irqrestore(m); +  }  static void @@ -87,17 +98,17 @@ ao_button_isr(void)  	uint8_t	b;  	for (b = 0; b < AO_BUTTON_COUNT; b++) -		_ao_debounce_start(&ao_button_debounce[b]); +		_ao_button_check(b);  }  #define init(b) do {							\ -		ao_button_debounce_init(&ao_button_debounce[b]);	\  		ao_enable_port(port(b));				\  									\  		ao_exti_setup(port(b), bit(b),				\  			      AO_BUTTON_MODE|AO_EXTI_MODE_FALLING|AO_EXTI_MODE_RISING|AO_EXTI_PRIORITY_MED, \ -			      ao_button_isr);			\ +			      ao_button_isr);				\  		ao_exti_enable(port(b), bit(b));			\ +		_ao_button_init(b);					\  	} while (0)  void @@ -118,5 +129,4 @@ ao_button_init(void)  #if AO_BUTTON_COUNT > 4  	init(4);  #endif -	ao_debounce_init();  } diff --git a/src/drivers/ao_cc1200.c b/src/drivers/ao_cc1200.c index 6547be39..6bccb188 100644 --- a/src/drivers/ao_cc1200.c +++ b/src/drivers/ao_cc1200.c @@ -20,6 +20,9 @@  #include <ao_exti.h>  #include <ao_fec.h>  #include <ao_packet.h> +#if HAS_PAD +#include <ao_pad.h> +#endif  static uint8_t ao_radio_mutex; @@ -813,6 +816,9 @@ ao_radio_test_cmd(void)  #if PACKET_HAS_SLAVE  		ao_packet_slave_stop();  #endif +#if HAS_PAD +		ao_pad_disable(); +#endif  		ao_radio_get(0xff);  		ao_radio_set_mode(AO_RADIO_MODE_TEST);  		ao_radio_strobe(CC1200_STX); @@ -838,6 +844,9 @@ ao_radio_test_cmd(void)  #if HAS_MONITOR  		ao_monitor_enable();  #endif +#if HAS_PAD +		ao_pad_enable(); +#endif  	}  } diff --git a/src/drivers/ao_event.c b/src/drivers/ao_event.c index 5c0d2863..8f88d778 100644 --- a/src/drivers/ao_event.c +++ b/src/drivers/ao_event.c @@ -41,6 +41,22 @@ ao_event_get(struct ao_event *ev)  		);  } +uint8_t +ao_event_get_for(struct ao_event *ev, uint16_t timeout) +{ +	uint8_t	empty = 1; +	ao_arch_critical( +		while ((empty = ao_event_queue_empty())) +			if (ao_sleep_for(&ao_event_queue, timeout)) +				break; +		if (!empty) { +			*ev = ao_event_queue[ao_event_queue_remove]; +			ao_event_queue_remove = ao_event_queue_next(ao_event_queue_remove); +		} +		); +	return empty; +} +  /* called with interrupts disabled */  void  ao_event_put_isr(uint8_t type, uint8_t unit, int32_t value) diff --git a/src/drivers/ao_event.h b/src/drivers/ao_event.h index 584a845a..ea89da23 100644 --- a/src/drivers/ao_event.h +++ b/src/drivers/ao_event.h @@ -32,6 +32,9 @@ struct ao_event {  void  ao_event_get(struct ao_event *ev); +uint8_t +ao_event_get_for(struct ao_event *ev, uint16_t timeout); +  void  ao_event_put_isr(uint8_t type, uint8_t unit, int32_t value); diff --git a/src/drivers/ao_lco_two.c b/src/drivers/ao_lco_two.c new file mode 100644 index 00000000..f53fef7d --- /dev/null +++ b/src/drivers/ao_lco_two.c @@ -0,0 +1,314 @@ +/* + * Copyright © 2012 Keith Packard <keithp@keithp.com> + * + * 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. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include <ao.h> +#include <ao_lco.h> +#include <ao_event.h> +#include <ao_lco_func.h> +#include <ao_radio_cmac.h> + +#define DEBUG	1 + +#if DEBUG +static uint8_t	ao_lco_debug; +#define DEBUG_EVENT	1 +#define DEBUG_STATUS	2 +#define PRINTD(l, ...) do { if (!(ao_lco_debug & l)) break; printf ("\r%5u %s: ", ao_tick_count, __func__); printf(__VA_ARGS__); flush(); } while(0) +#else +#define PRINTD(l,...) +#endif + +#define AO_LCO_VALID_LAST	1 +#define AO_LCO_VALID_EVER	2 + +static uint8_t	ao_lco_suspended; +static uint8_t	ao_lco_selected; +static uint8_t	ao_lco_valid; +static uint8_t	ao_lco_channels; +static uint16_t	ao_lco_tick_offset; + +/* UI values */ +static uint8_t	ao_lco_armed; +static uint8_t	ao_lco_firing; + +#define ao_lco_box	(ao_config.pad_box) + +static struct ao_pad_query	ao_pad_query; + +#define MASK_SIZE(n)	(((n) + 7) >> 3) +#define MASK_ID(n)	((n) >> 3) +#define MASK_SHIFT(n)	((n) & 7) + +static void +ao_lco_set_armed(int pad, int armed) +{ +	uint8_t	bit = (1 << pad); + +	if (armed) { +		ao_lco_selected |= bit; +		ao_lco_armed |= bit; +	} else { +		ao_lco_selected &= ~bit; +		ao_lco_armed &= ~bit; +	} +	PRINTD(DEBUG_EVENT, "pad %d bit 0x%x armed %d ao_lco_selected 0x%x ao_lco_armed 0x%x\n", +	       pad, bit, armed, ao_lco_selected, ao_lco_armed); +	ao_wakeup(&ao_lco_armed); +} + +static void +ao_lco_suspend(void) +{ +	if (!ao_lco_suspended) { +		PRINTD(DEBUG_EVENT, "suspend\n"); +		ao_lco_suspended = 1; +		ao_lco_selected = 0; +		ao_lco_armed = 0; +		ao_wakeup(&ao_pad_query); +	} +} + +static void +ao_lco_wakeup(void) +{ +	if (ao_lco_suspended) { +		ao_lco_suspended = 0; +		ao_wakeup(&ao_lco_suspended); +	} +} + +static void +ao_lco_input(void) +{ +	static struct ao_event	event; +	uint8_t	timeout; + +	ao_config_get(); +	for (;;) { +		if (ao_config.pad_idle && !ao_lco_suspended) { +			timeout = ao_event_get_for(&event, AO_SEC_TO_TICKS(ao_config.pad_idle)); +			if (timeout) { +				ao_lco_suspend(); +				continue; +			} +		} else { +			ao_event_get(&event); +		} +		ao_lco_wakeup(); +		PRINTD(DEBUG_EVENT, "event type %d unit %d value %d\n", +		       event.type, event.unit, event.value); +		switch (event.type) { +		case AO_EVENT_BUTTON: +			switch (event.unit) { +			case AO_BUTTON_ARM_0: +				ao_lco_set_armed(0, event.value); +				break; +#if AO_BUTTON_ARM_NUM > 1 +			case AO_BUTTON_ARM_1: +				ao_lco_set_armed(1, event.value); +				break; +#endif +			case AO_BUTTON_FIRE: +				if (ao_lco_armed) { +					ao_lco_firing = event.value; +					PRINTD(DEBUG_EVENT, "Firing %d\n", ao_lco_firing); +					ao_wakeup(&ao_lco_armed); +				} +				break; +			} +			break; +		} +	} +} + +static AO_LED_TYPE	continuity_led[AO_LED_CONTINUITY_NUM] = { +#ifdef AO_LED_CONTINUITY_0 +	AO_LED_CONTINUITY_0, +#endif +#ifdef AO_LED_CONTINUITY_1 +	AO_LED_CONTINUITY_1, +#endif +#ifdef AO_LED_CONTINUITY_2 +	AO_LED_CONTINUITY_2, +#endif +#ifdef AO_LED_CONTINUITY_3 +	AO_LED_CONTINUITY_3, +#endif +#ifdef AO_LED_CONTINUITY_4 +	AO_LED_CONTINUITY_4, +#endif +#ifdef AO_LED_CONTINUITY_5 +	AO_LED_CONTINUITY_5, +#endif +#ifdef AO_LED_CONTINUITY_6 +	AO_LED_CONTINUITY_6, +#endif +#ifdef AO_LED_CONTINUITY_7 +	AO_LED_CONTINUITY_7, +#endif +}; + +static uint8_t +ao_lco_get_channels(void) +{ +	int8_t			r; + +	r = ao_lco_query(ao_lco_box, &ao_pad_query, &ao_lco_tick_offset); +	if (r == AO_RADIO_CMAC_OK) { +		ao_lco_channels = ao_pad_query.channels; +		ao_lco_valid = AO_LCO_VALID_LAST | AO_LCO_VALID_EVER; +	} else +		ao_lco_valid &= ~AO_LCO_VALID_LAST; +	PRINTD(DEBUG_STATUS, "ao_lco_get_channels() rssi %d valid %d ret %d offset %d\n", ao_radio_cmac_rssi, ao_lco_valid, r, ao_lco_tick_offset); +	ao_wakeup(&ao_pad_query); +	return ao_lco_valid; +} + +static void +ao_lco_igniter_status(void) +{ +	uint8_t		c; +	uint8_t		t = 0; + +	for (;;) { +		ao_sleep(&ao_pad_query); +		while (ao_lco_suspended) { +			ao_led_off(AO_LED_GREEN|AO_LED_AMBER|AO_LED_RED|AO_LED_REMOTE_ARM); +			for (c = 0; c < AO_LED_CONTINUITY_NUM; c++) +				ao_led_off(continuity_led[c]); +			ao_sleep(&ao_lco_suspended); +		} +		PRINTD(DEBUG_STATUS, "RSSI %d VALID %d\n", ao_radio_cmac_rssi, ao_lco_valid); +		if (!(ao_lco_valid & AO_LCO_VALID_LAST)) { +			ao_led_on(AO_LED_RED); +			ao_led_off(AO_LED_GREEN|AO_LED_AMBER); +			continue; +		} +		if (ao_radio_cmac_rssi < -90) { +			ao_led_on(AO_LED_AMBER); +			ao_led_off(AO_LED_RED|AO_LED_GREEN); +		} else { +			ao_led_on(AO_LED_GREEN); +			ao_led_off(AO_LED_RED|AO_LED_AMBER); +		} +		if (ao_pad_query.arm_status) +			ao_led_on(AO_LED_REMOTE_ARM); +		else +			ao_led_off(AO_LED_REMOTE_ARM); + +		for (c = 0; c < AO_LED_CONTINUITY_NUM; c++) { +			uint8_t	status; + +			if (ao_pad_query.channels & (1 << c)) +				status = ao_pad_query.igniter_status[c]; +			else +				status = AO_PAD_IGNITER_STATUS_NO_IGNITER_RELAY_OPEN; +			PRINTD(DEBUG_STATUS, "\tchannel %d status %d\n", c, status); +			if (status == AO_PAD_IGNITER_STATUS_GOOD_IGNITER_RELAY_OPEN) +				ao_led_on(continuity_led[c]); +			else +				ao_led_off(continuity_led[c]); +		} +		t = 1-t; +	} +} + +static void +ao_lco_arm_warn(void) +{ +	int	i; +	for (;;) { +		while (ao_lco_suspended) +			ao_sleep(&ao_lco_suspended); +		while (!ao_lco_armed) +			ao_sleep(&ao_lco_armed); +		for (i = 0; i < ao_lco_armed; i++) { +			ao_beep_for(AO_BEEP_MID, AO_MS_TO_TICKS(100)); +			ao_delay(AO_MS_TO_TICKS(100)); +		} +		ao_delay(AO_MS_TO_TICKS(300)); +	} +} + +static struct ao_task ao_lco_input_task; +static struct ao_task ao_lco_monitor_task; +static struct ao_task ao_lco_arm_warn_task; +static struct ao_task ao_lco_igniter_status_task; + +static void +ao_lco_monitor(void) +{ +	uint16_t		delay; + +	ao_add_task(&ao_lco_input_task, ao_lco_input, "lco input"); +	ao_add_task(&ao_lco_arm_warn_task, ao_lco_arm_warn, "lco arm warn"); +	ao_add_task(&ao_lco_igniter_status_task, ao_lco_igniter_status, "lco igniter status"); +	ao_beep_for(AO_BEEP_MID, AO_MS_TO_TICKS(200)); +	for (;;) { +		while (ao_lco_suspended) +			ao_sleep(&ao_lco_suspended); + +		PRINTD(DEBUG_STATUS, "monitor armed %d firing %d\n", +		       ao_lco_armed, ao_lco_firing); + +		if (ao_lco_armed && ao_lco_firing) { +			ao_lco_ignite(); +		} else { +			ao_lco_get_channels(); +			if (ao_lco_armed) { +				if (ao_lco_selected) { +					PRINTD(DEBUG_STATUS, "Arming pads %x\n", +					       ao_lco_selected); +					if (ao_lco_valid & AO_LCO_VALID_EVER) { +						ao_lco_arm(ao_lco_box, ao_lco_selected, ao_lco_tick_offset); +						ao_delay(AO_MS_TO_TICKS(10)); +					} +				} +			} +		} +		if (ao_lco_armed && ao_lco_firing) +			delay = AO_MS_TO_TICKS(100); +		else { +			delay = AO_SEC_TO_TICKS(1); +		} +		ao_sleep_for(&ao_lco_armed, delay); +	} +} + +#if DEBUG +void +ao_lco_set_debug(void) +{ +	ao_cmd_decimal(); +	if (ao_cmd_status == ao_cmd_success) +		ao_lco_debug = ao_cmd_lex_i; +} + +__code struct ao_cmds ao_lco_cmds[] = { +	{ ao_lco_set_debug,	"D <0 off, 1 on>\0Debug" }, +	{ 0, NULL } +}; +#endif + +void +ao_lco_init(void) +{ +	ao_add_task(&ao_lco_monitor_task, ao_lco_monitor, "lco monitor"); +#if DEBUG +	ao_cmd_register(&ao_lco_cmds[0]); +#endif +} diff --git a/src/drivers/ao_ms5607.c b/src/drivers/ao_ms5607.c index 6098699e..ef31882e 100644 --- a/src/drivers/ao_ms5607.c +++ b/src/drivers/ao_ms5607.c @@ -24,9 +24,13 @@  __xdata struct ao_ms5607_prom	ao_ms5607_prom;  static __xdata uint8_t	  	ms5607_configured; +#ifndef AO_MS5607_SPI_SPEED +#define AO_MS5607_SPI_SPEED	AO_SPI_SPEED_FAST +#endif +  static void  ao_ms5607_start(void) { -	ao_spi_get_bit(AO_MS5607_CS_PORT, AO_MS5607_CS_PIN, AO_MS5607_CS, AO_MS5607_SPI_INDEX, AO_SPI_SPEED_FAST); +	ao_spi_get_bit(AO_MS5607_CS_PORT, AO_MS5607_CS_PIN, AO_MS5607_CS, AO_MS5607_SPI_INDEX, AO_MS5607_SPI_SPEED);  }  static void diff --git a/src/drivers/ao_packet_master.c b/src/drivers/ao_packet_master.c index 5e440db0..2beda4cb 100644 --- a/src/drivers/ao_packet_master.c +++ b/src/drivers/ao_packet_master.c @@ -117,6 +117,7 @@ ao_packet_forward(void) __reentrant  {  	char c;  	ao_packet_enable = 1; +	ao_packet_tx_used = 0;  	ao_cmd_white();  	flush(); diff --git a/src/drivers/ao_pad.c b/src/drivers/ao_pad.c index 419ea8d3..99a90e77 100644 --- a/src/drivers/ao_pad.c +++ b/src/drivers/ao_pad.c @@ -50,7 +50,11 @@ ao_siren(uint8_t v)  #ifdef AO_SIREN  	ao_gpio_set(AO_SIREN_PORT, AO_SIREN_PIN, AO_SIREN, v);  #else +#if HAS_BEEP  	ao_beep(v ? AO_BEEP_MID : 0); +#else +	(void) v; +#endif  #endif  } @@ -59,13 +63,15 @@ ao_strobe(uint8_t v)  {  #ifdef AO_STROBE  	ao_gpio_set(AO_STROBE_PORT, AO_STROBE_PIN, AO_STROBE, v); +#else +	(void) v;  #endif  }  static void  ao_pad_run(void)  { -	uint8_t	pins; +	AO_PORT_TYPE	pins;  	for (;;) {  		while (!ao_pad_ignite) @@ -90,18 +96,28 @@ ao_pad_run(void)  		if (ao_pad_ignite & (1 << 3))  			pins |= (1 << AO_PAD_PIN_3);  #endif -		AO_PAD_PORT = (AO_PAD_PORT & (~AO_PAD_ALL_PINS)) | pins; +		PRINTD("ignite pins 0x%x\n", pins); +		ao_gpio_set_bits(AO_PAD_PORT, pins);  		while (ao_pad_ignite) {  			ao_pad_ignite = 0;  			ao_delay(AO_PAD_FIRE_TIME);  		} -		AO_PAD_PORT &= ~(AO_PAD_ALL_PINS); +		ao_gpio_clr_bits(AO_PAD_PORT, pins); +		PRINTD("turn off pins 0x%x\n", pins);  	}  }  #define AO_PAD_ARM_SIREN_INTERVAL	200 +#ifndef AO_PYRO_R_PYRO_SENSE +#define AO_PYRO_R_PYRO_SENSE	100 +#define AO_PYRO_R_SENSE_GND	27 +#define AO_FIRE_R_POWER_FET	100 +#define AO_FIRE_R_FET_SENSE	100 +#define AO_FIRE_R_SENSE_GND	27 +#endif +  static void  ao_pad_monitor(void)  { @@ -109,7 +125,7 @@ ao_pad_monitor(void)  	uint8_t			sample;  	__pdata uint8_t		prev = 0, cur = 0;  	__pdata uint8_t		beeping = 0; -	__xdata struct ao_data	*packet; +	__xdata volatile struct ao_data	*packet;  	__pdata uint16_t	arm_beep_time = 0;  	sample = ao_data_head; @@ -120,12 +136,18 @@ ao_pad_monitor(void)  				ao_sleep((void *) DATA_TO_XDATA(&ao_data_head));  			); +  		packet = &ao_data_ring[sample];  		sample = ao_data_ring_next(sample);  		pyro = packet->adc.pyro; -#define VOLTS_TO_PYRO(x) ((int16_t) ((x) * 27.0 / 127.0 / 3.3 * 32767.0)) +#define VOLTS_TO_PYRO(x) ((int16_t) ((x) * ((1.0 * AO_PYRO_R_SENSE_GND) / \ +					    (1.0 * (AO_PYRO_R_SENSE_GND + AO_PYRO_R_PYRO_SENSE)) / 3.3 * AO_ADC_MAX))) + + +#define VOLTS_TO_FIRE(x) ((int16_t) ((x) * ((1.0 * AO_FIRE_R_SENSE_GND) / \ +					    (1.0 * (AO_FIRE_R_SENSE_GND + AO_FIRE_R_FET_SENSE)) / 3.3 * AO_ADC_MAX)))  		/* convert ADC value to voltage in tenths, then add .2 for the diode drop */  		query.battery = (packet->adc.batt + 96) / 192 + 2; @@ -133,14 +155,16 @@ ao_pad_monitor(void)  		if (pyro > VOLTS_TO_PYRO(10)) {  			query.arm_status = AO_PAD_ARM_STATUS_ARMED;  			cur |= AO_LED_ARMED; -		} else if (pyro < VOLTS_TO_PYRO(5)) { -			query.arm_status = AO_PAD_ARM_STATUS_DISARMED; -			arm_beep_time = 0; -		} else { +#if AO_FIRE_R_POWER_FET +		} else if (pyro > VOLTS_TO_PYRO(5)) {  			if ((ao_time() % 100) < 50)  				cur |= AO_LED_ARMED;  			query.arm_status = AO_PAD_ARM_STATUS_UNKNOWN;  			arm_beep_time = 0; +#endif +		} else { +			query.arm_status = AO_PAD_ARM_STATUS_DISARMED; +			arm_beep_time = 0;  		}  		if ((ao_time() - ao_pad_packet_time) > AO_SEC_TO_TICKS(2))  			cur |= AO_LED_RED; @@ -165,22 +189,39 @@ ao_pad_monitor(void)  			 *	27k            /  			 *		gnd ---  			 * +			 *		v_pyro \ +			 *	200k		igniter +			 *		output / +			 *	200k           \ +			 *		sense   relay +			 *	22k            / +			 *		gnd --- +			 *  			 *	If the relay is closed, then sense will be 0  			 *	If no igniter is present, then sense will be v_pyro * 27k/227k = pyro * 127 / 227 ~= pyro/2  			 *	If igniter is present, then sense will be v_pyro * 27k/127k ~= v_pyro / 20 = pyro  			 */ +#if AO_FIRE_R_POWER_FET  			if (sense <= pyro / 8) {  				status = AO_PAD_IGNITER_STATUS_NO_IGNITER_RELAY_CLOSED;  				if ((ao_time() % 100) < 50)  					cur |= AO_LED_CONTINUITY(c); -			} -			else if (pyro / 8 * 3 <= sense && sense <= pyro / 8 * 5) +			} else +			if (pyro / 8 * 3 <= sense && sense <= pyro / 8 * 5)  				status = AO_PAD_IGNITER_STATUS_NO_IGNITER_RELAY_OPEN;  			else if (pyro / 8 * 7 <= sense) {  				status = AO_PAD_IGNITER_STATUS_GOOD_IGNITER_RELAY_OPEN;  				cur |= AO_LED_CONTINUITY(c);  			} +#else +			if (sense >= pyro / 8 * 5) { +				status = AO_PAD_IGNITER_STATUS_GOOD_IGNITER_RELAY_OPEN; +				cur |= AO_LED_CONTINUITY(c); +			} else { +				status = AO_PAD_IGNITER_STATUS_NO_IGNITER_RELAY_OPEN; +			} +#endif  			query.igniter_status[c] = status;  		}  		if (cur != prev) { @@ -240,8 +281,14 @@ ao_pad_read_box(void)  	l = byte & 0xf;  	return h * 10 + l;  } -#else -#define ao_pad_read_box()	0 +#endif + +#if HAS_FIXED_PAD_BOX +#define ao_pad_read_box()	ao_config.pad_box +#endif + +#ifdef PAD_BOX +#define ao_pad_read_box()	PAD_BOX  #endif  static void diff --git a/src/drivers/ao_servo.c b/src/drivers/ao_servo.c new file mode 100644 index 00000000..b48a4112 --- /dev/null +++ b/src/drivers/ao_servo.c @@ -0,0 +1,118 @@ +/* + * Copyright © 2016 Keith Packard <keithp@keithp.com> + * + * 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. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include "ao.h" +#include "ao_servo.h" +#include "ao_pwm.h" +#include "ao_exti.h" + +static uint8_t	limit_wakeup; + +static void +ao_limit_isr(void) +{ +	ao_wakeup(&limit_wakeup); +} + +static void +ao_limit_enable(uint8_t dir) +{ +	if (dir == AO_SERVO_FORE) +		ao_exti_enable(AO_SERVO_LIMIT_FORE_PORT, AO_SERVO_LIMIT_FORE_BIT); +	else +		ao_exti_enable(AO_SERVO_LIMIT_BACK_PORT, AO_SERVO_LIMIT_BACK_BIT); +} + +static void +ao_limit_disable(uint8_t dir) +{ +	if (dir == AO_SERVO_FORE) +		ao_exti_disable(AO_SERVO_LIMIT_FORE_PORT, AO_SERVO_LIMIT_FORE_BIT); +	else +		ao_exti_disable(AO_SERVO_LIMIT_BACK_PORT, AO_SERVO_LIMIT_BACK_BIT); +} + +static uint8_t +ao_limit_get(uint8_t dir) +{ +	if (dir == AO_SERVO_FORE) +		return !ao_gpio_get(AO_SERVO_LIMIT_FORE_PORT, AO_SERVO_LIMIT_FORE_BIT, PIN); +	else +		return !ao_gpio_get(AO_SERVO_LIMIT_BACK_PORT, AO_SERVO_LIMIT_BACK_BIT, PIN); +} + +void +ao_servo_run(uint16_t speed, uint8_t dir, uint16_t timeout) +{ +	printf ("speed %d dir %d\n", speed, dir); + +	/* Turn on the motor */ +	ao_gpio_set(AO_SERVO_DIR_PORT, AO_SERVO_DIR_BIT, AO_SERVO_DIR_PIN, dir); +	ao_pwm_set(AO_SERVO_SPEED_PWM, speed); + +	/* Wait until the limit sensor is triggered */ +	ao_arch_block_interrupts(); +	ao_limit_enable(dir); +	while (!ao_limit_get(dir)) +		if (ao_sleep_for(&limit_wakeup, timeout)) +			break; +	ao_limit_disable(dir); +	ao_arch_release_interrupts(); + +	/* Turn off the motor */ +	ao_pwm_set(AO_SERVO_SPEED_PWM, 0); +} + +#define init_limit(p,b) do {						\ +		ao_enable_port(p);					\ +		ao_exti_setup(p, b,					\ +			      AO_EXTI_MODE_PULL_UP|AO_EXTI_MODE_FALLING|AO_EXTI_PRIORITY_MED, \ +			      ao_limit_isr);				\ +	} while (0) + + +static void +ao_servo_cmd(void) +{ +	uint8_t	dir; +	uint16_t speed; + +	ao_cmd_decimal(); +	dir = ao_cmd_lex_u32; +	ao_cmd_decimal(); +	speed = ao_cmd_lex_u32; +	if (ao_cmd_status != ao_cmd_success) +		return; + +	printf("Run servo %d\n", dir); +	ao_servo_run(speed, dir, AO_MS_TO_TICKS(200)); +} + +static const struct ao_cmds ao_servo_cmds[] = { +	{ ao_servo_cmd,	"S <dir> <speed>\0Run servo in indicated direction" }, +	{ 0, NULL }, +}; + + +void +ao_servo_init(void) +{ +	init_limit(AO_SERVO_LIMIT_FORE_PORT, AO_SERVO_LIMIT_FORE_BIT); +	init_limit(AO_SERVO_LIMIT_BACK_PORT, AO_SERVO_LIMIT_BACK_BIT); +	ao_enable_output(AO_SERVO_DIR_PORT, AO_SERVO_DIR_BIT, AO_SERVO_DIR_PIN, 0); +	ao_cmd_register(&ao_servo_cmds[0]); +} diff --git a/src/drivers/ao_servo.h b/src/drivers/ao_servo.h new file mode 100644 index 00000000..e1df347a --- /dev/null +++ b/src/drivers/ao_servo.h @@ -0,0 +1,41 @@ +/* + * Copyright © 2016 Keith Packard <keithp@keithp.com> + * + * 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. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#ifndef _AO_SERVO_H_ +#define _AO_SERVO_H_ + +void +ao_servo_run(uint16_t speed, uint8_t dir, uint16_t timeout); + +void +ao_servo_init(void); + +#define AO_SERVO_FORE	0 +#define AO_SERVO_BACK	1 + +/* To configure the servo: + * + *	#define AO_SERVO_PWM			<pwm index> + *	#define AO_SERVO_DIR_PORT		<gpio> + *	#define AO_SERVO_DIR_PIN		<pin> + *	#define AO_SERVO_LIMIT_FORE_PORT	<gpio> + *	#define AO_SERVO_LIMIT_FORE_PIN		<pin> + *	#define AO_SERVO_LIMIT_BACK_PORT	<gpio> + *	#define AO_SERVO_LIMIT_BACK_PIN		<pin> + */ + +#endif /* _AO_SERVO_H_ */ diff --git a/src/drivers/ao_trng_send.c b/src/drivers/ao_trng_send.c index bac6035c..171a345f 100644 --- a/src/drivers/ao_trng_send.c +++ b/src/drivers/ao_trng_send.c @@ -19,47 +19,247 @@  #include <ao_adc_fast.h>  #include <ao_crc.h>  #include <ao_trng_send.h> +#include <ao_exti.h> +#include <ao_power.h> + +static struct ao_task	ao_trng_send_task, ao_trng_send_raw_task; +static uint8_t		trng_running; +static AO_TICK_TYPE	trng_power_time; + +#define TRNG_ENABLE_DELAY	AO_MS_TO_TICKS(100) + +static uint8_t		random_mutex;  static void -ao_trng_send(void) +ao_trng_get_raw(uint16_t *buf) +{ +	uint16_t	i; +	uint16_t	t; +	uint16_t	v; + +	t = ao_adc_get(AO_USB_IN_SIZE>>1);	/* one 16-bit value per two output bytes */ +	for (i = 0; i < AO_USB_IN_SIZE / sizeof (uint16_t); i++) { +		v = ao_adc_ring[t]; +		*buf++ = v; +		t = (t + 1) & (AO_ADC_RING_SIZE - 1); +	} +	ao_adc_ack(AO_USB_IN_SIZE>>1); +} + +static void +ao_trng_send_raw(void)  {  	static uint16_t	*buffer[2];  	int		usb_buf_id; + +	if (!buffer[0]) { +		buffer[0] = ao_usb_alloc(); +		buffer[1] = ao_usb_alloc(); +		if (!buffer[0]) +			ao_exit(); +	} + +	usb_buf_id = 0; + +	for (;;) { +		ao_mutex_get(&random_mutex); +		if (!trng_running) { +			AO_TICK_TYPE	delay; + +			delay = trng_power_time + TRNG_ENABLE_DELAY - ao_time(); +			if (delay > TRNG_ENABLE_DELAY) +				delay = TRNG_ENABLE_DELAY; + +			/* Delay long enough for the HV power supply +			 * to stabilize so that the first bits we read +			 * aren't of poor quality +			 */ +			ao_delay(delay); +			trng_running = TRUE; +		} +#ifdef AO_LED_TRNG_RAW +		ao_led_on(AO_LED_TRNG_RAW); +#endif +		ao_trng_get_raw(buffer[usb_buf_id]); +#ifdef AO_LED_TRNG_RAW +		ao_led_off(AO_LED_TRNG_RAW); +#endif +		ao_mutex_put(&random_mutex); +		ao_usb_write2(buffer[usb_buf_id], AO_USB_IN_SIZE); +		usb_buf_id = 1-usb_buf_id; +	} +} + +/* Make sure there's at least 8 bits of variance in the samples */ +#define MIN_VARIANCE		(128 * 128) + +/* Make sure the signal is spread around a bit */ +#define MAX_VARIANCE		(512 * 512) + +#define ADD_STATS(value) do {			\ +		sum += (value);			\ +		sum2 += (value) * (value);	\ +	} while(0) + +#define VARIANCE(n)	((sum2 - (sum / (n) * sum)) / (n)) + +static int +ao_trng_get_cooked(uint16_t *buf) +{  	uint16_t	i; -	uint16_t	*buf;  	uint16_t	t;  	uint32_t	*rnd = (uint32_t *) ao_adc_ring; +	int32_t 	sum, sum2, var; + +	sum = sum2 = 0; +	t = ao_adc_get(AO_USB_IN_SIZE) >> 1;		/* one 16-bit value per output byte */ +	for (i = 0; i < AO_USB_IN_SIZE / sizeof (uint16_t); i++) { +		uint32_t	v; +		uint16_t	v1, v2; + +		/* Fetch two values in one operation */ +		v = rnd[t]; +		t = (t + 1) & ((AO_ADC_RING_SIZE >> 1) - 1); + +		*buf++ = ao_crc_in_32_out_16(v); + +		v1 = v; +		v2 = v >> 16; + +		ADD_STATS(v1); +		ADD_STATS(v2); +	} +	ao_adc_ack(AO_USB_IN_SIZE); +	var = VARIANCE(2 * AO_USB_IN_SIZE / sizeof (uint16_t)); +	return var >= MIN_VARIANCE && var <= MAX_VARIANCE; +} + +#define AO_TRNG_START_WAIT	1024 +#define AO_TRNG_START_CHECK	32 + +static void +ao_trng_send(void) +{ +	static uint16_t	*buffer[2]; +	int	usb_buf_id; +	int	good_bits; +	int	failed; +	int	s;  	if (!buffer[0]) {  		buffer[0] = ao_usb_alloc();  		buffer[1] = ao_usb_alloc();  		if (!buffer[0]) -			return; +			ao_exit();  	}  	usb_buf_id = 0; +#ifdef AO_TRNG_ENABLE_PORT +	ao_gpio_set(AO_TRNG_ENABLE_PORT, AO_TRNG_ENABLE_BIT, AO_TRNG_ENABLE_PIN, 1); +#endif +	trng_power_time = ao_time(); +  	ao_crc_reset(); +	ao_delay(TRNG_ENABLE_DELAY); + +	for (s = 0; s < AO_TRNG_START_WAIT; s++) { +		if (ao_trng_get_cooked(buffer[0])) +			break; +		ao_delay(AO_MS_TO_TICKS(10)); +	} + +	/* Validate the hardware before enabling USB */ +	failed = 0; +	for (s = 0; s < AO_TRNG_START_CHECK; s++) { +		if (!ao_trng_get_cooked(buffer[0])) { +			failed++; +			ao_delay(AO_MS_TO_TICKS(10)); +		} +	} +	if (failed > AO_TRNG_START_CHECK / 4) +		ao_panic(AO_PANIC_DMA); + +	ao_add_task(&ao_trng_send_raw_task, ao_trng_send_raw, "trng_send_raw"); + +#ifdef AO_USB_START_DISABLED +	ao_usb_enable(); +#endif +  	for (;;) { -		ao_led_on(AO_LED_TRNG_ACTIVE); -		t = ao_adc_get(AO_USB_IN_SIZE) >> 1;	/* one 16-bit value per output byte */ -		buf = buffer[usb_buf_id]; -		for (i = 0; i < AO_USB_IN_SIZE / sizeof (uint16_t); i++) { -			*buf++ = ao_crc_in_32_out_16(rnd[t]); -			t = (t + 1) & ((AO_ADC_RING_SIZE>>1) - 1); +		ao_mutex_get(&random_mutex); +		if (!trng_running) { +			AO_TICK_TYPE	delay; + +			delay = trng_power_time + TRNG_ENABLE_DELAY - ao_time(); +			if (delay > TRNG_ENABLE_DELAY) +				delay = TRNG_ENABLE_DELAY; + +			/* Delay long enough for the HV power supply +			 * to stabilize so that the first bits we read +			 * aren't of poor quality +			 */ +			ao_delay(delay); +			trng_running = TRUE; +		} +#ifdef AO_LED_TRNG_COOKED +		ao_led_on(AO_LED_TRNG_COOKED); +#endif +		good_bits = ao_trng_get_cooked(buffer[usb_buf_id]); +#ifdef AO_LED_TRNG_COOKED +		ao_led_off(AO_LED_TRNG_COOKED); +#endif +		ao_mutex_put(&random_mutex); +		if (good_bits) { +			ao_usb_write(buffer[usb_buf_id], AO_USB_IN_SIZE); +			usb_buf_id = 1-usb_buf_id; +			failed = 0; +		} else { +			failed++; +			ao_delay(AO_MS_TO_TICKS(10)); +			if (failed > 10) { +				ao_usb_disable(); +				ao_panic(AO_PANIC_DMA); +			}  		} -		ao_adc_ack(AO_USB_IN_SIZE); -		ao_led_off(AO_LED_TRNG_ACTIVE); -		ao_usb_write(buffer[usb_buf_id], AO_USB_IN_SIZE); -		usb_buf_id = 1-usb_buf_id;  	}  } -static struct ao_task ao_trng_send_task; +#if AO_POWER_MANAGEMENT + +static void ao_trng_suspend(void *arg) +{ +	(void) arg; +#ifdef AO_TRNG_ENABLE_PORT +	ao_gpio_set(AO_TRNG_ENABLE_PORT, AO_TRNG_ENABLE_BIT, AO_TRNG_ENABLE_PIN, 0); +#endif +	trng_running = FALSE; +} + +static void ao_trng_resume(void *arg) +{ +	(void) arg; +#ifdef AO_TRNG_ENABLE_PORT +	ao_gpio_set(AO_TRNG_ENABLE_PORT, AO_TRNG_ENABLE_BIT, AO_TRNG_ENABLE_PIN, 1); +#endif +	trng_power_time = ao_time(); +} + +static struct ao_power ao_trng_power = { +	.suspend = ao_trng_suspend, +	.resume = ao_trng_resume +}; + +#endif  void  ao_trng_send_init(void)  { +#ifdef AO_TRNG_ENABLE_PORT +	ao_enable_output(AO_TRNG_ENABLE_PORT, AO_TRNG_ENABLE_BIT, AO_TRNG_ENABLE_PIN, 0); +	ao_power_register(&ao_trng_power); +#endif +	ao_enable_input(AO_RAW_PORT, AO_RAW_BIT, AO_EXTI_MODE_PULL_UP);  	ao_add_task(&ao_trng_send_task, ao_trng_send, "trng_send");  } diff --git a/src/easymega-v1.0/ao_pins.h b/src/easymega-v1.0/ao_pins.h index a5e55638..773e58d9 100644 --- a/src/easymega-v1.0/ao_pins.h +++ b/src/easymega-v1.0/ao_pins.h @@ -321,6 +321,7 @@ struct ao_adc {   */  #define HAS_MMA655X		1 +#define AO_MMA655X_INVERT	0  #define AO_MMA655X_SPI_INDEX	AO_SPI_1_PB3_PB4_PB5  #define AO_MMA655X_CS_PORT	(&stm_gpioc)  #define AO_MMA655X_CS_PIN	12 diff --git a/src/kernel/ao.h b/src/kernel/ao.h index 59a469ae..6ed0299e 100644 --- a/src/kernel/ao.h +++ b/src/kernel/ao.h @@ -124,6 +124,16 @@ ao_timer_init(void);  void  ao_clock_init(void); +#if AO_POWER_MANAGEMENT +/* Go to low power clock */ +void +ao_clock_suspend(void); + +/* Restart full-speed clock */ +void +ao_clock_resume(void); +#endif +  /*   * ao_mutex.c   */ @@ -810,6 +820,8 @@ struct ao_fifo {  } while(0)  #define ao_fifo_full(f)		((((f).insert + 1) & (AO_FIFO_SIZE-1)) == (f).remove) +#define ao_fifo_mostly(f)	((((f).insert - (f).remove) & (AO_FIFO_SIZE-1)) >= (AO_FIFO_SIZE * 3 / 4)) +#define ao_fifo_barely(f)	((((f).insert - (f).remove) & (AO_FIFO_SIZE-1)) >= (AO_FIFO_SIZE * 1 / 4))  #define ao_fifo_empty(f)	((f).insert == (f).remove)  #if PACKET_HAS_MASTER || PACKET_HAS_SLAVE diff --git a/src/kernel/ao_config.c b/src/kernel/ao_config.c index b0d3e541..f95ca893 100644 --- a/src/kernel/ao_config.c +++ b/src/kernel/ao_config.c @@ -224,6 +224,12 @@ _ao_config_get(void)  		if (minor < 22)  			ao_config.aprs_format = AO_CONFIG_DEFAULT_APRS_FORMAT;  #endif +#if HAS_FIXED_PAD_BOX +		if (minor < 22) +			ao_config.pad_box = 1; +		if (minor < 23) +			ao_config.pad_idle = 120; +#endif  		ao_config.minor = AO_CONFIG_MINOR;  		ao_config_dirty = 1;  	} @@ -899,6 +905,42 @@ ao_config_aprs_format_show(void)  }  #endif /* HAS_APRS */ +#if HAS_FIXED_PAD_BOX +void +ao_config_pad_box_show(void) +{ +	printf ("Pad box: %d\n", ao_config.pad_box); +} + +void +ao_config_pad_box_set(void) +{ +	ao_cmd_decimal(); +	if (ao_cmd_status != ao_cmd_success) +		return; +	_ao_config_edit_start(); +	ao_config.pad_box = ao_cmd_lex_i; +	_ao_config_edit_finish(); +} + +void +ao_config_pad_idle_show(void) +{ +	printf ("Idle timeout: %d\n", ao_config.pad_idle); +} + +void +ao_config_pad_idle_set(void) +{ +	ao_cmd_decimal(); +	if (ao_cmd_status != ao_cmd_success) +		return; +	_ao_config_edit_start(); +	ao_config.pad_idle = ao_cmd_lex_i; +	_ao_config_edit_finish(); +} +#endif +  struct ao_config_var {  	__code char	*str;  	void		(*set)(void) __reentrant; @@ -993,6 +1035,12 @@ __code struct ao_config_var ao_config_vars[] = {  	{ "C <0 compressed, 1 uncompressed>\0APRS format",  	  ao_config_aprs_format_set, ao_config_aprs_format_show },  #endif +#if HAS_FIXED_PAD_BOX +	{ "B <box>\0Set pad box (1-99)", +	  ao_config_pad_box_set, ao_config_pad_box_show }, +	{ "i <seconds>\0Set idle timeout (0 disable)", +	  ao_config_pad_idle_set, ao_config_pad_idle_show }, +#endif  	{ "s\0Show",  	  ao_config_show,		0 },  #if HAS_EEPROM diff --git a/src/kernel/ao_config.h b/src/kernel/ao_config.h index cfe8555c..3c73ea49 100644 --- a/src/kernel/ao_config.h +++ b/src/kernel/ao_config.h @@ -57,7 +57,7 @@  #endif  #define AO_CONFIG_MAJOR	1 -#define AO_CONFIG_MINOR	22 +#define AO_CONFIG_MINOR	23  #define AO_AES_LEN 16 @@ -118,6 +118,10 @@ struct ao_config {  #if HAS_APRS  	uint8_t		aprs_format;		/* minor version 22 */  #endif +#if HAS_FIXED_PAD_BOX +	uint8_t		pad_box;		/* minor version 22 */ +	uint8_t		pad_idle;		/* minor version 23 */ +#endif  };  #define AO_APRS_FORMAT_COMPRESSED	0 diff --git a/src/kernel/ao_data.h b/src/kernel/ao_data.h index 8f75ad87..6ee0965d 100644 --- a/src/kernel/ao_data.h +++ b/src/kernel/ao_data.h @@ -269,6 +269,10 @@ typedef int16_t accel_t;  #define AO_ACCEL_INVERT		4095 +#ifndef AO_MMA655X_INVERT +#error AO_MMA655X_INVERT not defined +#endif +  #define ao_data_accel(packet)			((packet)->mma655x)  #if AO_MMA655X_INVERT  #define ao_data_accel_cook(packet)		(AO_ACCEL_INVERT - (packet)->mma655x) diff --git a/src/stm/ao_fast_timer.h b/src/kernel/ao_fast_timer.h index 90fb3930..90fb3930 100644 --- a/src/stm/ao_fast_timer.h +++ b/src/kernel/ao_fast_timer.h diff --git a/src/kernel/ao_flight.c b/src/kernel/ao_flight.c index 251dbc02..9ba02bb8 100644 --- a/src/kernel/ao_flight.c +++ b/src/kernel/ao_flight.c @@ -370,8 +370,10 @@ ao_flight(void)  				{  					ao_flight_state = ao_flight_landed; +#if HAS_ADC  					/* turn off the ADC capture */  					ao_timer_set_adc_interval(0); +#endif  					ao_wakeup(DATA_TO_XDATA(&ao_flight_state));  				} diff --git a/src/kernel/ao_log.h b/src/kernel/ao_log.h index f86fb359..fdd428c2 100644 --- a/src/kernel/ao_log.h +++ b/src/kernel/ao_log.h @@ -49,6 +49,7 @@ extern __pdata enum ao_flight_state ao_log_state;  #define AO_LOG_FORMAT_TELEMINI		8	/* 16-byte MS5607 baro only, 3.3V supply */  #define AO_LOG_FORMAT_TELEGPS		9	/* 32 byte telegps records */  #define AO_LOG_FORMAT_TELEMEGA		10	/* 32 byte typed telemega records with 32 bit gyro cal */ +#define AO_LOG_FORMAT_DETHERM		11	/* 16-byte MS5607 baro only, no ADC */  #define AO_LOG_FORMAT_NONE		127	/* No log at all */  extern __code uint8_t ao_log_format; diff --git a/src/kernel/ao_log_mini.c b/src/kernel/ao_log_mini.c index 0ca3ed06..844f38aa 100644 --- a/src/kernel/ao_log_mini.c +++ b/src/kernel/ao_log_mini.c @@ -110,9 +110,11 @@ ao_log(void)  					      ao_data_ring[ao_log_data_pos].ms5607_raw.pres);  				ao_log_pack24(log.u.sensor.temp,  					      ao_data_ring[ao_log_data_pos].ms5607_raw.temp); +#if AO_LOG_FORMAT != AO_LOG_FORMAT_DETHERM  				log.u.sensor.sense_a = ao_data_ring[ao_log_data_pos].adc.sense_a;  				log.u.sensor.sense_m = ao_data_ring[ao_log_data_pos].adc.sense_m;  				log.u.sensor.v_batt = ao_data_ring[ao_log_data_pos].adc.v_batt; +#endif  				ao_log_mini(&log);  				if (ao_log_state <= ao_flight_coast)  					next_sensor = log.tick + AO_SENSOR_INTERVAL_ASCENT; diff --git a/src/kernel/ao_panic.c b/src/kernel/ao_panic.c index c29cd8fe..e280f98c 100644 --- a/src/kernel/ao_panic.c +++ b/src/kernel/ao_panic.c @@ -38,10 +38,15 @@ ao_panic_delay(uint8_t n)  {  	uint8_t	i = 0, j = 0; -	while (n--) +	while (n--) { +#ifdef AO_PANIC_DELAY_SCALE +	uint8_t s = AO_PANIC_DELAY_SCALE; +	while (s--) +#endif  		while (--j)  			while (--i)  				ao_arch_nop(); +	}  }  void @@ -56,16 +61,16 @@ ao_panic(uint8_t reason)  	ao_arch_block_interrupts();  	for (;;) {  		ao_panic_delay(20); +#if HAS_BEEP  		for (n = 0; n < 5; n++) { -			ao_led_on(AO_LED_PANIC);  			ao_beep(AO_BEEP_HIGH);  			ao_panic_delay(1); -			ao_led_off(AO_LED_PANIC);  			ao_beep(AO_BEEP_LOW);  			ao_panic_delay(1);  		}  		ao_beep(AO_BEEP_OFF);  		ao_panic_delay(2); +#endif  #ifdef SDCC  #pragma disable_warning 126 diff --git a/src/kernel/ao_power.c b/src/kernel/ao_power.c new file mode 100644 index 00000000..bead5944 --- /dev/null +++ b/src/kernel/ao_power.c @@ -0,0 +1,80 @@ +/* + * Copyright © 2016 Keith Packard <keithp@keithp.com> + * + * 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. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include <ao.h> +#include <ao_power.h> + +static struct ao_power	*head, *tail; + +void +ao_power_register(struct ao_power *power) +{ +	if (power->registered) +		return; +	power->registered = TRUE; +	if (tail) { +		tail->next = power; +		power->prev = tail; +		tail = power; +	} else { +		head = tail = power; +	} +#ifdef AO_LED_POWER +	ao_led_on(AO_LED_POWER); +#endif +} + +void +ao_power_unregister(struct ao_power *power) +{ +	if (!power->registered) +		return; +	power->registered = FALSE; +	if (power->prev) +		power->prev->next = power->next; +	else +		head = power->next; +	if (power->next) +		power->next->prev = power->prev; +	else +		tail = power->prev; +} + +void +ao_power_suspend(void) +{ +	struct ao_power	*p; + +#ifdef AO_LED_POWER +	ao_led_off(AO_LED_POWER); +#endif +	for (p = tail; p; p = p->prev) +		p->suspend(p->arg); +} + +void +ao_power_resume(void) +{ +	struct ao_power	*p; + +	for (p = head; p; p = p->next) +		p->resume(p->arg); +#ifdef AO_LED_POWER +	ao_led_on(AO_LED_POWER); +#endif +} + diff --git a/src/kernel/ao_power.h b/src/kernel/ao_power.h new file mode 100644 index 00000000..98a8c1c7 --- /dev/null +++ b/src/kernel/ao_power.h @@ -0,0 +1,53 @@ +/* + * Copyright © 2016 Keith Packard <keithp@keithp.com> + * + * 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. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#ifndef _AO_POWER_H_ +#define _AO_POWER_H_ + +#if AO_POWER_MANAGEMENT + +struct ao_power { +	struct ao_power	*prev, *next; + +	void (*suspend)(void *arg); +	void (*resume)(void *arg); +	void *arg; +	uint8_t	registered; +}; + +void +ao_power_register(struct ao_power *power); + +void +ao_power_unregister(struct ao_power *power); + +void +ao_power_suspend(void); + +void +ao_power_resume(void); + +#else /* AO_POWER_MANAGEMENT */ + +#define ao_power_register(power) +#define ao_power_unregister(power) +#define ao_power_suspend() +#define ao_power_resume() + +#endif /* else AO_POWER_MANAGEMENT */ + +#endif /* _AO_POWER_H_ */ diff --git a/src/kernel/ao_product.c b/src/kernel/ao_product.c index c711a4d2..3a829b3a 100644 --- a/src/kernel/ao_product.c +++ b/src/kernel/ao_product.c @@ -33,11 +33,32 @@ const char ao_product[] = AO_iProduct_STRING;  #define AO_USB_MAX_POWER	100  #endif -#ifndef AO_USB_INTERFACE_CLASS -#define AO_USB_INTERFACE_CLASS	0x02 +#ifndef AO_USB_SELF_POWER +#define AO_USB_SELF_POWER	1 +#endif + +#define AO_USB_DEVICE_CLASS_COMMUNICATION	0x02 +#define AO_USB_INTERFACE_CLASS_CONTROL_CDC	0x02 +#define AO_USB_INTERFACE_CLASS_DATA_CDC		0x0A + +#ifndef AO_USB_DEVICE_CLASS +#define AO_USB_DEVICE_CLASS		AO_USB_DEVICE_CLASS_COMMUNICATION +#endif + +#ifndef AO_USB_INTERFACE_CLASS_DATA +#define AO_USB_INTERFACE_CLASS_CONTROL	AO_USB_INTERFACE_CLASS_CONTROL_CDC +#define AO_USB_INTERFACE_CLASS_DATA	AO_USB_INTERFACE_CLASS_DATA_CDC  #endif  #include "ao_usb.h" + +#define HEADER_LEN	       	9 +#define CONTROL_CLASS_LEN	35 +#define DATA_LEN		(9 + 7 * AO_USB_HAS_OUT + 7 * AO_USB_HAS_IN + 7 * AO_USB_HAS_IN2) + +#define TOTAL_LENGTH		(HEADER_LEN + AO_USB_HAS_INT * CONTROL_CLASS_LEN + DATA_LEN) +#define NUM_INTERFACES		(AO_USB_HAS_INT + 1) +  /* USB descriptors in one giant block of bytes */  AO_ROMCONFIG_SYMBOL(0x00aa) uint8_t ao_usb_descriptors [] =  { @@ -45,7 +66,7 @@ AO_ROMCONFIG_SYMBOL(0x00aa) uint8_t ao_usb_descriptors [] =  	0x12,  	AO_USB_DESC_DEVICE,  	LE_WORD(0x0110),	/*  bcdUSB */ -	0x02,			/*  bDeviceClass */ +	AO_USB_DEVICE_CLASS,	/*  bDeviceClass */  	0x00,			/*  bDeviceSubClass */  	0x00,			/*  bDeviceProtocol */  	AO_USB_CONTROL_SIZE,	/*  bMaxPacketSize */ @@ -60,20 +81,21 @@ AO_ROMCONFIG_SYMBOL(0x00aa) uint8_t ao_usb_descriptors [] =  	/* Configuration descriptor */  	0x09,  	AO_USB_DESC_CONFIGURATION, -	LE_WORD(67),		/*  wTotalLength */ -	0x02,			/*  bNumInterfaces */ +	LE_WORD(TOTAL_LENGTH),	/*  wTotalLength */ +	NUM_INTERFACES,		/*  bNumInterfaces */  	0x01,			/*  bConfigurationValue */  	0x00,			/*  iConfiguration */ -	0xC0,			/*  bmAttributes */ +	0x80 | (AO_USB_SELF_POWER << 6),	/*  bmAttributes */  	AO_USB_MAX_POWER >> 1,	/*  bMaxPower, 2mA units */ +#if AO_USB_HAS_INT  	/* Control class interface */  	0x09,  	AO_USB_DESC_INTERFACE,  	0x00,			/*  bInterfaceNumber */  	0x00,			/*  bAlternateSetting */  	0x01,			/*  bNumEndPoints */ -	AO_USB_INTERFACE_CLASS,	/*  bInterfaceClass */ +	AO_USB_INTERFACE_CLASS_CONTROL,	/*  bInterfaceClass */  	0x02,			/*  bInterfaceSubClass */  	0x01,			/*  bInterfaceProtocol, linux requires value of 1 for the cdc_acm module */  	0x00,			/*  iInterface */ @@ -111,18 +133,20 @@ AO_ROMCONFIG_SYMBOL(0x00aa) uint8_t ao_usb_descriptors [] =  	0x03,			/* bmAttributes = intr */  	LE_WORD(8),		/* wMaxPacketSize */  	0xff,			/* bInterval */ +#endif  	/* Data class interface descriptor */  	0x09,  	AO_USB_DESC_INTERFACE, -	0x01,			/* bInterfaceNumber */ -	0x00,			/* bAlternateSetting */ -	0x02,			/* bNumEndPoints */ -	0x0A,			/* bInterfaceClass = data */ -	0x00,			/* bInterfaceSubClass */ -	0x00,			/* bInterfaceProtocol */ -	0x00,			/* iInterface */ - +	AO_USB_HAS_INT,			/* bInterfaceNumber */ +	0x00,				/* bAlternateSetting */ +	AO_USB_HAS_OUT + AO_USB_HAS_IN + AO_USB_HAS_IN2,	/* bNumEndPoints */ +	AO_USB_INTERFACE_CLASS_DATA,	/* bInterfaceClass = data */ +	0x00,				/* bInterfaceSubClass */ +	0x00,				/* bInterfaceProtocol */ +	0x00,				/* iInterface */ + +#if AO_USB_HAS_OUT  	/* Data EP OUT */  	0x07,  	AO_USB_DESC_ENDPOINT, @@ -130,7 +154,9 @@ AO_ROMCONFIG_SYMBOL(0x00aa) uint8_t ao_usb_descriptors [] =  	0x02,			/* bmAttributes = bulk */  	LE_WORD(AO_USB_OUT_SIZE),/* wMaxPacketSize */  	0x00,			/* bInterval */ +#endif +#if AO_USB_HAS_IN  	/* Data EP in */  	0x07,  	AO_USB_DESC_ENDPOINT, @@ -138,6 +164,17 @@ AO_ROMCONFIG_SYMBOL(0x00aa) uint8_t ao_usb_descriptors [] =  	0x02,			/* bmAttributes = bulk */  	LE_WORD(AO_USB_IN_SIZE),/* wMaxPacketSize */  	0x00,			/* bInterval */ +#endif + +#if AO_USB_HAS_IN2 +	/* Data EP in 2 */ +	0x07, +	AO_USB_DESC_ENDPOINT, +	AO_USB_IN2_EP|0x80,	/* bEndpointAddress */ +	0x02,			/* bmAttributes = bulk */ +	LE_WORD(AO_USB_IN_SIZE),/* wMaxPacketSize */ +	0x00,			/* bInterval */ +#endif  	/* String descriptors */  	0x04, diff --git a/src/kernel/ao_task.c b/src/kernel/ao_task.c index 55e423bb..e430edc6 100644 --- a/src/kernel/ao_task.c +++ b/src/kernel/ao_task.c @@ -355,7 +355,6 @@ ao_yield(void) ao_arch_naked_define  	 */  	if (ao_cur_task->wchan == NULL)  		ao_task_to_run_queue(ao_cur_task); -	ao_cur_task = NULL;  	for (;;) {  		ao_arch_memory_barrier();  		if (!ao_list_is_empty(&run_queue)) @@ -425,6 +424,7 @@ ao_sleep(__xdata void *wchan)  void  ao_wakeup(__xdata void *wchan) __reentrant  { +	ao_validate_cur_stack();  #if HAS_TASK_QUEUE  	struct ao_task	*sleep, *next;  	struct ao_list	*sleep_queue; @@ -442,10 +442,12 @@ ao_wakeup(__xdata void *wchan) __reentrant  	}  	ao_arch_irqrestore(flags);  #else +	{  	uint8_t	i;  	for (i = 0; i < ao_num_tasks; i++)  		if (ao_tasks[i]->wchan == wchan)  			ao_tasks[i]->wchan = NULL; +	}  #endif  	ao_check_stack();  } diff --git a/src/kernel/ao_task.h b/src/kernel/ao_task.h index c6bec0e3..0e353fe8 100644 --- a/src/kernel/ao_task.h +++ b/src/kernel/ao_task.h @@ -56,6 +56,10 @@ extern __data uint8_t ao_num_tasks;  extern __xdata struct ao_task *__data ao_cur_task;  extern __data uint8_t ao_task_minimize_latency;	/* Reduce IRQ latency */ +#ifndef HAS_ARCH_VALIDATE_CUR_STACK +#define ao_validate_cur_stack() +#endif +  /*   ao_task.c   */ diff --git a/src/kernel/ao_usb.h b/src/kernel/ao_usb.h index 1ce4f82f..8f3e7813 100644 --- a/src/kernel/ao_usb.h +++ b/src/kernel/ao_usb.h @@ -105,6 +105,23 @@ extern __code __at (0x00aa) uint8_t ao_usb_descriptors [];  #ifndef AO_USB_OUT_EP  #define AO_USB_OUT_EP		4  #define AO_USB_IN_EP		5 +#define AO_USB_IN2_EP		6 +#endif + +#ifndef AO_USB_HAS_OUT +#define AO_USB_HAS_OUT	1 +#endif + +#ifndef AO_USB_HAS_IN +#define AO_USB_HAS_IN	1 +#endif + +#ifndef AO_USB_HAS_INT +#define AO_USB_HAS_INT	1 +#endif + +#ifndef AO_USB_HAS_IN2 +#define AO_USB_HAS_IN2	0  #endif  /* diff --git a/src/lpc/ao_arch_funcs.h b/src/lpc/ao_arch_funcs.h index fbe641d8..dbb41538 100644 --- a/src/lpc/ao_arch_funcs.h +++ b/src/lpc/ao_arch_funcs.h @@ -227,6 +227,28 @@ ao_spi_duplex(const void *out, void *in, uint16_t len, uint8_t spi_index);  void  ao_spi_init(void); +static inline void +ao_spi_send_sync(const void *block, uint16_t len, uint8_t spi_index) +{ +	ao_spi_send(block, len, spi_index); +} + +static inline void ao_spi_send_byte(uint8_t byte, uint8_t spi_index) +{ +	struct lpc_ssp	*lpc_ssp; +	switch (spi_index) { +	case 0: +		lpc_ssp = &lpc_ssp0; +		break; +	case 1: +		lpc_ssp = &lpc_ssp1; +		break; +	} +	lpc_ssp->dr = byte; +	while ((lpc_ssp->sr & (1 << LPC_SSP_SR_RNE)) == 0); +	(void) lpc_ssp->dr; +} +  #define ao_spi_init_cs(port, mask) do {					\  		uint8_t __bit__;					\  		for (__bit__ = 0; __bit__ < 32; __bit__++) {		\ diff --git a/src/lpc/ao_fast_timer_lpc.c b/src/lpc/ao_fast_timer_lpc.c new file mode 100644 index 00000000..c4f26fc4 --- /dev/null +++ b/src/lpc/ao_fast_timer_lpc.c @@ -0,0 +1,110 @@ +/* + * Copyright © 2016 Keith Packard <keithp@keithp.com> + * + * 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. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include <ao.h> +#include <ao_fast_timer.h> + +static void (*ao_fast_timer_callback[AO_FAST_TIMER_MAX])(void); +static uint8_t ao_fast_timer_count; +static uint8_t ao_fast_timer_users; + +static void +ao_fast_timer_enable(void) +{ +	lpc_ct16b0.tcr = ((1 << LPC_CT16B_TCR_CEN) | +			  (1 << LPC_CT16B_TCR_CRST)); +} + +static void +ao_fast_timer_disable(void) +{ +	lpc_ct16b0.tcr = ((0 << LPC_CT16B_TCR_CEN) | +			  (0 << LPC_CT16B_TCR_CRST)); +} + +void +ao_fast_timer_on(void (*callback)(void)) +{ +	ao_fast_timer_callback[ao_fast_timer_count] = callback; +	if (!ao_fast_timer_count++) +		ao_fast_timer_enable(); +} + +void +ao_fast_timer_off(void (*callback)(void)) +{ +	uint8_t	n; + +	for (n = 0; n < ao_fast_timer_count; n++) +		if (ao_fast_timer_callback[n] == callback) { +			for (; n < ao_fast_timer_count-1; n++) { +				ao_fast_timer_callback[n] = ao_fast_timer_callback[n+1]; +			} +			if (!--ao_fast_timer_count) +				ao_fast_timer_disable(); +			break; +		} +} + +void lpc_ct16b0_isr(void) +{ +	uint32_t	v = lpc_ct16b0.ir; +	int		i; + +	lpc_ct16b0.ir = v; +	if (v & (1 << LPC_CT16B_IR_MR0INT)) { +		for (i = 0; i < ao_fast_timer_count; i++) +			(*ao_fast_timer_callback[i])(); +	} +} + +#ifndef FAST_TIMER_FREQ +#define FAST_TIMER_FREQ	10000 +#endif + +#define TIMER_FAST	(AO_LPC_SYSCLK / FAST_TIMER_FREQ) + +void +ao_fast_timer_init(void) +{ +	if (!ao_fast_timer_users) { + +		lpc_nvic_set_enable(LPC_ISR_CT16B0_POS); +		lpc_nvic_set_priority(LPC_ISR_CT16B0_POS, AO_LPC_NVIC_CLOCK_PRIORITY); +		/* Turn on 16-bit timer CT16B0 */ + +		lpc_scb.sysahbclkctrl |= 1 << LPC_SCB_SYSAHBCLKCTRL_CT16B0; + +		/* Disable timer */ +		lpc_ct16b0.tcr = 0; + +		/* scale factor 1 */ +		lpc_ct16b0.pr = 0; +		lpc_ct16b0.pc = 0; + +		lpc_ct16b0.mcr = ((1 << LPC_CT16B_MCR_MR0I) | +				  (1 << LPC_CT16B_MCR_MR0R)); + +		lpc_ct16b0.mr[0] = TIMER_FAST; + +		ao_fast_timer_disable(); +	} +	if (ao_fast_timer_users == AO_FAST_TIMER_MAX) +		ao_panic(AO_PANIC_FAST_TIMER); +	ao_fast_timer_users++; +} + diff --git a/src/lpc/ao_timer_lpc.c b/src/lpc/ao_timer_lpc.c index 44fb410e..623559eb 100644 --- a/src/lpc/ao_timer_lpc.c +++ b/src/lpc/ao_timer_lpc.c @@ -99,7 +99,7 @@ ao_clock_init(void)  				 (1 << LPC_SCB_SYSAHBCLKCTRL_FLASHARRAY) |  				 (1 << LPC_SCB_SYSAHBCLKCTRL_GPIO) |  				 (1 << LPC_SCB_SYSAHBCLKCTRL_IOCON)); -				  +  	/* Enable the brown-out detection at the highest voltage to  	 * make sure the flash part remains happy  	 */ @@ -112,21 +112,21 @@ ao_clock_init(void)  	/* Turn the IRC clock back on */  	lpc_scb.pdruncfg &= ~(1 << LPC_SCB_PDRUNCFG_IRC_PD);  	ao_clock_delay(); -	 +  	/* Switch to the IRC clock */  	lpc_scb.mainclksel = LPC_SCB_MAINCLKSEL_SEL_IRC << LPC_SCB_MAINCLKSEL_SEL;  	lpc_scb.mainclkuen = (0 << LPC_SCB_MAINCLKUEN_ENA);  	lpc_scb.mainclkuen = (1 << LPC_SCB_MAINCLKUEN_ENA);  	while (!(lpc_scb.mainclkuen & (1 << LPC_SCB_MAINCLKUEN_ENA)))  		; -	 +  	/* Switch USB to the main clock */  	lpc_scb.usbclksel = (LPC_SCB_USBCLKSEL_SEL_MAIN_CLOCK << LPC_SCB_USBCLKSEL_SEL);  	lpc_scb.usbclkuen = (0 << LPC_SCB_USBCLKUEN_ENA);  	lpc_scb.usbclkuen = (1 << LPC_SCB_USBCLKUEN_ENA);  	while (!(lpc_scb.usbclkuen & (1 << LPC_SCB_USBCLKUEN_ENA)))  		; -	 +  	/* Find a PLL post divider ratio that gets the FCCO in range */  	for (p = 0; p < 4; p++)  		if (AO_LPC_CLKOUT << (1 + p) >= AO_LPC_FCCO_MIN) @@ -163,12 +163,12 @@ ao_clock_init(void)  	lpc_scb.syspllclkuen = (1 << LPC_SCB_SYSPLLCLKUEN_ENA);  	while (!(lpc_scb.syspllclkuen & (1 << LPC_SCB_SYSPLLCLKUEN_ENA)))  		; -	 +  	/* Turn on the PLL */  	lpc_scb.pdruncfg &= ~(1 << LPC_SCB_PDRUNCFG_SYSPLL_PD);  	/* Wait for it to lock */ -	 +  	for (i = 0; i < 20000; i++)  		if (lpc_scb.syspllstat & (1 << LPC_SCB_SYSPLLSTAT_LOCK))  			break; @@ -199,7 +199,7 @@ ao_clock_init(void)  	lpc_scb.usbpllclkuen = (1 << LPC_SCB_USBPLLCLKUEN_ENA);  	while (!(lpc_scb.usbpllclkuen & (1 << LPC_SCB_USBPLLCLKUEN_ENA)))  		; -	 +  	/* Power down everything we don't need */  	lpc_scb.pdruncfg = ((1 << LPC_SCB_PDRUNCFG_IRCOUT_PD) |  			    (1 << LPC_SCB_PDRUNCFG_IRC_PD) | diff --git a/src/lpc/lpc.h b/src/lpc/lpc.h index 9408ceab..40d412d0 100644 --- a/src/lpc/lpc.h +++ b/src/lpc/lpc.h @@ -411,7 +411,7 @@ struct lpc_scb {  	vuint32_t	mainclksel;	/* 0x70 */  	vuint32_t	mainclkuen;  	vuint32_t	sysahbclkdiv; -	uint32_t	r7c;		 +	uint32_t	r7c;  	vuint32_t	sysahbclkctrl;	/* 0x80 */  	uint32_t	r84[3]; @@ -429,14 +429,14 @@ struct lpc_scb {  	uint32_t	rcc;  	uint32_t	rd0[4]; -	 +  	vuint32_t	clkoutsel;	/* 0xe0 */  	vuint32_t	clkoutuen;  	vuint32_t	clkoutdiv;  	uint32_t	rec; -	 +  	uint32_t	rf0[4];		/* 0xf0 */ -	 +  	vuint32_t	pioporcap0;	/* 0x100 */  	vuint32_t	pioporcap1;  	uint32_t	r102[2]; @@ -445,7 +445,7 @@ struct lpc_scb {  	uint32_t	r120[4];	/* 0x120 */  	uint32_t	r130[4];	/* 0x130 */  	uint32_t	r140[4];	/* 0x140 */ -	 +  	vuint32_t	bodctrl;	/* 0x150 */  	vuint32_t	systckcal;  	uint32_t	r158[2]; @@ -479,7 +479,7 @@ struct lpc_scb {  	uint32_t	r240[12 * 4];	/* 0x240 */  	uint32_t	r300[15 * 4];	/* 0x300 */ -			      +  	uint32_t	r3f0;		/* 0x3f0 */  	vuint32_t	device_id;  }; @@ -680,7 +680,7 @@ struct lpc_gpio {  	vuint32_t	word[0x40];	/* 0x1000 */  	uint8_t		r1100[0x2000 - 0x1100]; -	 +  	vuint32_t	dir[2];		/* 0x2000 */  	uint8_t		r2008[0x2080 - 0x2008]; @@ -1032,7 +1032,7 @@ lpc_nvic_enabled(int irq) {  	return (lpc_nvic.iser >> irq) & 1;  } -	 +  static inline void  lpc_nvic_set_pending(int irq) {  	lpc_nvic.ispr = (1 << irq); @@ -1201,18 +1201,118 @@ extern struct lpc_adc lpc_adc;  #define LPC_ADC_STAT_OVERRUN	8  #define LPC_ADC_STAT_ADINT	16 +struct lpc_ct16b { +	vuint32_t	ir;	/* 0x00 */ +	vuint32_t	tcr; +	vuint32_t	tc; +	vuint32_t	pr; + +	vuint32_t	pc;	/* 0x10 */ +	vuint32_t	mcr; +	vuint32_t	mr[4];	/* 0x18 */ +	vuint32_t	ccr;	/* 0x28 */ +	vuint32_t	cr0; + +	vuint32_t	cr1_0;	/* 0x30 (only for ct16b0 */ +	vuint32_t	cr1_1;	/* 0x34 (only for ct16b1 */ +	uint32_t	r38; +	vuint32_t	emr; + +	uint8_t		r40[0x70 - 0x40]; + +	vuint32_t	ctcr;	/* 0x70 */ +	vuint32_t	pwmc; +}; + +extern struct lpc_ct16b	lpc_ct16b0, lpc_ct16b1; + +#define lpc_ct16b0	(*(struct lpc_ct16b *) 0x4000c000) +#define lpc_ct16b1	(*(struct lpc_ct16b *) 0x40010000) + +#define LPC_CT16B_IR_MR0INT	0 +#define LPC_CT16B_IR_MR1INT	1 +#define LPC_CT16B_IR_MR2INT	2 +#define LPC_CT16B_IR_MR3INT	3 +#define LPC_CT16B_IR_CR0INT	4 +#define LPC_CT16B0_IR_CR1INT	6 +#define LPC_CT16B1_IR_CR1INT	5 + +#define LPC_CT16B_TCR_CEN	0 +#define LPC_CT16B_TCR_CRST	1 + +#define LPC_CT16B_MCR_MR0I	0 +#define LPC_CT16B_MCR_MR0R	1 +#define LPC_CT16B_MCR_MR0S	2 +#define LPC_CT16B_MCR_MR1I	3 +#define LPC_CT16B_MCR_MR1R	4 +#define LPC_CT16B_MCR_MR1S	5 +#define LPC_CT16B_MCR_MR2I	6 +#define LPC_CT16B_MCR_MR2R	7 +#define LPC_CT16B_MCR_MR2S	8 +#define LPC_CT16B_MCR_MR3I	9 +#define LPC_CT16B_MCR_MR3R	10 +#define LPC_CT16B_MCR_MR3S	11 + +#define LPC_CT16B_CCR_CAP0RE	0 +#define LPC_CT16B_CCR_CAP0FE	1 +#define LPC_CT16B_CCR_CAP0I	2 +#define LPC_CT16B0_CCR_CAP1RE	6 +#define LPC_CT16B0_CCR_CAP1FE	7 +#define LPC_CT16B0_CCR_CAP1I	8 +#define LPC_CT16B1_CCR_CAP1RE	3 +#define LPC_CT16B1_CCR_CAP1FE	4 +#define LPC_CT16B1_CCR_CAP1I	5 + +#define LPC_CT16B_EMR_EM0	0 +#define LPC_CT16B_EMR_EM1	1 +#define LPC_CT16B_EMR_EM2	2 +#define LPC_CT16B_EMR_EM3	3 +#define LPC_CT16B_EMR_EMC0	4 +#define LPC_CT16B_EMR_EMC1	6 +#define LPC_CT16B_EMR_EMC2	8 +#define LPC_CT16B_EMR_EMC3	10 + +#define LPC_CT16B_EMR_EMC_NOTHING	0 +#define LPC_CT16B_EMR_EMC_CLEAR		1 +#define LPC_CT16B_EMR_EMC_SET		2 +#define LPC_CT16B_EMR_EMC_TOGGLE	3 + +#define LPC_CT16B_CCR_CTM	0 +#define  LPC_CT16B_CCR_CTM_TIMER		0 +#define  LPC_CT16B_CCR_CTM_COUNTER_RISING	1 +#define  LPC_CT16B_CCR_CTM_COUNTER_FALLING	2 +#define  LPC_CT16B_CCR_CTM_COUNTER_BOTH		3 +#define LPC_CT16B_CCR_CIS	2 +#define  LPC_CT16B_CCR_CIS_CAP0			0 +#define  LPC_CT16B0_CCR_CIS_CAP1		2 +#define  LPC_CT16B1_CCR_CIS_CAP1		1 +#define LPC_CT16B_CCR_ENCC	4 +#define LPC_CT16B_CCR_SELCC	5 +#define  LPC_CT16B_CCR_SELCC_RISING_CAP0	0 +#define  LPC_CT16B_CCR_SELCC_FALLING_CAP0	1 +#define  LPC_CT16B0_CCR_SELCC_RISING_CAP1	4 +#define  LPC_CT16B0_CCR_SELCC_FALLING_CAP1	5 +#define  LPC_CT16B1_CCR_SELCC_RISING_CAP1	2 +#define  LPC_CT16B1_CCR_SELCC_FALLING_CAP1	3 +#define LPC_CT16B_CCR_ + +#define LPC_CT16B_PWMC_PWMEN0	0 +#define LPC_CT16B_PWMC_PWMEN1	1 +#define LPC_CT16B_PWMC_PWMEN2	2 +#define LPC_CT16B_PWMC_PWMEN3	3 +  struct lpc_ct32b {  	vuint32_t	ir;	/* 0x00 */  	vuint32_t	tcr;  	vuint32_t	tc;  	vuint32_t	pr; -	 +  	vuint32_t	pc;	/* 0x10 */  	vuint32_t	mcr;  	vuint32_t	mr[4];	/* 0x18 */  	vuint32_t	ccr;	/* 0x28 */  	vuint32_t	cr0; -	 +  	vuint32_t	cr1_0;	/* 0x30 (only for ct32b0 */  	vuint32_t	cr1_1;	/* 0x34 (only for ct32b1 */  	uint32_t	r38; diff --git a/src/lpc/registers.ld b/src/lpc/registers.ld index a523c39c..61dd9e70 100644 --- a/src/lpc/registers.ld +++ b/src/lpc/registers.ld @@ -1,6 +1,8 @@  lpc_usb_sram	= 0x20004000;  lpc_usb_endpoint = 0x20004700;  lpc_usart	= 0x40008000; +lpc_ct16b0	= 0x4000c000; +lpc_ct16b1	= 0x40010000;  lpc_ct32b0	= 0x40014000;  lpc_ct32b1	= 0x40018000;  lpc_adc		= 0x4001c000; diff --git a/src/stm/ao_arch.h b/src/stm/ao_arch.h index a6276c5a..f9508b8f 100644 --- a/src/stm/ao_arch.h +++ b/src/stm/ao_arch.h @@ -25,7 +25,9 @@   * STM32L definitions and code fragments for AltOS   */ +#ifndef AO_STACK_SIZE  #define AO_STACK_SIZE	512 +#endif  #define AO_LED_TYPE	uint16_t diff --git a/src/stm/ao_arch_funcs.h b/src/stm/ao_arch_funcs.h index 42f1a2e5..2c017c79 100644 --- a/src/stm/ao_arch_funcs.h +++ b/src/stm/ao_arch_funcs.h @@ -82,6 +82,34 @@ ao_spi_send_fixed(uint8_t value, uint16_t len, uint8_t spi_index);  void  ao_spi_send_sync(void *block, uint16_t len, uint8_t spi_index); +static inline void +ao_spi_send_byte(uint8_t byte, uint8_t spi_index) +{ +	struct stm_spi	*stm_spi; + +	switch (AO_SPI_INDEX(spi_index)) { +	case 0: +		stm_spi = &stm_spi1; +		break; +	case 1: +		stm_spi = &stm_spi2; +		break; +	} + +	stm_spi->cr2 = ((0 << STM_SPI_CR2_TXEIE) | +			(0 << STM_SPI_CR2_RXNEIE) | +			(0 << STM_SPI_CR2_ERRIE) | +			(0 << STM_SPI_CR2_SSOE) | +			(0 << STM_SPI_CR2_TXDMAEN) | +			(0 << STM_SPI_CR2_RXDMAEN)); + +	/* Clear RXNE */ +	(void) stm_spi->dr; + +	while (!(stm_spi->sr & (1 << STM_SPI_SR_TXE))); +	stm_spi->dr = byte; +} +  void  ao_spi_recv(void *block, uint16_t len, uint8_t spi_index); @@ -149,6 +177,11 @@ ao_spi_try_get_mask(struct stm_gpio *reg, uint16_t mask, uint8_t bus, uint32_t s  #define ao_gpio_get(port, bit, pin) stm_gpio_get(port, bit) +#define ao_gpio_set_bits(port, bits) stm_gpio_set_bits(port, bits) + +#define ao_gpio_clr_bits(port, bits) stm_gpio_clr_bits(port, bits); + +  #define ao_enable_output(port,bit,pin,v) do {			\  		ao_enable_port(port);				\  		ao_gpio_set(port, bit, pin, v);			\ @@ -245,12 +278,35 @@ ao_i2c_recv(void *block, uint16_t len, uint8_t i2c_index, uint8_t stop);  void  ao_i2c_init(void); +#if USE_SERIAL_1_SW_FLOW || USE_SERIAL_2_SW_FLOW || USE_SERIAL_3_SW_FLOW +#define HAS_SERIAL_SW_FLOW 1 +#else +#define HAS_SERIAL_SW_FLOW 0 +#endif + +#if USE_SERIAL_1_FLOW && !USE_SERIAL_1_SW_FLOW || USE_SERIAL_2_FLOW && !USE_SERIAL_2_SW_FLOW || USE_SERIAL_3_FLOW && !USE_SERIAL_3_SW_FLOW +#define HAS_SERIAL_HW_FLOW 1 +#else +#define HAS_SERIAL_HW_FLOW 0 +#endif +  /* ao_serial_stm.c */  struct ao_stm_usart {  	struct ao_fifo		rx_fifo;  	struct ao_fifo		tx_fifo;  	struct stm_usart	*reg; -	uint8_t			tx_started; +	uint8_t			tx_running; +	uint8_t			draining; +#if HAS_SERIAL_SW_FLOW +	/* RTS - 0 if we have FIFO space, 1 if not +	 * CTS - 0 if we can send, 0 if not +	 */ +	struct stm_gpio		*gpio_rts; +	struct stm_gpio		*gpio_cts; +	uint8_t			pin_rts; +	uint8_t			pin_cts; +	uint8_t			rts; +#endif  };  #if HAS_SERIAL_1 @@ -359,6 +415,22 @@ static inline void ao_arch_restore_stack(void) {  #define HAS_SAMPLE_PROFILE 0  #endif +#if DEBUG +#define HAS_ARCH_VALIDATE_CUR_STACK	1 + +static inline void +ao_validate_cur_stack(void) +{ +	uint8_t		*psp; + +	asm("mrs %0,psp" : "=&r" (psp)); +	if (ao_cur_task && +	    psp <= ao_cur_task->stack && +	    psp >= ao_cur_task->stack - 256) +		ao_panic(AO_PANIC_STACK); +} +#endif +  #if !HAS_SAMPLE_PROFILE  #define HAS_ARCH_START_SCHEDULER	1 diff --git a/src/stm/ao_serial_stm.c b/src/stm/ao_serial_stm.c index 88f2d029..bf079060 100644 --- a/src/stm/ao_serial_stm.c +++ b/src/stm/ao_serial_stm.c @@ -16,6 +16,7 @@   */  #include <ao.h> +#include <ao_exti.h>  void  ao_debug_out(char c) @@ -26,40 +27,80 @@ ao_debug_out(char c)  	stm_usart1.dr = c;  } -static void +static int  _ao_usart_tx_start(struct ao_stm_usart *usart)  { -	if (!ao_fifo_empty(usart->tx_fifo) && !usart->tx_started) -	{ -		usart->tx_started = 1; -		ao_fifo_remove(usart->tx_fifo, usart->reg->dr); +	if (!ao_fifo_empty(usart->tx_fifo)) { +#if HAS_SERIAL_SW_FLOW +		if (usart->gpio_cts && ao_gpio_get(usart->gpio_cts, usart->pin_cts, foo) == 1) { +			ao_exti_enable(usart->gpio_cts, usart->pin_cts); +			return 0; +		} +#endif +		if (usart->reg->sr & (1 << STM_USART_SR_TXE)) +		{ +			usart->tx_running = 1; +			usart->reg->cr1 |= (1 << STM_USART_CR1_TXEIE) | (1 << STM_USART_CR1_TCIE); +			ao_fifo_remove(usart->tx_fifo, usart->reg->dr); +			ao_wakeup(&usart->tx_fifo); +			return 1; +		}  	} +	return 0;  } +#if HAS_SERIAL_SW_FLOW  static void -ao_usart_isr(struct ao_stm_usart *usart, int stdin) +_ao_usart_cts(struct ao_stm_usart *usart)  { -	uint32_t	sr; - -	sr = usart->reg->sr; -	usart->reg->sr = 0; +	if (_ao_usart_tx_start(usart)) +		ao_exti_disable(usart->gpio_cts, usart->pin_cts); +} +#endif -	if (sr & (1 << STM_USART_SR_RXNE)) { -		char c = usart->reg->dr; -		if (!ao_fifo_full(usart->rx_fifo)) -			ao_fifo_insert(usart->rx_fifo, c); -		ao_wakeup(&usart->rx_fifo); -		if (stdin) -			ao_wakeup(&ao_stdin_ready); +static void +_ao_usart_rx(struct ao_stm_usart *usart, int stdin) +{ +	if (usart->reg->sr & (1 << STM_USART_SR_RXNE)) { +		if (!ao_fifo_full(usart->rx_fifo)) { +			ao_fifo_insert(usart->rx_fifo, usart->reg->dr); +			ao_wakeup(&usart->rx_fifo); +			if (stdin) +				ao_wakeup(&ao_stdin_ready); +#if HAS_SERIAL_SW_FLOW +			/* If the fifo is nearly full, turn off RTS and wait +			 * for it to drain a bunch +			 */ +			if (usart->gpio_rts && ao_fifo_mostly(usart->rx_fifo)) { +				ao_gpio_set(usart->gpio_rts, usart->pin_rts, usart->pin_rts, 1); +				usart->rts = 0; +			} +#endif +		} else { +			usart->reg->cr1 &= ~(1 << STM_USART_CR1_RXNEIE); +		}  	} -	if (sr & (1 << STM_USART_SR_TC)) { -		usart->tx_started = 0; -		_ao_usart_tx_start(usart); -		ao_wakeup(&usart->tx_fifo); +} + +static void +ao_usart_isr(struct ao_stm_usart *usart, int stdin) +{ +	_ao_usart_rx(usart, stdin); + +	if (!_ao_usart_tx_start(usart)) +		usart->reg->cr1 &= ~(1<< STM_USART_CR1_TXEIE); + +	if (usart->reg->sr & (1 << STM_USART_SR_TC)) { +		usart->tx_running = 0; +		usart->reg->cr1 &= ~(1 << STM_USART_CR1_TCIE); +		if (usart->draining) { +			usart->draining = 0; +			ao_wakeup(&usart->tx_fifo); +		}  	}  } -int +static int  _ao_usart_pollchar(struct ao_stm_usart *usart)  {  	int	c; @@ -69,12 +110,23 @@ _ao_usart_pollchar(struct ao_stm_usart *usart)  	else {  		uint8_t	u;  		ao_fifo_remove(usart->rx_fifo,u); +		if ((usart->reg->cr1 & (1 << STM_USART_CR1_RXNEIE)) == 0) { +			if (ao_fifo_barely(usart->rx_fifo)) +				usart->reg->cr1 |= (1 << STM_USART_CR1_RXNEIE); +		} +#if HAS_SERIAL_SW_FLOW +		/* If we've cleared RTS, check if there's space now and turn it back on */ +		if (usart->gpio_rts && usart->rts == 0 && ao_fifo_barely(usart->rx_fifo)) { +			ao_gpio_set(usart->gpio_rts, usart->pin_rts, foo, 0); +			usart->rts = 1; +		} +#endif  		c = u;  	}  	return c;  } -char +static char  ao_usart_getchar(struct ao_stm_usart *usart)  {  	int c; @@ -91,7 +143,7 @@ _ao_usart_sleep_for(struct ao_stm_usart *usart, uint16_t timeout)  	return ao_sleep_for(&usart->rx_fifo, timeout);  } -void +static void  ao_usart_putchar(struct ao_stm_usart *usart, char c)  {  	ao_arch_block_interrupts(); @@ -102,12 +154,14 @@ ao_usart_putchar(struct ao_stm_usart *usart, char c)  	ao_arch_release_interrupts();  } -void +static void  ao_usart_drain(struct ao_stm_usart *usart)  {  	ao_arch_block_interrupts(); -	while (!ao_fifo_empty(usart->tx_fifo)) +	while (!ao_fifo_empty(usart->tx_fifo) || usart->tx_running) { +		usart->draining = 1;  		ao_sleep(&usart->tx_fifo); +	}  	ao_arch_release_interrupts();  } @@ -131,7 +185,7 @@ static const struct {  	},  }; -void +static void  ao_usart_set_speed(struct ao_stm_usart *usart, uint8_t speed)  {  	if (speed > AO_SERIAL_SPEED_115200) @@ -139,7 +193,7 @@ ao_usart_set_speed(struct ao_stm_usart *usart, uint8_t speed)  	usart->reg->brr = ao_usart_speeds[speed].brr;  } -void +static void  ao_usart_init(struct ao_stm_usart *usart)  {  	usart->reg->cr1 = ((0 << STM_USART_CR1_OVER8) | @@ -150,7 +204,7 @@ ao_usart_init(struct ao_stm_usart *usart)  			  (0 << STM_USART_CR1_PS) |  			  (0 << STM_USART_CR1_PEIE) |  			  (0 << STM_USART_CR1_TXEIE) | -			  (1 << STM_USART_CR1_TCIE) | +			  (0 << STM_USART_CR1_TCIE) |  			  (1 << STM_USART_CR1_RXNEIE) |  			  (0 << STM_USART_CR1_IDLEIE) |  			  (1 << STM_USART_CR1_TE) | @@ -185,12 +239,14 @@ ao_usart_init(struct ao_stm_usart *usart)  	ao_usart_set_speed(usart, AO_SERIAL_SPEED_9600);  } -void +#if HAS_SERIAL_HW_FLOW +static void  ao_usart_set_flow(struct ao_stm_usart *usart)  {  	usart->reg->cr3 |= ((1 << STM_USART_CR3_CTSE) |  			    (1 << STM_USART_CR3_RTSE));  } +#endif  #if HAS_SERIAL_1 @@ -231,6 +287,7 @@ ao_serial1_drain(void)  void  ao_serial1_set_speed(uint8_t speed)  { +	ao_usart_drain(&ao_stm_usart1);  	ao_usart_set_speed(&ao_stm_usart1, speed);  }  #endif	/* HAS_SERIAL_1 */ @@ -274,15 +331,25 @@ ao_serial2_drain(void)  void  ao_serial2_set_speed(uint8_t speed)  { +	ao_usart_drain(&ao_stm_usart2);  	ao_usart_set_speed(&ao_stm_usart2, speed);  } + +#if HAS_SERIAL_SW_FLOW +void +ao_serial2_cts(void) +{ +	_ao_usart_cts(&ao_stm_usart2); +} +#endif +  #endif	/* HAS_SERIAL_2 */  #if HAS_SERIAL_3  struct ao_stm_usart ao_stm_usart3; -void stm_usart3_isr(void) { ao_usart_isr(&ao_stm_usart3, USE_SERIAL_2_STDIN); } +void stm_usart3_isr(void) { ao_usart_isr(&ao_stm_usart3, USE_SERIAL_3_STDIN); }  char  ao_serial3_getchar(void) @@ -311,10 +378,39 @@ _ao_serial3_sleep_for(uint16_t timeout)  void  ao_serial3_set_speed(uint8_t speed)  { +	ao_usart_drain(&ao_stm_usart3);  	ao_usart_set_speed(&ao_stm_usart3, speed);  } + +void +ao_serial3_drain(void) +{ +	ao_usart_drain(&ao_stm_usart3); +}  #endif	/* HAS_SERIAL_3 */ +#if HAS_SERIAL_SW_FLOW +static void +ao_serial_set_sw_rts_cts(struct ao_stm_usart *usart, +			 void (*isr)(void), +			 struct stm_gpio *port_rts, +			 int pin_rts, +			 struct stm_gpio *port_cts, +			 int pin_cts) +{ +	/* Pull RTS low to note that there's space in the FIFO +	 */ +	ao_enable_output(port_rts, pin_rts, foo, 0); +	usart->gpio_rts = port_rts; +	usart->pin_rts = pin_rts; +	usart->rts = 1; + +	ao_exti_setup(port_cts, pin_cts, AO_EXTI_MODE_FALLING|AO_EXTI_PRIORITY_MED, isr); +	usart->gpio_cts = port_cts; +	usart->pin_cts = pin_cts; +} +#endif +  void  ao_serial_init(void)  { @@ -367,10 +463,19 @@ ao_serial_init(void)  	stm_afr_set(&stm_gpioa, 2, STM_AFR_AF7);  	stm_afr_set(&stm_gpioa, 3, STM_AFR_AF7); -#if USE_SERIAL_2_FLOW +# if USE_SERIAL_2_FLOW +#  if USE_SERIAL_2_SW_FLOW +	ao_serial_set_sw_rts_cts(&ao_stm_usart2, +				 ao_serial2_cts, +				 SERIAL_2_PORT_RTS, +				 SERIAL_2_PIN_RTS, +				 SERIAL_2_PORT_CTS, +				 SERIAL_2_PIN_CTS); +#  else  	stm_afr_set(&stm_gpioa, 0, STM_AFR_AF7);  	stm_afr_set(&stm_gpioa, 1, STM_AFR_AF7); -#endif +#  endif +# endif  #else  #if SERIAL_2_PD5_PD6  	stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_GPIODEN); @@ -389,7 +494,7 @@ ao_serial_init(void)  	ao_stm_usart2.reg = &stm_usart2;  	ao_usart_init(&ao_stm_usart2); -#if USE_SERIAL_2_FLOW +#if USE_SERIAL_2_FLOW && !USE_SERIAL_2_SW_FLOW  	ao_usart_set_flow(&ao_stm_usart2);  #endif diff --git a/src/stm/ao_timer.c b/src/stm/ao_timer.c index 8db62e76..91ede84b 100644 --- a/src/stm/ao_timer.c +++ b/src/stm/ao_timer.c @@ -41,6 +41,7 @@ volatile __data uint8_t	ao_data_count;  void stm_systick_isr(void)  { +	ao_validate_cur_stack();  	if (stm_systick.csr & (1 << STM_SYSTICK_CSR_COUNTFLAG)) {  		++ao_tick_count;  #if HAS_TASK_QUEUE diff --git a/src/stm/stm32l.h b/src/stm/stm32l.h index 01afedc6..0b6b2798 100644 --- a/src/stm/stm32l.h +++ b/src/stm/stm32l.h @@ -166,6 +166,16 @@ stm_gpio_set(struct stm_gpio *gpio, int pin, uint8_t value) {  	gpio->bsrr = ((uint32_t) (value ^ 1) << (pin + 16)) | ((uint32_t) value << pin);  } +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; diff --git a/src/stmf0/Makefile-flash.defs b/src/stmf0/Makefile-flash.defs index 706b93ee..29d6ae45 100644 --- a/src/stmf0/Makefile-flash.defs +++ b/src/stmf0/Makefile-flash.defs @@ -39,17 +39,24 @@ LDFLAGS=$(CFLAGS) -L$(TOPDIR)/stmf0 -Wl,-Taltos-loader.ld  PROGNAME=altos-flash  PROG=$(HARDWARE)-$(PROGNAME)-$(VERSION).elf +BIN=$(HARDWARE)-$(PROGNAME)-$(VERSION).bin + +MAKEBIN=$(TOPDIR)/../ao-tools/ao-makebin/ao-makebin +FLASH_ADDR=0x08000000 + +all: $(PROG) $(BIN)  $(PROG): Makefile $(OBJ) altos-loader.ld  	$(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(OBJ) $(LIBS) +$(BIN): $(PROG) +	$(MAKEBIN) --output=$@ --base=$(FLASH_ADDR) $(PROG) +	  ao_product.h: ao-make-product.5c $(TOPDIR)/Version  	$(call quiet,NICKLE,$<) $< -m altusmetrum.org -i $(IDPRODUCT) -p $(PRODUCT) -v $(VERSION) > $@  $(OBJ): $(INC) -all: $(PROG) -  distclean:	clean  clean: diff --git a/src/stmf0/ao_adc_fast.c b/src/stmf0/ao_adc_fast.c index 26e6691c..0a2e2c5c 100644 --- a/src/stmf0/ao_adc_fast.c +++ b/src/stmf0/ao_adc_fast.c @@ -72,7 +72,9 @@ _ao_adc_start(void)  			    (1 << STM_DMA_CCR_MINC) |  			    (0 << STM_DMA_CCR_PINC) |  			    (0 << STM_DMA_CCR_CIRC) | -			    (STM_DMA_CCR_DIR_PER_TO_MEM << STM_DMA_CCR_DIR)); +			    (STM_DMA_CCR_DIR_PER_TO_MEM << STM_DMA_CCR_DIR) | +			    (1 << STM_DMA_CCR_TCIE)); +  	ao_dma_set_isr(STM_DMA_INDEX(STM_DMA_CHANNEL_ADC_1), ao_adc_dma_done);  	ao_dma_start(STM_DMA_INDEX(STM_DMA_CHANNEL_ADC_1)); @@ -83,7 +85,6 @@ void  ao_adc_init(void)  {  	uint32_t	chselr; -	int		i;  	/* Reset ADC */  	stm_rcc.apb2rstr |= (1 << STM_RCC_APB2RSTR_ADCRST); @@ -157,12 +158,13 @@ ao_adc_init(void)  	/* Shortest sample time */  	stm_adc.smpr = STM_ADC_SMPR_SMP_1_5 << STM_ADC_SMPR_SMP; +	/* Turn off enable and start */ +	stm_adc.cr &= ~((1 << STM_ADC_CR_ADEN) | (1 << STM_ADC_CR_ADSTART)); +  	/* Calibrate */  	stm_adc.cr |= (1 << STM_ADC_CR_ADCAL); -	for (i = 0; i < 0xf000; i++) { -		if ((stm_adc.cr & (1 << STM_ADC_CR_ADCAL)) == 0) -			break; -	} +	while ((stm_adc.cr & (1 << STM_ADC_CR_ADCAL)) != 0) +		;  	/* Enable */  	stm_adc.cr |= (1 << STM_ADC_CR_ADEN); diff --git a/src/stmf0/ao_arch.h b/src/stmf0/ao_arch.h index 6ee71ef9..2597cadc 100644 --- a/src/stmf0/ao_arch.h +++ b/src/stmf0/ao_arch.h @@ -25,7 +25,9 @@   * STM32F0 definitions and code fragments for AltOS   */ +#ifndef AO_STACK_SIZE  #define AO_STACK_SIZE	512 +#endif  #define AO_LED_TYPE	uint16_t @@ -115,6 +117,7 @@ extern const uint32_t ao_radio_cal;  #define AO_PCLK1	(AO_HCLK / AO_APB1_PRESCALER)  #define AO_PCLK2	(AO_HCLK / AO_APB2_PRESCALER)  #define AO_SYSTICK	(AO_HCLK) +#define AO_PANIC_DELAY_SCALE  (AO_SYSCLK / 12000000)  #if AO_APB1_PRESCALER == 1  #define AO_TIM23467_CLK		AO_PCLK1 @@ -128,10 +131,10 @@ extern const uint32_t ao_radio_cal;  #define AO_TIM91011_CLK		(2 * AO_PCLK2)  #endif -#define AO_STM_NVIC_HIGH_PRIORITY	4 -#define AO_STM_NVIC_CLOCK_PRIORITY	6 -#define AO_STM_NVIC_MED_PRIORITY	8 -#define AO_STM_NVIC_LOW_PRIORITY	10 +#define AO_STM_NVIC_HIGH_PRIORITY	(0 << 6) +#define AO_STM_NVIC_CLOCK_PRIORITY	(1 << 6) +#define AO_STM_NVIC_MED_PRIORITY	(2 << 6) +#define AO_STM_NVIC_LOW_PRIORITY	(3 << 6)  void ao_lcd_stm_init(void); diff --git a/src/stmf0/ao_arch_funcs.h b/src/stmf0/ao_arch_funcs.h index 3db96be2..ccfa3fc7 100644 --- a/src/stmf0/ao_arch_funcs.h +++ b/src/stmf0/ao_arch_funcs.h @@ -18,25 +18,27 @@  #ifndef _AO_ARCH_FUNCS_H_  #define _AO_ARCH_FUNCS_H_ +#include <ao_power.h> +  /* ao_spi_stm.c   */ -/* PCLK is set to 16MHz (HCLK 32MHz, APB prescaler 2) */ +/* PCLK is set to 48MHz (HCLK 48MHz, HPRE 1, PPRE 1) */ -#define AO_SPI_SPEED_8MHz	STM_SPI_CR1_BR_PCLK_2 -#define AO_SPI_SPEED_4MHz	STM_SPI_CR1_BR_PCLK_4 -#define AO_SPI_SPEED_2MHz	STM_SPI_CR1_BR_PCLK_8 -#define AO_SPI_SPEED_1MHz	STM_SPI_CR1_BR_PCLK_16 -#define AO_SPI_SPEED_500kHz	STM_SPI_CR1_BR_PCLK_32 -#define AO_SPI_SPEED_250kHz	STM_SPI_CR1_BR_PCLK_64 -#define AO_SPI_SPEED_125kHz	STM_SPI_CR1_BR_PCLK_128 -#define AO_SPI_SPEED_62500Hz	STM_SPI_CR1_BR_PCLK_256 +#define AO_SPI_SPEED_24MHz	STM_SPI_CR1_BR_PCLK_2 +#define AO_SPI_SPEED_12MHz	STM_SPI_CR1_BR_PCLK_4 +#define AO_SPI_SPEED_6MHz	STM_SPI_CR1_BR_PCLK_8 +#define AO_SPI_SPEED_3MHz	STM_SPI_CR1_BR_PCLK_16 +#define AO_SPI_SPEED_1500kHz	STM_SPI_CR1_BR_PCLK_32 +#define AO_SPI_SPEED_750kHz	STM_SPI_CR1_BR_PCLK_64 +#define AO_SPI_SPEED_375kHz	STM_SPI_CR1_BR_PCLK_128 +#define AO_SPI_SPEED_187500Hz	STM_SPI_CR1_BR_PCLK_256 -#define AO_SPI_SPEED_FAST	AO_SPI_SPEED_8MHz +#define AO_SPI_SPEED_FAST	AO_SPI_SPEED_24MHz  /* Companion bus wants something no faster than 200kHz */ -#define AO_SPI_SPEED_200kHz	AO_SPI_SPEED_125kHz +#define AO_SPI_SPEED_200kHz	AO_SPI_SPEED_187500Hz  #define AO_SPI_CONFIG_1		0x00  #define AO_SPI_1_CONFIG_PA5_PA6_PA7	AO_SPI_CONFIG_1 @@ -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 {				\ @@ -395,6 +413,9 @@ ao_usb_free(uint16_t *buffer);  void  ao_usb_write(uint16_t *buffer, uint16_t len); + +void +ao_usb_write2(uint16_t *buffer, uint16_t len);  #endif /* AO_USB_DIRECTIO */  #endif /* _AO_ARCH_FUNCS_H_ */ diff --git a/src/stmf0/ao_dma_stm.c b/src/stmf0/ao_dma_stm.c index 78fabe18..e90c6bf8 100644 --- a/src/stmf0/ao_dma_stm.c +++ b/src/stmf0/ao_dma_stm.c @@ -28,9 +28,7 @@ static uint8_t ao_dma_allocated[STM_NUM_DMA];  static uint8_t ao_dma_mutex[STM_NUM_DMA];  static uint8_t ao_dma_active; -#define id(ch)		STM_DMA_INDEX(ch) -#define id_mask(id)	(STM_DMA_ISR_MASK << (id)) -#define ch_mask(ch)	id_mask(id(ch)) +#define ch_mask(id)	(STM_DMA_ISR_MASK << STM_DMA_ISR(id))  static void  ao_dma_isr(uint8_t low_index, uint8_t high_index, uint32_t mask) { @@ -41,7 +39,7 @@ ao_dma_isr(uint8_t low_index, uint8_t high_index, uint32_t mask) {  	/* Ack them */  	stm_dma.ifcr = isr;  	for (index = low_index; index <= high_index; index++) { -		if (isr & id_mask(index)) { +		if (isr & ch_mask(index)) {  			if (ao_dma_config[index].isr)  				(*ao_dma_config[index].isr)(index);  			else { @@ -52,9 +50,25 @@ ao_dma_isr(uint8_t low_index, uint8_t high_index, uint32_t mask) {  	}  } -void stm_dma_ch1_isr(void) { ao_dma_isr(id(1), id(1), ch_mask(1)); } -void stm_dma_ch2_3_isr(void) { ao_dma_isr(id(2), id(3), ch_mask(2) | ch_mask(3)); } -void stm_dma1_ch4_5_6_isr(void) { ao_dma_isr(id(4), id(6), ch_mask(4) | ch_mask(5) | ch_mask(6)); } +void stm_dma_ch1_isr(void) { +	ao_dma_isr(STM_DMA_INDEX(1), +		   STM_DMA_INDEX(1), +		   ch_mask(STM_DMA_INDEX(1))); +} + +void stm_dma_ch2_3_isr(void) { +	ao_dma_isr(STM_DMA_INDEX(2), +		   STM_DMA_INDEX(3), +		   ch_mask(STM_DMA_INDEX(2)) | +		   ch_mask(STM_DMA_INDEX(3))); +} + +void stm_dma1_ch4_5_6_isr(void) { +	ao_dma_isr(STM_DMA_INDEX(4), STM_DMA_INDEX(6), +		   ch_mask(STM_DMA_INDEX(4)) | +		   ch_mask(STM_DMA_INDEX(5)) | +		   ch_mask(STM_DMA_INDEX(6))); +}  void  ao_dma_set_transfer(uint8_t 		index, @@ -73,11 +87,12 @@ ao_dma_set_transfer(uint8_t 		index,  		if (ao_dma_active++ == 0)  			stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_DMAEN);  		); -	stm_dma.channel[index].ccr = ccr | (1 << STM_DMA_CCR_TCIE); +	ao_dma_config[index].isr = NULL; +	ao_dma_done[index] = 0;  	stm_dma.channel[index].cndtr = count;  	stm_dma.channel[index].cpar = peripheral;  	stm_dma.channel[index].cmar = memory; -	ao_dma_config[index].isr = NULL; +	stm_dma.channel[index].ccr = ccr;  }  void @@ -89,7 +104,6 @@ ao_dma_set_isr(uint8_t index, void (*isr)(int))  void  ao_dma_start(uint8_t index)  { -	ao_dma_done[index] = 0;  	stm_dma.channel[index].ccr |= (1 << STM_DMA_CCR_EN);  } diff --git a/src/stmf0/ao_exti.h b/src/stmf0/ao_exti.h index ebea224d..192611bd 100644 --- a/src/stmf0/ao_exti.h +++ b/src/stmf0/ao_exti.h @@ -28,7 +28,7 @@  #define AO_EXTI_PIN_NOCONFIGURE	64  void -ao_exti_setup(struct stm_gpio *gpio, uint8_t pin, uint8_t mode, void (*callback)()); +ao_exti_setup(struct stm_gpio *gpio, uint8_t pin, uint8_t mode, void (*callback)(void));  void  ao_exti_set_mode(struct stm_gpio *gpio, uint8_t pin, uint8_t mode); diff --git a/src/stmf0/ao_exti_stm.c b/src/stmf0/ao_exti_stm.c new file mode 100644 index 00000000..910afcf7 --- /dev/null +++ b/src/stmf0/ao_exti_stm.c @@ -0,0 +1,149 @@ +/* + * Copyright © 2016 Keith Packard <keithp@keithp.com> + * + * 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. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include <ao.h> +#include <ao_exti.h> + +static void	(*ao_exti_callback[16])(void); + +uint32_t	ao_last_exti; + +static void ao_exti_range_isr(uint8_t first, uint8_t last, uint16_t mask) { +	uint16_t	pending = (ao_last_exti = stm_exti.pr) & mask; +	uint8_t		pin; +	static uint16_t	last_mask; +	static uint8_t	last_pin; + +	if (pending == last_mask) { +		stm_exti.pr = last_mask; +		(*ao_exti_callback[last_pin])(); +		return; +	} +	stm_exti.pr = pending; +	for (pin = first; pin <= last; pin++) +		if ((pending & ((uint32_t) 1 << pin)) && ao_exti_callback[pin]) { +			last_mask = (1 << pin); +			last_pin = pin; +			(*ao_exti_callback[pin])(); +		} +} + +void stm_exti0_1_isr(void) { ao_exti_range_isr(0, 1, 0x0003); } +void stm_exti2_3_isr(void) { ao_exti_range_isr(2, 3, 0x000c); } +void stm_exti4_15_isr(void) { ao_exti_range_isr(4, 15, 0xfff0); } + +void +ao_exti_setup (struct stm_gpio *gpio, uint8_t pin, uint8_t mode, void (*callback)(void)) { +	uint32_t	mask = 1 << pin; +	uint32_t	pupdr; +	uint8_t		irq; +	uint8_t		prio; + +	ao_exti_callback[pin] = callback; + +	/* configure gpio to interrupt routing */ +	stm_exticr_set(gpio, pin); + +	if (!(mode & AO_EXTI_PIN_NOCONFIGURE)) { +		/* configure pin as input, setting selected pull-up/down mode */ +		stm_moder_set(gpio, pin, STM_MODER_INPUT); +		switch (mode & (AO_EXTI_MODE_PULL_UP|AO_EXTI_MODE_PULL_DOWN)) { +		case 0: +		default: +			pupdr  = STM_PUPDR_NONE; +			break; +		case AO_EXTI_MODE_PULL_UP: +			pupdr = STM_PUPDR_PULL_UP; +			break; +		case AO_EXTI_MODE_PULL_DOWN: +			pupdr = STM_PUPDR_PULL_DOWN; +			break; +		} +		stm_pupdr_set(gpio, pin, pupdr); +	} + +	/* Set interrupt mask and rising/falling mode */ +	stm_exti.imr &= ~mask; +	if (mode & AO_EXTI_MODE_RISING) +		stm_exti.rtsr |= mask; +	else +		stm_exti.rtsr &= ~mask; +	if (mode & AO_EXTI_MODE_FALLING) +		stm_exti.ftsr |= mask; +	else +		stm_exti.ftsr &= ~mask; + +	if (pin <= 1) +		irq = STM_ISR_EXTI0_1_POS; +	else if (pin <= 3) +		irq = STM_ISR_EXTI2_3_POS; +	else +		irq = STM_ISR_EXTI4_15_POS; + +	/* Set priority */ +	prio = AO_STM_NVIC_MED_PRIORITY; +	if (mode & AO_EXTI_PRIORITY_LOW) +		prio = AO_STM_NVIC_LOW_PRIORITY; +	else if (mode & AO_EXTI_PRIORITY_HIGH) +		prio = AO_STM_NVIC_HIGH_PRIORITY; + +	stm_nvic_set_priority(irq, prio); +	stm_nvic_set_enable(irq); +} + +void +ao_exti_set_mode(struct stm_gpio *gpio, uint8_t pin, uint8_t mode) { +	(void) gpio; + +	uint32_t	mask = 1 << pin; + +	if (mode & AO_EXTI_MODE_RISING) +		stm_exti.rtsr |= mask; +	else +		stm_exti.rtsr &= ~mask; +	if (mode & AO_EXTI_MODE_FALLING) +		stm_exti.ftsr |= mask; +	else +		stm_exti.ftsr &= ~mask; +} + +void +ao_exti_set_callback(struct stm_gpio *gpio, uint8_t pin, void (*callback)()) { +	(void) gpio; +	ao_exti_callback[pin] = callback; +} + +void +ao_exti_enable(struct stm_gpio *gpio, uint8_t pin) { +	uint32_t	mask = (1 << pin); +	(void) gpio; +	stm_exti.pr = mask; +	stm_exti.imr |= (1 << pin); +} + +void +ao_exti_disable(struct stm_gpio *gpio, uint8_t pin) { +	uint32_t	mask = (1 << pin); +	(void) gpio; +	stm_exti.imr &= ~mask; +	stm_exti.pr = mask; +} + +void +ao_exti_init(void) +{ +} diff --git a/src/stmf0/ao_gpio.c b/src/stmf0/ao_gpio.c new file mode 100644 index 00000000..c7bf0797 --- /dev/null +++ b/src/stmf0/ao_gpio.c @@ -0,0 +1,71 @@ +/* + * Copyright © 2016 Keith Packard <keithp@keithp.com> + * + * 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. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include <ao.h> + +static void +ao_gpio_suspend(void *arg) +{ +	struct stm_gpio *port = arg; +	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); +} + +static void +ao_gpio_resume(void *arg) +{ +	struct stm_gpio *port = arg; +	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); +} + +struct ao_power	ao_power_gpioa = { +	.suspend = ao_gpio_suspend, +	.resume = ao_gpio_resume, +	.arg = &stm_gpioa +}; + +struct ao_power	ao_power_gpiob = { +	.suspend = ao_gpio_suspend, +	.resume = ao_gpio_resume, +	.arg = &stm_gpiob +}; + +struct ao_power	ao_power_gpioc = { +	.suspend = ao_gpio_suspend, +	.resume = ao_gpio_resume, +	.arg = &stm_gpioc +}; + +struct ao_power	ao_power_gpiof = { +	.suspend = ao_gpio_suspend, +	.resume = ao_gpio_resume, +	.arg = &stm_gpiof +}; + diff --git a/src/stmf0/ao_pwm.c b/src/stmf0/ao_pwm.c new file mode 100644 index 00000000..c1e157f5 --- /dev/null +++ b/src/stmf0/ao_pwm.c @@ -0,0 +1,214 @@ +/* + * Copyright © 2016 Keith Packard <keithp@keithp.com> + * + * 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. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include "ao.h" +#include "ao_pwm.h" + +static uint8_t	pwm_running; + +static uint16_t	pwm_value[NUM_PWM]; + +static void +ao_pwm_up(void) +{ +	if (pwm_running++ == 0) { +		struct stm_tim23	*tim = AO_PWM_TIMER; + +		tim->ccr1 = 0; +		tim->ccr2 = 0; +		tim->ccr3 = 0; +		tim->ccr4 = 0; +		tim->arr = PWM_MAX - 1;	/* turn on the timer */ +		tim->cr1 = ((STM_TIM23_CR1_CKD_1 << STM_TIM23_CR1_CKD) | +			    (0 << STM_TIM23_CR1_ARPE) | +			    (STM_TIM23_CR1_CMS_EDGE << STM_TIM23_CR1_CMS) | +			    (STM_TIM23_CR1_DIR_UP << STM_TIM23_CR1_DIR) | +			    (0 << STM_TIM23_CR1_OPM) | +			    (0 << STM_TIM23_CR1_URS) | +			    (0 << STM_TIM23_CR1_UDIS) | +			    (1 << STM_TIM23_CR1_CEN)); + +		/* Set the timer running */ +		tim->egr = (1 << STM_TIM23_EGR_UG); +	} +} + +static void +ao_pwm_down(void) +{ +	if (--pwm_running == 0) { +		struct stm_tim23	*tim = AO_PWM_TIMER; + +		tim->arr = 0; +		tim->cr1 = ((STM_TIM23_CR1_CKD_1 << STM_TIM23_CR1_CKD) | +			    (0 << STM_TIM23_CR1_ARPE) | +			    (STM_TIM23_CR1_CMS_EDGE << STM_TIM23_CR1_CMS) | +			    (STM_TIM23_CR1_DIR_UP << STM_TIM23_CR1_DIR) | +			    (0 << STM_TIM23_CR1_OPM) | +			    (0 << STM_TIM23_CR1_URS) | +			    (0 << STM_TIM23_CR1_UDIS) | +			    (0 << STM_TIM23_CR1_CEN)); + +		/* Stop the timer */ +		tim->egr = (1 << STM_TIM23_EGR_UG); +	} +} + +void +ao_pwm_set(uint8_t pwm, uint16_t value) +{ +	struct stm_tim23	*tim = AO_PWM_TIMER; +	uint8_t			ch = AO_PWM_0_CH; + +	if (value > PWM_MAX) +		value = PWM_MAX; +	if (value != 0) { +		if (pwm_value[pwm] == 0) +			ao_pwm_up(); +	} +#if NUM_PWM > 1 +	switch (pwm) { +	case 0: +		ch = AO_PWM_0_CH; +		break; +	case 1: +		ch = AO_PWM_0_CH; +		break; +#if NUM_PWM > 2 +	case 2: +		ch = AO_PWM_0_CH; +		break; +#endif +#if NUM_PWM > 3 +	case 3: +		ch = AO_PWM_0_CH; +		break; +#endif +	} +#endif + +	switch (ch) { +	case 1: +		tim->ccr1 = value; +		break; +	case 2: +		tim->ccr2 = value; +		break; +	case 3: +		tim->ccr3 = value; +		break; +	case 4: +		tim->ccr4 = value; +		break; +	} +	if (value == 0) { +		if (pwm_value[pwm] != 0) +			ao_pwm_down(); +	} +	pwm_value[pwm] = value; +} + +static void +ao_pwm_cmd(void) +{ +	uint8_t	ch; +	uint16_t val; + +	ao_cmd_decimal(); +	ch = ao_cmd_lex_u32; +	ao_cmd_decimal(); +	val = ao_cmd_lex_u32; +	if (ao_cmd_status != ao_cmd_success) +		return; + +	printf("Set channel %d to %d\n", ch, val); +	ao_pwm_set(ch, val); +} + +static const struct ao_cmds ao_pwm_cmds[] = { +	{ ao_pwm_cmd,	"P <ch> <val>\0Set PWM ch to val" }, +	{ 0, NULL }, +}; + +void +ao_pwm_init(void) +{ +	struct stm_tim23	*tim = AO_PWM_TIMER; + +	stm_rcc.apb1enr |= (1 << AO_PWM_TIMER_ENABLE); + +	tim->cr1 = 0; +	tim->psc = AO_PWM_TIMER_SCALE - 1; +	tim->cnt = 0; +	tim->ccer = ((1 << STM_TIM23_CCER_CC1E) | +		     (0 << STM_TIM23_CCER_CC1P) | +		     (1 << STM_TIM23_CCER_CC2E) | +		     (0 << STM_TIM23_CCER_CC2P) | +		     (1 << STM_TIM23_CCER_CC3E) | +		     (0 << STM_TIM23_CCER_CC3P) | +		     (1 << STM_TIM23_CCER_CC4E) | +		     (0 << STM_TIM23_CCER_CC4P)); + +	tim->ccmr1 = ((0 << STM_TIM23_CCMR1_OC2CE) | +		      (STM_TIM23_CCMR1_OC2M_PWM_MODE_1 << STM_TIM23_CCMR1_OC2M) | +		      (0 << STM_TIM23_CCMR1_OC2PE) | +		      (0 << STM_TIM23_CCMR1_OC2FE) | +		      (STM_TIM23_CCMR1_CC2S_OUTPUT << STM_TIM23_CCMR1_CC2S) | + +		      (0 << STM_TIM23_CCMR1_OC1CE) | +		      (STM_TIM23_CCMR1_OC1M_PWM_MODE_1 << STM_TIM23_CCMR1_OC1M) | +		      (0 << STM_TIM23_CCMR1_OC1PE) | +		      (0 << STM_TIM23_CCMR1_OC1FE) | +		      (STM_TIM23_CCMR1_CC1S_OUTPUT << STM_TIM23_CCMR1_CC1S)); + + +	tim->ccmr2 = ((0 << STM_TIM23_CCMR2_OC4CE) | +		      (STM_TIM23_CCMR2_OC4M_PWM_MODE_1 << STM_TIM23_CCMR2_OC4M) | +		      (0 << STM_TIM23_CCMR2_OC4PE) | +		      (0 << STM_TIM23_CCMR2_OC4FE) | +		      (STM_TIM23_CCMR2_CC4S_OUTPUT << STM_TIM23_CCMR2_CC4S) | + +		      (0 << STM_TIM23_CCMR2_OC3CE) | +		      (STM_TIM23_CCMR2_OC3M_PWM_MODE_1 << STM_TIM23_CCMR2_OC3M) | +		      (0 << STM_TIM23_CCMR2_OC3PE) | +		      (0 << STM_TIM23_CCMR2_OC3FE) | +		      (STM_TIM23_CCMR2_CC3S_OUTPUT << STM_TIM23_CCMR2_CC3S)); +	tim->egr = 0; + +	tim->sr = 0; +	tim->dier = 0; +	tim->smcr = 0; +	tim->cr2 = ((0 << STM_TIM23_CR2_TI1S) | +		    (STM_TIM23_CR2_MMS_RESET<< STM_TIM23_CR2_MMS) | +		    (0 << STM_TIM23_CR2_CCDS)); + +	stm_afr_set(AO_PWM_0_GPIO, AO_PWM_0_PIN, STM_AFR_AF1); +	stm_ospeedr_set(AO_PWM_0_GPIO, AO_PWM_0_PIN, STM_OSPEEDR_MEDIUM); +#if NUM_PWM > 1 +	stm_afr_set(AO_PWM_1_GPIO, AO_PWM_1_PIN, STM_AFR_AF1); +	stm_ospeedr_set(AO_PWM_1_GPIO, AO_PWM_1_PIN, STM_OSPEEDR_MEDIUM); +#endif +#if NUM_PWM > 2 +	stm_afr_set(AO_PWM_2_GPIO, AO_PWM_2_PIN, STM_AFR_AF1); +	stm_ospeedr_set(AO_PWM_2_GPIO, AO_PWM_2_PIN, STM_OSPEEDR_MEDIUM); +#endif +#if NUM_PWM > 3 +	stm_afr_set(AO_PWM_3_GPIO, AO_PWM_3_PIN, STM_AFR_AF1); +	stm_ospeedr_set(AO_PWM_3_GPIO, AO_PWM_3_PIN, STM_OSPEEDR_MEDIUM); +#endif +	ao_cmd_register(&ao_pwm_cmds[0]); +} diff --git a/src/stmf0/ao_spi_stm.c b/src/stmf0/ao_spi_stm.c new file mode 100644 index 00000000..55bf59d2 --- /dev/null +++ b/src/stmf0/ao_spi_stm.c @@ -0,0 +1,478 @@ +/* + * Copyright © 2016 Keith Packard <keithp@keithp.com> + * + * 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. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include <ao.h> + +struct ao_spi_stm_info { +	uint8_t	miso_dma_index; +	uint8_t mosi_dma_index; +	struct stm_spi *stm_spi; +}; + +static uint8_t		ao_spi_mutex[STM_NUM_SPI]; +static uint8_t		ao_spi_index[STM_NUM_SPI]; + +static const struct ao_spi_stm_info ao_spi_stm_info[STM_NUM_SPI] = { +	{ +		.miso_dma_index = STM_DMA_INDEX(STM_DMA_CHANNEL_SPI1_RX), +		.mosi_dma_index = STM_DMA_INDEX(STM_DMA_CHANNEL_SPI1_TX), +		&stm_spi1 +	}, +	{ +		.miso_dma_index = STM_DMA_INDEX(STM_DMA_CHANNEL_SPI2_RX), +		.mosi_dma_index = STM_DMA_INDEX(STM_DMA_CHANNEL_SPI2_TX), +		&stm_spi2 +	} +}; + +static uint8_t	spi_dev_null; + + + +#define SPI_CR2	((0 << STM_SPI_CR2_LDMA_TX) |				\ +		 (0 << STM_SPI_CR2_LDMA_RX) |				\ +		 (1 << STM_SPI_CR2_FRXTH) |				\ +		 (STM_SPI_CR2_DS_8 << STM_SPI_CR2_DS) |			\ +		 (0 << STM_SPI_CR2_TXEIE) |				\ +		 (0 << STM_SPI_CR2_RXNEIE) |				\ +		 (0 << STM_SPI_CR2_ERRIE) |				\ +		 (STM_SPI_CR2_FRF_MOTOROLA << STM_SPI_CR2_FRF) |	\ +		 (0 << STM_SPI_CR2_NSSP) |				\ +		 (0 << STM_SPI_CR2_SSOE)) + +#define SPI_CR2_DMA	(SPI_CR2 |			\ +			 (1 << STM_SPI_CR2_TXDMAEN) |	\ +			 (1 << STM_SPI_CR2_RXDMAEN)) + +#define SPI_CR2_SYNC	(SPI_CR2 |			\ +			 (0 << STM_SPI_CR2_TXDMAEN) |	\ +			 (0 << STM_SPI_CR2_RXDMAEN)) + +void +ao_spi_send(const void *block, uint16_t len, uint8_t spi_index) +{ +	struct stm_spi *stm_spi = ao_spi_stm_info[AO_SPI_INDEX(spi_index)].stm_spi; +	uint8_t	mosi_dma_index = ao_spi_stm_info[AO_SPI_INDEX(spi_index)].mosi_dma_index; +	uint8_t	miso_dma_index = ao_spi_stm_info[AO_SPI_INDEX(spi_index)].miso_dma_index; + +	/* Set up the transmit DMA to deliver data */ +	ao_dma_set_transfer(mosi_dma_index, +			    &stm_spi->dr, +			    (void *) block, +			    len, +			    (0 << STM_DMA_CCR_MEM2MEM) | +			    (STM_DMA_CCR_PL_MEDIUM << STM_DMA_CCR_PL) | +			    (STM_DMA_CCR_MSIZE_8 << STM_DMA_CCR_MSIZE) | +			    (STM_DMA_CCR_PSIZE_8 << STM_DMA_CCR_PSIZE) | +			    (1 << STM_DMA_CCR_MINC) | +			    (0 << STM_DMA_CCR_PINC) | +			    (0 << STM_DMA_CCR_CIRC) | +			    (STM_DMA_CCR_DIR_MEM_TO_PER << STM_DMA_CCR_DIR) | +			    (0 << STM_DMA_CCR_TCIE)); + +	/* Clear RXNE */ +	(void) stm_spi->dr; + +	/* Set up the receive DMA -- when this is done, we know the SPI unit +	 * is idle. Without this, we'd have to poll waiting for the BSY bit to +	 * be cleared +	 */ +	ao_dma_set_transfer(miso_dma_index, +			    &stm_spi->dr, +			    &spi_dev_null, +			    len, +			    (0 << STM_DMA_CCR_MEM2MEM) | +			    (STM_DMA_CCR_PL_MEDIUM << STM_DMA_CCR_PL) | +			    (STM_DMA_CCR_MSIZE_8 << STM_DMA_CCR_MSIZE) | +			    (STM_DMA_CCR_PSIZE_8 << STM_DMA_CCR_PSIZE) | +			    (0 << STM_DMA_CCR_MINC) | +			    (0 << STM_DMA_CCR_PINC) | +			    (0 << STM_DMA_CCR_CIRC) | +			    (STM_DMA_CCR_DIR_PER_TO_MEM << STM_DMA_CCR_DIR) | +			    (1 << STM_DMA_CCR_TCIE)); + +	stm_spi->cr2 = SPI_CR2_DMA; + +	ao_dma_start(miso_dma_index); +	ao_dma_start(mosi_dma_index); +	ao_arch_critical( +		while (!ao_dma_done[miso_dma_index]) +			ao_sleep(&ao_dma_done[miso_dma_index]); +		); +	ao_dma_done_transfer(mosi_dma_index); +	ao_dma_done_transfer(miso_dma_index); +} + +void +ao_spi_send_fixed(uint8_t value, uint16_t len, uint8_t spi_index) +{ +	struct stm_spi *stm_spi = ao_spi_stm_info[AO_SPI_INDEX(spi_index)].stm_spi; +	uint8_t	mosi_dma_index = ao_spi_stm_info[AO_SPI_INDEX(spi_index)].mosi_dma_index; +	uint8_t	miso_dma_index = ao_spi_stm_info[AO_SPI_INDEX(spi_index)].miso_dma_index; + +	/* Set up the transmit DMA to deliver data */ +	ao_dma_set_transfer(mosi_dma_index, +			    &stm_spi->dr, +			    &value, +			    len, +			    (0 << STM_DMA_CCR_MEM2MEM) | +			    (STM_DMA_CCR_PL_MEDIUM << STM_DMA_CCR_PL) | +			    (STM_DMA_CCR_MSIZE_8 << STM_DMA_CCR_MSIZE) | +			    (STM_DMA_CCR_PSIZE_8 << STM_DMA_CCR_PSIZE) | +			    (0 << STM_DMA_CCR_MINC) | +			    (0 << STM_DMA_CCR_PINC) | +			    (0 << STM_DMA_CCR_CIRC) | +			    (STM_DMA_CCR_DIR_MEM_TO_PER << STM_DMA_CCR_DIR) | +			    (0 << STM_DMA_CCR_TCIE)); + +	/* Clear RXNE */ +	(void) stm_spi->dr; + +	/* Set up the receive DMA -- when this is done, we know the SPI unit +	 * is idle. Without this, we'd have to poll waiting for the BSY bit to +	 * be cleared +	 */ +	ao_dma_set_transfer(miso_dma_index, +			    &stm_spi->dr, +			    &spi_dev_null, +			    len, +			    (0 << STM_DMA_CCR_MEM2MEM) | +			    (STM_DMA_CCR_PL_MEDIUM << STM_DMA_CCR_PL) | +			    (STM_DMA_CCR_MSIZE_8 << STM_DMA_CCR_MSIZE) | +			    (STM_DMA_CCR_PSIZE_8 << STM_DMA_CCR_PSIZE) | +			    (0 << STM_DMA_CCR_MINC) | +			    (0 << STM_DMA_CCR_PINC) | +			    (0 << STM_DMA_CCR_CIRC) | +			    (STM_DMA_CCR_DIR_PER_TO_MEM << STM_DMA_CCR_DIR) | +			    (1 << STM_DMA_CCR_TCIE)); + +	stm_spi->cr2 = SPI_CR2_DMA; +	ao_dma_start(miso_dma_index); +	ao_dma_start(mosi_dma_index); +	ao_arch_critical( +		while (!ao_dma_done[miso_dma_index]) +			ao_sleep(&ao_dma_done[miso_dma_index]); +		); +	ao_dma_done_transfer(mosi_dma_index); +	ao_dma_done_transfer(miso_dma_index); +} + +void +ao_spi_send_sync(void *block, uint16_t len, uint8_t spi_index) +{ +	uint8_t		*b = block; +	struct stm_spi	*stm_spi = ao_spi_stm_info[AO_SPI_INDEX(spi_index)].stm_spi; + +	stm_spi->cr2 = SPI_CR2_SYNC; + +	/* Clear RXNE */ +	(void) stm_spi->dr; + +	while (len--) { +		while (!(stm_spi->sr & (1 << STM_SPI_SR_TXE))); +		stm_spi->dr = *b++; +	} +} + +void +ao_spi_recv(void *block, uint16_t len, uint8_t spi_index) +{ +	struct stm_spi *stm_spi = ao_spi_stm_info[AO_SPI_INDEX(spi_index)].stm_spi; +	uint8_t	mosi_dma_index = ao_spi_stm_info[AO_SPI_INDEX(spi_index)].mosi_dma_index; +	uint8_t	miso_dma_index = ao_spi_stm_info[AO_SPI_INDEX(spi_index)].miso_dma_index; + +	spi_dev_null = 0xff; + +	/* Set up transmit DMA to make the SPI hardware actually run */ +	ao_dma_set_transfer(mosi_dma_index, +			    &stm_spi->dr, +			    &spi_dev_null, +			    len, +			    (0 << STM_DMA_CCR_MEM2MEM) | +			    (STM_DMA_CCR_PL_MEDIUM << STM_DMA_CCR_PL) | +			    (STM_DMA_CCR_MSIZE_8 << STM_DMA_CCR_MSIZE) | +			    (STM_DMA_CCR_PSIZE_8 << STM_DMA_CCR_PSIZE) | +			    (0 << STM_DMA_CCR_MINC) | +			    (0 << STM_DMA_CCR_PINC) | +			    (0 << STM_DMA_CCR_CIRC) | +			    (STM_DMA_CCR_DIR_MEM_TO_PER << STM_DMA_CCR_DIR) | +			    (0 << STM_DMA_CCR_TCIE)); + +	/* Clear RXNE */ +	(void) stm_spi->dr; + +	/* Set up the receive DMA to capture data */ +	ao_dma_set_transfer(miso_dma_index, +			    &stm_spi->dr, +			    block, +			    len, +			    (0 << STM_DMA_CCR_MEM2MEM) | +			    (STM_DMA_CCR_PL_MEDIUM << STM_DMA_CCR_PL) | +			    (STM_DMA_CCR_MSIZE_8 << STM_DMA_CCR_MSIZE) | +			    (STM_DMA_CCR_PSIZE_8 << STM_DMA_CCR_PSIZE) | +			    (1 << STM_DMA_CCR_MINC) | +			    (0 << STM_DMA_CCR_PINC) | +			    (0 << STM_DMA_CCR_CIRC) | +			    (STM_DMA_CCR_DIR_PER_TO_MEM << STM_DMA_CCR_DIR) | +			    (1 << STM_DMA_CCR_TCIE)); + +	stm_spi->cr2 = SPI_CR2_DMA; +	ao_dma_start(miso_dma_index); +	ao_dma_start(mosi_dma_index); + +	/* Wait until the SPI unit is done */ +	ao_arch_critical( +		while (!ao_dma_done[miso_dma_index]) +			ao_sleep(&ao_dma_done[miso_dma_index]); +		); + +	ao_dma_done_transfer(mosi_dma_index); +	ao_dma_done_transfer(miso_dma_index); +} + +void +ao_spi_duplex(void *out, void *in, uint16_t len, uint8_t spi_index) +{ +	struct stm_spi *stm_spi = ao_spi_stm_info[AO_SPI_INDEX(spi_index)].stm_spi; +	uint8_t	mosi_dma_index = ao_spi_stm_info[AO_SPI_INDEX(spi_index)].mosi_dma_index; +	uint8_t	miso_dma_index = ao_spi_stm_info[AO_SPI_INDEX(spi_index)].miso_dma_index; + +	/* Set up transmit DMA to send data */ +	ao_dma_set_transfer(mosi_dma_index, +			    &stm_spi->dr, +			    out, +			    len, +			    (0 << STM_DMA_CCR_MEM2MEM) | +			    (STM_DMA_CCR_PL_MEDIUM << STM_DMA_CCR_PL) | +			    (STM_DMA_CCR_MSIZE_8 << STM_DMA_CCR_MSIZE) | +			    (STM_DMA_CCR_PSIZE_8 << STM_DMA_CCR_PSIZE) | +			    (1 << STM_DMA_CCR_MINC) | +			    (0 << STM_DMA_CCR_PINC) | +			    (0 << STM_DMA_CCR_CIRC) | +			    (STM_DMA_CCR_DIR_MEM_TO_PER << STM_DMA_CCR_DIR) | +			    (0 << STM_DMA_CCR_TCIE)); + +	/* Clear RXNE */ +	(void) stm_spi->dr; + +	/* Set up the receive DMA to capture data */ +	ao_dma_set_transfer(miso_dma_index, +			    &stm_spi->dr, +			    in, +			    len, +			    (0 << STM_DMA_CCR_MEM2MEM) | +			    (STM_DMA_CCR_PL_MEDIUM << STM_DMA_CCR_PL) | +			    (STM_DMA_CCR_MSIZE_8 << STM_DMA_CCR_MSIZE) | +			    (STM_DMA_CCR_PSIZE_8 << STM_DMA_CCR_PSIZE) | +			    (1 << STM_DMA_CCR_MINC) | +			    (0 << STM_DMA_CCR_PINC) | +			    (0 << STM_DMA_CCR_CIRC) | +			    (STM_DMA_CCR_DIR_PER_TO_MEM << STM_DMA_CCR_DIR) | +			    (1 << STM_DMA_CCR_TCIE)); + +	stm_spi->cr2 = SPI_CR2_DMA; +	ao_dma_start(miso_dma_index); +	ao_dma_start(mosi_dma_index); + +	/* Wait until the SPI unit is done */ +	ao_arch_critical( +		while (!ao_dma_done[miso_dma_index]) +			ao_sleep(&ao_dma_done[miso_dma_index]); +		); + +	ao_dma_done_transfer(mosi_dma_index); +	ao_dma_done_transfer(miso_dma_index); +} + +static void +ao_spi_disable_index(uint8_t spi_index) +{ +	/* Disable current config +	 */ +	switch (AO_SPI_INDEX(spi_index)) { +	case STM_SPI_INDEX(1): +		switch (spi_index) { +		case AO_SPI_1_PA5_PA6_PA7: +			stm_gpio_set(&stm_gpioa, 5, 1); +			stm_moder_set(&stm_gpioa, 5, STM_MODER_OUTPUT); +			stm_moder_set(&stm_gpioa, 6, STM_MODER_INPUT); +			stm_moder_set(&stm_gpioa, 7, STM_MODER_OUTPUT); +			break; +		case AO_SPI_1_PB3_PB4_PB5: +			stm_gpio_set(&stm_gpiob, 3, 1); +			stm_moder_set(&stm_gpiob, 3, STM_MODER_OUTPUT); +			stm_moder_set(&stm_gpiob, 4, STM_MODER_INPUT); +			stm_moder_set(&stm_gpiob, 5, STM_MODER_OUTPUT); +			break; +		} +		break; +	case STM_SPI_INDEX(2): +		switch (spi_index) { +		case AO_SPI_2_PB13_PB14_PB15: +			stm_gpio_set(&stm_gpiob, 13, 1); +			stm_moder_set(&stm_gpiob, 13, STM_MODER_OUTPUT); +			stm_moder_set(&stm_gpiob, 14, STM_MODER_INPUT); +			stm_moder_set(&stm_gpiob, 15, STM_MODER_OUTPUT); +			break; +		} +		break; +	} +} + +static void +ao_spi_enable_index(uint8_t spi_index) +{ +	switch (AO_SPI_INDEX(spi_index)) { +	case STM_SPI_INDEX(1): +		switch (spi_index) { +		case AO_SPI_1_PA5_PA6_PA7: +			stm_afr_set(&stm_gpioa, 5, STM_AFR_AF0); +			stm_afr_set(&stm_gpioa, 6, STM_AFR_AF0); +			stm_afr_set(&stm_gpioa, 7, STM_AFR_AF0); +			break; +		case AO_SPI_1_PB3_PB4_PB5: +			stm_afr_set(&stm_gpiob, 3, STM_AFR_AF0); +			stm_afr_set(&stm_gpiob, 4, STM_AFR_AF0); +			stm_afr_set(&stm_gpiob, 5, STM_AFR_AF0); +			break; +		} +		break; +	case STM_SPI_INDEX(2): +		switch (spi_index) { +		case AO_SPI_2_PB13_PB14_PB15: +			stm_afr_set(&stm_gpiob, 13, STM_AFR_AF0); +			stm_afr_set(&stm_gpiob, 14, STM_AFR_AF0); +			stm_afr_set(&stm_gpiob, 15, STM_AFR_AF0); +			break; +		} +		break; +	} +} + +static void +ao_spi_config(uint8_t spi_index, uint32_t speed) +{ +	uint8_t		id = AO_SPI_INDEX(spi_index); +	struct stm_spi	*stm_spi = ao_spi_stm_info[id].stm_spi; + +	stm_spi->cr2 = SPI_CR2; +	stm_spi->cr1 = ((0 << STM_SPI_CR1_BIDIMODE) |			/* Three wire mode */ +			(0 << STM_SPI_CR1_BIDIOE) | +			(0 << STM_SPI_CR1_CRCEN) |			/* CRC disabled */ +			(0 << STM_SPI_CR1_CRCNEXT) | +			(0 << STM_SPI_CR1_CRCL) | +			(0 << STM_SPI_CR1_RXONLY) | +			(1 << STM_SPI_CR1_SSM) |        		/* Software SS handling */ +			(1 << STM_SPI_CR1_SSI) |			/*  ... */ +			(0 << STM_SPI_CR1_LSBFIRST) |			/* Big endian */ +			(1 << STM_SPI_CR1_SPE) |			/* Enable SPI unit */ +			(speed << STM_SPI_CR1_BR) |			/* baud rate to pclk/4 */ +			(1 << STM_SPI_CR1_MSTR) | +			(0 << STM_SPI_CR1_CPOL) |			/* Format 0 */ +			(0 << STM_SPI_CR1_CPHA)); + +	if (spi_index != ao_spi_index[id]) { + +		/* Disable old config +		 */ +		ao_spi_disable_index(ao_spi_index[id]); + +		/* Enable new config +		 */ +		ao_spi_enable_index(spi_index); + +		/* Remember current config +		 */ +		ao_spi_index[id] = spi_index; +	} +} + +uint8_t +ao_spi_try_get(uint8_t spi_index, uint32_t speed, uint8_t task_id) +{ +	uint8_t		id = AO_SPI_INDEX(spi_index); + +	if (!ao_mutex_try(&ao_spi_mutex[id], task_id)) +		return 0; +	ao_spi_config(spi_index, speed); +	return 1; +} + +void +ao_spi_get(uint8_t spi_index, uint32_t speed) +{ +	uint8_t		id = AO_SPI_INDEX(spi_index); +	ao_mutex_get(&ao_spi_mutex[id]); +	ao_spi_config(spi_index, speed); +} + +void +ao_spi_put(uint8_t spi_index) +{ +	uint8_t		id = AO_SPI_INDEX(spi_index); +	struct stm_spi	*stm_spi = ao_spi_stm_info[id].stm_spi; + +	stm_spi->cr1 = 0; +	ao_mutex_put(&ao_spi_mutex[id]); +} + +static void +ao_spi_channel_init(uint8_t spi_index) +{ +	uint8_t		id = AO_SPI_INDEX(spi_index); +	struct stm_spi	*stm_spi = ao_spi_stm_info[id].stm_spi; + +	ao_spi_disable_index(spi_index); + +	stm_spi->cr1 = 0; +	(void) stm_spi->sr; +	stm_spi->cr2 = SPI_CR2_SYNC; +} + +void +ao_spi_init(void) +{ +#if HAS_SPI_1 +# if SPI_1_PA5_PA6_PA7 +	stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_IOPAEN); +	stm_ospeedr_set(&stm_gpioa, 5, SPI_1_OSPEEDR); +	stm_ospeedr_set(&stm_gpioa, 6, SPI_1_OSPEEDR); +	stm_ospeedr_set(&stm_gpioa, 7, SPI_1_OSPEEDR); +# endif +# if SPI_1_PB3_PB4_PB5 +	stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_IOPBEN); +	stm_ospeedr_set(&stm_gpiob, 3, SPI_1_OSPEEDR); +	stm_ospeedr_set(&stm_gpiob, 4, SPI_1_OSPEEDR); +	stm_ospeedr_set(&stm_gpiob, 5, SPI_1_OSPEEDR); +# endif +	stm_rcc.apb2enr |= (1 << STM_RCC_APB2ENR_SPI1EN); +	ao_spi_index[0] = AO_SPI_CONFIG_NONE; +	ao_spi_channel_init(STM_SPI_INDEX(1)); +#endif + +#if HAS_SPI_2 +# if SPI_2_PB10_PB13_PB14 +	stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_IOPBEN); +	stm_ospeedr_set(&stm_gpiob, 13, SPI_2_OSPEEDR); +	stm_ospeedr_set(&stm_gpiob, 14, SPI_2_OSPEEDR); +	stm_ospeedr_set(&stm_gpiob, 15, SPI_2_OSPEEDR); +# endif +	stm_rcc.apb1enr |= (1 << STM_RCC_APB1ENR_SPI2EN); +	ao_spi_index[1] = AO_SPI_CONFIG_NONE; +	ao_spi_channel_init(STM_SPI_INDEX(2)); +#endif +} diff --git a/src/stmf0/ao_timer.c b/src/stmf0/ao_timer.c index 3aae7e55..e5bf04a3 100644 --- a/src/stmf0/ao_timer.c +++ b/src/stmf0/ao_timer.c @@ -50,12 +50,14 @@ void stm_systick_isr(void)  #if AO_DATA_ALL  		if (++ao_data_count == ao_data_interval) {  			ao_data_count = 0; +#if HAS_ADC  #if HAS_FAKE_FLIGHT  			if (ao_fake_flight_active)  				ao_fake_flight_poll();  			else  #endif  				ao_adc_poll(); +#endif  #if (AO_DATA_ALL & ~(AO_DATA_ADC))  			ao_wakeup((void *) &ao_data_count);  #endif @@ -92,6 +94,7 @@ ao_timer_init(void)  #endif +#if AO_HSI48  static void  ao_clock_enable_crs(void)  { @@ -127,15 +130,12 @@ ao_clock_enable_crs(void)  		      (0 << STM_CRS_CR_ERRIE) |  		      (0 << STM_CRS_CR_SYNCWARNIE) |  		      (0 << STM_CRS_CR_SYNCOKIE)); -  } +#endif -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(); @@ -153,15 +153,17 @@ 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 +	uint32_t	cfgr; +#define STM_RCC_CFGR_SWS_TARGET_CLOCK		STM_RCC_CFGR_SWS_PLL +#define STM_RCC_CFGR_SW_TARGET_CLOCK		STM_RCC_CFGR_SW_PLL  #define STM_PLLSRC				AO_HSE -#define STM_RCC_CFGR_PLLSRC_TARGET_CLOCK	1 +#define STM_RCC_CFGR_PLLSRC_TARGET_CLOCK	STM_RCC_CFGR_PLLSRC_HSE  #if AO_HSE_BYPASS  	stm_rcc.cr |= (1 << STM_RCC_CR_HSEBYP); @@ -172,6 +174,33 @@ 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 +	/* Disable the PLL */ +	stm_rcc.cr &= ~(1 << STM_RCC_CR_PLLON); +	while (stm_rcc.cr & (1 << STM_RCC_CR_PLLRDY)) +		asm("nop"); + +	/* PLLVCO to 48MHz (for USB) -> PLLMUL = 3 */ +	cfgr = stm_rcc.cfgr; +	cfgr &= ~(STM_RCC_CFGR_PLLMUL_MASK << STM_RCC_CFGR_PLLMUL); +	cfgr |= (AO_RCC_CFGR_PLLMUL << STM_RCC_CFGR_PLLMUL); + +	/* PLL source */ +	cfgr &= ~(1 << STM_RCC_CFGR_PLLSRC); +	cfgr |= (STM_RCC_CFGR_PLLSRC_TARGET_CLOCK  << STM_RCC_CFGR_PLLSRC); +	stm_rcc.cfgr = cfgr; + +	/* Disable pre divider */ +	stm_rcc.cfgr2 = (STM_RCC_CFGR2_PREDIV_1 << STM_RCC_CFGR2_PREDIV); + +	/* Enable the PLL and wait for it */ +	stm_rcc.cr |= (1 << STM_RCC_CR_PLLON); +	while (!(stm_rcc.cr & (1 << STM_RCC_CR_PLLRDY))) +		asm("nop"); + +#endif +  #endif @@ -196,10 +225,50 @@ ao_clock_init(void)  #define STM_PLLSRC				STM_HSI  #define STM_RCC_CFGR_PLLSRC_TARGET_CLOCK	0  #endif +} + +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  #ifdef STM_PLLSRC -#error No code for PLL initialization yet +	/* USB PLL source */ +	stm_rcc.cfgr3 |= (1 << STM_RCC_CFGR3_USBSW);  #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 */ @@ -228,29 +297,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 */ @@ -264,3 +315,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..253506d5 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 @@ -27,6 +29,10 @@  #error "must define AO_PA11_PA12_RMP"  #endif +#ifndef AO_POWER_MANAGEMENT +#define AO_POWER_MANAGEMENT	0 +#endif +  #ifndef USE_USB_STDIO  #define USE_USB_STDIO	1  #endif @@ -83,23 +89,42 @@ static uint16_t	ao_usb_sram_addr;  static uint16_t	*ao_usb_ep0_tx_buffer;  static uint16_t	*ao_usb_ep0_rx_buffer; +#if AO_USB_HAS_INT  /* Pointer to interrupt buffer in USB memory */  static uint16_t ao_usb_int_tx_offset; +#endif  /* Pointer to bulk data tx/rx buffers in USB memory */ +#if AO_USB_HAS_IN  static uint16_t ao_usb_in_tx_offset;  static uint16_t	*ao_usb_in_tx_buffer; -static uint16_t ao_usb_out_rx_offset; -static uint16_t	*ao_usb_out_rx_buffer;  /* System ram shadow of USB buffer; writing individual bytes is   * too much of a pain (sigh) */  static uint8_t	ao_usb_tx_buffer[AO_USB_IN_SIZE];  static uint8_t	ao_usb_tx_count; +#endif +#if AO_USB_HAS_OUT +static uint16_t ao_usb_out_rx_offset; +static uint16_t	*ao_usb_out_rx_buffer; + +/* System ram shadow of USB buffer; writing individual bytes is + * too much of a pain (sigh) */  static uint8_t	ao_usb_rx_buffer[AO_USB_OUT_SIZE];  static uint8_t	ao_usb_rx_count, ao_usb_rx_pos; +#endif +#if AO_USB_HAS_IN2 +static uint16_t ao_usb_in2_tx_offset; +static uint16_t *ao_usb_in2_tx_buffer; + +/* System ram shadow of USB buffer; writing individual bytes is + * too much of a pain (sigh) */ +static uint8_t	ao_usb_tx2_buffer[AO_USB_IN_SIZE]; +static uint8_t	ao_usb_tx2_count; +#endif +  /*   * End point register indices   */ @@ -108,6 +133,7 @@ static uint8_t	ao_usb_rx_count, ao_usb_rx_pos;  #define AO_USB_INT_EPR		1  #define AO_USB_OUT_EPR		2  #define AO_USB_IN_EPR		3 +#define AO_USB_IN2_EPR		4  /* Marks when we don't need to send an IN packet.   * This happens only when the last IN packet is not full, @@ -122,6 +148,16 @@ static uint8_t	ao_usb_in_flushed;   */  static uint8_t	ao_usb_in_pending; +#if AO_USB_HAS_IN2 +/* Marks when we have delivered an IN packet to the hardware + * and it has not been received yet. ao_sleep on this address + * to wait for it to be delivered. + */ +static uint8_t	ao_usb_in2_pending; +static uint16_t	in2_count; +static uint8_t	ao_usb_in2_flushed; +#endif +  /* Marks when an OUT packet has been received by the hardware   * but not pulled to the shadow buffer.   */ @@ -129,10 +165,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; @@ -338,16 +373,29 @@ ao_usb_alloc_buffers(void)  	ao_usb_ep0_rx_buffer = ao_usb_packet_buffer_addr(ao_usb_sram_addr);  	ao_usb_sram_addr += AO_USB_CONTROL_SIZE; + +#if AO_USB_HAS_INT  	ao_usb_int_tx_offset = ao_usb_sram_addr;  	ao_usb_sram_addr += AO_USB_INT_SIZE; +#endif +#if AO_USB_HAS_OUT  	ao_usb_out_rx_buffer = ao_usb_packet_buffer_addr(ao_usb_sram_addr);  	ao_usb_out_rx_offset = ao_usb_sram_addr;  	ao_usb_sram_addr += AO_USB_OUT_SIZE; +#endif +#if AO_USB_HAS_IN  	ao_usb_in_tx_buffer = ao_usb_packet_buffer_addr(ao_usb_sram_addr);  	ao_usb_in_tx_offset = ao_usb_sram_addr;  	ao_usb_sram_addr += AO_USB_IN_SIZE; +#endif + +#if AO_USB_HAS_IN2 +	ao_usb_in2_tx_buffer = ao_usb_packet_buffer_addr(ao_usb_sram_addr); +	ao_usb_in2_tx_offset = ao_usb_sram_addr; +	ao_usb_sram_addr += AO_USB_IN_SIZE; +#endif  }  static void @@ -396,6 +444,7 @@ ao_usb_set_configuration(void)  {  	debug ("ao_usb_set_configuration\n"); +#if AO_USB_HAS_INT  	/* Set up the INT end point */  	ao_usb_bdt[AO_USB_INT_EPR].single.addr_tx = ao_usb_int_tx_offset;  	ao_usb_bdt[AO_USB_INT_EPR].single.count_tx = 0; @@ -405,7 +454,9 @@ ao_usb_set_configuration(void)  		       STM_USB_EPR_EP_TYPE_INTERRUPT,  		       STM_USB_EPR_STAT_RX_DISABLED,  		       STM_USB_EPR_STAT_TX_NAK); +#endif +#if AO_USB_HAS_OUT  	/* Set up the OUT end point */  	ao_usb_bdt[AO_USB_OUT_EPR].single.addr_rx = ao_usb_out_rx_offset;  	ao_usb_bdt[AO_USB_OUT_EPR].single.count_rx = ((1 << STM_USB_BDT_COUNT_RX_BL_SIZE) | @@ -416,7 +467,9 @@ ao_usb_set_configuration(void)  		       STM_USB_EPR_EP_TYPE_BULK,  		       STM_USB_EPR_STAT_RX_VALID,  		       STM_USB_EPR_STAT_TX_DISABLED); +#endif +#if AO_USB_HAS_IN  	/* Set up the IN end point */  	ao_usb_bdt[AO_USB_IN_EPR].single.addr_tx = ao_usb_in_tx_offset;  	ao_usb_bdt[AO_USB_IN_EPR].single.count_tx = 0; @@ -426,6 +479,19 @@ ao_usb_set_configuration(void)  		       STM_USB_EPR_EP_TYPE_BULK,  		       STM_USB_EPR_STAT_RX_DISABLED,  		       STM_USB_EPR_STAT_TX_NAK); +#endif + +#if AO_USB_HAS_IN2 +	/* Set up the IN2 end point */ +	ao_usb_bdt[AO_USB_IN2_EPR].single.addr_tx = ao_usb_in2_tx_offset; +	ao_usb_bdt[AO_USB_IN2_EPR].single.count_tx = 0; + +	ao_usb_init_ep(AO_USB_IN2_EPR, +		       AO_USB_IN2_EP, +		       STM_USB_EPR_EP_TYPE_BULK, +		       STM_USB_EPR_STAT_RX_DISABLED, +		       STM_USB_EPR_STAT_TX_NAK); +#endif  	ao_usb_running = 1;  #if AO_USB_DIRECTIO @@ -559,6 +625,36 @@ ao_usb_ep0_in_start(uint16_t max)  static struct ao_usb_line_coding ao_usb_line_coding = {115200, 0, 0, 8}; +#if AO_USB_DEVICE_ID_SERIAL +static uint8_t ao_usb_serial[2 + 48]; + +/* Convert a 32-bit value to 8 hexidecimal UCS2 characters */ +static void +hex_to_ucs2(uint32_t in, uint8_t *out) +{ +	int	i; + +	for (i = 28; i >= 0; i -= 4) { +		uint8_t	bits = (in >> i) & 0xf; +		*out++ = ((bits < 10) ? '0' : ('a' - 10)) + bits; +		*out++ = 0; +	} +} + +/* Encode the device ID (96 bits) in hexidecimal to use as a device + * serial number + */ +static void +ao_usb_serial_init(void) +{ +	ao_usb_serial[0] = 50;	/* length */ +	ao_usb_serial[1] = AO_USB_DESC_STRING; +	hex_to_ucs2(stm_device_id.u_id0, ao_usb_serial + 2 + 0); +	hex_to_ucs2(stm_device_id.u_id1, ao_usb_serial + 2 + 16); +	hex_to_ucs2(stm_device_id.u_id2, ao_usb_serial + 2 + 32); +} +#endif +  /* Walk through the list of descriptors and find a match   */  static void @@ -576,6 +672,13 @@ ao_usb_get_descriptor(uint16_t value)  				len = descriptor[2];  			else  				len = descriptor[0]; +#if AO_USB_DEVICE_ID_SERIAL +			/* Slightly hacky - the serial number is string 3 */ +			if (type == AO_USB_DESC_STRING && (value & 0xff) == 3) { +				descriptor = ao_usb_serial; +				len = sizeof (ao_usb_serial); +			} +#endif  			ao_usb_ep0_in_set(descriptor, len);  			break;  		} @@ -686,11 +789,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(); @@ -721,6 +819,25 @@ ao_usb_ep0_handle(uint8_t receive)  	}  } +#if AO_POWER_MANAGEMENT +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(); +} +#endif +  void  stm_usb_isr(void)  { @@ -773,6 +890,16 @@ stm_usb_isr(void)  				ao_wakeup(&ao_usb_in_pending);  			}  			break; +#if AO_USB_HAS_IN2 +		case AO_USB_IN2_EPR: +			++in2_count; +			_tx_dbg1("TX2 ISR", epr); +			if (ao_usb_epr_ctr_tx(epr)) { +				ao_usb_in2_pending = 0; +				ao_wakeup(&ao_usb_in2_pending); +			} +			break; +#endif  		case AO_USB_INT_EPR:  			++int_count;  			if (ao_usb_epr_ctr_tx(epr)) @@ -784,12 +911,22 @@ 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 AO_POWER_MANAGEMENT +	if (istr & (1 << STM_USB_ISTR_SUSP)) { +		debug ("\tsuspend\n"); +		ao_usb_suspend(); +	} +	if (istr & (1 << STM_USB_ISTR_WKUP)) { +		debug ("\twakeup\n"); +		ao_usb_wakeup(); +	} +#endif  } +#if AO_USB_HAS_IN  /* Queue the current IN buffer for transmission */  static void  _ao_usb_in_send(void) @@ -868,7 +1005,90 @@ ao_usb_putchar(char c)  	}  	ao_arch_release_interrupts();  } +#endif + +#if AO_USB_HAS_IN2 +/* Queue the current IN buffer for transmission */ +static void +_ao_usb_in2_send(void) +{ +	_tx_dbg0("in2_send start"); +	debug ("send2 %d\n", ao_usb_tx_count); +	while (ao_usb_in2_pending) +		ao_sleep(&ao_usb_in2_pending); +	ao_usb_in2_pending = 1; +	if (ao_usb_tx2_count != AO_USB_IN_SIZE) +		ao_usb_in2_flushed = 1; +	ao_usb_copy_tx(ao_usb_tx2_buffer, ao_usb_in2_tx_buffer, ao_usb_tx2_count); +	ao_usb_bdt[AO_USB_IN2_EPR].single.addr_tx = ao_usb_in_tx_offset; +	ao_usb_bdt[AO_USB_IN2_EPR].single.count_tx = ao_usb_tx_count; +	ao_usb_tx2_count = 0; +	_ao_usb_set_stat_tx(AO_USB_IN2_EPR, STM_USB_EPR_STAT_TX_VALID); +	_tx_dbg0("in2_send end"); +} + +/* Wait for a free IN buffer. Interrupts are blocked */ +static void +_ao_usb_in2_wait(void) +{ +	for (;;) { +		/* Check if the current buffer is writable */ +		if (ao_usb_tx2_count < AO_USB_IN_SIZE) +			break; + +		_tx_dbg0("in2_wait top"); +		/* Wait for an IN buffer to be ready */ +		while (ao_usb_in2_pending) +			ao_sleep(&ao_usb_in2_pending); +		_tx_dbg0("in_wait bottom"); +	} +} + +void +ao_usb_flush2(void) +{ +	if (!ao_usb_running) +		return; + +	/* Anytime we've sent a character since +	 * the last time we flushed, we'll need +	 * to send a packet -- the only other time +	 * we would send a packet is when that +	 * packet was full, in which case we now +	 * want to send an empty packet +	 */ +	ao_arch_block_interrupts(); +	while (!ao_usb_in2_flushed) { +		_tx_dbg0("flush2 top"); +		_ao_usb_in2_send(); +		_tx_dbg0("flush2 end"); +	} +	ao_arch_release_interrupts(); +} + +void +ao_usb_putchar2(char c) +{ +	if (!ao_usb_running) +		return; + +	ao_arch_block_interrupts(); +	_ao_usb_in2_wait(); +	ao_usb_in2_flushed = 0; +	ao_usb_tx2_buffer[ao_usb_tx2_count++] = (uint8_t) c; + +	/* Send the packet when full */ +	if (ao_usb_tx2_count == AO_USB_IN_SIZE) { +		_tx_dbg0("putchar2 full"); +		_ao_usb_in2_send(); +		_tx_dbg0("putchar2 flushed"); +	} +	ao_arch_release_interrupts(); +} +#endif + +#if AO_USB_HAS_OUT  static void  _ao_usb_out_recv(void)  { @@ -925,6 +1145,7 @@ ao_usb_getchar(void)  	ao_arch_release_interrupts();  	return c;  } +#endif  #if AO_USB_DIRECTIO  uint16_t * @@ -979,6 +1200,43 @@ ao_usb_write(uint16_t *buffer, uint16_t len)  	_ao_usb_set_stat_tx(AO_USB_IN_EPR, STM_USB_EPR_STAT_TX_VALID);  	ao_arch_release_interrupts();  } + +#if AO_USB_HAS_IN2 +void +ao_usb_write2(uint16_t *buffer, uint16_t len) +{ +	ao_arch_block_interrupts(); + +	/* Wait for everything to be ready at the same time */ +	for (;;) { +		/* Make sure USB is connected */ +		if (!ao_usb_running) { +			ao_sleep(&ao_usb_running); +			continue; +		} + +		/* Flush any pending regular I/O */ +		if (ao_usb_tx2_count) { +			_ao_usb_in2_send(); +			continue; +		} + +		/* Wait for an idle IN buffer */ +		if (ao_usb_in2_pending) { +			ao_sleep(&ao_usb_in2_pending); +			continue; +		} +		break; +	} + +	ao_usb_in2_pending = 1; +	ao_usb_in2_flushed = (len != AO_USB_IN_SIZE); +	ao_usb_bdt[AO_USB_IN2_EPR].single.addr_tx = ao_usb_packet_buffer_offset(buffer); +	ao_usb_bdt[AO_USB_IN2_EPR].single.count_tx = len; +	_ao_usb_set_stat_tx(AO_USB_IN2_EPR, STM_USB_EPR_STAT_TX_VALID); +	ao_arch_release_interrupts(); +} +#endif  #endif  void @@ -1050,8 +1308,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) | +			(AO_POWER_MANAGEMENT << STM_USB_CNTR_WKUPM) | +			(AO_POWER_MANAGEMENT << STM_USB_CNTR_SUSPM) |  			(1 << STM_USB_CNTR_RESETM) |  			(0 << STM_USB_CNTR_SOFM) |  			(0 << STM_USB_CNTR_ESOFM) | @@ -1086,7 +1344,7 @@ ao_usb_echo(void)  }  #endif -#if USB_DEBUG +#if USB_STATUS  static void  ao_usb_irq(void)  { @@ -1109,7 +1367,13 @@ ao_usb_init(void)  	/* Set PA11/PA12 remapping bit */  	stm_syscfg.cfgr1 |= (AO_PA11_PA12_RMP << STM_SYSCFG_CFGR1_PA11_PA12_RMP); +#ifndef AO_USB_START_DISABLED  	ao_usb_enable(); +#endif + +#if AO_USB_DEVICE_ID_SERIAL +	ao_usb_serial_init(); +#endif  	debug ("ao_usb_init\n");  	ao_usb_ep0_state = AO_USB_EP0_IDLE; @@ -1119,7 +1383,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 diff --git a/src/stmf0/registers.ld b/src/stmf0/registers.ld index 598fc1af..1f9862b1 100644 --- a/src/stmf0/registers.ld +++ b/src/stmf0/registers.ld @@ -54,4 +54,4 @@ stm_mpu    = 0xe000ed90;  /* calibration data in system memory */  stm_cal = 0x1ffff7b8;  stm_flash_size_04x = 0x1ffff7cc; -stm_device_id = 0x1ff80050; +stm_device_id = 0x1ffff7ac; diff --git a/src/stmf0/stm32f0.h b/src/stmf0/stm32f0.h index ce8ca456..33eb9c88 100644 --- a/src/stmf0/stm32f0.h +++ b/src/stmf0/stm32f0.h @@ -475,6 +475,24 @@ extern struct stm_rcc stm_rcc;  #define STM_RCC_CR2_HSI14RDY		1  #define STM_RCC_CR2_HSI14ON		0 +#define STM_RCC_CFGR2_PREDIV		0 +#define  STM_RCC_CFGR2_PREDIV_1			0x0 +#define  STM_RCC_CFGR2_PREDIV_2			0x1 +#define  STM_RCC_CFGR2_PREDIV_3			0x2 +#define  STM_RCC_CFGR2_PREDIV_4			0x3 +#define  STM_RCC_CFGR2_PREDIV_5			0x4 +#define  STM_RCC_CFGR2_PREDIV_6			0x5 +#define  STM_RCC_CFGR2_PREDIV_7			0x6 +#define  STM_RCC_CFGR2_PREDIV_8			0x7 +#define  STM_RCC_CFGR2_PREDIV_9			0x8 +#define  STM_RCC_CFGR2_PREDIV_10		0x9 +#define  STM_RCC_CFGR2_PREDIV_11		0xa +#define  STM_RCC_CFGR2_PREDIV_12		0xb +#define  STM_RCC_CFGR2_PREDIV_13		0xc +#define  STM_RCC_CFGR2_PREDIV_14		0xd +#define  STM_RCC_CFGR2_PREDIV_15		0xe +#define  STM_RCC_CFGR2_PREDIV_16		0xf +  #define STM_RCC_CFGR3_USART3SW		18  #define STM_RCC_CFGR3_USART2SW		16  #define STM_RCC_CFGR3_ADCSW		8 @@ -795,7 +813,7 @@ isr(tim7)  #define STM_ISR_TSC_POS			8  #define STM_ISR_DMA_CH1_POS		9  #define STM_ISR_DMA_CH2_3_DMA2_CH1_2_POS	10 -#define STM_ISR_DMA_CH44_5_6_7_DMA2_CH3_4_5_POS	11 +#define STM_ISR_DMA_CH4_5_6_7_DMA2_CH3_4_5_POS	11  #define STM_ISR_ADC_COMP_POS		12  #define STM_ISR_TIM1_BRK_UP_TRG_COM_POS	13  #define STM_ISR_TIM1_CC_POS		14 @@ -819,8 +837,11 @@ isr(tim7)  struct stm_syscfg {  	vuint32_t	cfgr1; +	uint32_t	reserved_04;  	vuint32_t	exticr[4];  	vuint32_t	cfgr2; +	uint8_t		reserved_1c[0x80-0x1c]; +	vuint32_t	itline[31];  };  extern struct stm_syscfg stm_syscfg; @@ -858,7 +879,13 @@ extern struct stm_syscfg stm_syscfg;  #define  STM_SYSCFG_CFGR1_MEM_MODE_SRAM		3  #define  STM_SYSCFG_CFGR1_MEM_MODE_MASK		3 -#if 0 +#define STM_SYSCFG_EXTICR_PA		0 +#define STM_SYSCFG_EXTICR_PB		1 +#define STM_SYSCFG_EXTICR_PC		2 +#define STM_SYSCFG_EXTICR_PD		3 +#define STM_SYSCFG_EXTICR_PE		4 +#define STM_SYSCFG_EXTICR_PF		5 +  static inline void  stm_exticr_set(struct stm_gpio *gpio, int pin) {  	uint8_t	reg = pin >> 2; @@ -879,8 +906,6 @@ stm_exticr_set(struct stm_gpio *gpio, int pin) {  	stm_syscfg.exticr[reg] = (stm_syscfg.exticr[reg] & ~(0xf << shift)) | val << shift;  } -#endif -  struct stm_dma_channel {  	vuint32_t	ccr; @@ -890,7 +915,7 @@ struct stm_dma_channel {  	vuint32_t	reserved;  }; -#define STM_NUM_DMA	6 +#define STM_NUM_DMA	5  struct stm_dma {  	vuint32_t		isr; @@ -900,7 +925,7 @@ struct stm_dma {  extern struct stm_dma stm_dma; -/* DMA channels go from 1 to 6, instead of 0 to 5 (sigh) +/* DMA channels go from 1 to 5, instead of 0 to 4 (sigh)   */  #define STM_DMA_INDEX(channel)		((channel) - 1) @@ -1042,7 +1067,7 @@ extern struct stm_spi stm_spi1, stm_spi2, stm_spi3;  #define STM_SPI_CR1_BIDIOE		14  #define STM_SPI_CR1_CRCEN		13  #define STM_SPI_CR1_CRCNEXT		12 -#define STM_SPI_CR1_DFF			11 +#define STM_SPI_CR1_CRCL		11  #define STM_SPI_CR1_RXONLY		10  #define STM_SPI_CR1_SSM			9  #define STM_SPI_CR1_SSI			8 @@ -1063,17 +1088,43 @@ extern struct stm_spi stm_spi1, stm_spi2, stm_spi3;  #define STM_SPI_CR1_CPOL		1  #define STM_SPI_CR1_CPHA		0 +#define STM_SPI_CR2_LDMA_TX	14 +#define STM_SPI_CR2_LDMA_RX	13 +#define STM_SPI_CR2_FRXTH	12 +#define STM_SPI_CR2_DS		8 +#define  STM_SPI_CR2_DS_4		0x3 +#define  STM_SPI_CR2_DS_5		0x4 +#define  STM_SPI_CR2_DS_6		0x5 +#define  STM_SPI_CR2_DS_7		0x6 +#define  STM_SPI_CR2_DS_8		0x7 +#define  STM_SPI_CR2_DS_9		0x8 +#define  STM_SPI_CR2_DS_10		0x9 +#define  STM_SPI_CR2_DS_11		0xa +#define  STM_SPI_CR2_DS_12		0xb +#define  STM_SPI_CR2_DS_13		0xc +#define  STM_SPI_CR2_DS_14		0xd +#define  STM_SPI_CR2_DS_15		0xe +#define  STM_SPI_CR2_DS_16		0xf  #define STM_SPI_CR2_TXEIE	7  #define STM_SPI_CR2_RXNEIE	6  #define STM_SPI_CR2_ERRIE	5 +#define STM_SPI_CR2_FRF		4 +# define STM_SPI_CR2_FRF_MOTOROLA	0 +# define STM_SPI_CR2_FRF_TI		1 +#define STM_SPI_CR2_NSSP	3  #define STM_SPI_CR2_SSOE	2  #define STM_SPI_CR2_TXDMAEN	1  #define STM_SPI_CR2_RXDMAEN	0 +#define STM_SPI_SR_FTLVL	11 +#define STM_SPI_SR_FRLVL	9 +#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 @@ -1293,7 +1344,7 @@ extern struct stm_i2c stm_i2c1, stm_i2c2;  #define STM_I2C_CCR_CCR		0  #define  STM_I2C_CCR_MASK	0x7ff -struct stm_tim234 { +struct stm_tim23 {  	vuint32_t	cr1;  	vuint32_t	cr2;  	vuint32_t	smcr; @@ -1318,204 +1369,205 @@ struct stm_tim234 {  	uint32_t	reserved_44;  	vuint32_t	dcr;  	vuint32_t	dmar; - -	uint32_t	reserved_50;  }; -extern struct stm_tim234 stm_tim2, stm_tim3, stm_tim4; - -#define STM_TIM234_CR1_CKD	8 -#define  STM_TIM234_CR1_CKD_1		0 -#define  STM_TIM234_CR1_CKD_2		1 -#define  STM_TIM234_CR1_CKD_4		2 -#define  STM_TIM234_CR1_CKD_MASK	3 -#define STM_TIM234_CR1_ARPE	7 -#define STM_TIM234_CR1_CMS	5 -#define  STM_TIM234_CR1_CMS_EDGE	0 -#define  STM_TIM234_CR1_CMS_CENTER_1	1 -#define  STM_TIM234_CR1_CMS_CENTER_2	2 -#define  STM_TIM234_CR1_CMS_CENTER_3	3 -#define  STM_TIM234_CR1_CMS_MASK	3 -#define STM_TIM234_CR1_DIR	4 -#define  STM_TIM234_CR1_DIR_UP		0 -#define  STM_TIM234_CR1_DIR_DOWN	1 -#define STM_TIM234_CR1_OPM	3 -#define STM_TIM234_CR1_URS	2 -#define STM_TIM234_CR1_UDIS	1 -#define STM_TIM234_CR1_CEN	0 - -#define STM_TIM234_CR2_TI1S	7 -#define STM_TIM234_CR2_MMS	4 -#define  STM_TIM234_CR2_MMS_RESET		0 -#define  STM_TIM234_CR2_MMS_ENABLE		1 -#define  STM_TIM234_CR2_MMS_UPDATE		2 -#define  STM_TIM234_CR2_MMS_COMPARE_PULSE	3 -#define  STM_TIM234_CR2_MMS_COMPARE_OC1REF	4 -#define  STM_TIM234_CR2_MMS_COMPARE_OC2REF	5 -#define  STM_TIM234_CR2_MMS_COMPARE_OC3REF	6 -#define  STM_TIM234_CR2_MMS_COMPARE_OC4REF	7 -#define  STM_TIM234_CR2_MMS_MASK		7 -#define STM_TIM234_CR2_CCDS	3 - -#define STM_TIM234_SMCR_ETP	15 -#define STM_TIM234_SMCR_ECE	14 -#define STM_TIM234_SMCR_ETPS	12 -#define  STM_TIM234_SMCR_ETPS_OFF		0 -#define  STM_TIM234_SMCR_ETPS_DIV_2	       	1 -#define  STM_TIM234_SMCR_ETPS_DIV_4		2 -#define  STM_TIM234_SMCR_ETPS_DIV_8		3 -#define  STM_TIM234_SMCR_ETPS_MASK		3 -#define STM_TIM234_SMCR_ETF	8 -#define  STM_TIM234_SMCR_ETF_NONE		0 -#define  STM_TIM234_SMCR_ETF_INT_N_2		1 -#define  STM_TIM234_SMCR_ETF_INT_N_4		2 -#define  STM_TIM234_SMCR_ETF_INT_N_8		3 -#define  STM_TIM234_SMCR_ETF_DTS_2_N_6		4 -#define  STM_TIM234_SMCR_ETF_DTS_2_N_8		5 -#define  STM_TIM234_SMCR_ETF_DTS_4_N_6		6 -#define  STM_TIM234_SMCR_ETF_DTS_4_N_8		7 -#define  STM_TIM234_SMCR_ETF_DTS_8_N_6		8 -#define  STM_TIM234_SMCR_ETF_DTS_8_N_8		9 -#define  STM_TIM234_SMCR_ETF_DTS_16_N_5		10 -#define  STM_TIM234_SMCR_ETF_DTS_16_N_6		11 -#define  STM_TIM234_SMCR_ETF_DTS_16_N_8		12 -#define  STM_TIM234_SMCR_ETF_DTS_32_N_5		13 -#define  STM_TIM234_SMCR_ETF_DTS_32_N_6		14 -#define  STM_TIM234_SMCR_ETF_DTS_32_N_8		15 -#define  STM_TIM234_SMCR_ETF_MASK		15 -#define STM_TIM234_SMCR_MSM	7 -#define STM_TIM234_SMCR_TS	4 -#define  STM_TIM234_SMCR_TS_ITR0		0 -#define  STM_TIM234_SMCR_TS_ITR1		1 -#define  STM_TIM234_SMCR_TS_ITR2		2 -#define  STM_TIM234_SMCR_TS_ITR3		3 -#define  STM_TIM234_SMCR_TS_TI1F_ED		4 -#define  STM_TIM234_SMCR_TS_TI1FP1		5 -#define  STM_TIM234_SMCR_TS_TI2FP2		6 -#define  STM_TIM234_SMCR_TS_ETRF		7 -#define  STM_TIM234_SMCR_TS_MASK		7 -#define STM_TIM234_SMCR_OCCS	3 -#define STM_TIM234_SMCR_SMS	0 -#define  STM_TIM234_SMCR_SMS_DISABLE		0 -#define  STM_TIM234_SMCR_SMS_ENCODER_MODE_1	1 -#define  STM_TIM234_SMCR_SMS_ENCODER_MODE_2	2 -#define  STM_TIM234_SMCR_SMS_ENCODER_MODE_3	3 -#define  STM_TIM234_SMCR_SMS_RESET_MODE		4 -#define  STM_TIM234_SMCR_SMS_GATED_MODE		5 -#define  STM_TIM234_SMCR_SMS_TRIGGER_MODE	6 -#define  STM_TIM234_SMCR_SMS_EXTERNAL_CLOCK	7 -#define  STM_TIM234_SMCR_SMS_MASK		7 - -#define STM_TIM234_SR_CC4OF	12 -#define STM_TIM234_SR_CC3OF	11 -#define STM_TIM234_SR_CC2OF	10 -#define STM_TIM234_SR_CC1OF	9 -#define STM_TIM234_SR_TIF	6 -#define STM_TIM234_SR_CC4IF	4 -#define STM_TIM234_SR_CC3IF	3 -#define STM_TIM234_SR_CC2IF	2 -#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_OC2M_SET_HIGH_ON_MATCH	1 -#define  STM_TIM234_CCMR1_OC2M_SET_LOW_ON_MATCH		2 -#define  STM_TIM234_CCMR1_OC2M_TOGGLE			3 -#define  STM_TIM234_CCMR1_OC2M_FORCE_LOW		4 -#define  STM_TIM234_CCMR1_OC2M_FORCE_HIGH		5 -#define  STM_TIM234_CCMR1_OC2M_PWM_MODE_1		6 -#define  STM_TIM234_CCMR1_OC2M_PWM_MODE_2		7 -#define  STM_TIM234_CCMR1_OC2M_MASK			7 -#define STM_TIM234_CCMR1_OC2PE	11 -#define STM_TIM234_CCMR1_OC2FE	10 -#define STM_TIM234_CCMR1_CC2S	8 -#define  STM_TIM234_CCMR1_CC2S_OUTPUT			0 -#define  STM_TIM234_CCMR1_CC2S_INPUT_TI2		1 -#define  STM_TIM234_CCMR1_CC2S_INPUT_TI1		2 -#define  STM_TIM234_CCMR1_CC2S_INPUT_TRC		3 -#define  STM_TIM234_CCMR1_CC2S_MASK			3 - -#define STM_TIM234_CCMR1_OC1CE	7 -#define STM_TIM234_CCMR1_OC1M	4 -#define  STM_TIM234_CCMR1_OC1M_FROZEN			0 -#define  STM_TIM234_CCMR1_OC1M_SET_HIGH_ON_MATCH	1 -#define  STM_TIM234_CCMR1_OC1M_SET_LOW_ON_MATCH		2 -#define  STM_TIM234_CCMR1_OC1M_TOGGLE			3 -#define  STM_TIM234_CCMR1_OC1M_FORCE_LOW		4 -#define  STM_TIM234_CCMR1_OC1M_FORCE_HIGH		5 -#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_OC1FE	2 -#define STM_TIM234_CCMR1_CC1S	0 -#define  STM_TIM234_CCMR1_CC1S_OUTPUT			0 -#define  STM_TIM234_CCMR1_CC1S_INPUT_TI1		1 -#define  STM_TIM234_CCMR1_CC1S_INPUT_TI2		2 -#define  STM_TIM234_CCMR1_CC1S_INPUT_TRC		3 -#define  STM_TIM234_CCMR1_CC1S_MASK			3 - -#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_OC4M_SET_LOW_ON_MATCH		2 -#define  STM_TIM234_CCMR2_OC4M_TOGGLE			3 -#define  STM_TIM234_CCMR2_OC4M_FORCE_LOW		4 -#define  STM_TIM234_CCMR2_OC4M_FORCE_HIGH		5 -#define  STM_TIM234_CCMR2_OC4M_PWM_MODE_1		6 -#define  STM_TIM234_CCMR2_OC4M_PWM_MODE_2		7 -#define  STM_TIM234_CCMR2_OC4M_MASK			7 -#define STM_TIM234_CCMR2_OC4PE	11 -#define STM_TIM234_CCMR2_OC4FE	10 -#define STM_TIM234_CCMR2_CC4S	8 -#define  STM_TIM234_CCMR2_CC4S_OUTPUT			0 -#define  STM_TIM234_CCMR2_CC4S_INPUT_TI4		1 -#define  STM_TIM234_CCMR2_CC4S_INPUT_TI3		2 -#define  STM_TIM234_CCMR2_CC4S_INPUT_TRC		3 -#define  STM_TIM234_CCMR2_CC4S_MASK			3 - -#define STM_TIM234_CCMR2_OC3CE	7 -#define STM_TIM234_CCMR2_OC3M	4 -#define  STM_TIM234_CCMR2_OC3M_FROZEN			0 -#define  STM_TIM234_CCMR2_OC3M_SET_HIGH_ON_MATCH	1 -#define  STM_TIM234_CCMR2_OC3M_SET_LOW_ON_MATCH		2 -#define  STM_TIM234_CCMR2_OC3M_TOGGLE			3 -#define  STM_TIM234_CCMR2_OC3M_FORCE_LOW		4 -#define  STM_TIM234_CCMR2_OC3M_FORCE_HIGH		5 -#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_OC3FE	2 -#define STM_TIM234_CCMR2_CC3S	0 -#define  STM_TIM234_CCMR2_CC3S_OUTPUT			0 -#define  STM_TIM234_CCMR2_CC3S_INPUT_TI3		1 -#define  STM_TIM234_CCMR2_CC3S_INPUT_TI4		2 -#define  STM_TIM234_CCMR2_CC3S_INPUT_TRC		3 -#define  STM_TIM234_CCMR2_CC3S_MASK			3 - -#define STM_TIM234_CCER_CC4NP	15 -#define STM_TIM234_CCER_CC4P	13 -#define STM_TIM234_CCER_CC4E	12 -#define STM_TIM234_CCER_CC3NP	11 -#define STM_TIM234_CCER_CC3P	9 -#define STM_TIM234_CCER_CC3E	8 -#define STM_TIM234_CCER_CC2NP	7 -#define STM_TIM234_CCER_CC2P	5 -#define STM_TIM234_CCER_CC2E	4 -#define STM_TIM234_CCER_CC1NP	3 -#define STM_TIM234_CCER_CC1P	1 -#define STM_TIM234_CCER_CC1E	0 +extern struct stm_tim23 stm_tim2, stm_tim3; + +#define stm_tim3	(*(struct stm_tim23 *) 0x40000400) +#define stm_tim2	(*(struct stm_tim23 *) 0x40000000) + +#define STM_TIM23_CR1_CKD	8 +#define  STM_TIM23_CR1_CKD_1		0 +#define  STM_TIM23_CR1_CKD_2		1 +#define  STM_TIM23_CR1_CKD_4		2 +#define  STM_TIM23_CR1_CKD_MASK	3 +#define STM_TIM23_CR1_ARPE	7 +#define STM_TIM23_CR1_CMS	5 +#define  STM_TIM23_CR1_CMS_EDGE		0 +#define  STM_TIM23_CR1_CMS_CENTER_1	1 +#define  STM_TIM23_CR1_CMS_CENTER_2	2 +#define  STM_TIM23_CR1_CMS_CENTER_3	3 +#define  STM_TIM23_CR1_CMS_MASK		3 +#define STM_TIM23_CR1_DIR	4 +#define  STM_TIM23_CR1_DIR_UP		0 +#define  STM_TIM23_CR1_DIR_DOWN		1 +#define STM_TIM23_CR1_OPM	3 +#define STM_TIM23_CR1_URS	2 +#define STM_TIM23_CR1_UDIS	1 +#define STM_TIM23_CR1_CEN	0 + +#define STM_TIM23_CR2_TI1S	7 +#define STM_TIM23_CR2_MMS	4 +#define  STM_TIM23_CR2_MMS_RESET		0 +#define  STM_TIM23_CR2_MMS_ENABLE		1 +#define  STM_TIM23_CR2_MMS_UPDATE		2 +#define  STM_TIM23_CR2_MMS_COMPARE_PULSE	3 +#define  STM_TIM23_CR2_MMS_COMPARE_OC1REF	4 +#define  STM_TIM23_CR2_MMS_COMPARE_OC2REF	5 +#define  STM_TIM23_CR2_MMS_COMPARE_OC3REF	6 +#define  STM_TIM23_CR2_MMS_COMPARE_OC4REF	7 +#define  STM_TIM23_CR2_MMS_MASK			7 +#define STM_TIM23_CR2_CCDS	3 + +#define STM_TIM23_SMCR_ETP	15 +#define STM_TIM23_SMCR_ECE	14 +#define STM_TIM23_SMCR_ETPS	12 +#define  STM_TIM23_SMCR_ETPS_OFF		0 +#define  STM_TIM23_SMCR_ETPS_DIV_2	       	1 +#define  STM_TIM23_SMCR_ETPS_DIV_4		2 +#define  STM_TIM23_SMCR_ETPS_DIV_8		3 +#define  STM_TIM23_SMCR_ETPS_MASK		3 +#define STM_TIM23_SMCR_ETF	8 +#define  STM_TIM23_SMCR_ETF_NONE		0 +#define  STM_TIM23_SMCR_ETF_INT_N_2		1 +#define  STM_TIM23_SMCR_ETF_INT_N_4		2 +#define  STM_TIM23_SMCR_ETF_INT_N_8		3 +#define  STM_TIM23_SMCR_ETF_DTS_2_N_6		4 +#define  STM_TIM23_SMCR_ETF_DTS_2_N_8		5 +#define  STM_TIM23_SMCR_ETF_DTS_4_N_6		6 +#define  STM_TIM23_SMCR_ETF_DTS_4_N_8		7 +#define  STM_TIM23_SMCR_ETF_DTS_8_N_6		8 +#define  STM_TIM23_SMCR_ETF_DTS_8_N_8		9 +#define  STM_TIM23_SMCR_ETF_DTS_16_N_5		10 +#define  STM_TIM23_SMCR_ETF_DTS_16_N_6		11 +#define  STM_TIM23_SMCR_ETF_DTS_16_N_8		12 +#define  STM_TIM23_SMCR_ETF_DTS_32_N_5		13 +#define  STM_TIM23_SMCR_ETF_DTS_32_N_6		14 +#define  STM_TIM23_SMCR_ETF_DTS_32_N_8		15 +#define  STM_TIM23_SMCR_ETF_MASK		15 +#define STM_TIM23_SMCR_MSM	7 +#define STM_TIM23_SMCR_TS	4 +#define  STM_TIM23_SMCR_TS_ITR0			0 +#define  STM_TIM23_SMCR_TS_ITR1			1 +#define  STM_TIM23_SMCR_TS_ITR2			2 +#define  STM_TIM23_SMCR_TS_ITR3			3 +#define  STM_TIM23_SMCR_TS_TI1F_ED		4 +#define  STM_TIM23_SMCR_TS_TI1FP1		5 +#define  STM_TIM23_SMCR_TS_TI2FP2		6 +#define  STM_TIM23_SMCR_TS_ETRF			7 +#define  STM_TIM23_SMCR_TS_MASK			7 +#define STM_TIM23_SMCR_OCCS	3 +#define STM_TIM23_SMCR_SMS	0 +#define  STM_TIM23_SMCR_SMS_DISABLE		0 +#define  STM_TIM23_SMCR_SMS_ENCODER_MODE_1	1 +#define  STM_TIM23_SMCR_SMS_ENCODER_MODE_2	2 +#define  STM_TIM23_SMCR_SMS_ENCODER_MODE_3	3 +#define  STM_TIM23_SMCR_SMS_RESET_MODE		4 +#define  STM_TIM23_SMCR_SMS_GATED_MODE		5 +#define  STM_TIM23_SMCR_SMS_TRIGGER_MODE	6 +#define  STM_TIM23_SMCR_SMS_EXTERNAL_CLOCK	7 +#define  STM_TIM23_SMCR_SMS_MASK		7 + +#define STM_TIM23_SR_CC4OF	12 +#define STM_TIM23_SR_CC3OF	11 +#define STM_TIM23_SR_CC2OF	10 +#define STM_TIM23_SR_CC1OF	9 +#define STM_TIM23_SR_TIF	6 +#define STM_TIM23_SR_CC4IF	4 +#define STM_TIM23_SR_CC3IF	3 +#define STM_TIM23_SR_CC2IF	2 +#define STM_TIM23_SR_CC1IF	1 +#define STM_TIM23_SR_UIF	0 + +#define STM_TIM23_EGR_TG	6 +#define STM_TIM23_EGR_CC4G	4 +#define STM_TIM23_EGR_CC3G	3 +#define STM_TIM23_EGR_CC2G	2 +#define STM_TIM23_EGR_CC1G	1 +#define STM_TIM23_EGR_UG	0 + +#define STM_TIM23_CCMR1_OC2CE	15 +#define STM_TIM23_CCMR1_OC2M	12 +#define  STM_TIM23_CCMR1_OC2M_FROZEN			0 +#define  STM_TIM23_CCMR1_OC2M_SET_HIGH_ON_MATCH		1 +#define  STM_TIM23_CCMR1_OC2M_SET_LOW_ON_MATCH		2 +#define  STM_TIM23_CCMR1_OC2M_TOGGLE			3 +#define  STM_TIM23_CCMR1_OC2M_FORCE_LOW			4 +#define  STM_TIM23_CCMR1_OC2M_FORCE_HIGH		5 +#define  STM_TIM23_CCMR1_OC2M_PWM_MODE_1		6 +#define  STM_TIM23_CCMR1_OC2M_PWM_MODE_2		7 +#define  STM_TIM23_CCMR1_OC2M_MASK			7 +#define STM_TIM23_CCMR1_OC2PE	11 +#define STM_TIM23_CCMR1_OC2FE	10 +#define STM_TIM23_CCMR1_CC2S	8 +#define  STM_TIM23_CCMR1_CC2S_OUTPUT			0 +#define  STM_TIM23_CCMR1_CC2S_INPUT_TI2			1 +#define  STM_TIM23_CCMR1_CC2S_INPUT_TI1			2 +#define  STM_TIM23_CCMR1_CC2S_INPUT_TRC			3 +#define  STM_TIM23_CCMR1_CC2S_MASK			3 + +#define STM_TIM23_CCMR1_OC1CE	7 +#define STM_TIM23_CCMR1_OC1M	4 +#define  STM_TIM23_CCMR1_OC1M_FROZEN			0 +#define  STM_TIM23_CCMR1_OC1M_SET_HIGH_ON_MATCH		1 +#define  STM_TIM23_CCMR1_OC1M_SET_LOW_ON_MATCH		2 +#define  STM_TIM23_CCMR1_OC1M_TOGGLE			3 +#define  STM_TIM23_CCMR1_OC1M_FORCE_LOW			4 +#define  STM_TIM23_CCMR1_OC1M_FORCE_HIGH		5 +#define  STM_TIM23_CCMR1_OC1M_PWM_MODE_1		6 +#define  STM_TIM23_CCMR1_OC1M_PWM_MODE_2		7 +#define  STM_TIM23_CCMR1_OC1M_MASK			7 +#define STM_TIM23_CCMR1_OC1PE	11 +#define STM_TIM23_CCMR1_OC1FE	2 +#define STM_TIM23_CCMR1_CC1S	0 +#define  STM_TIM23_CCMR1_CC1S_OUTPUT			0 +#define  STM_TIM23_CCMR1_CC1S_INPUT_TI1			1 +#define  STM_TIM23_CCMR1_CC1S_INPUT_TI2			2 +#define  STM_TIM23_CCMR1_CC1S_INPUT_TRC			3 +#define  STM_TIM23_CCMR1_CC1S_MASK			3 + +#define STM_TIM23_CCMR2_OC4CE	15 +#define STM_TIM23_CCMR2_OC4M	12 +#define  STM_TIM23_CCMR2_OC4M_FROZEN			0 +#define  STM_TIM23_CCMR2_OC4M_SET_HIGH_ON_MATCH	1 +#define  STM_TIM23_CCMR2_OC4M_SET_LOW_ON_MATCH		2 +#define  STM_TIM23_CCMR2_OC4M_TOGGLE			3 +#define  STM_TIM23_CCMR2_OC4M_FORCE_LOW			4 +#define  STM_TIM23_CCMR2_OC4M_FORCE_HIGH		5 +#define  STM_TIM23_CCMR2_OC4M_PWM_MODE_1		6 +#define  STM_TIM23_CCMR2_OC4M_PWM_MODE_2		7 +#define  STM_TIM23_CCMR2_OC4M_MASK			7 +#define STM_TIM23_CCMR2_OC4PE	11 +#define STM_TIM23_CCMR2_OC4FE	10 +#define STM_TIM23_CCMR2_CC4S	8 +#define  STM_TIM23_CCMR2_CC4S_OUTPUT			0 +#define  STM_TIM23_CCMR2_CC4S_INPUT_TI4			1 +#define  STM_TIM23_CCMR2_CC4S_INPUT_TI3			2 +#define  STM_TIM23_CCMR2_CC4S_INPUT_TRC			3 +#define  STM_TIM23_CCMR2_CC4S_MASK			3 + +#define STM_TIM23_CCMR2_OC3CE	7 +#define STM_TIM23_CCMR2_OC3M	4 +#define  STM_TIM23_CCMR2_OC3M_FROZEN			0 +#define  STM_TIM23_CCMR2_OC3M_SET_HIGH_ON_MATCH		1 +#define  STM_TIM23_CCMR2_OC3M_SET_LOW_ON_MATCH		2 +#define  STM_TIM23_CCMR2_OC3M_TOGGLE			3 +#define  STM_TIM23_CCMR2_OC3M_FORCE_LOW			4 +#define  STM_TIM23_CCMR2_OC3M_FORCE_HIGH		5 +#define  STM_TIM23_CCMR2_OC3M_PWM_MODE_1		6 +#define  STM_TIM23_CCMR2_OC3M_PWM_MODE_2		7 +#define  STM_TIM23_CCMR2_OC3M_MASK			7 +#define STM_TIM23_CCMR2_OC3PE	11 +#define STM_TIM23_CCMR2_OC3FE	2 +#define STM_TIM23_CCMR2_CC3S	0 +#define  STM_TIM23_CCMR2_CC3S_OUTPUT			0 +#define  STM_TIM23_CCMR2_CC3S_INPUT_TI3			1 +#define  STM_TIM23_CCMR2_CC3S_INPUT_TI4			2 +#define  STM_TIM23_CCMR2_CC3S_INPUT_TRC			3 +#define  STM_TIM23_CCMR2_CC3S_MASK			3 + +#define STM_TIM23_CCER_CC4NP	15 +#define STM_TIM23_CCER_CC4P	13 +#define STM_TIM23_CCER_CC4E	12 +#define STM_TIM23_CCER_CC3NP	11 +#define STM_TIM23_CCER_CC3P	9 +#define STM_TIM23_CCER_CC3E	8 +#define STM_TIM23_CCER_CC2NP	7 +#define STM_TIM23_CCER_CC2P	5 +#define STM_TIM23_CCER_CC2E	4 +#define STM_TIM23_CCER_CC1NP	3 +#define STM_TIM23_CCER_CC1P	1 +#define STM_TIM23_CCER_CC1E	0  struct stm_usb {  	struct { diff --git a/src/telebt-v3.0/.gitignore b/src/telebt-v3.0/.gitignore new file mode 100644 index 00000000..a7d61147 --- /dev/null +++ b/src/telebt-v3.0/.gitignore @@ -0,0 +1,2 @@ +ao_product.h +telebt-*.elf diff --git a/src/telebt-v3.0/ao_pins.h b/src/telebt-v3.0/ao_pins.h index a6a01662..50584940 100644 --- a/src/telebt-v3.0/ao_pins.h +++ b/src/telebt-v3.0/ao_pins.h @@ -52,8 +52,13 @@  #define USE_SERIAL_2_STDIN	1  #define DELAY_SERIAL_2_STDIN	1  #define USE_SERIAL_2_FLOW	1 +#define USE_SERIAL_2_SW_FLOW	1  #define SERIAL_2_PA2_PA3	1  #define SERIAL_2_PD5_PD6	0 +#define SERIAL_2_PORT_RTS	(&stm_gpioa) +#define SERIAL_2_PIN_RTS	0 +#define SERIAL_2_PORT_CTS	(&stm_gpioa) +#define SERIAL_2_PIN_CTS	1  #define HAS_SERIAL_3		0  #define USE_SERIAL_3_STDIN	0 diff --git a/src/telebt-v3.0/ao_telebt.c b/src/telebt-v3.0/ao_telebt.c index 44ee4f3d..1fe06b1a 100644 --- a/src/telebt-v3.0/ao_telebt.c +++ b/src/telebt-v3.0/ao_telebt.c @@ -31,7 +31,6 @@ main(void)  	ao_clock_init();  	ao_task_init(); -	ao_serial_init();  	ao_led_init(LEDS_AVAILABLE);  	ao_led_on(AO_LED_RED);  	ao_timer_init(); diff --git a/src/telefire-v0.1/ao_pins.h b/src/telefire-v0.1/ao_pins.h index 47ae663f..1087c7c9 100644 --- a/src/telefire-v0.1/ao_pins.h +++ b/src/telefire-v0.1/ao_pins.h @@ -39,6 +39,8 @@  #define PACKET_HAS_MASTER	0  #define PACKET_HAS_SLAVE	0 +#define PAD_BOX			0 +  #define AO_LED_CONTINUITY(c)	(1 << ((c) + 2))  #define AO_LED_CONTINUITY_MASK	(0xc)  #define AO_LED_ARMED		0x10 diff --git a/src/telefiretwo-v0.1/.gitignore b/src/telefiretwo-v0.1/.gitignore new file mode 100644 index 00000000..e89f9fd7 --- /dev/null +++ b/src/telefiretwo-v0.1/.gitignore @@ -0,0 +1,2 @@ +telefiretwo-* +ao_product.h diff --git a/src/telefiretwo-v0.1/Makefile b/src/telefiretwo-v0.1/Makefile new file mode 100644 index 00000000..6454d6fd --- /dev/null +++ b/src/telefiretwo-v0.1/Makefile @@ -0,0 +1,89 @@ +# +# TeleFire build file +# + +include ../stm/Makefile.defs + +INC = \ +	ao.h \ +	ao_pins.h \ +	ao_arch.h \ +	ao_arch_funcs.h \ +	ao_pad.h \ +	ao_product.h \ +	ao_radio_spi.h \ +	ao_radio_cmac.h \ +	ao_cc1200_CC1200.h \ +	ao_cc1200.h \ +	stm32l.h +# +# Common AltOS sources +# + +#PROFILE=ao_profile.c +#PROFILE_DEF=-DAO_PROFILE=1 + +ALTOS_SRC = \ +	ao_boot_chain.c \ +	ao_interrupt.c \ +	ao_product.c \ +	ao_romconfig.c \ +	ao_cmd.c \ +	ao_adc_stm.c \ +	ao_data.c \ +	ao_config.c \ +	ao_task.c \ +	ao_led.c \ +	ao_stdio.c \ +	ao_panic.c \ +	ao_timer.c \ +	ao_mutex.c \ +	ao_freq.c \ +	ao_dma_stm.c \ +	ao_spi_stm.c \ +	ao_eeprom_stm.c \ +	ao_usb_stm.c \ +	ao_exti_stm.c \ +	ao_cc1200.c \ +	ao_radio_cmac.c \ +	ao_aes.c \ +	ao_aes_tables.c \ +	ao_pad.c \ +	ao_radio_cmac_cmd.c + +PRODUCT_SRC = \ +	ao_telefiretwo.c + +PRODUCT=TeleFire-v0.1 +PRODUCT_DEF=-DTELEFIRETWO_V_0_1 +IDPRODUCT=0x000f + +CFLAGS = $(PRODUCT_DEF) $(STM_CFLAGS) $(PROFILE_DEF) -Os -g + +PROGNAME = telefiretwo-v0.1 +PROG = $(PROGNAME)-$(VERSION).elf +HEX = $(PROGNAME)-$(VERSION).ihx + +SRC = $(ALTOS_SRC) $(PRODUCT_SRC) +OBJ=$(SRC:.c=.o) + +all: $(PROG) $(HEX) + +$(PROG): Makefile $(OBJ) altos.ld +	$(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(OBJ) $(LIBS) + +$(OBJ): $(INC) + +ao_product.h: ao-make-product.5c ../Version +	$(call quiet,NICKLE,$<) $< -m altusmetrum.org -i $(IDPRODUCT) -p $(PRODUCT) -v $(VERSION) > $@ + +distclean:	clean + +clean: +	rm -f *.o $(PROGNAME)-*.elf $(PROGNAME)-*.ihx +	rm -f ao_product.h + +install: + +uninstall: + diff --git a/src/telefiretwo-v0.1/ao_pins.h b/src/telefiretwo-v0.1/ao_pins.h new file mode 100644 index 00000000..fd840f47 --- /dev/null +++ b/src/telefiretwo-v0.1/ao_pins.h @@ -0,0 +1,211 @@ +/* + * Copyright © 2010 Keith Packard <keithp@keithp.com> + * + * 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. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#ifndef _AO_PINS_H_ +#define _AO_PINS_H_ + +#define HAS_RADIO		1 +#define HAS_RADIO_RATE		1 +#define HAS_TELEMETRY		0 + +#define HAS_FLIGHT		0 +#define HAS_USB			1 +#define HAS_BEEP		0 +#define HAS_GPS			0 +#define HAS_SERIAL_1		0 +#define HAS_ADC			1 +#define HAS_DBG			0 +#define HAS_EEPROM		1 +#define HAS_LOG			0 +#define HAS_PAD			1 +#define USE_INTERNAL_FLASH	1 +#define IGNITE_ON_P0		0 +#define PACKET_HAS_MASTER	0 +#define PACKET_HAS_SLAVE	0 +#define AO_DATA_RING		32 +#define HAS_FIXED_PAD_BOX	1 + +/* 8MHz High speed external crystal */ +#define AO_HSE			8000000 + +/* PLLVCO = 96MHz (so that USB will work) */ +#define AO_PLLMUL		12 +#define AO_RCC_CFGR_PLLMUL	(STM_RCC_CFGR_PLLMUL_12) + +#define AO_CC1200_FOSC		40000000 + +/* SYSCLK = 32MHz (no need to go faster than CPU) */ +#define AO_PLLDIV		3 +#define AO_RCC_CFGR_PLLDIV	(STM_RCC_CFGR_PLLDIV_3) + +/* HCLK = 32MHz (CPU clock) */ +#define AO_AHB_PRESCALER	1 +#define AO_RCC_CFGR_HPRE_DIV	STM_RCC_CFGR_HPRE_DIV_1 + +/* Run APB1 at 16MHz (HCLK/2) */ +#define AO_APB1_PRESCALER	2 +#define AO_RCC_CFGR_PPRE1_DIV	STM_RCC_CFGR_PPRE2_DIV_2 + +/* Run APB2 at 16MHz (HCLK/2) */ +#define AO_APB2_PRESCALER	2 +#define AO_RCC_CFGR_PPRE2_DIV	STM_RCC_CFGR_PPRE2_DIV_2 + +#define HAS_EEPROM		1 +#define USE_INTERNAL_FLASH	1 +#define USE_EEPROM_CONFIG	1 +#define USE_STORAGE_CONFIG	0 +#define HAS_USB			1 +#define HAS_BEEP		0 +#define HAS_RADIO		1 +#define HAS_RADIO_RATE		1 +#define HAS_TELEMETRY		0 +#define HAS_AES			1 + +#define HAS_SPI_1		0 +#define SPI_1_PA5_PA6_PA7	0 +#define SPI_1_PB3_PB4_PB5	0 +#define SPI_1_PE13_PE14_PE15	0 + +#define HAS_SPI_2		1	/* CC1200 */ +#define SPI_2_PB13_PB14_PB15	1 +#define SPI_2_PD1_PD3_PD4	0 +#define SPI_2_GPIO		(&stm_gpiob) +#define SPI_2_SCK		13 +#define SPI_2_MISO		14 +#define SPI_2_MOSI		15 +#define SPI_2_OSPEEDR		STM_OSPEEDR_10MHz + +#define HAS_I2C_1		0 + +#define HAS_I2C_2		0 + +#define PACKET_HAS_SLAVE	0 +#define PACKET_HAS_MASTER	0 + +#define FAST_TIMER_FREQ		10000	/* .1ms for debouncing */ + +/* + * Radio is a cc1200 connected via SPI + */ + +#define AO_RADIO_CAL_DEFAULT 	5695733 + +#define AO_FEC_DEBUG		0 +#define AO_CC1200_SPI_CS_PORT	(&stm_gpioa) +#define AO_CC1200_SPI_CS_PIN	7 +#define AO_CC1200_SPI_BUS	AO_SPI_2_PB13_PB14_PB15 +#define AO_CC1200_SPI		stm_spi2 + +#define AO_CC1200_INT_PORT		(&stm_gpiob) +#define AO_CC1200_INT_PIN		(11) + +#define AO_CC1200_INT_GPIO	2 +#define AO_CC1200_INT_GPIO_IOCFG	CC1200_IOCFG2 + +#define LED_PORT_0		(&stm_gpioa) +#define LED_PORT_1		(&stm_gpiob) + +#define LED_PORT_0_ENABLE	STM_RCC_AHBENR_GPIOAEN +#define LED_PORT_1_ENABLE	STM_RCC_AHBENR_GPIOBEN + +/* Port A, pins 4-6 */ +#define LED_PORT_0_SHIFT	4 +#define LED_PORT_0_MASK		0x7 +#define LED_PIN_GREEN		0 +#define LED_PIN_AMBER		1 +#define LED_PIN_RED		2 +#define AO_LED_RED		(1 << LED_PIN_RED) +#define AO_LED_AMBER		(1 << LED_PIN_AMBER) +#define AO_LED_GREEN		(1 << LED_PIN_GREEN) + +/* Port B, pins 3-5 */ +#define LED_PORT_1_SHIFT	0 +#define LED_PORT_1_MASK		(0x7 << 3) +#define LED_PIN_CONT_1		3 +#define LED_PIN_CONT_0		4 +#define LED_PIN_ARMED		5 + +#define AO_LED_ARMED		(1 << LED_PIN_ARMED) +#define AO_LED_CONTINUITY(c)	(1 << (4 - (c))) +#define AO_LED_CONTINUITY_MASK	(0x3 << 3) + +#define LEDS_AVAILABLE		(LED_PORT_0_MASK|LED_PORT_1_MASK) + +#define SPI_CS_PORT	P1 +#define SPI_CS_SEL	P1SEL +#define SPI_CS_DIR	P1DIR + +#define SPI_CONST	0x00 + +#define AO_PAD_NUM		2 +#define	AO_PAD_PORT		(&stm_gpiob) + +#define AO_PAD_PIN_0		9 +#define AO_PAD_ADC_0		0 + +#define AO_PAD_PIN_1		8 +#define AO_PAD_ADC_1		1 + +#define AO_PAD_ALL_PINS		((1 << AO_PAD_PIN_0) | (1 << AO_PAD_PIN_1)) +#define AO_PAD_ALL_CHANNELS	((1 << 0) | (1 << 1)) + +/* test these values with real igniters */ +#define AO_PAD_RELAY_CLOSED	3524 +#define AO_PAD_NO_IGNITER	16904 +#define AO_PAD_GOOD_IGNITER	22514 + +#define AO_PAD_ADC_PYRO		8 +#define AO_PAD_ADC_BATT		2 + +#define AO_ADC_FIRST_PIN	0 + +#define AO_NUM_ADC		4 + +#define AO_ADC_SQ1		AO_PAD_ADC_0 +#define AO_ADC_SQ2		AO_PAD_ADC_1 +#define AO_ADC_SQ3		AO_PAD_ADC_PYRO +#define AO_ADC_SQ4		AO_PAD_ADC_BATT + +#define AO_PYRO_R_PYRO_SENSE	200 +#define AO_PYRO_R_SENSE_GND	22 + +#define AO_FIRE_R_POWER_FET	0 +#define AO_FIRE_R_FET_SENSE	200 +#define AO_FIRE_R_SENSE_GND	22 + +#define HAS_ADC_TEMP		0 + +struct ao_adc { +	int16_t		sense[AO_PAD_NUM]; +	int16_t		pyro; +	int16_t		batt; +}; + +#define AO_ADC_DUMP(p)							\ +	printf ("tick: %5u 0: %5d 1: %5d pyro: %5d batt %5d\n", \ +		(p)->tick,						\ +		(p)->adc.sense[0],					\ +		(p)->adc.sense[1],					\ +		(p)->adc.pyro,						\ +		(p)->adc.batt) + +#define AO_ADC_PINS	((1 << AO_PAD_ADC_0) | \ +			 (1 << AO_PAD_ADC_1) | \ +			 (1 << AO_PAD_ADC_PYRO) | \ +			 (1 << AO_PAD_ADC_BATT)) + +#endif /* _AO_PINS_H_ */ diff --git a/src/telefiretwo-v0.1/ao_telefiretwo.c b/src/telefiretwo-v0.1/ao_telefiretwo.c new file mode 100644 index 00000000..38629d86 --- /dev/null +++ b/src/telefiretwo-v0.1/ao_telefiretwo.c @@ -0,0 +1,54 @@ +/* + * Copyright © 2012 Keith Packard <keithp@keithp.com> + * + * 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. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include <ao.h> +#include <ao_pad.h> +#include <ao_exti.h> +#include <ao_radio_cmac_cmd.h> + +void +main(void) +{ +	ao_clock_init(); + +	ao_led_init(LEDS_AVAILABLE); + +	ao_task_init(); + +	ao_timer_init(); +	ao_spi_init(); +	ao_dma_init(); +	ao_exti_init(); + +	ao_cmd_init(); + +	ao_adc_init(); + +	ao_eeprom_init(); + +	ao_radio_init(); + +	ao_usb_init(); + +	ao_config_init(); + +	ao_pad_init(); + +//	ao_radio_cmac_cmd_init(); + +	ao_start_scheduler(); +} diff --git a/src/telefiretwo-v0.1/flash-loader/.gitignore b/src/telefiretwo-v0.1/flash-loader/.gitignore new file mode 100644 index 00000000..65fe7eab --- /dev/null +++ b/src/telefiretwo-v0.1/flash-loader/.gitignore @@ -0,0 +1,2 @@ +*.elf +*.ihx diff --git a/src/telefiretwo-v0.1/flash-loader/Makefile b/src/telefiretwo-v0.1/flash-loader/Makefile new file mode 100644 index 00000000..108cd554 --- /dev/null +++ b/src/telefiretwo-v0.1/flash-loader/Makefile @@ -0,0 +1,8 @@ +# +# AltOS flash loader build +# +# + +TOPDIR=../.. +HARDWARE=telefiretwo-v0.1 +include $(TOPDIR)/stm/Makefile-flash.defs diff --git a/src/telefiretwo-v0.1/flash-loader/ao_pins.h b/src/telefiretwo-v0.1/flash-loader/ao_pins.h new file mode 100644 index 00000000..daa9048d --- /dev/null +++ b/src/telefiretwo-v0.1/flash-loader/ao_pins.h @@ -0,0 +1,32 @@ +/* + * Copyright © 2013 Keith Packard <keithp@keithp.com> + * + * 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. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#ifndef _AO_PINS_H_ +#define _AO_PINS_H_ + +/* External crystal at 8MHz */ +#define AO_HSE		8000000 + +#include <ao_flash_stm_pins.h> + +#define AO_BOOT_PIN			1 +#define AO_BOOT_APPLICATION_GPIO	stm_gpiob +#define AO_BOOT_APPLICATION_PIN		6 +#define AO_BOOT_APPLICATION_VALUE	1 +#define AO_BOOT_APPLICATION_MODE	AO_EXTI_MODE_PULL_UP + +#endif /* _AO_PINS_H_ */ diff --git a/src/telefiretwo-v0.2/.gitignore b/src/telefiretwo-v0.2/.gitignore new file mode 100644 index 00000000..e89f9fd7 --- /dev/null +++ b/src/telefiretwo-v0.2/.gitignore @@ -0,0 +1,2 @@ +telefiretwo-* +ao_product.h diff --git a/src/telefiretwo-v0.2/Makefile b/src/telefiretwo-v0.2/Makefile new file mode 100644 index 00000000..30985f9c --- /dev/null +++ b/src/telefiretwo-v0.2/Makefile @@ -0,0 +1,90 @@ +# +# TeleFire build file +# + +include ../stm/Makefile.defs + +INC = \ +	ao.h \ +	ao_pins.h \ +	ao_arch.h \ +	ao_arch_funcs.h \ +	ao_pad.h \ +	ao_product.h \ +	ao_radio_spi.h \ +	ao_radio_cmac.h \ +	ao_cc1200_CC1200.h \ +	ao_cc1200.h \ +	stm32l.h +# +# Common AltOS sources +# + +#PROFILE=ao_profile.c +#PROFILE_DEF=-DAO_PROFILE=1 + +ALTOS_SRC = \ +	ao_boot_chain.c \ +	ao_interrupt.c \ +	ao_product.c \ +	ao_romconfig.c \ +	ao_cmd.c \ +	ao_adc_stm.c \ +	ao_data.c \ +	ao_config.c \ +	ao_task.c \ +	ao_led.c \ +	ao_stdio.c \ +	ao_panic.c \ +	ao_timer.c \ +	ao_mutex.c \ +	ao_freq.c \ +	ao_dma_stm.c \ +	ao_spi_stm.c \ +	ao_beep_stm.c \ +	ao_eeprom_stm.c \ +	ao_usb_stm.c \ +	ao_exti_stm.c \ +	ao_cc1200.c \ +	ao_radio_cmac.c \ +	ao_aes.c \ +	ao_aes_tables.c \ +	ao_pad.c \ +	ao_radio_cmac_cmd.c + +PRODUCT_SRC = \ +	ao_telefiretwo.c + +PRODUCT=TeleFire-v0.2 +PRODUCT_DEF=-DTELEFIRETWO_V_0_2 +IDPRODUCT=0x000f + +CFLAGS = $(PRODUCT_DEF) $(STM_CFLAGS) $(PROFILE_DEF) -Os -g + +PROGNAME = telefiretwo-v0.2 +PROG = $(PROGNAME)-$(VERSION).elf +HEX = $(PROGNAME)-$(VERSION).ihx + +SRC = $(ALTOS_SRC) $(PRODUCT_SRC) +OBJ=$(SRC:.c=.o) + +all: $(PROG) $(HEX) + +$(PROG): Makefile $(OBJ) altos.ld +	$(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(OBJ) $(LIBS) + +$(OBJ): $(INC) + +ao_product.h: ao-make-product.5c ../Version +	$(call quiet,NICKLE,$<) $< -m altusmetrum.org -i $(IDPRODUCT) -p $(PRODUCT) -v $(VERSION) > $@ + +distclean:	clean + +clean: +	rm -f *.o $(PROGNAME)-*.elf $(PROGNAME)-*.ihx +	rm -f ao_product.h + +install: + +uninstall: + diff --git a/src/telefiretwo-v0.2/ao_pins.h b/src/telefiretwo-v0.2/ao_pins.h new file mode 100644 index 00000000..0fddc6df --- /dev/null +++ b/src/telefiretwo-v0.2/ao_pins.h @@ -0,0 +1,210 @@ +/* + * Copyright © 2010 Keith Packard <keithp@keithp.com> + * + * 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. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#ifndef _AO_PINS_H_ +#define _AO_PINS_H_ + +#define HAS_RADIO		1 +#define HAS_RADIO_RATE		1 +#define HAS_TELEMETRY		0 + +#define HAS_FLIGHT		0 +#define HAS_USB			1 +#define HAS_BEEP		1 +#define BEEPER_CHANNEL		4 +#define HAS_GPS			0 +#define HAS_SERIAL_1		0 +#define HAS_ADC			1 +#define HAS_DBG			0 +#define HAS_EEPROM		1 +#define HAS_LOG			0 +#define HAS_PAD			1 +#define USE_INTERNAL_FLASH	1 +#define IGNITE_ON_P0		0 +#define PACKET_HAS_MASTER	0 +#define PACKET_HAS_SLAVE	0 +#define AO_DATA_RING		32 +#define HAS_FIXED_PAD_BOX	1 + +/* 8MHz High speed external crystal */ +#define AO_HSE			8000000 + +/* PLLVCO = 96MHz (so that USB will work) */ +#define AO_PLLMUL		12 +#define AO_RCC_CFGR_PLLMUL	(STM_RCC_CFGR_PLLMUL_12) + +#define AO_CC1200_FOSC		40000000 + +/* SYSCLK = 32MHz (no need to go faster than CPU) */ +#define AO_PLLDIV		3 +#define AO_RCC_CFGR_PLLDIV	(STM_RCC_CFGR_PLLDIV_3) + +/* HCLK = 32MHz (CPU clock) */ +#define AO_AHB_PRESCALER	1 +#define AO_RCC_CFGR_HPRE_DIV	STM_RCC_CFGR_HPRE_DIV_1 + +/* Run APB1 at 16MHz (HCLK/2) */ +#define AO_APB1_PRESCALER	2 +#define AO_RCC_CFGR_PPRE1_DIV	STM_RCC_CFGR_PPRE2_DIV_2 + +/* Run APB2 at 16MHz (HCLK/2) */ +#define AO_APB2_PRESCALER	2 +#define AO_RCC_CFGR_PPRE2_DIV	STM_RCC_CFGR_PPRE2_DIV_2 + +#define HAS_EEPROM		1 +#define USE_INTERNAL_FLASH	1 +#define USE_EEPROM_CONFIG	1 +#define USE_STORAGE_CONFIG	0 +#define HAS_USB			1 +#define HAS_RADIO		1 +#define HAS_RADIO_RATE		1 +#define HAS_TELEMETRY		0 +#define HAS_AES			1 + +#define HAS_SPI_1		0 +#define SPI_1_PA5_PA6_PA7	0 +#define SPI_1_PB3_PB4_PB5	0 +#define SPI_1_PE13_PE14_PE15	0 + +#define HAS_SPI_2		1	/* CC1200 */ +#define SPI_2_PB13_PB14_PB15	1 +#define SPI_2_PD1_PD3_PD4	0 +#define SPI_2_GPIO		(&stm_gpiob) +#define SPI_2_SCK		13 +#define SPI_2_MISO		14 +#define SPI_2_MOSI		15 +#define SPI_2_OSPEEDR		STM_OSPEEDR_10MHz + +#define HAS_I2C_1		0 + +#define HAS_I2C_2		0 + +#define PACKET_HAS_SLAVE	0 +#define PACKET_HAS_MASTER	0 + +#define FAST_TIMER_FREQ		10000	/* .1ms for debouncing */ + +/* + * Radio is a cc1200 connected via SPI + */ + +#define AO_RADIO_CAL_DEFAULT 	5695733 + +#define AO_FEC_DEBUG		0 +#define AO_CC1200_SPI_CS_PORT	(&stm_gpioa) +#define AO_CC1200_SPI_CS_PIN	7 +#define AO_CC1200_SPI_BUS	AO_SPI_2_PB13_PB14_PB15 +#define AO_CC1200_SPI		stm_spi2 + +#define AO_CC1200_INT_PORT		(&stm_gpiob) +#define AO_CC1200_INT_PIN		(11) + +#define AO_CC1200_INT_GPIO	2 +#define AO_CC1200_INT_GPIO_IOCFG	CC1200_IOCFG2 + +#define LED_PORT_0		(&stm_gpioa) +#define LED_PORT_1		(&stm_gpiob) + +#define LED_PORT_0_ENABLE	STM_RCC_AHBENR_GPIOAEN +#define LED_PORT_1_ENABLE	STM_RCC_AHBENR_GPIOBEN + +/* Port A, pins 4-6 */ +#define LED_PORT_0_SHIFT	4 +#define LED_PORT_0_MASK		0x7 +#define LED_PIN_GREEN		0 +#define LED_PIN_AMBER		1 +#define LED_PIN_RED		2 +#define AO_LED_RED		(1 << LED_PIN_RED) +#define AO_LED_AMBER		(1 << LED_PIN_AMBER) +#define AO_LED_GREEN		(1 << LED_PIN_GREEN) + +/* Port B, pins 4-5 */ +#define LED_PORT_1_SHIFT	0 +#define LED_PORT_1_MASK		(0x3 << 4) +#define LED_PIN_CONT_0		4 +#define LED_PIN_ARMED		5 + +#define AO_LED_ARMED		(1 << LED_PIN_ARMED) +#define AO_LED_CONTINUITY(c)	(1 << (4 - (c))) +#define AO_LED_CONTINUITY_MASK	(0x1 << 4) + +#define LEDS_AVAILABLE		(LED_PORT_0_MASK|LED_PORT_1_MASK) + +/* Alarm A */ +#define AO_SIREN +#define AO_SIREN_PORT		(&stm_gpiob) +#define AO_SIREN_PIN		8 + +/* Alarm B */ +#define AO_STROBE +#define AO_STROBE_PORT		(&stm_gpiob) +#define AO_STROBE_PIN		9 + +#define SPI_CONST	0x00 + +#define AO_PAD_NUM		1 +#define	AO_PAD_PORT		(&stm_gpioa) + +#define AO_PAD_PIN_0		1 +#define AO_PAD_ADC_0		0 + +#define AO_PAD_ALL_PINS		((1 << AO_PAD_PIN_0)) +#define AO_PAD_ALL_CHANNELS	((1 << 0)) + +/* test these values with real igniters */ +#define AO_PAD_RELAY_CLOSED	3524 +#define AO_PAD_NO_IGNITER	16904 +#define AO_PAD_GOOD_IGNITER	22514 + +#define AO_PAD_ADC_PYRO		2 +#define AO_PAD_ADC_BATT		8 + +#define AO_ADC_FIRST_PIN	0 + +#define AO_NUM_ADC		3 + +#define AO_ADC_SQ1		AO_PAD_ADC_0 +#define AO_ADC_SQ2		AO_PAD_ADC_PYRO +#define AO_ADC_SQ3		AO_PAD_ADC_BATT + +#define AO_PYRO_R_PYRO_SENSE	200 +#define AO_PYRO_R_SENSE_GND	22 + +#define AO_FIRE_R_POWER_FET	0 +#define AO_FIRE_R_FET_SENSE	200 +#define AO_FIRE_R_SENSE_GND	22 + +#define HAS_ADC_TEMP		0 + +struct ao_adc { +	int16_t		sense[AO_PAD_NUM]; +	int16_t		pyro; +	int16_t		batt; +}; + +#define AO_ADC_DUMP(p)							\ +	printf ("tick: %5u 0: %5d pyro: %5d batt %5d\n", \ +		(p)->tick,						\ +		(p)->adc.sense[0],					\ +		(p)->adc.pyro,						\ +		(p)->adc.batt) + +#define AO_ADC_PINS	((1 << AO_PAD_ADC_0) | \ +			 (1 << AO_PAD_ADC_PYRO) | \ +			 (1 << AO_PAD_ADC_BATT)) + +#endif /* _AO_PINS_H_ */ diff --git a/src/telefiretwo-v0.2/ao_telefiretwo.c b/src/telefiretwo-v0.2/ao_telefiretwo.c new file mode 100644 index 00000000..38629d86 --- /dev/null +++ b/src/telefiretwo-v0.2/ao_telefiretwo.c @@ -0,0 +1,54 @@ +/* + * Copyright © 2012 Keith Packard <keithp@keithp.com> + * + * 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. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include <ao.h> +#include <ao_pad.h> +#include <ao_exti.h> +#include <ao_radio_cmac_cmd.h> + +void +main(void) +{ +	ao_clock_init(); + +	ao_led_init(LEDS_AVAILABLE); + +	ao_task_init(); + +	ao_timer_init(); +	ao_spi_init(); +	ao_dma_init(); +	ao_exti_init(); + +	ao_cmd_init(); + +	ao_adc_init(); + +	ao_eeprom_init(); + +	ao_radio_init(); + +	ao_usb_init(); + +	ao_config_init(); + +	ao_pad_init(); + +//	ao_radio_cmac_cmd_init(); + +	ao_start_scheduler(); +} diff --git a/src/telefiretwo-v0.2/flash-loader/.gitignore b/src/telefiretwo-v0.2/flash-loader/.gitignore new file mode 100644 index 00000000..65fe7eab --- /dev/null +++ b/src/telefiretwo-v0.2/flash-loader/.gitignore @@ -0,0 +1,2 @@ +*.elf +*.ihx diff --git a/src/telefiretwo-v0.2/flash-loader/Makefile b/src/telefiretwo-v0.2/flash-loader/Makefile new file mode 100644 index 00000000..2b029ee0 --- /dev/null +++ b/src/telefiretwo-v0.2/flash-loader/Makefile @@ -0,0 +1,8 @@ +# +# AltOS flash loader build +# +# + +TOPDIR=../.. +HARDWARE=telefiretwo-v0.2 +include $(TOPDIR)/stm/Makefile-flash.defs diff --git a/src/telefiretwo-v0.2/flash-loader/ao_pins.h b/src/telefiretwo-v0.2/flash-loader/ao_pins.h new file mode 100644 index 00000000..daa9048d --- /dev/null +++ b/src/telefiretwo-v0.2/flash-loader/ao_pins.h @@ -0,0 +1,32 @@ +/* + * Copyright © 2013 Keith Packard <keithp@keithp.com> + * + * 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. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#ifndef _AO_PINS_H_ +#define _AO_PINS_H_ + +/* External crystal at 8MHz */ +#define AO_HSE		8000000 + +#include <ao_flash_stm_pins.h> + +#define AO_BOOT_PIN			1 +#define AO_BOOT_APPLICATION_GPIO	stm_gpiob +#define AO_BOOT_APPLICATION_PIN		6 +#define AO_BOOT_APPLICATION_VALUE	1 +#define AO_BOOT_APPLICATION_MODE	AO_EXTI_MODE_PULL_UP + +#endif /* _AO_PINS_H_ */ diff --git a/src/telelco-v0.2/Makefile b/src/telelco-v0.2/Makefile index 7a21f099..8c1ced6c 100644 --- a/src/telelco-v0.2/Makefile +++ b/src/telelco-v0.2/Makefile @@ -22,7 +22,6 @@ INC = \  	ao_radio_spi.h \  	ao_radio_cmac.h \  	ao_cc1120_CC1120.h \ -	ao_debounce.h \  	stm32l.h  # @@ -61,7 +60,6 @@ ALTOS_SRC = \  	ao_fec_tx.c \  	ao_fec_rx.c \  	ao_seven_segment.c \ -	ao_debounce.c \  	ao_quadrature.c \  	ao_button.c \  	ao_event.c \ diff --git a/src/telelco-v0.3/Makefile b/src/telelco-v0.3/Makefile index 83d3fc43..0bb0f9dc 100644 --- a/src/telelco-v0.3/Makefile +++ b/src/telelco-v0.3/Makefile @@ -23,7 +23,6 @@ INC = \  	ao_radio_cmac.h \  	ao_cc1200_CC1200.h \  	ao_cc1200.h \ -	ao_debounce.h \  	stm32l.h  # @@ -62,7 +61,6 @@ ALTOS_SRC = \  	ao_fec_tx.c \  	ao_fec_rx.c \  	ao_seven_segment.c \ -	ao_debounce.c \  	ao_quadrature.c \  	ao_button.c \  	ao_event.c \ diff --git a/src/telelcotwo-v0.1/.gitignore b/src/telelcotwo-v0.1/.gitignore new file mode 100644 index 00000000..a32ec26e --- /dev/null +++ b/src/telelcotwo-v0.1/.gitignore @@ -0,0 +1,2 @@ +ao_product.h +telelco*.elf diff --git a/src/telelcotwo-v0.1/Makefile b/src/telelcotwo-v0.1/Makefile new file mode 100644 index 00000000..42188bb2 --- /dev/null +++ b/src/telelcotwo-v0.1/Makefile @@ -0,0 +1,96 @@ +# +# AltOS build for TeleLCO +# +# + +include ../stm/Makefile.defs + +INC = \ +	ao.h \ +	ao_arch.h \ +	ao_arch_funcs.h \ +	ao_boot.h \ +	ao_companion.h \ +	ao_data.h \ +	ao_sample.h \ +	ao_pins.h \ +	ao_product.h \ +	ao_radio_spi.h \ +	ao_radio_cmac.h \ +	ao_cc1200_CC1200.h \ +	ao_cc1200.h \ +	stm32l.h + +# +# Common AltOS sources +# + +#PROFILE=ao_profile.c +#PROFILE_DEF=-DAO_PROFILE=1 + +ALTOS_SRC = \ +	ao_boot_chain.c \ +	ao_interrupt.c \ +	ao_product.c \ +	ao_romconfig.c \ +	ao_cmd.c \ +	ao_config.c \ +	ao_task.c \ +	ao_led.c \ +	ao_stdio.c \ +	ao_panic.c \ +	ao_timer.c \ +	ao_mutex.c \ +	ao_freq.c \ +	ao_dma_stm.c \ +	ao_spi_stm.c \ +	ao_beep_stm.c \ +	ao_eeprom_stm.c \ +	ao_fast_timer.c \ +	ao_usb_stm.c \ +	ao_exti_stm.c \ +	ao_cc1200.c \ +	ao_radio_cmac.c \ +	ao_aes.c \ +	ao_aes_tables.c \ +	ao_fec_tx.c \ +	ao_fec_rx.c \ +	ao_button.c \ +	ao_event.c \ +	ao_lco_two.c \ +	ao_lco_func.c \ +	ao_lco_cmd.c \ +	ao_radio_cmac_cmd.c + +PRODUCT=TeleLCOTwo-v0.1 +PRODUCT_DEF=-DTELELCOTWO +IDPRODUCT=0x0023 + +CFLAGS = $(PRODUCT_DEF) $(STM_CFLAGS) $(PROFILE_DEF) -Os -g + +PROGNAME=telelcotwo-v0.1 +PROG=$(PROGNAME)-$(VERSION).elf +HEX=$(PROGNAME)-$(VERSION).ihx + +SRC=$(ALTOS_SRC) ao_telelcotwo.c +OBJ=$(SRC:.c=.o) + +all: $(PROG) $(HEX) + +$(PROG): Makefile $(OBJ) altos.ld +	$(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(OBJ) $(LIBS) + +$(OBJ): $(INC) + +ao_product.h: ao-make-product.5c ../Version +	$(call quiet,NICKLE,$<) $< -m altusmetrum.org -i $(IDPRODUCT) -p $(PRODUCT) -v $(VERSION) > $@ + +distclean:	clean + +clean: +	rm -f *.o $(PROGNAME)-*.elf $(PROGNAME)-*.ihx +	rm -f ao_product.h + +install: + +uninstall: diff --git a/src/telelcotwo-v0.1/ao_pins.h b/src/telelcotwo-v0.1/ao_pins.h new file mode 100644 index 00000000..ce797a38 --- /dev/null +++ b/src/telelcotwo-v0.1/ao_pins.h @@ -0,0 +1,172 @@ +/* + * Copyright © 2012 Keith Packard <keithp@keithp.com> + * + * 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. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#ifndef _AO_PINS_H_ +#define _AO_PINS_H_ + +/* 8MHz High speed external crystal */ +#define AO_HSE			8000000 + +/* PLLVCO = 96MHz (so that USB will work) */ +#define AO_PLLMUL		12 +#define AO_RCC_CFGR_PLLMUL	(STM_RCC_CFGR_PLLMUL_12) + +#define AO_CC1200_FOSC		40000000 + +/* SYSCLK = 32MHz (no need to go faster than CPU) */ +#define AO_PLLDIV		3 +#define AO_RCC_CFGR_PLLDIV	(STM_RCC_CFGR_PLLDIV_3) + +/* HCLK = 32MHz (CPU clock) */ +#define AO_AHB_PRESCALER	1 +#define AO_RCC_CFGR_HPRE_DIV	STM_RCC_CFGR_HPRE_DIV_1 + +/* Run APB1 at 16MHz (HCLK/2) */ +#define AO_APB1_PRESCALER	2 +#define AO_RCC_CFGR_PPRE1_DIV	STM_RCC_CFGR_PPRE2_DIV_2 + +/* Run APB2 at 16MHz (HCLK/2) */ +#define AO_APB2_PRESCALER	2 +#define AO_RCC_CFGR_PPRE2_DIV	STM_RCC_CFGR_PPRE2_DIV_2 + +#define HAS_EEPROM		1 +#define USE_INTERNAL_FLASH	1 +#define USE_EEPROM_CONFIG	1 +#define USE_STORAGE_CONFIG	0 +#define HAS_USB			1 +#define HAS_BEEP		1 +#define BEEPER_CHANNEL		4 +#define HAS_RADIO		1 +#define HAS_RADIO_RATE		1 +#define HAS_TELEMETRY		0 +#define HAS_AES			1 +#define HAS_FIXED_PAD_BOX	1 + +#define HAS_SPI_1		0 +#define SPI_1_PA5_PA6_PA7	0 +#define SPI_1_PB3_PB4_PB5	0 +#define SPI_1_PE13_PE14_PE15	0 + +#define HAS_SPI_2		1	/* CC1200 */ +#define SPI_2_PB13_PB14_PB15	1 +#define SPI_2_PD1_PD3_PD4	0 +#define SPI_2_GPIO		(&stm_gpiod) +#define SPI_2_SCK		13 +#define SPI_2_MISO		14 +#define SPI_2_MOSI		15 +#define SPI_2_OSPEEDR		STM_OSPEEDR_10MHz + +#define HAS_I2C_1		0 + +#define HAS_I2C_2		0 + +#define PACKET_HAS_SLAVE	0 +#define PACKET_HAS_MASTER	0 + +#define FAST_TIMER_FREQ		10000	/* .1ms for debouncing */ + +/* + * Radio is a cc1200 connected via SPI + */ + +#define AO_RADIO_CAL_DEFAULT 	5695733 + +#define AO_FEC_DEBUG		0 +#define AO_CC1200_SPI_CS_PORT	(&stm_gpioa) +#define AO_CC1200_SPI_CS_PIN	7 +#define AO_CC1200_SPI_BUS	AO_SPI_2_PB13_PB14_PB15 +#define AO_CC1200_SPI		stm_spi2 + +#define AO_CC1200_INT_PORT		(&stm_gpiob) +#define AO_CC1200_INT_PIN		(11) + +#define AO_CC1200_INT_GPIO	2 +#define AO_CC1200_INT_GPIO_IOCFG	CC1200_IOCFG2 + +#define LOW_LEVEL_DEBUG		0 + +#define LED_PORT_0		(&stm_gpioa) +#define LED_PORT_1		(&stm_gpiob) + +#define LED_PORT_0_ENABLE	STM_RCC_AHBENR_GPIOAEN +#define LED_PORT_1_ENABLE	STM_RCC_AHBENR_GPIOBEN + +/* Port A, pins 4-6 */ +#define LED_PORT_0_SHIFT	4 +#define LED_PORT_0_MASK		0x7 + +#define LED_PIN_GREEN		0 +#define LED_PIN_AMBER		1 +#define LED_PIN_RED		2 + +#define AO_LED_RED		(1 << LED_PIN_RED) +#define AO_LED_AMBER		(1 << LED_PIN_AMBER) +#define AO_LED_GREEN		(1 << LED_PIN_GREEN) + +/* Port B, pins 3-5 */ +#define LED_PORT_1_SHIFT	0 +#define LED_PORT_1_MASK		(0x7 << 3) + +#define LED_PIN_CONTINUITY_1	3 +#define LED_PIN_CONTINUITY_0	4 +#define LED_PIN_REMOTE_ARM	5 + +#define AO_LED_CONTINUITY_1	(1 << LED_PIN_CONTINUITY_1) +#define AO_LED_CONTINUITY_0	(1 << LED_PIN_CONTINUITY_0) + +#define AO_LED_CONTINUITY_NUM	2 + +#define AO_LED_REMOTE_ARM	(1 << LED_PIN_REMOTE_ARM) + +#define LEDS_AVAILABLE		(AO_LED_RED |		\ +				 AO_LED_AMBER |		\ +				 AO_LED_GREEN |		\ +				 AO_LED_CONTINUITY_1 |	\ +				 AO_LED_CONTINUITY_0 |	\ +				 AO_LED_REMOTE_ARM) + +/* + * Use event queue for input devices + */ + +#define AO_EVENT		1 + +/* + * Buttons + */ + +#define AO_BUTTON_COUNT		3 +#define AO_BUTTON_MODE		AO_EXTI_MODE_PULL_UP + +#define AO_BUTTON_0_PORT	&stm_gpioa +#define AO_BUTTON_0		0 + +#define AO_BUTTON_ARM_0		0 + +#define AO_BUTTON_1_PORT	&stm_gpioa +#define AO_BUTTON_1		1 + +#define AO_BUTTON_ARM_1		1 + +#define AO_BUTTON_ARM_NUM	2 + +#define AO_BUTTON_2_PORT	&stm_gpioa +#define AO_BUTTON_2		2 + +#define AO_BUTTON_FIRE		2 + +#endif /* _AO_PINS_H_ */ diff --git a/src/telelcotwo-v0.1/ao_telelcotwo.c b/src/telelcotwo-v0.1/ao_telelcotwo.c new file mode 100644 index 00000000..318875e3 --- /dev/null +++ b/src/telelcotwo-v0.1/ao_telelcotwo.c @@ -0,0 +1,65 @@ +/* + * Copyright © 2011 Keith Packard <keithp@keithp.com> + * + * 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. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include <ao.h> +#include <ao_exti.h> +#include <ao_packet.h> +#include <ao_companion.h> +#include <ao_profile.h> +#include <ao_pyro.h> +#include <ao_aes.h> +#include <ao_button.h> +#include <ao_lco.h> +#include <ao_lco_cmd.h> +#include <ao_radio_cmac_cmd.h> +#include <ao_eeprom.h> + +int +main(void) +{ +	ao_clock_init(); + +	ao_led_init(LEDS_AVAILABLE); +	ao_led_on(AO_LED_GREEN); +	ao_beep_init(); +	ao_task_init(); + +	ao_timer_init(); + +	ao_spi_init(); +	ao_dma_init(); +	ao_exti_init(); + +	ao_cmd_init(); + +	ao_button_init(); + +	ao_eeprom_init(); + +	ao_radio_init(); + +	ao_usb_init(); + +	ao_config_init(); + +	ao_lco_init(); +	ao_lco_cmd_init(); +//	ao_radio_cmac_cmd_init(); + +	ao_start_scheduler(); +	return 0; +} diff --git a/src/telelcotwo-v0.1/flash-loader/Makefile b/src/telelcotwo-v0.1/flash-loader/Makefile new file mode 100644 index 00000000..69833314 --- /dev/null +++ b/src/telelcotwo-v0.1/flash-loader/Makefile @@ -0,0 +1,8 @@ +# +# AltOS flash loader build +# +# + +TOPDIR=../.. +HARDWARE=telelcotwo-v0.1 +include $(TOPDIR)/stm/Makefile-flash.defs diff --git a/src/telelcotwo-v0.1/flash-loader/ao_pins.h b/src/telelcotwo-v0.1/flash-loader/ao_pins.h new file mode 100644 index 00000000..266bff6c --- /dev/null +++ b/src/telelcotwo-v0.1/flash-loader/ao_pins.h @@ -0,0 +1,34 @@ +/* + * Copyright © 2013 Keith Packard <keithp@keithp.com> + * + * 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. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#ifndef _AO_PINS_H_ +#define _AO_PINS_H_ + +/* External crystal at 8MHz */ +#define AO_HSE		8000000 + +#include <ao_flash_stm_pins.h> + +/* Fire switch. Press at power on to get boot loader */ + +#define AO_BOOT_PIN			1 +#define AO_BOOT_APPLICATION_GPIO	stm_gpioa +#define AO_BOOT_APPLICATION_PIN		2 +#define AO_BOOT_APPLICATION_VALUE	1 +#define AO_BOOT_APPLICATION_MODE	AO_EXTI_MODE_PULL_UP + +#endif /* _AO_PINS_H_ */ diff --git a/src/telemega-v0.1/ao_pins.h b/src/telemega-v0.1/ao_pins.h index 7ccc6085..1815ef54 100644 --- a/src/telemega-v0.1/ao_pins.h +++ b/src/telemega-v0.1/ao_pins.h @@ -346,6 +346,7 @@ struct ao_adc {   */  #define HAS_MMA655X		1 +#define AO_MMA655X_INVERT	0  #define AO_MMA655X_SPI_INDEX	AO_SPI_1_PE13_PE14_PE15  #define AO_MMA655X_CS_PORT	(&stm_gpiod)  #define AO_MMA655X_CS_PIN	4 diff --git a/src/telemega-v1.0/ao_pins.h b/src/telemega-v1.0/ao_pins.h index 664546c2..b81e59a9 100644 --- a/src/telemega-v1.0/ao_pins.h +++ b/src/telemega-v1.0/ao_pins.h @@ -348,6 +348,7 @@ struct ao_adc {   */  #define HAS_MMA655X		1 +#define AO_MMA655X_INVERT	0  #define AO_MMA655X_SPI_INDEX	AO_SPI_1_PE13_PE14_PE15  #define AO_MMA655X_CS_PORT	(&stm_gpiod)  #define AO_MMA655X_CS_PIN	4 diff --git a/src/telemega-v2.0/ao_pins.h b/src/telemega-v2.0/ao_pins.h index 9095a350..242f0ab2 100644 --- a/src/telemega-v2.0/ao_pins.h +++ b/src/telemega-v2.0/ao_pins.h @@ -348,6 +348,7 @@ struct ao_adc {   */  #define HAS_MMA655X		1 +#define AO_MMA655X_INVERT	0  #define AO_MMA655X_SPI_INDEX	AO_SPI_1_PE13_PE14_PE15  #define AO_MMA655X_CS_PORT	(&stm_gpiod)  #define AO_MMA655X_CS_PIN	4 diff --git a/src/telerepeat-v1.0/.gitignore b/src/telerepeat-v1.0/.gitignore new file mode 100644 index 00000000..4bb125bc --- /dev/null +++ b/src/telerepeat-v1.0/.gitignore @@ -0,0 +1,2 @@ +telerepeat-* +ao_product.h diff --git a/src/telerepeat-v1.0/.sdcdbrc b/src/telerepeat-v1.0/.sdcdbrc new file mode 100644 index 00000000..2c77e32b --- /dev/null +++ b/src/telerepeat-v1.0/.sdcdbrc @@ -0,0 +1,2 @@ +--directory=../cc1111:../product:../kernel:../drivers:. + diff --git a/src/test/plotem b/src/test/plotem new file mode 100755 index 00000000..8bc392cf --- /dev/null +++ b/src/test/plotem @@ -0,0 +1,10 @@ +gnuplot -persist << EOF +set ylabel "altitude (m)" +set y2label "error" +set xlabel "time (s)" +set xtics border out nomirror +set ytics border out nomirror +set y2tics border out nomirror +plot "$1" using 1:3 with lines axes x1y1 title "raw height",\ +"$1" using 1:21 with lines axes x1y2 title "error" +EOF | 
