From 35cb2dc51708ab572a4c72422e5902a313eda58e Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 6 Oct 2012 17:56:23 -0700 Subject: altos/stm: Clean up SPI pin configuration code Make sure none of the pin configurations are being used at startup time. Split out the pin configuration into separate functions. Signed-off-by: Keith Packard --- src/stm/ao_spi_stm.c | 199 ++++++++++++++++++++++++++++----------------------- 1 file changed, 109 insertions(+), 90 deletions(-) (limited to 'src/stm') diff --git a/src/stm/ao_spi_stm.c b/src/stm/ao_spi_stm.c index ade86a27..5b823e3e 100644 --- a/src/stm/ao_spi_stm.c +++ b/src/stm/ao_spi_stm.c @@ -24,7 +24,7 @@ struct ao_spi_stm_info { }; static uint8_t ao_spi_mutex[STM_NUM_SPI]; -static uint8_t ao_spi_config[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] = { { @@ -267,97 +267,100 @@ ao_spi_duplex(void *out, void *in, uint16_t len, uint8_t spi_index) ao_dma_done_transfer(miso_dma_index); } -void -ao_spi_get(uint8_t spi_index, uint32_t speed) +static void +ao_spi_disable_index(uint8_t spi_index) { - struct stm_spi *stm_spi = ao_spi_stm_info[AO_SPI_INDEX(spi_index)].stm_spi; - uint8_t config = AO_SPI_CONFIG(spi_index); - - ao_mutex_get(&ao_spi_mutex[AO_SPI_INDEX(spi_index)]); - if (config != ao_spi_config[AO_SPI_INDEX(spi_index)]) { - - /* Disable current config - */ - switch (AO_SPI_INDEX(spi_index)) { - case STM_SPI_INDEX(1): - switch (ao_spi_config[AO_SPI_INDEX(spi_index)]) { - case AO_SPI_1_CONFIG_PA5_PA6_PA7: - stm_gpio_set(&stm_gpioa, 5, 0); - 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_CONFIG_PB3_PB4_PB5: - stm_gpio_set(&stm_gpiob, 3, 0); - 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; - case AO_SPI_1_CONFIG_PE13_PE14_PE15: - stm_gpio_set(&stm_gpioe, 13, 0); - stm_moder_set(&stm_gpioe, 13, STM_MODER_OUTPUT); - stm_moder_set(&stm_gpioe, 14, STM_MODER_INPUT); - stm_moder_set(&stm_gpioe, 15, STM_MODER_OUTPUT); - break; - } + /* 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, 0); + 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, 0); + 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; - case STM_SPI_INDEX(2): - switch (ao_spi_config[AO_SPI_INDEX(spi_index)]) { - case AO_SPI_2_CONFIG_PB13_PB14_PB15: - stm_gpio_set(&stm_gpiob, 13, 0); - 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; - case AO_SPI_2_CONFIG_PD1_PD3_PD4: - stm_gpio_set(&stm_gpiod, 1, 0); - stm_moder_set(&stm_gpiod, 1, STM_MODER_OUTPUT); - stm_moder_set(&stm_gpiod, 3, STM_MODER_INPUT); - stm_moder_set(&stm_gpiod, 4, STM_MODER_OUTPUT); - break; - } + case AO_SPI_1_PE13_PE14_PE15: + stm_gpio_set(&stm_gpioe, 13, 0); + stm_moder_set(&stm_gpioe, 13, STM_MODER_OUTPUT); + stm_moder_set(&stm_gpioe, 14, STM_MODER_INPUT); + stm_moder_set(&stm_gpioe, 15, 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, 0); + 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; + case AO_SPI_2_PD1_PD3_PD4: + stm_gpio_set(&stm_gpiod, 1, 0); + stm_moder_set(&stm_gpiod, 1, STM_MODER_OUTPUT); + stm_moder_set(&stm_gpiod, 3, STM_MODER_INPUT); + stm_moder_set(&stm_gpiod, 4, STM_MODER_OUTPUT); + break; + } + break; + } +} - /* Enable new config - */ - switch (AO_SPI_INDEX(spi_index)) { - case 0: - switch (AO_SPI_CONFIG(spi_index)) { - case AO_SPI_1_CONFIG_PA5_PA6_PA7: - stm_afr_set(&stm_gpioa, 5, STM_AFR_AF5); - stm_afr_set(&stm_gpioa, 6, STM_AFR_AF5); - stm_afr_set(&stm_gpioa, 7, STM_AFR_AF5); - break; - case AO_SPI_1_CONFIG_PB3_PB4_PB5: - stm_afr_set(&stm_gpiob, 3, STM_AFR_AF5); - stm_afr_set(&stm_gpiob, 4, STM_AFR_AF5); - stm_afr_set(&stm_gpiob, 5, STM_AFR_AF5); - break; - case AO_SPI_1_CONFIG_PE13_PE14_PE15: - stm_afr_set(&stm_gpioe, 13, STM_AFR_AF5); - stm_afr_set(&stm_gpioe, 14, STM_AFR_AF5); - stm_afr_set(&stm_gpioe, 15, STM_AFR_AF5); - 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_AF5); + stm_afr_set(&stm_gpioa, 6, STM_AFR_AF5); + stm_afr_set(&stm_gpioa, 7, STM_AFR_AF5); + break; + case AO_SPI_1_PB3_PB4_PB5: + stm_afr_set(&stm_gpiob, 3, STM_AFR_AF5); + stm_afr_set(&stm_gpiob, 4, STM_AFR_AF5); + stm_afr_set(&stm_gpiob, 5, STM_AFR_AF5); + break; + case AO_SPI_1_PE13_PE14_PE15: + stm_afr_set(&stm_gpioe, 13, STM_AFR_AF5); + stm_afr_set(&stm_gpioe, 14, STM_AFR_AF5); + stm_afr_set(&stm_gpioe, 15, STM_AFR_AF5); break; - case 1: - switch (AO_SPI_CONFIG(spi_index)) { - case AO_SPI_2_CONFIG_PB13_PB14_PB15: - stm_afr_set(&stm_gpiob, 13, STM_AFR_AF5); - stm_afr_set(&stm_gpiob, 14, STM_AFR_AF5); - stm_afr_set(&stm_gpiob, 15, STM_AFR_AF5); - break; - case AO_SPI_2_CONFIG_PD1_PD3_PD4: - stm_afr_set(&stm_gpiod, 1, STM_AFR_AF5); - stm_afr_set(&stm_gpiod, 3, STM_AFR_AF5); - stm_afr_set(&stm_gpiod, 4, STM_AFR_AF5); - 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_AF5); + stm_afr_set(&stm_gpiob, 14, STM_AFR_AF5); + stm_afr_set(&stm_gpiob, 15, STM_AFR_AF5); + break; + case AO_SPI_2_PD1_PD3_PD4: + stm_afr_set(&stm_gpiod, 1, STM_AFR_AF5); + stm_afr_set(&stm_gpiod, 3, STM_AFR_AF5); + stm_afr_set(&stm_gpiod, 4, STM_AFR_AF5); break; } - ao_spi_config[AO_SPI_INDEX(spi_index)] = AO_SPI_CONFIG(spi_index); + break; } +} + +void +ao_spi_get(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; + + ao_mutex_get(&ao_spi_mutex[id]); stm_spi->cr1 = ((0 << STM_SPI_CR1_BIDIMODE) | /* Three wire mode */ (0 << STM_SPI_CR1_BIDIOE) | (0 << STM_SPI_CR1_CRCEN) | /* CRC disabled */ @@ -372,21 +375,39 @@ ao_spi_get(uint8_t spi_index, uint32_t speed) (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; + } } void ao_spi_put(uint8_t spi_index) { - struct stm_spi *stm_spi = ao_spi_stm_info[AO_SPI_INDEX(spi_index)].stm_spi; + 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[AO_SPI_INDEX(spi_index)]); + ao_mutex_put(&ao_spi_mutex[id]); } static void ao_spi_channel_init(uint8_t spi_index) { - struct stm_spi *stm_spi = ao_spi_stm_info[AO_SPI_INDEX(spi_index)].stm_spi; + 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; @@ -412,7 +433,7 @@ ao_spi_init(void) stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_GPIOEEN); # endif stm_rcc.apb2enr |= (1 << STM_RCC_APB2ENR_SPI1EN); - ao_spi_config[0] = AO_SPI_CONFIG_NONE; + ao_spi_index[0] = AO_SPI_CONFIG_NONE; ao_spi_channel_init(0); #endif @@ -423,10 +444,8 @@ ao_spi_init(void) # if SPI_2_PD1_PD3_PD4 stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_GPIODEN); # endif - stm_rcc.apb1enr |= (1 << STM_RCC_APB1ENR_SPI2EN); - ao_spi_config[1] = AO_SPI_CONFIG_NONE; - + ao_spi_index[1] = AO_SPI_CONFIG_NONE; ao_spi_channel_init(1); #endif } -- cgit v1.2.3 From 6d47dd1d9104745cf68bef23b066c5033ca30a84 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 6 Oct 2012 19:39:15 -0700 Subject: altos/stm: Set SPI clock high for disabled SPI busses This should avoid an accidental low->high transition when switching between multiple SPI busses. Signed-off-by: Keith Packard --- src/stm/ao_spi_stm.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'src/stm') diff --git a/src/stm/ao_spi_stm.c b/src/stm/ao_spi_stm.c index 5b823e3e..599d7ee0 100644 --- a/src/stm/ao_spi_stm.c +++ b/src/stm/ao_spi_stm.c @@ -276,19 +276,19 @@ ao_spi_disable_index(uint8_t spi_index) case STM_SPI_INDEX(1): switch (spi_index) { case AO_SPI_1_PA5_PA6_PA7: - stm_gpio_set(&stm_gpioa, 5, 0); + 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, 0); + 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; case AO_SPI_1_PE13_PE14_PE15: - stm_gpio_set(&stm_gpioe, 13, 0); + stm_gpio_set(&stm_gpioe, 13, 1); stm_moder_set(&stm_gpioe, 13, STM_MODER_OUTPUT); stm_moder_set(&stm_gpioe, 14, STM_MODER_INPUT); stm_moder_set(&stm_gpioe, 15, STM_MODER_OUTPUT); @@ -298,13 +298,13 @@ ao_spi_disable_index(uint8_t spi_index) case STM_SPI_INDEX(2): switch (spi_index) { case AO_SPI_2_PB13_PB14_PB15: - stm_gpio_set(&stm_gpiob, 13, 0); + 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; case AO_SPI_2_PD1_PD3_PD4: - stm_gpio_set(&stm_gpiod, 1, 0); + stm_gpio_set(&stm_gpiod, 1, 1); stm_moder_set(&stm_gpiod, 1, STM_MODER_OUTPUT); stm_moder_set(&stm_gpiod, 3, STM_MODER_INPUT); stm_moder_set(&stm_gpiod, 4, STM_MODER_OUTPUT); -- cgit v1.2.3 From 39c5738acdfdf0c87b64de6135fe107971cfa12b Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 8 Oct 2012 23:04:16 -0700 Subject: altos: Go back to recording sensor data in globals Instead of trying to get things into the ring from a variety of functions, go back to the simpler method of storing them in globals and having the ADC code just pluck out the most recent values. Signed-off-by: Keith Packard --- src/core/ao_data.h | 9 +-------- src/drivers/ao_hmc5883.c | 4 +++- src/drivers/ao_hmc5883.h | 2 ++ src/drivers/ao_mma655x.c | 4 +++- src/drivers/ao_mma655x.h | 1 + src/drivers/ao_mpu6000.c | 4 +++- src/drivers/ao_mpu6000.h | 2 ++ src/drivers/ao_ms5607.c | 4 +++- src/drivers/ao_ms5607.h | 2 ++ src/stm/ao_adc_stm.c | 17 +++++++++++++++++ 10 files changed, 37 insertions(+), 12 deletions(-) (limited to 'src/stm') diff --git a/src/core/ao_data.h b/src/core/ao_data.h index 2b9ef5ac..30208dfb 100644 --- a/src/core/ao_data.h +++ b/src/core/ao_data.h @@ -85,14 +85,7 @@ extern volatile __data uint8_t ao_data_count; /* * Mark a section of data as ready, check for data complete */ -#define AO_DATA_PRESENT(bit) do { \ - if ((ao_data_present |= (bit)) == AO_DATA_ALL) { \ - ao_data_ring[ao_data_head].tick = ao_tick_count; \ - ao_data_head = ao_data_ring_next(ao_data_head); \ - ao_data_present = 0; \ - ao_wakeup((void *) &ao_data_head); \ - } \ - } while (0); +#define AO_DATA_PRESENT(bit) (ao_data_present |= (bit)) /* * Wait until it is time to write a sensor sample; this is diff --git a/src/drivers/ao_hmc5883.c b/src/drivers/ao_hmc5883.c index ade6c263..059fc2c8 100644 --- a/src/drivers/ao_hmc5883.c +++ b/src/drivers/ao_hmc5883.c @@ -123,12 +123,14 @@ ao_hmc5883_setup(void) return 1; } +struct ao_hmc5883_sample ao_hmc5883_current; + static void ao_hmc5883(void) { ao_hmc5883_setup(); for (;;) { - ao_hmc5883_sample((struct ao_hmc5883_sample *) &ao_data_ring[ao_data_head].hmc5883); + ao_hmc5883_sample(&ao_hmc5883_current); ao_arch_critical( AO_DATA_PRESENT(AO_DATA_HMC5883); AO_DATA_WAIT(); diff --git a/src/drivers/ao_hmc5883.h b/src/drivers/ao_hmc5883.h index 55690978..ff2725eb 100644 --- a/src/drivers/ao_hmc5883.h +++ b/src/drivers/ao_hmc5883.h @@ -79,6 +79,8 @@ struct ao_hmc5883_sample { int16_t x, y, z; }; +extern struct ao_hmc5883_sample ao_hmc5883_current; + void ao_hmc5883_init(void); diff --git a/src/drivers/ao_mma655x.c b/src/drivers/ao_mma655x.c index 005bc684..18c5317c 100644 --- a/src/drivers/ao_mma655x.c +++ b/src/drivers/ao_mma655x.c @@ -250,12 +250,14 @@ __code struct ao_cmds ao_mma655x_cmds[] = { { 0, NULL }, }; +uint16_t ao_mma655x_current; + static void ao_mma655x(void) { ao_mma655x_setup(); for (;;) { - ao_data_ring[ao_data_head].mma655x = ao_mma655x_value(); + ao_mma655x_current = ao_mma655x_value(); ao_arch_critical( AO_DATA_PRESENT(AO_DATA_MMA655X); AO_DATA_WAIT(); diff --git a/src/drivers/ao_mma655x.h b/src/drivers/ao_mma655x.h index 9c0c59dc..2d951e07 100644 --- a/src/drivers/ao_mma655x.h +++ b/src/drivers/ao_mma655x.h @@ -78,6 +78,7 @@ #define AO_MMA655X_COUNT 0x15 #define AO_MMA655X_OFFCORR 0x16 +extern uint16_t ao_mma655x_current; void ao_mma655x_init(void); diff --git a/src/drivers/ao_mpu6000.c b/src/drivers/ao_mpu6000.c index b3e284e0..49596705 100644 --- a/src/drivers/ao_mpu6000.c +++ b/src/drivers/ao_mpu6000.c @@ -240,13 +240,15 @@ ao_mpu6000_setup(void) ao_mpu6000_configured = 1; } +struct ao_mpu6000_sample ao_mpu6000_current; + static void ao_mpu6000(void) { ao_mpu6000_setup(); for (;;) { - ao_mpu6000_sample((struct ao_mpu6000_sample *) &ao_data_ring[ao_data_head].mpu6000); + ao_mpu6000_sample(&ao_mpu6000_current); ao_arch_critical( AO_DATA_PRESENT(AO_DATA_MPU6000); AO_DATA_WAIT(); diff --git a/src/drivers/ao_mpu6000.h b/src/drivers/ao_mpu6000.h index ca76b081..ab36d6f2 100644 --- a/src/drivers/ao_mpu6000.h +++ b/src/drivers/ao_mpu6000.h @@ -155,6 +155,8 @@ struct ao_mpu6000_sample { int16_t gyro_z; }; +extern struct ao_mpu6000_sample ao_mpu6000_current; + void ao_mpu6000_init(void); diff --git a/src/drivers/ao_ms5607.c b/src/drivers/ao_ms5607.c index 3295baac..492199b8 100644 --- a/src/drivers/ao_ms5607.c +++ b/src/drivers/ao_ms5607.c @@ -207,13 +207,15 @@ ao_ms5607_convert(struct ao_ms5607_sample *sample, struct ao_ms5607_value *value value->temp = TEMP; } +struct ao_ms5607_sample ao_ms5607_current; + static void ao_ms5607(void) { ao_ms5607_setup(); for (;;) { - ao_ms5607_sample((struct ao_ms5607_sample *) &ao_data_ring[ao_data_head].ms5607_raw); + ao_ms5607_sample(&ao_ms5607_current); ao_arch_critical( AO_DATA_PRESENT(AO_DATA_MS5607); AO_DATA_WAIT(); diff --git a/src/drivers/ao_ms5607.h b/src/drivers/ao_ms5607.h index e9c364d9..4c29f6a7 100644 --- a/src/drivers/ao_ms5607.h +++ b/src/drivers/ao_ms5607.h @@ -56,6 +56,8 @@ struct ao_ms5607_value { int32_t temp; /* in °C * 100 */ }; +extern struct ao_ms5607_sample ao_ms5607_current; + void ao_ms5607_init(void); diff --git a/src/stm/ao_adc_stm.c b/src/stm/ao_adc_stm.c index 18ca6ea0..48fc4262 100644 --- a/src/stm/ao_adc_stm.c +++ b/src/stm/ao_adc_stm.c @@ -43,6 +43,23 @@ static void ao_adc_done(int index) { AO_DATA_PRESENT(AO_DATA_ADC); ao_dma_done_transfer(STM_DMA_INDEX(STM_DMA_CHANNEL_ADC1)); + if (ao_data_present == AO_DATA_ALL) { +#if HAS_MS5607 + ao_data_ring[ao_data_head].ms5607_raw = ao_ms5607_current; +#endif +#if HAS_MMA655X + ao_data_ring[ao_data_head].mma655x = ao_mma655x_current; +#endif +#if HAS_HMC5883 + ao_data_ring[ao_data_head].hmc5883 = ao_hmc5883_current; +#endif +#if HAS_MPU6000 + ao_data_ring[ao_data_head].mpu6000 = ao_mpu6000_current; +#endif + ao_data_ring[ao_data_head].tick = ao_tick_count; + ao_data_head = ao_data_ring_next(ao_data_head); + ao_wakeup((void *) &ao_data_head); + } ao_adc_ready = 1; } -- cgit v1.2.3 From 80227c08444d5c82fd43320644cdeec6f34fee1b Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 15 Oct 2012 00:06:10 -0700 Subject: altos/stm: Declare all SPI bus speeds Just list them all so users can pick what they like Signed-off-by: Keith Packard --- src/stm/ao_arch_funcs.h | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) (limited to 'src/stm') diff --git a/src/stm/ao_arch_funcs.h b/src/stm/ao_arch_funcs.h index d4fbea37..e66d20d7 100644 --- a/src/stm/ao_arch_funcs.h +++ b/src/stm/ao_arch_funcs.h @@ -21,9 +21,22 @@ /* ao_spi_stm.c */ -#define AO_SPI_SPEED_FAST STM_SPI_CR1_BR_PCLK_4 +/* PCLK is set to 16MHz (HCLK 32MHz, APB prescaler 2) */ + +#define AO_SPI_SPEED_8MHz STM_SPI_CR1_BR_PCLK_2 /* This doesn't appear to work */ +#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_200kHz STM_SPI_CR1_BR_PCLK_256 +#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_FAST AO_SPI_SPEED_4MHz + +/* Companion bus wants something no faster than 200kHz */ + +#define AO_SPI_SPEED_200kHz AO_SPI_SPEED_125kHz #define AO_SPI_CONFIG_1 0x00 #define AO_SPI_1_CONFIG_PA5_PA6_PA7 AO_SPI_CONFIG_1 -- cgit v1.2.3 From eea141b2f35722bad4cd31d9484d6d794646f815 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 21 Oct 2012 13:01:03 -0700 Subject: altos/stm: Stop spewing clock out PA8 pin This was used to debug the clock bringup, but is not useful anymore, and probably a bad idea to boot. Signed-off-by: Keith Packard --- src/stm/ao_timer.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src/stm') diff --git a/src/stm/ao_timer.c b/src/stm/ao_timer.c index 1132f748..f3011d3f 100644 --- a/src/stm/ao_timer.c +++ b/src/stm/ao_timer.c @@ -266,6 +266,7 @@ ao_clock_init(void) stm_rcc.csr |= (1 << STM_RCC_CSR_RMVF); +#if DEBUG_THE_CLOCK /* Output SYSCLK on PA8 for measurments */ stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_GPIOAEN); @@ -276,4 +277,5 @@ ao_clock_init(void) stm_rcc.cfgr |= (STM_RCC_CFGR_MCOPRE_DIV_1 << STM_RCC_CFGR_MCOPRE); stm_rcc.cfgr |= (STM_RCC_CFGR_MCOSEL_HSE << STM_RCC_CFGR_MCOSEL); +#endif } -- cgit v1.2.3 From 09aa379fc57cd4f30c18c7bda2532a79109354c2 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 24 Oct 2012 23:55:00 -0700 Subject: altos: Force beep timer regs reload when enabling beeper Without this, there can be a long delay between asking for the beeper and having it actually start sounding. Signed-off-by: Keith Packard --- src/stm/ao_beep_stm.c | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) (limited to 'src/stm') diff --git a/src/stm/ao_beep_stm.c b/src/stm/ao_beep_stm.c index 37c30e25..4761fbfc 100644 --- a/src/stm/ao_beep_stm.c +++ b/src/stm/ao_beep_stm.c @@ -26,15 +26,6 @@ ao_beep(uint8_t beep) } else { stm_rcc.apb1enr |= (1 << STM_RCC_APB1ENR_TIM3EN); - stm_tim3.cr1 = ((STM_TIM234_CR1_CKD_1 << STM_TIM234_CR1_CKD) | - (0 << STM_TIM234_CR1_ARPE) | - (STM_TIM234_CR1_CMS_EDGE << STM_TIM234_CR1_CMS) | - (0 << STM_TIM234_CR1_DIR) | - (0 << STM_TIM234_CR1_OPM) | - (0 << STM_TIM234_CR1_URS) | - (0 << STM_TIM234_CR1_UDIS) | - (0 << STM_TIM234_CR1_CEN)); - stm_tim3.cr2 = ((0 << STM_TIM234_CR2_TI1S) | (STM_TIM234_CR2_MMS_RESET << STM_TIM234_CR2_MMS) | (0 << STM_TIM234_CR2_CCDS)); @@ -102,6 +93,9 @@ ao_beep(uint8_t beep) (0 << STM_TIM234_CR1_URS) | (0 << STM_TIM234_CR1_UDIS) | (1 << STM_TIM234_CR1_CEN)); + + /* Update the values */ + stm_tim3.egr = (1 << STM_TIM234_EGR_UG); } } -- cgit v1.2.3 From b119e19604aa557a40e848c60d98a67b5f259bbd Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 23 Oct 2012 22:17:49 -0700 Subject: altos: profiling on STM32L Add sample-based profiling, using a 1kHz timer Signed-off-by: Keith Packard --- src/core/ao_flight.c | 2 +- src/core/ao_sample_profile.c | 173 ++++++++++++++++++++++++++++++++++++ src/core/ao_sample_profile.h | 29 ++++++ src/core/ao_task.c | 16 ++++ src/core/ao_task.h | 13 ++- src/drivers/ao_cc1120.c | 14 +-- src/drivers/ao_ms5607.c | 8 +- src/megametrum-v0.1/Makefile | 11 ++- src/megametrum-v0.1/ao_megametrum.c | 6 ++ src/stm/ao_arch.h | 2 +- src/stm/ao_sample_profile_timer.c | 115 ++++++++++++++++++++++++ src/stm/ao_sample_profile_timer.h | 32 +++++++ src/stm/stm32l.h | 134 +++++++++++++++++++++++++++- 13 files changed, 541 insertions(+), 14 deletions(-) create mode 100644 src/core/ao_sample_profile.c create mode 100644 src/core/ao_sample_profile.h create mode 100644 src/stm/ao_sample_profile_timer.c create mode 100644 src/stm/ao_sample_profile_timer.h (limited to 'src/stm') diff --git a/src/core/ao_flight.c b/src/core/ao_flight.c index aa4f6961..64c95063 100644 --- a/src/core/ao_flight.c +++ b/src/core/ao_flight.c @@ -115,7 +115,7 @@ ao_flight(void) { /* Set pad mode - we can fly! */ ao_flight_state = ao_flight_pad; -#if HAS_USB && HAS_RADIO && !HAS_FLIGHT_DEBUG +#if HAS_USB && HAS_RADIO && !HAS_FLIGHT_DEBUG && !HAS_SAMPLE_PROFILE /* Disable the USB controller in flight mode * to save power */ diff --git a/src/core/ao_sample_profile.c b/src/core/ao_sample_profile.c new file mode 100644 index 00000000..1d9ed414 --- /dev/null +++ b/src/core/ao_sample_profile.c @@ -0,0 +1,173 @@ +/* + * Copyright © 2012 Keith Packard + * + * 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 +#include +#include + +#ifndef AO_SAMPLE_PROFILE_LOW_PC +#define AO_SAMPLE_PROFILE_LOW_PC 0x08000000 +#endif + +#ifndef AO_SAMPLE_PROFILE_HIGH_PC +#define AO_SAMPLE_PROFILE_HIGH_PC (AO_SAMPLE_PROFILE_LOW_PC + 44 * 1024) +#endif + +#ifndef AO_SAMPLE_PROFILE_SHIFT +#define AO_SAMPLE_PROFILE_SHIFT 6 +#endif + +#define AO_SAMPLE_PROFILE_RANGE (AO_SAMPLE_PROFILE_HIGH_PC - AO_SAMPLE_PROFILE_LOW_PC) +#define AO_SAMPLE_PROFILE_NUM (AO_SAMPLE_PROFILE_RANGE >> AO_SAMPLE_PROFILE_SHIFT) + +static uint16_t prev_tick; +static uint16_t samples[AO_SAMPLE_PROFILE_NUM]; +static uint8_t missed[AO_SAMPLE_PROFILE_NUM/8]; +static uint16_t max_miss; +static uint32_t task, isr, os, idle; + +extern uint8_t ao_idle_loc; + +void +ao_sample_profile_point(uint32_t pc, uint16_t tick, uint8_t in_isr) +{ + uint16_t delta = tick - prev_tick; + + if (pc < AO_SAMPLE_PROFILE_LOW_PC) + return; + if (pc >= AO_SAMPLE_PROFILE_HIGH_PC) + return; + if (ao_cur_task) { + uint8_t *sp; + int32_t sp_delta; + + asm("mov %0,sp" : "=&r" (sp)); + sp_delta = sp - (uint8_t *) ao_cur_task->stack; + if (-96 < sp_delta && sp_delta < 16) + ao_panic(AO_PANIC_STACK); + } + + if (in_isr) + isr += delta; + else if (ao_cur_task) { + ao_cur_task->ticks += delta; + task += delta; + } else if (pc == (uint32_t) &ao_idle_loc) + idle += delta; + else + os += delta; + + pc -= AO_SAMPLE_PROFILE_LOW_PC; + pc >>= AO_SAMPLE_PROFILE_SHIFT; + samples[pc] += delta; + + if (delta > 1) + missed[pc >> 3] |= (1 << (pc & 7)); + if (delta > max_miss) + max_miss = delta; + prev_tick = tick; +} + +static void +ao_sample_profile_start(void) +{ + prev_tick = ao_sample_profile_timer_start(); +} + +static void +ao_sample_profile_stop(void) +{ + ao_sample_profile_timer_stop(); +} + +static void +ao_sample_profile_dump(void) +{ + uint16_t a; + uint8_t t; + + printf ("task %6d\n", task); + printf ("isr %6d\n", isr); + printf ("os %6d\n", os); + printf ("idle %6d\n", idle); + printf ("irq blocked %d\n", max_miss); + for (t = 0; t < ao_num_tasks; t++) + printf ("task %6d %6d %6d %s\n", + ao_tasks[t]->ticks, + ao_tasks[t]->yields, + ao_tasks[t]->max_run, + ao_tasks[t]->name); + for (a = 0; a < AO_SAMPLE_PROFILE_NUM; a++) { + if (samples[a]) + printf ("%04x %c %u\n", + (a << AO_SAMPLE_PROFILE_SHIFT) + AO_SAMPLE_PROFILE_LOW_PC, + missed[a >> 3] & (1 << (a & 7)) ? '*' : ' ', + samples[a]); + } +} + +static void +ao_sample_profile_clear(void) +{ + int t; + + task = isr = os = idle = 0; + max_miss = 0; + memset(samples, '\0', sizeof (samples)); + memset(missed, '\0', sizeof (missed)); + for (t = 0; t < ao_num_tasks; t++) { + ao_tasks[t]->ticks = 0; + ao_tasks[t]->yields = 0; + ao_tasks[t]->max_run = 0; + } +} + +static void +ao_sample_profile_cmd(void) +{ + ao_cmd_white(); + switch (ao_cmd_lex_c) { + case '1': + ao_sample_profile_start(); + break; + case '0': + ao_sample_profile_stop(); + break; + case 'd': + ao_sample_profile_dump(); + break; + case 'c': + ao_sample_profile_clear(); + break; + default: + ao_cmd_status = ao_cmd_syntax_error; + break; + } +} + +static __code struct ao_cmds ao_sample_profile_cmds[] = { + { ao_sample_profile_cmd, "S <1 start,0 stop, d dump,c clear>\0Sample profile" }, + { 0, NULL } +}; + +void +ao_sample_profile_init(void) +{ + ao_sample_profile_timer_init(); + ao_cmd_register(&ao_sample_profile_cmds[0]); + ao_sample_profile_clear(); +} diff --git a/src/core/ao_sample_profile.h b/src/core/ao_sample_profile.h new file mode 100644 index 00000000..dbc29d3d --- /dev/null +++ b/src/core/ao_sample_profile.h @@ -0,0 +1,29 @@ +/* + * Copyright © 2012 Keith Packard + * + * 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_SAMPLE_PROFILE_H_ +#define _AO_SAMPLE_PROFILE_H_ + +#include + +void +ao_sample_profile_point(uint32_t pc, uint16_t tick, uint8_t in_isr); + +void +ao_sample_profile_init(void); + +#endif /* _AO_SAMPLE_PROFILE_H_ */ diff --git a/src/core/ao_task.c b/src/core/ao_task.c index 65654731..c2b1b270 100644 --- a/src/core/ao_task.c +++ b/src/core/ao_task.c @@ -16,6 +16,10 @@ */ #include +#include +#if HAS_SAMPLE_PROFILE +#include +#endif #define AO_NO_TASK_INDEX 0xff @@ -67,6 +71,8 @@ ao_add_task(__xdata struct ao_task * task, void (*start)(void), __code char *nam ao_arch_init_stack(task, start); } +__xdata uint8_t ao_idle; + /* Task switching function. This must not use any stack variables */ void ao_yield(void) ao_arch_naked_define @@ -77,6 +83,13 @@ ao_yield(void) ao_arch_naked_define ao_cur_task_index = ao_num_tasks-1; else { +#if HAS_SAMPLE_PROFILE + uint16_t tick = ao_sample_profile_timer_value(); + uint16_t run = tick - ao_cur_task->start; + if (run > ao_cur_task->max_run) + ao_cur_task->max_run = run; + ++ao_cur_task->yields; +#endif ao_arch_save_stack(); } @@ -110,6 +123,9 @@ ao_yield(void) ao_arch_naked_define if (ao_cur_task_index == ao_last_task_index) ao_arch_cpu_idle(); } +#if HAS_SAMPLE_PROFILE + ao_cur_task->start = ao_sample_profile_timer_value(); +#endif } #if AO_CHECK_STACK cli(); diff --git a/src/core/ao_task.h b/src/core/ao_task.h index 18edd866..4319d632 100644 --- a/src/core/ao_task.h +++ b/src/core/ao_task.h @@ -26,13 +26,22 @@ struct ao_task { uint8_t task_id; /* unique id */ __code char *name; /* task name */ uint8_t stack[AO_STACK_SIZE]; /* saved stack */ +#if HAS_SAMPLE_PROFILE + uint32_t ticks; + uint32_t yields; + uint16_t start; + uint16_t max_run; +#endif }; -extern __xdata struct ao_task *__data ao_cur_task; - #define AO_NUM_TASKS 16 /* maximum number of tasks */ #define AO_NO_TASK 0 /* no task id */ +extern __xdata struct ao_task * __xdata ao_tasks[AO_NUM_TASKS]; +extern __data uint8_t ao_num_tasks; +extern __data uint8_t ao_cur_task_index; +extern __xdata struct ao_task *__data ao_cur_task; + /* ao_task.c */ diff --git a/src/drivers/ao_cc1120.c b/src/drivers/ao_cc1120.c index 2f9c296f..7428bead 100644 --- a/src/drivers/ao_cc1120.c +++ b/src/drivers/ao_cc1120.c @@ -21,6 +21,9 @@ #include #include +#define AO_RADIO_MAX_RECV sizeof(struct ao_packet) +#define AO_RADIO_MAX_SEND sizeof(struct ao_packet) + uint8_t ao_radio_wake; uint8_t ao_radio_mutex; uint8_t ao_radio_abort; @@ -559,18 +562,19 @@ ao_radio_test_cmd(void) } } +static uint8_t tx_data[(AO_RADIO_MAX_SEND + 4) * 2]; + void ao_radio_send(const void *d, uint8_t size) { uint8_t marc_status; - static uint8_t encode[256]; - uint8_t *e = encode; + uint8_t *e = tx_data; uint8_t encode_len; uint8_t this_len; uint8_t started = 0; uint8_t fifo_space; - encode_len = ao_fec_encode(d, size, encode); + encode_len = ao_fec_encode(d, size, tx_data); ao_radio_get(encode_len); @@ -611,8 +615,6 @@ ao_radio_send(const void *d, uint8_t size) ao_radio_put(); } -#define AO_RADIO_MAX_RECV 90 - static uint8_t rx_data[(AO_RADIO_MAX_RECV + 4) * 2 * 8]; static uint16_t rx_data_count; static uint16_t rx_data_consumed; @@ -1026,6 +1028,7 @@ ao_radio_init(void) ao_radio_configured = 0; ao_spi_init_cs (AO_CC1120_SPI_CS_PORT, (1 << AO_CC1120_SPI_CS_PIN)); +#if 0 AO_CC1120_SPI_CS_PORT->bsrr = ((uint32_t) (1 << AO_CC1120_SPI_CS_PIN)); for (i = 0; i < 10000; i++) { if ((SPI_2_PORT->idr & (1 << SPI_2_MISO_PIN)) == 0) @@ -1034,6 +1037,7 @@ ao_radio_init(void) AO_CC1120_SPI_CS_PORT->bsrr = (1 << AO_CC1120_SPI_CS_PIN); if (i == 10000) ao_panic(AO_PANIC_SELF_TEST_CC1120); +#endif /* Enable the EXTI interrupt for the appropriate pin */ ao_enable_port(AO_CC1120_INT_PORT); diff --git a/src/drivers/ao_ms5607.c b/src/drivers/ao_ms5607.c index 077a40e6..ce0bcf4b 100644 --- a/src/drivers/ao_ms5607.c +++ b/src/drivers/ao_ms5607.c @@ -130,6 +130,7 @@ static uint32_t ao_ms5607_get_sample(uint8_t cmd) { uint8_t reply[3]; uint8_t read; + uint32_t loops; ao_ms5607_done = 0; @@ -141,10 +142,15 @@ ao_ms5607_get_sample(uint8_t cmd) { #if AO_MS5607_PRIVATE_PINS ao_spi_put(AO_MS5607_SPI_INDEX); #endif +// loops = 0; cli(); - while (!ao_ms5607_done) + while (!ao_ms5607_done) { +// loops++; ao_sleep((void *) &ao_ms5607_done); + } sei(); +// if (loops > 1) +// printf ("ms5607 loops %d\n", loops); #if AO_MS5607_PRIVATE_PINS stm_gpio_set(AO_MS5607_CS_PORT, AO_MS5607_CS_PIN, 1); #else diff --git a/src/megametrum-v0.1/Makefile b/src/megametrum-v0.1/Makefile index 0e0534a5..b100fafc 100644 --- a/src/megametrum-v0.1/Makefile +++ b/src/megametrum-v0.1/Makefile @@ -22,7 +22,9 @@ INC = \ ao_mma655x.h \ ao_cc1120_CC1120.h \ ao_profile.h \ + ao_task.h \ ao_whiten.h \ + ao_sample_profile.h \ stm32l.h # @@ -32,6 +34,10 @@ INC = \ #PROFILE=ao_profile.c #PROFILE_DEF=-DAO_PROFILE=1 +SAMPLE_PROFILE=ao_sample_profile.c \ + ao_sample_profile_timer.c +SAMPLE_PROFILE_DEF=-DHAS_SAMPLE_PROFILE=1 + # ao_hmc5883.c ALTOS_SRC = \ @@ -80,13 +86,14 @@ ALTOS_SRC = \ ao_packet.c \ ao_companion.c \ ao_pyro.c \ - $(PROFILE) + $(PROFILE) \ + $(SAMPLE_PROFILE) PRODUCT=MegaMetrum-v0.1 PRODUCT_DEF=-DMEGAMETRUM IDPRODUCT=0x0023 -CFLAGS = $(PRODUCT_DEF) $(STM_CFLAGS) $(PROFILE_DEF) -Os -g +CFLAGS = $(PRODUCT_DEF) $(STM_CFLAGS) $(PROFILE_DEF) $(SAMPLE_PROFILE_DEF) -Os -g PROGNAME=megametrum-v0.1 PROG=$(PROGNAME)-$(VERSION).elf diff --git a/src/megametrum-v0.1/ao_megametrum.c b/src/megametrum-v0.1/ao_megametrum.c index d3ae4690..114f144f 100644 --- a/src/megametrum-v0.1/ao_megametrum.c +++ b/src/megametrum-v0.1/ao_megametrum.c @@ -24,6 +24,9 @@ #include #include #include +#if HAS_SAMPLE_PROFILE +#include +#endif #include int @@ -78,6 +81,9 @@ main(void) #if AO_PROFILE ao_profile_init(); #endif +#if HAS_SAMPLE_PROFILE + ao_sample_profile_init(); +#endif ao_start_scheduler(); return 0; diff --git a/src/stm/ao_arch.h b/src/stm/ao_arch.h index 87eda18b..f2de719c 100644 --- a/src/stm/ao_arch.h +++ b/src/stm/ao_arch.h @@ -143,7 +143,7 @@ extern const uint32_t ao_radio_cal; #define ao_arch_cpu_idle() do { \ - asm("wfi"); \ + asm(".global ao_idle_loc\n\twfi\nao_idle_loc:"); \ } while (0) #define ao_arch_restore_stack() do { \ diff --git a/src/stm/ao_sample_profile_timer.c b/src/stm/ao_sample_profile_timer.c new file mode 100644 index 00000000..d5af3a57 --- /dev/null +++ b/src/stm/ao_sample_profile_timer.c @@ -0,0 +1,115 @@ +/* + * Copyright © 2012 Keith Packard + * + * 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 +#include + +struct stm_exception { + uint32_t r0; + uint32_t r1; + uint32_t r2; + uint32_t r3; + uint32_t r12; + uint32_t lr; + uint32_t pc; + uint32_t psr; +}; + +void +stm_tim10_isr(void) +{ + struct stm_exception *ex; + + asm("mov %0,sp" : "=&r" (ex)); + + stm_tim10.sr = 0; + ao_sample_profile_point(ex->pc, stm_tim11.cnt, (ex->psr & 0xff) != 0); +} + +uint16_t +ao_sample_profile_timer_start(void) +{ + /* Reset counts */ + stm_tim11.cnt = 0; + stm_tim10.cnt = 0; + + /* Turn on timer 11 */ + stm_tim11.cr1 = ((0 << STM_TIM1011_CR1_CKD) | + (0 << STM_TIM1011_CR1_ARPE) | + (1 << STM_TIM1011_CR1_URS) | + (0 << STM_TIM1011_CR1_UDIS) | + (1 << STM_TIM1011_CR1_CEN)); + + /* Turn on timer 10 */ + stm_tim10.cr1 = ((0 << STM_TIM1011_CR1_CKD) | + (0 << STM_TIM1011_CR1_ARPE) | + (1 << STM_TIM1011_CR1_URS) | + (0 << STM_TIM1011_CR1_UDIS) | + (1 << STM_TIM1011_CR1_CEN)); + return stm_tim11.cnt; +} + +void +ao_sample_profile_timer_stop(void) +{ + stm_tim10.cr1 = 0; + stm_tim11.cr1 = 0; +} + +#if AO_APB2_PRESCALER > 1 +#define TIMER_91011_SCALER 2 +#else +#define TIMER_91011_SCALER 1 +#endif + +#define TIMER_10kHz ((AO_PCLK2 * TIMER_91011_SCALER) / 10000) +#define TIMER_1kHz ((AO_PCLK2 * TIMER_91011_SCALER) / 1000) + +void +ao_sample_profile_timer_init(void) +{ + /* Turn on power for timer 10 and 11 */ + stm_rcc.apb2enr |= (1 << STM_RCC_APB2ENR_TIM10EN) | (1 << STM_RCC_APB2ENR_TIM11EN); + + /* Timer 10 is the 1kHz interrupt */ + stm_tim10.cr1 = 0; + stm_tim10.psc = TIMER_10kHz; + stm_tim10.arr = 9; + stm_tim10.cnt = 0; + + /* Enable timer 10 update interrupt */ + stm_tim10.dier = (1 << STM_TIM1011_DIER_UIE); + + /* Poke timer to reload values */ + stm_tim10.egr |= (1 << STM_TIM1011_EGR_UG); + + /* Timer 11 is the 1kHz counter */ + stm_tim11.cr1 = 0; + stm_tim11.psc = TIMER_1kHz; + stm_tim11.arr = 0xffff; + stm_tim11.cnt = 0; + + /* Disable interrupts for timer 11 */ + stm_tim11.dier = 0; + + /* Poke timer to reload values */ + stm_tim11.egr |= (1 << STM_TIM1011_EGR_UG); + + stm_tim10.sr = 0; + stm_nvic_set_enable(STM_ISR_TIM10_POS); + stm_nvic_set_priority(STM_ISR_TIM10_POS, AO_STM_NVIC_HIGH_PRIORITY); +} diff --git a/src/stm/ao_sample_profile_timer.h b/src/stm/ao_sample_profile_timer.h new file mode 100644 index 00000000..1da1bfb4 --- /dev/null +++ b/src/stm/ao_sample_profile_timer.h @@ -0,0 +1,32 @@ +/* + * Copyright © 2012 Keith Packard + * + * 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_SAMPLE_PROFILE_TIMER_H_ +#define _AO_SAMPLE_PROFILE_TIMER_H_ + +uint16_t +ao_sample_profile_timer_start(void); + +void +ao_sample_profile_timer_stop(void); + +void +ao_sample_profile_timer_init(void); + +#define ao_sample_profile_timer_value() ((uint16_t) stm_tim11.cnt) + +#endif /* _AO_SAMPLE_PROFILE_TIMER_H_ */ diff --git a/src/stm/stm32l.h b/src/stm/stm32l.h index 25f5af07..e950d09b 100644 --- a/src/stm/stm32l.h +++ b/src/stm/stm32l.h @@ -254,8 +254,138 @@ struct stm_tim { }; extern struct stm_tim stm_tim9; -extern struct stm_tim stm_tim10; -extern struct stm_tim stm_tim11; + +struct stm_tim1011 { + vuint32_t cr1; + uint32_t unused_4; + vuint32_t smcr; + vuint32_t dier; + vuint32_t sr; + vuint32_t egr; + vuint32_t ccmr1; + uint32_t unused_1c; + vuint32_t ccer; + vuint32_t cnt; + vuint32_t psc; + vuint32_t arr; + uint32_t unused_30; + vuint32_t ccr1; + uint32_t unused_38; + uint32_t unused_3c; + uint32_t unused_40; + uint32_t unused_44; + uint32_t unused_48; + uint32_t unused_4c; + vuint32_t or; +}; + +extern struct stm_tim1011 stm_tim10; +extern struct stm_tim1011 stm_tim11; + +#define STM_TIM1011_CR1_CKD 8 +#define STM_TIM1011_CR1_CKD_1 0 +#define STM_TIM1011_CR1_CKD_2 1 +#define STM_TIM1011_CR1_CKD_4 2 +#define STM_TIM1011_CR1_CKD_MASK 3 +#define STM_TIM1011_CR1_ARPE 7 +#define STM_TIM1011_CR1_URS 2 +#define STM_TIM1011_CR1_UDIS 1 +#define STM_TIM1011_CR1_CEN 0 + +#define STM_TIM1011_SMCR_ETP 15 +#define STM_TIM1011_SMCR_ECE 14 +#define STM_TIM1011_SMCR_ETPS 12 +#define STM_TIM1011_SMCR_ETPS_OFF 0 +#define STM_TIM1011_SMCR_ETPS_2 1 +#define STM_TIM1011_SMCR_ETPS_4 2 +#define STM_TIM1011_SMCR_ETPS_8 3 +#define STM_TIM1011_SMCR_ETPS_MASK 3 +#define STM_TIM1011_SMCR_ETF 8 +#define STM_TIM1011_SMCR_ETF_NONE 0 +#define STM_TIM1011_SMCR_ETF_CK_INT_2 1 +#define STM_TIM1011_SMCR_ETF_CK_INT_4 2 +#define STM_TIM1011_SMCR_ETF_CK_INT_8 3 +#define STM_TIM1011_SMCR_ETF_DTS_2_6 4 +#define STM_TIM1011_SMCR_ETF_DTS_2_8 5 +#define STM_TIM1011_SMCR_ETF_DTS_4_6 6 +#define STM_TIM1011_SMCR_ETF_DTS_4_8 7 +#define STM_TIM1011_SMCR_ETF_DTS_8_6 8 +#define STM_TIM1011_SMCR_ETF_DTS_8_8 9 +#define STM_TIM1011_SMCR_ETF_DTS_16_5 10 +#define STM_TIM1011_SMCR_ETF_DTS_16_6 11 +#define STM_TIM1011_SMCR_ETF_DTS_16_8 12 +#define STM_TIM1011_SMCR_ETF_DTS_32_5 13 +#define STM_TIM1011_SMCR_ETF_DTS_32_6 14 +#define STM_TIM1011_SMCR_ETF_DTS_32_8 15 +#define STM_TIM1011_SMCR_ETF_MASK 15 + +#define STM_TIM1011_DIER_CC1E 1 +#define STM_TIM1011_DIER_UIE 0 + +#define STM_TIM1011_SR_CC1OF 9 +#define STM_TIM1011_SR_CC1IF 1 +#define STM_TIM1011_SR_UIF 0 + +#define STM_TIM1011_EGR_CC1G 1 +#define STM_TIM1011_EGR_UG 0 + +#define STM_TIM1011_CCMR1_OC1CE 7 +#define STM_TIM1011_CCMR1_OC1M 4 +#define STM_TIM1011_CCMR1_OC1M_FROZEN 0 +#define STM_TIM1011_CCMR1_OC1M_SET_1_ACTIVE_ON_MATCH 1 +#define STM_TIM1011_CCMR1_OC1M_SET_1_INACTIVE_ON_MATCH 2 +#define STM_TIM1011_CCMR1_OC1M_TOGGLE 3 +#define STM_TIM1011_CCMR1_OC1M_FORCE_INACTIVE 4 +#define STM_TIM1011_CCMR1_OC1M_FORCE_ACTIVE 5 +#define STM_TIM1011_CCMR1_OC1M_PWM_MODE_1 6 +#define STM_TIM1011_CCMR1_OC1M_PWM_MODE_2 7 +#define STM_TIM1011_CCMR1_OC1M_MASK 7 +#define STM_TIM1011_CCMR1_OC1PE 3 +#define STM_TIM1011_CCMR1_OC1FE 2 +#define STM_TIM1011_CCMR1_CC1S 0 +#define STM_TIM1011_CCMR1_CC1S_OUTPUT 0 +#define STM_TIM1011_CCMR1_CC1S_INPUT_TI1 1 +#define STM_TIM1011_CCMR1_CC1S_INPUT_TI2 2 +#define STM_TIM1011_CCMR1_CC1S_INPUT_TRC 3 +#define STM_TIM1011_CCMR1_CC1S_MASK 3 + +#define STM_TIM1011_CCMR1_IC1F_NONE 0 +#define STM_TIM1011_CCMR1_IC1F_CK_INT_2 1 +#define STM_TIM1011_CCMR1_IC1F_CK_INT_4 2 +#define STM_TIM1011_CCMR1_IC1F_CK_INT_8 3 +#define STM_TIM1011_CCMR1_IC1F_DTS_2_6 4 +#define STM_TIM1011_CCMR1_IC1F_DTS_2_8 5 +#define STM_TIM1011_CCMR1_IC1F_DTS_4_6 6 +#define STM_TIM1011_CCMR1_IC1F_DTS_4_8 7 +#define STM_TIM1011_CCMR1_IC1F_DTS_8_6 8 +#define STM_TIM1011_CCMR1_IC1F_DTS_8_8 9 +#define STM_TIM1011_CCMR1_IC1F_DTS_16_5 10 +#define STM_TIM1011_CCMR1_IC1F_DTS_16_6 11 +#define STM_TIM1011_CCMR1_IC1F_DTS_16_8 12 +#define STM_TIM1011_CCMR1_IC1F_DTS_32_5 13 +#define STM_TIM1011_CCMR1_IC1F_DTS_32_6 14 +#define STM_TIM1011_CCMR1_IC1F_DTS_32_8 15 +#define STM_TIM1011_CCMR1_IC1F_MASK 15 +#define STM_TIM1011_CCMR1_IC1PSC 2 +#define STM_TIM1011_CCMR1_IC1PSC_1 0 +#define STM_TIM1011_CCMR1_IC1PSC_2 1 +#define STM_TIM1011_CCMR1_IC1PSC_4 2 +#define STM_TIM1011_CCMR1_IC1PSC_8 3 +#define STM_TIM1011_CCMR1_IC1PSC_MASK 3 +#define STM_TIM1011_CCMR1_CC1S 0 + +#define STM_TIM1011_CCER_CC1NP 3 +#define STM_TIM1011_CCER_CC1P 1 +#define STM_TIM1011_CCER_CC1E 0 + +#define STM_TIM1011_OR_TI1_RMP_RI 3 +#define STM_TIM1011_ETR_RMP 2 +#define STM_TIM1011_TI1_RMP 0 +#define STM_TIM1011_TI1_RMP_GPIO 0 +#define STM_TIM1011_TI1_RMP_LSI 1 +#define STM_TIM1011_TI1_RMP_LSE 2 +#define STM_TIM1011_TI1_RMP_RTC 3 +#define STM_TIM1011_TI1_RMP_MASK 3 /* Flash interface */ -- cgit v1.2.3 From e80fa6de4ccc5c4851eab9fb941f9282d2e3eb16 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 24 Oct 2012 22:35:32 -0700 Subject: altos: Replace __critical usage with ao_arch_critical as needed sdcc offers __critical as a machine-independent way to block interrupts, but as gcc doesn't, we need to use a compiler-independent construct instead. ao_arch_critical has been around since the AVR port, but some old __critical usages remained. This fixes a bunch of random hangs when communicating with MM over USB or the radio as the various stdio loops were running without interrupts blocked between the test and the sleep. Signed-off-by: Keith Packard --- src/core/ao.h | 2 +- src/core/ao_ignite.c | 10 ++++++---- src/core/ao_mutex.c | 8 ++++---- src/core/ao_packet.h | 2 +- src/core/ao_panic.c | 3 ++- src/core/ao_stdio.c | 26 ++++++++++++++------------ src/drivers/ao_btm.c | 24 +++++++++++++----------- src/drivers/ao_packet.c | 8 +++++++- src/drivers/ao_packet_master.c | 2 +- src/stm/ao_arch.h | 26 +++++++++++++++++++++++--- src/stm/ao_timer.c | 8 +++++--- src/stm/ao_usb_stm.c | 38 ++++++++++++++++++++++---------------- 12 files changed, 99 insertions(+), 58 deletions(-) (limited to 'src/stm') diff --git a/src/core/ao.h b/src/core/ao.h index e559e876..2b375cfd 100644 --- a/src/core/ao.h +++ b/src/core/ao.h @@ -101,7 +101,7 @@ ao_delay(uint16_t ticks); /* Set the ADC interval */ void -ao_timer_set_adc_interval(uint8_t interval) __critical; +ao_timer_set_adc_interval(uint8_t interval); /* Timer interrupt */ void diff --git a/src/core/ao_ignite.c b/src/core/ao_ignite.c index c7829fc3..693b7c7a 100644 --- a/src/core/ao_ignite.c +++ b/src/core/ao_ignite.c @@ -21,10 +21,12 @@ __xdata struct ao_ignition ao_ignition[2]; void -ao_ignite(enum ao_igniter igniter) __critical +ao_ignite(enum ao_igniter igniter) { + cli(); ao_ignition[igniter].request = 1; ao_wakeup(&ao_ignition); + sei(); } #ifndef AO_SENSE_DROGUE @@ -39,12 +41,12 @@ ao_igniter_status(enum ao_igniter igniter) __pdata int16_t value; __pdata uint8_t request, firing, fired; - __critical { + ao_arch_critical( ao_data_get(&packet); request = ao_ignition[igniter].request; fired = ao_ignition[igniter].fired; firing = ao_ignition[igniter].firing; - } + ); if (firing || (request && !fired)) return ao_igniter_active; @@ -79,7 +81,7 @@ ao_igniter_status(enum ao_igniter igniter) #endif void -ao_igniter_fire(enum ao_igniter igniter) __critical +ao_igniter_fire(enum ao_igniter igniter) { ao_ignition[igniter].firing = 1; switch(ao_config.ignite_mode) { diff --git a/src/core/ao_mutex.c b/src/core/ao_mutex.c index c82a7d57..952ff462 100644 --- a/src/core/ao_mutex.c +++ b/src/core/ao_mutex.c @@ -22,11 +22,11 @@ ao_mutex_get(__xdata uint8_t *mutex) __reentrant { if (*mutex == ao_cur_task->task_id) ao_panic(AO_PANIC_MUTEX); - __critical { + ao_arch_critical( while (*mutex) ao_sleep(mutex); *mutex = ao_cur_task->task_id; - } + ); } void @@ -34,8 +34,8 @@ ao_mutex_put(__xdata uint8_t *mutex) __reentrant { if (*mutex != ao_cur_task->task_id) ao_panic(AO_PANIC_MUTEX); - __critical { + ao_arch_critical( *mutex = 0; ao_wakeup(mutex); - } + ); } diff --git a/src/core/ao_packet.h b/src/core/ao_packet.h index 9058c347..0eafd3b2 100644 --- a/src/core/ao_packet.h +++ b/src/core/ao_packet.h @@ -63,7 +63,7 @@ void ao_packet_putchar(char c) __reentrant; char -ao_packet_pollchar(void) __critical; +ao_packet_pollchar(void); #if PACKET_HAS_MASTER /* ao_packet_master.c */ diff --git a/src/core/ao_panic.c b/src/core/ao_panic.c index 3c0b471e..c29cd8fe 100644 --- a/src/core/ao_panic.c +++ b/src/core/ao_panic.c @@ -53,7 +53,8 @@ ao_panic(uint8_t reason) ao_cur_task = NULL; printf ("panic %d\n", reason); #endif - __critical for (;;) { + ao_arch_block_interrupts(); + for (;;) { ao_panic_delay(20); for (n = 0; n < 5; n++) { ao_led_on(AO_LED_PANIC); diff --git a/src/core/ao_stdio.c b/src/core/ao_stdio.c index 656b23c9..8cf66a23 100644 --- a/src/core/ao_stdio.c +++ b/src/core/ao_stdio.c @@ -96,21 +96,23 @@ flush(void) __xdata uint8_t ao_stdin_ready; char -getchar(void) __reentrant __critical +getchar(void) __reentrant { char c; - int8_t stdio = ao_cur_stdio; + ao_arch_critical( + int8_t stdio = ao_cur_stdio; - for (;;) { - c = ao_stdios[stdio].pollchar(); - if (c != AO_READ_AGAIN) - break; - if (++stdio == ao_num_stdios) - stdio = 0; - if (stdio == ao_cur_stdio) - ao_sleep(&ao_stdin_ready); - } - ao_cur_stdio = stdio; + for (;;) { + c = ao_stdios[stdio].pollchar(); + if (c != AO_READ_AGAIN) + break; + if (++stdio == ao_num_stdios) + stdio = 0; + if (stdio == ao_cur_stdio) + ao_sleep(&ao_stdin_ready); + } + ao_cur_stdio = stdio; + ); return c; } diff --git a/src/drivers/ao_btm.c b/src/drivers/ao_btm.c index f193ac8e..f3816047 100644 --- a/src/drivers/ao_btm.c +++ b/src/drivers/ao_btm.c @@ -312,18 +312,20 @@ __xdata struct ao_task ao_btm_task; #endif void -ao_btm_check_link() __critical +ao_btm_check_link() { - /* Check the pin and configure the interrupt detector to wait for the - * pin to flip the other way - */ - if (BT_LINK_PIN) { - ao_btm_connected = 0; - PICTL |= BT_PICTL_ICON; - } else { - ao_btm_connected = 1; - PICTL &= ~BT_PICTL_ICON; - } + ao_arch_critical( + /* Check the pin and configure the interrupt detector to wait for the + * pin to flip the other way + */ + if (BT_LINK_PIN) { + ao_btm_connected = 0; + PICTL |= BT_PICTL_ICON; + } else { + ao_btm_connected = 1; + PICTL &= ~BT_PICTL_ICON; + } + ); } void diff --git a/src/drivers/ao_packet.c b/src/drivers/ao_packet.c index 2bada949..3c1e7a18 100644 --- a/src/drivers/ao_packet.c +++ b/src/drivers/ao_packet.c @@ -155,6 +155,9 @@ ao_packet_flush(void) void ao_packet_putchar(char c) __reentrant { + /* No need to block interrupts, all variables here + * are only manipulated in task context + */ while (ao_packet_tx_used == AO_PACKET_MAX && ao_packet_enable) { #if PACKET_HAS_MASTER ao_packet_flush(); @@ -167,8 +170,11 @@ ao_packet_putchar(char c) __reentrant } char -ao_packet_pollchar(void) __critical +ao_packet_pollchar(void) { + /* No need to block interrupts, all variables here + * are only manipulated in task context + */ if (!ao_packet_enable) return AO_READ_AGAIN; diff --git a/src/drivers/ao_packet_master.c b/src/drivers/ao_packet_master.c index e97a6648..481232df 100644 --- a/src/drivers/ao_packet_master.c +++ b/src/drivers/ao_packet_master.c @@ -18,7 +18,7 @@ #include "ao.h" static char -ao_packet_getchar(void) __critical +ao_packet_getchar(void) { char c; while ((c = ao_packet_pollchar()) == AO_READ_AGAIN) { diff --git a/src/stm/ao_arch.h b/src/stm/ao_arch.h index f2de719c..0c3cfc91 100644 --- a/src/stm/ao_arch.h +++ b/src/stm/ao_arch.h @@ -43,7 +43,6 @@ #define __xdata #define __code const #define __reentrant -#define __critical #define __interrupt(n) #define __at(n) @@ -83,8 +82,29 @@ extern const uint32_t ao_radio_cal; #define ao_arch_task_members\ uint32_t *sp; /* saved stack pointer */ -#define cli() asm("cpsid i") -#define sei() asm("cpsie i") +#define ao_arch_block_interrupts() asm("cpsid i") +#define ao_arch_release_interrupts() asm("cpsie i") + +#define cli() ao_arch_block_interrupts() +#define sei() ao_arch_release_interrupts() + +static uint32_t +ao_arch_irqsave(void) { + uint32_t primask; + asm("mrs %0,primask" : "=&r" (primask)); + ao_arch_block_interrupts(); + return primask; +} + +static void +ao_arch_irqrestore(uint32_t primask) { + asm("msr primask,%0" : : "r" (primask)); +} + +static void +ao_arch_memory_barrier() { + asm volatile("" ::: "memory"); +} #define ao_arch_init_stack(task, start) do { \ uint32_t *sp = (uint32_t *) (task->stack + AO_STACK_SIZE); \ diff --git a/src/stm/ao_timer.c b/src/stm/ao_timer.c index f3011d3f..d82a803e 100644 --- a/src/stm/ao_timer.c +++ b/src/stm/ao_timer.c @@ -56,10 +56,12 @@ void stm_tim6_isr(void) #if HAS_ADC void -ao_timer_set_adc_interval(uint8_t interval) __critical +ao_timer_set_adc_interval(uint8_t interval) { - ao_data_interval = interval; - ao_data_count = 0; + ao_arch_critical( + ao_data_interval = interval; + ao_data_count = 0; + ); } #endif diff --git a/src/stm/ao_usb_stm.c b/src/stm/ao_usb_stm.c index 4f37a7d9..8e7dacc5 100644 --- a/src/stm/ao_usb_stm.c +++ b/src/stm/ao_usb_stm.c @@ -799,25 +799,23 @@ ao_usb_in_send(void) ao_usb_tx_count = 0; } -/* Wait for a free IN buffer */ +/* Wait for a free IN buffer. Interrupts are blocked */ static void -ao_usb_in_wait(void) +_ao_usb_in_wait(void) { for (;;) { /* Check if the current buffer is writable */ if (ao_usb_tx_count < AO_USB_IN_SIZE) break; - cli(); /* Wait for an IN buffer to be ready */ while (ao_usb_in_pending) ao_sleep(&ao_usb_in_pending); - sei(); } } void -ao_usb_flush(void) __critical +ao_usb_flush(void) { if (!ao_usb_running) return; @@ -829,24 +827,25 @@ ao_usb_flush(void) __critical * packet was full, in which case we now * want to send an empty packet */ + ao_arch_block_interrupts(); if (!ao_usb_in_flushed) { ao_usb_in_flushed = 1; - cli(); /* Wait for an IN buffer to be ready */ while (ao_usb_in_pending) ao_sleep(&ao_usb_in_pending); - sei(); ao_usb_in_send(); } + ao_arch_release_interrupts(); } void -ao_usb_putchar(char c) __critical __reentrant +ao_usb_putchar(char c) { if (!ao_usb_running) return; - ao_usb_in_wait(); + ao_arch_block_interrupts(); + _ao_usb_in_wait(); ao_usb_in_flushed = 0; ao_usb_tx_buffer[ao_usb_tx_count++] = (uint8_t) c; @@ -854,10 +853,11 @@ ao_usb_putchar(char c) __critical __reentrant /* Send the packet when full */ if (ao_usb_tx_count == AO_USB_IN_SIZE) ao_usb_in_send(); + ao_arch_release_interrupts(); } static void -ao_usb_out_recv(void) +_ao_usb_out_recv(void) { ao_usb_out_avail = 0; @@ -888,7 +888,7 @@ _ao_usb_pollchar(void) /* Check to see if a packet has arrived */ if (!ao_usb_out_avail) return AO_READ_AGAIN; - ao_usb_out_recv(); + _ao_usb_out_recv(); } /* Pull a character out of the fifo */ @@ -900,27 +900,28 @@ char ao_usb_pollchar(void) { char c; - cli(); + ao_arch_block_interrupts(); c = _ao_usb_pollchar(); - sei(); + ao_arch_release_interrupts(); return c; } char -ao_usb_getchar(void) __critical +ao_usb_getchar(void) { char c; - cli(); + ao_arch_block_interrupts(); while ((c = _ao_usb_pollchar()) == AO_READ_AGAIN) ao_sleep(&ao_stdin_ready); - sei(); + ao_arch_release_interrupts(); return c; } void ao_usb_disable(void) { + ao_arch_block_interrupts(); stm_usb.cntr = (1 << STM_USB_CNTR_FRES); stm_usb.istr = 0; @@ -932,6 +933,7 @@ ao_usb_disable(void) /* Disable the interface */ stm_rcc.apb1enr &+ ~(1 << STM_RCC_APB1ENR_USBEN); + ao_arch_release_interrupts(); } void @@ -954,6 +956,8 @@ ao_usb_enable(void) * pulled low and doesn't work at all */ + ao_arch_block_interrupts(); + /* Route interrupts */ stm_nvic_set_priority(STM_ISR_USB_LP_POS, 3); stm_nvic_set_enable(STM_ISR_USB_LP_POS); @@ -985,6 +989,8 @@ ao_usb_enable(void) (0 << STM_USB_CNTR_PDWN) | (0 << STM_USB_CNTR_FRES)); + ao_arch_release_interrupts(); + for (t = 0; t < 1000; t++) ao_arch_nop(); /* Enable USB pull-up */ -- cgit v1.2.3 From 4b13d3c659240e5a8347b1ba7ab0bf1d8355eba3 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 24 Oct 2012 22:46:55 -0700 Subject: altos: Add stack-guard code. Uses STM MPU to trap stack overflow. This marks the lowest portion of the stack as inaccessible to the CPU, causing the processor to fault when it reaches it. The fault then generates a panic message so that the user can know what happened. Signed-off-by: Keith Packard --- src/core/ao.h | 1 + src/core/ao_task.c | 6 ++ src/megametrum-v0.1/Makefile | 10 ++- src/megametrum-v0.1/ao_megametrum.c | 7 ++ src/stm-bringup/Makefile | 2 +- src/stm-bringup/ao.h | 18 +++++ src/stm/ao_interrupt.c | 3 +- src/stm/ao_mpu.h | 29 +++++++ src/stm/ao_mpu_stm.c | 149 ++++++++++++++++++++++++++++++++++++ src/stm/registers.ld | 2 + src/stm/stm32l.h | 64 ++++++++++++++++ 11 files changed, 286 insertions(+), 5 deletions(-) create mode 100644 src/stm-bringup/ao.h create mode 100644 src/stm/ao_mpu.h create mode 100644 src/stm/ao_mpu_stm.c (limited to 'src/stm') diff --git a/src/core/ao.h b/src/core/ao.h index 2b375cfd..87e69e19 100644 --- a/src/core/ao.h +++ b/src/core/ao.h @@ -64,6 +64,7 @@ #define AO_PANIC_BT 11 /* Communications with bluetooth device failed */ #define AO_PANIC_STACK 12 /* Stack overflow */ #define AO_PANIC_SPI 13 /* SPI communication failure */ +#define AO_PANIC_CRASH 14 /* Processor crashed */ #define AO_PANIC_SELF_TEST_CC1120 0x40 | 1 /* Self test failure */ #define AO_PANIC_SELF_TEST_HMC5883 0x40 | 2 /* Self test failure */ #define AO_PANIC_SELF_TEST_MPU6000 0x40 | 3 /* Self test failure */ diff --git a/src/core/ao_task.c b/src/core/ao_task.c index c2b1b270..df70b906 100644 --- a/src/core/ao_task.c +++ b/src/core/ao_task.c @@ -20,6 +20,9 @@ #if HAS_SAMPLE_PROFILE #include #endif +#if HAS_STACK_GUARD +#include +#endif #define AO_NO_TASK_INDEX 0xff @@ -127,6 +130,9 @@ ao_yield(void) ao_arch_naked_define ao_cur_task->start = ao_sample_profile_timer_value(); #endif } +#if HAS_STACK_GUARD + ao_mpu_stack_guard(ao_cur_task->stack); +#endif #if AO_CHECK_STACK cli(); in_yield = 0; diff --git a/src/megametrum-v0.1/Makefile b/src/megametrum-v0.1/Makefile index b100fafc..487a643f 100644 --- a/src/megametrum-v0.1/Makefile +++ b/src/megametrum-v0.1/Makefile @@ -25,11 +25,13 @@ INC = \ ao_task.h \ ao_whiten.h \ ao_sample_profile.h \ + ao_mpu.h \ stm32l.h # # Common AltOS sources # +# ao_hmc5883.c #PROFILE=ao_profile.c #PROFILE_DEF=-DAO_PROFILE=1 @@ -38,7 +40,8 @@ SAMPLE_PROFILE=ao_sample_profile.c \ ao_sample_profile_timer.c SAMPLE_PROFILE_DEF=-DHAS_SAMPLE_PROFILE=1 -# ao_hmc5883.c +STACK_GUARD=ao_mpu_stm.c +STACK_GUARD_DEF=-DHAS_STACK_GUARD=1 ALTOS_SRC = \ ao_interrupt.c \ @@ -87,13 +90,14 @@ ALTOS_SRC = \ ao_companion.c \ ao_pyro.c \ $(PROFILE) \ - $(SAMPLE_PROFILE) + $(SAMPLE_PROFILE) \ + $(STACK_GUARD) PRODUCT=MegaMetrum-v0.1 PRODUCT_DEF=-DMEGAMETRUM IDPRODUCT=0x0023 -CFLAGS = $(PRODUCT_DEF) $(STM_CFLAGS) $(PROFILE_DEF) $(SAMPLE_PROFILE_DEF) -Os -g +CFLAGS = $(PRODUCT_DEF) $(STM_CFLAGS) $(PROFILE_DEF) $(SAMPLE_PROFILE_DEF) $(STACK_GUARD_DEF) -Os -g PROGNAME=megametrum-v0.1 PROG=$(PROGNAME)-$(VERSION).elf diff --git a/src/megametrum-v0.1/ao_megametrum.c b/src/megametrum-v0.1/ao_megametrum.c index 114f144f..43c2292d 100644 --- a/src/megametrum-v0.1/ao_megametrum.c +++ b/src/megametrum-v0.1/ao_megametrum.c @@ -28,12 +28,19 @@ #include #endif #include +#if HAS_STACK_GUARD +#include +#endif int main(void) { ao_clock_init(); +#if HAS_STACK_GUARD + ao_mpu_init(); +#endif + ao_serial_init(); ao_led_init(LEDS_AVAILABLE); ao_led_on(AO_LED_GREEN); diff --git a/src/stm-bringup/Makefile b/src/stm-bringup/Makefile index d45e836d..5cc94bd9 100644 --- a/src/stm-bringup/Makefile +++ b/src/stm-bringup/Makefile @@ -12,7 +12,7 @@ PDCLIB=/home/keithp/sat C_LIB=$(PDCLIB)/lib/pdclib.a C_INC=-I$(PDCLIB)/include -DEF_CFLAGS=-g -std=gnu99 -Os -mlittle-endian -mthumb -ffreestanding -nostdlib -I../../src/stm $(C_INC) +DEF_CFLAGS=-g -std=gnu99 -Os -mlittle-endian -mthumb -ffreestanding -nostdlib -I. -I../../src/stm $(C_INC) # to run from SRAM LD_FLAGS_RAM=-L../stm -Wl,-Taltos-ram.ld diff --git a/src/stm-bringup/ao.h b/src/stm-bringup/ao.h new file mode 100644 index 00000000..27204fae --- /dev/null +++ b/src/stm-bringup/ao.h @@ -0,0 +1,18 @@ +/* + * Copyright © 2012 Keith Packard + * + * 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. + */ + +#define ao_panic(n) for(;;); diff --git a/src/stm/ao_interrupt.c b/src/stm/ao_interrupt.c index 6b4a9700..a423d8b1 100644 --- a/src/stm/ao_interrupt.c +++ b/src/stm/ao_interrupt.c @@ -15,6 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ +#include #include "stm32l.h" #include @@ -28,7 +29,7 @@ extern char __bss_start__, __bss_end__; void stm_halt_isr(void) { - for(;;); + ao_panic(AO_PANIC_CRASH); } void stm_ignore_isr(void) diff --git a/src/stm/ao_mpu.h b/src/stm/ao_mpu.h new file mode 100644 index 00000000..cc6132a5 --- /dev/null +++ b/src/stm/ao_mpu.h @@ -0,0 +1,29 @@ +/* + * Copyright © 2012 Keith Packard + * + * 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_MPU_H_ +#define _AO_MPU_H_ + +extern uint32_t ao_mpu_dregion; + +void +ao_mpu_stack_guard(void *stack); + +void +ao_mpu_init(void); + +#endif /* _AO_MPU_H_ */ diff --git a/src/stm/ao_mpu_stm.c b/src/stm/ao_mpu_stm.c new file mode 100644 index 00000000..969d7446 --- /dev/null +++ b/src/stm/ao_mpu_stm.c @@ -0,0 +1,149 @@ +/* + * Copyright © 2012 Keith Packard + * + * 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 +#include + +static uint32_t stm_mpu_dregion; + +void +ao_mpu_init(void) +{ + uint32_t region; + + /* Check to see how many regions we have */ + stm_mpu_dregion = (stm_mpu.typer >> STM_MPU_TYPER_DREGION) & STM_MPU_TYPER_DREGION_MASK; + + /* No MPU at all */ + if (stm_mpu_dregion == 0) + return; + + /* Disable MPU */ + stm_mpu.cr = ((0 << STM_MPU_CR_PRIVDEFENA) | + (0 << STM_MPU_CR_HFNMIENA) | + (0 << STM_MPU_CR_ENABLE)); + + /* Disable all regions */ + for (region = 0; region < stm_mpu_dregion; region++) { + /* Set the base address and RNR value */ + stm_mpu.rbar = ((0 & (STM_MPU_RBAR_ADDR_MASK << STM_MPU_RBAR_ADDR)) | + (1 << STM_MPU_RBAR_VALID) | + (region << STM_MPU_RBAR_REGION)); + + /* Disable this region */ + stm_mpu.rasr = 0; + } + + region = 0; + + /* Flash */ + /* 0x00000000 - 0x1fffffff */ + stm_mpu.rbar = (0x0000000 | + (1 << STM_MPU_RBAR_VALID) | + (region << STM_MPU_RBAR_REGION)); + + stm_mpu.rasr = ((0 << STM_MPU_RASR_XN) | + (STM_MPU_RASR_AP_RO_RO << STM_MPU_RASR_AP) | + (5 << STM_MPU_RASR_TEX) | + (0 << STM_MPU_RASR_C) | + (1 << STM_MPU_RASR_B) | + (0 << STM_MPU_RASR_S) | + (0 << STM_MPU_RASR_SRD) | + (28 << STM_MPU_RASR_SIZE) | + (1 << STM_MPU_RASR_ENABLE)); + region++; + + /* Ram */ + /* 0x20000000 - 0x3fffffff */ + stm_mpu.rbar = (0x20000000 | + (1 << STM_MPU_RBAR_VALID) | + (region << STM_MPU_RBAR_REGION)); + + stm_mpu.rasr = ((0 << STM_MPU_RASR_XN) | + (STM_MPU_RASR_AP_RW_RW << STM_MPU_RASR_AP) | + (5 << STM_MPU_RASR_TEX) | + (0 << STM_MPU_RASR_C) | + (1 << STM_MPU_RASR_B) | + (0 << STM_MPU_RASR_S) | + (0 << STM_MPU_RASR_SRD) | + (28 << STM_MPU_RASR_SIZE) | + (1 << STM_MPU_RASR_ENABLE)); + region++; + + /* Peripherals */ + + /* 0x4000000 - 0x7ffffff */ + stm_mpu.rbar = (0x40000000 | + (1 << STM_MPU_RBAR_VALID) | + (region << STM_MPU_RBAR_REGION)); + + stm_mpu.rasr = ((1 << STM_MPU_RASR_XN) | + (STM_MPU_RASR_AP_RW_RW << STM_MPU_RASR_AP) | + (2 << STM_MPU_RASR_TEX) | + (0 << STM_MPU_RASR_C) | + (0 << STM_MPU_RASR_B) | + (0 << STM_MPU_RASR_S) | + (0 << STM_MPU_RASR_SRD) | + (29 << STM_MPU_RASR_SIZE) | + (1 << STM_MPU_RASR_ENABLE)); + region++; + + /* 0x8000000 - 0xffffffff */ + stm_mpu.rbar = (0x80000000 | + (1 << STM_MPU_RBAR_VALID) | + (region << STM_MPU_RBAR_REGION)); + + stm_mpu.rasr = ((1 << STM_MPU_RASR_XN) | + (STM_MPU_RASR_AP_RW_RW << STM_MPU_RASR_AP) | + (2 << STM_MPU_RASR_TEX) | + (0 << STM_MPU_RASR_C) | + (0 << STM_MPU_RASR_B) | + (0 << STM_MPU_RASR_S) | + (0 << STM_MPU_RASR_SRD) | + (30 << STM_MPU_RASR_SIZE) | + (1 << STM_MPU_RASR_ENABLE)); + region++; + + /* Enable MPU */ + stm_mpu.cr = ((0 << STM_MPU_CR_PRIVDEFENA) | + (0 << STM_MPU_CR_HFNMIENA) | + (1 << STM_MPU_CR_ENABLE)); +} + +/* + * Protect the base of the stack from CPU access + */ + +void +ao_mpu_stack_guard(void *base) +{ + uintptr_t addr = (uintptr_t) base; + + /* Round up to cover the lowest possible 32-byte region */ + addr = (addr + ~(STM_MPU_RBAR_ADDR_MASK << STM_MPU_RBAR_ADDR)) & (STM_MPU_RBAR_ADDR_MASK << STM_MPU_RBAR_ADDR); + + stm_mpu.rbar = addr | (1 << STM_MPU_RBAR_VALID) | (7 << STM_MPU_RBAR_REGION); + stm_mpu.rasr = ((1 << STM_MPU_RASR_XN) | + (STM_MPU_RASR_AP_NONE_NONE << STM_MPU_RASR_AP) | + (5 << STM_MPU_RASR_TEX) | + (0 << STM_MPU_RASR_C) | + (1 << STM_MPU_RASR_B) | + (0 << STM_MPU_RASR_S) | + (0 << STM_MPU_RASR_SRD) | + (4 << STM_MPU_RASR_SIZE) | + (1 << STM_MPU_RASR_ENABLE)); +} diff --git a/src/stm/registers.ld b/src/stm/registers.ld index fd61e486..f8b224a2 100644 --- a/src/stm/registers.ld +++ b/src/stm/registers.ld @@ -46,5 +46,7 @@ stm_tim2 = 0x40000000; stm_nvic = 0xe000e100; +stm_mpu = 0xe000ed90; + /* calibration data in system memory */ stm_temp_cal = 0x1ff80078; diff --git a/src/stm/stm32l.h b/src/stm/stm32l.h index e950d09b..d953aee4 100644 --- a/src/stm/stm32l.h +++ b/src/stm/stm32l.h @@ -901,6 +901,63 @@ stm_nvic_get_priority(int irq) { return (stm_nvic.ipr[IRQ_PRIO_REG(irq)] >> IRQ_PRIO_BIT(irq)) & IRQ_PRIO_MASK(0); } +struct stm_mpu { + vuint32_t typer; + vuint32_t cr; + vuint32_t rnr; + vuint32_t rbar; + + vuint32_t rasr; + vuint32_t rbar_a1; + vuint32_t rasr_a1; + vuint32_t rbar_a2; + vuint32_t rasr_a2; + vuint32_t rbar_a3; + vuint32_t rasr_a3; +}; + +extern struct stm_mpu stm_mpu; + +#define STM_MPU_TYPER_IREGION 16 +#define STM_MPU_TYPER_IREGION_MASK 0xff +#define STM_MPU_TYPER_DREGION 8 +#define STM_MPU_TYPER_DREGION_MASK 0xff +#define STM_MPU_TYPER_SEPARATE 0 + +#define STM_MPU_CR_PRIVDEFENA 2 +#define STM_MPU_CR_HFNMIENA 1 +#define STM_MPU_CR_ENABLE 0 + +#define STM_MPU_RNR_REGION 0 +#define STM_MPU_RNR_REGION_MASK 0xff + +#define STM_MPU_RBAR_ADDR 5 +#define STM_MPU_RBAR_ADDR_MASK 0x7ffffff + +#define STM_MPU_RBAR_VALID 4 +#define STM_MPU_RBAR_REGION 0 +#define STM_MPU_RBAR_REGION_MASK 0xf + +#define STM_MPU_RASR_XN 28 +#define STM_MPU_RASR_AP 24 +#define STM_MPU_RASR_AP_NONE_NONE 0 +#define STM_MPU_RASR_AP_RW_NONE 1 +#define STM_MPU_RASR_AP_RW_RO 2 +#define STM_MPU_RASR_AP_RW_RW 3 +#define STM_MPU_RASR_AP_RO_NONE 5 +#define STM_MPU_RASR_AP_RO_RO 6 +#define STM_MPU_RASR_AP_MASK 7 +#define STM_MPU_RASR_TEX 19 +#define STM_MPU_RASR_TEX_MASK 7 +#define STM_MPU_RASR_S 18 +#define STM_MPU_RASR_C 17 +#define STM_MPU_RASR_B 16 +#define STM_MPU_RASR_SRD 8 +#define STM_MPU_RASR_SRD_MASK 0xff +#define STM_MPU_RASR_SIZE 1 +#define STM_MPU_RASR_SIZE_MASK 0x1f +#define STM_MPU_RASR_ENABLE 0 + #define isr(name) void stm_ ## name ## _isr(void); isr(nmi) @@ -1568,6 +1625,13 @@ extern struct stm_tim234 stm_tim2, stm_tim3, stm_tim4; #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 -- cgit v1.2.3 From b49c751749dcd3e78991463c098f8d916f52179d Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 24 Oct 2012 23:50:55 -0700 Subject: altos: Add task queues. This replaces the array-based scheduler with a queue-based one instead. It should have the same basic scheduling semantics, but it walks shorter lists for each operation, making it much more efficient when the system has a lot of tasks. Signed-off-by: Keith Packard --- src/core/ao_list.h | 213 ++++++++++++++++++++++ src/core/ao_task.c | 340 ++++++++++++++++++++++++++++++++++-- src/core/ao_task.h | 21 ++- src/megametrum-v0.1/ao_megametrum.c | 1 + src/megametrum-v0.1/ao_pins.h | 2 + src/stm/ao_timer.c | 4 + 6 files changed, 564 insertions(+), 17 deletions(-) create mode 100644 src/core/ao_list.h (limited to 'src/stm') diff --git a/src/core/ao_list.h b/src/core/ao_list.h new file mode 100644 index 00000000..23cf1841 --- /dev/null +++ b/src/core/ao_list.h @@ -0,0 +1,213 @@ +/* + * Copyright © 2012 Keith Packard + * + * 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_LIST_H_ +#define _AO_LIST_H_ + +#include + +struct ao_list { + struct ao_list *next, *prev; +}; + +static inline void +ao_list_init(struct ao_list *list) +{ + list->next = list->prev = list; +} + +static inline void +__ao_list_add(struct ao_list *list, struct ao_list *prev, struct ao_list *next) +{ + next->prev = list; + list->next = next; + list->prev = prev; + prev->next = list; +} + +/** + * Insert a new element after the given list head. The new element does not + * need to be initialised as empty list. + * The list changes from: + * head → some element → ... + * to + * head → new element → older element → ... + * + * Example: + * struct foo *newfoo = malloc(...); + * ao_list_add(&newfoo->entry, &bar->list_of_foos); + * + * @param entry The new element to prepend to the list. + * @param head The existing list. + */ +static inline void +ao_list_insert(struct ao_list *entry, struct ao_list *head) +{ + __ao_list_add(entry, head, head->next); +} + +/** + * Append a new element to the end of the list given with this list head. + * + * The list changes from: + * head → some element → ... → lastelement + * to + * head → some element → ... → lastelement → new element + * + * Example: + * struct foo *newfoo = malloc(...); + * ao_list_append(&newfoo->entry, &bar->list_of_foos); + * + * @param entry The new element to prepend to the list. + * @param head The existing list. + */ +static inline void +ao_list_append(struct ao_list *entry, struct ao_list *head) +{ + __ao_list_add(entry, head->prev, head); +} + +static inline void +__ao_list_del(struct ao_list *prev, struct ao_list *next) +{ + next->prev = prev; + prev->next = next; +} + +/** + * Remove the element from the list it is in. Using this function will reset + * the pointers to/from this element so it is removed from the list. It does + * NOT free the element itself or manipulate it otherwise. + * + * Using ao_list_del on a pure list head (like in the example at the top of + * this file) will NOT remove the first element from + * the list but rather reset the list as empty list. + * + * Example: + * ao_list_del(&foo->entry); + * + * @param entry The element to remove. + */ +static inline void +ao_list_del(struct ao_list *entry) +{ + __ao_list_del(entry->prev, entry->next); + ao_list_init(entry); +} + +/** + * Check if the list is empty. + * + * Example: + * ao_list_is_empty(&bar->list_of_foos); + * + * @return True if the list contains one or more elements or False otherwise. + */ +static inline uint8_t +ao_list_is_empty(struct ao_list *head) +{ + return head->next == head; +} + +/** + * Returns a pointer to the container of this list element. + * + * Example: + * struct foo* f; + * f = container_of(&foo->entry, struct foo, entry); + * assert(f == foo); + * + * @param ptr Pointer to the struct ao_list. + * @param type Data type of the list element. + * @param member Member name of the struct ao_list field in the list element. + * @return A pointer to the data struct containing the list head. + */ +#define ao_container_of(ptr, type, member) \ + (type *)((char *)(ptr) - offsetof(type, member)) + +/** + * Alias of ao_container_of + */ +#define ao_list_entry(ptr, type, member) \ + ao_container_of(ptr, type, member) + +/** + * Retrieve the first list entry for the given list pointer. + * + * Example: + * struct foo *first; + * first = ao_list_first_entry(&bar->list_of_foos, struct foo, list_of_foos); + * + * @param ptr The list head + * @param type Data type of the list element to retrieve + * @param member Member name of the struct ao_list field in the list element. + * @return A pointer to the first list element. + */ +#define ao_list_first_entry(ptr, type, member) \ + ao_list_entry((ptr)->next, type, member) + +/** + * Retrieve the last list entry for the given listpointer. + * + * Example: + * struct foo *first; + * first = ao_list_last_entry(&bar->list_of_foos, struct foo, list_of_foos); + * + * @param ptr The list head + * @param type Data type of the list element to retrieve + * @param member Member name of the struct ao_list field in the list element. + * @return A pointer to the last list element. + */ +#define ao_list_last_entry(ptr, type, member) \ + ao_list_entry((ptr)->prev, type, member) + +/** + * Loop through the list given by head and set pos to struct in the list. + * + * Example: + * struct foo *iterator; + * ao_list_for_each_entry(iterator, &bar->list_of_foos, entry) { + * [modify iterator] + * } + * + * This macro is not safe for node deletion. Use ao_list_for_each_entry_safe + * instead. + * + * @param pos Iterator variable of the type of the list elements. + * @param head List head + * @param member Member name of the struct ao_list in the list elements. + * + */ +#define ao_list_for_each_entry(pos, head, type, member) \ + for (pos = ao_container_of((head)->next, type, member); \ + &pos->member != (head); \ + pos = ao_container_of(pos->member.next, type, member)) + +/** + * Loop through the list, keeping a backup pointer to the element. This + * macro allows for the deletion of a list element while looping through the + * list. + * + * See ao_list_for_each_entry for more details. + */ +#define ao_list_for_each_entry_safe(pos, tmp, head, type, member) \ + for ((pos = ao_container_of((head)->next, type, member)), \ + (tmp = ao_container_of(pos->member.next, type, member)); \ + &pos->member != (head); \ + (pos = tmp), (tmp = ao_container_of(pos->member.next, type, member))) + +#endif /* _AO_LIST_H_ */ diff --git a/src/core/ao_task.c b/src/core/ao_task.c index df70b906..a11979f0 100644 --- a/src/core/ao_task.c +++ b/src/core/ao_task.c @@ -24,13 +24,18 @@ #include #endif +#define DEBUG 0 + #define AO_NO_TASK_INDEX 0xff __xdata struct ao_task * __xdata ao_tasks[AO_NUM_TASKS]; __data uint8_t ao_num_tasks; -__data uint8_t ao_cur_task_index; __xdata struct ao_task *__data ao_cur_task; +#if !HAS_TASK_QUEUE +static __data uint8_t ao_cur_task_index; +#endif + #ifdef ao_arch_task_globals ao_arch_task_globals #endif @@ -49,6 +54,225 @@ static inline void ao_check_stack(void) { #define ao_check_stack() #endif +#if HAS_TASK_QUEUE + +#define SLEEP_HASH_SIZE 17 + +static struct ao_list run_queue; +static struct ao_list alarm_queue; +static struct ao_list sleep_queue[SLEEP_HASH_SIZE]; + +static void +ao_task_to_run_queue(struct ao_task *task) +{ + ao_list_del(&task->queue); + ao_list_append(&task->queue, &run_queue); +} + +static struct ao_list * +ao_task_sleep_queue(void *wchan) +{ + return &sleep_queue[(uintptr_t) wchan % SLEEP_HASH_SIZE]; +} + +static void +ao_task_to_sleep_queue(struct ao_task *task, void *wchan) +{ + ao_list_del(&task->queue); + ao_list_append(&task->queue, ao_task_sleep_queue(wchan)); +} + +#if DEBUG +static void +ao_task_validate_alarm_queue(void) +{ + struct ao_task *alarm, *prev = NULL; + int i; + + if (ao_list_is_empty(&alarm_queue)) + return; + ao_list_for_each_entry(alarm, &alarm_queue, struct ao_task, alarm_queue) { + if (prev) { + if ((int16_t) (alarm->alarm - prev->alarm) < 0) { + ao_panic(1); + } + } + prev = alarm; + } + for (i = 0; i < ao_num_tasks; i++) { + alarm = ao_tasks[i]; + if (alarm->alarm) { + if (ao_list_is_empty(&alarm->alarm_queue)) + ao_panic(2); + } else { + if (!ao_list_is_empty(&alarm->alarm_queue)) + ao_panic(3); + } + } +} +#else +#define ao_task_validate_alarm_queue() +#endif + +static void +ao_task_to_alarm_queue(struct ao_task *task) +{ + struct ao_task *alarm; + ao_list_for_each_entry(alarm, &alarm_queue, struct ao_task, alarm_queue) { + if ((int16_t) (alarm->alarm - task->alarm) >= 0) { + ao_list_insert(&task->alarm_queue, alarm->alarm_queue.prev); + ao_task_validate_alarm_queue(); + return; + } + } + ao_list_append(&task->alarm_queue, &alarm_queue); + ao_task_validate_alarm_queue(); +} + +static void +ao_task_from_alarm_queue(struct ao_task *task) +{ + ao_list_del(&task->alarm_queue); + ao_task_validate_alarm_queue(); +} + +static void +ao_task_init_queue(struct ao_task *task) +{ + ao_list_init(&task->queue); + ao_list_init(&task->alarm_queue); +} + +static void +ao_task_exit_queue(struct ao_task *task) +{ + ao_list_del(&task->queue); + ao_list_del(&task->alarm_queue); +} + +void +ao_task_check_alarm(uint16_t tick) +{ + struct ao_task *alarm, *next; + int i; + + if (ao_num_tasks == 0) + return; + ao_list_for_each_entry_safe(alarm, next, &alarm_queue, struct ao_task, alarm_queue) { + if ((int16_t) (tick - alarm->alarm) < 0) + break; + alarm->alarm = 0; + ao_task_from_alarm_queue(alarm); + ao_task_to_run_queue(alarm); + } +} + +void +ao_task_init(void) +{ + uint8_t i; + ao_list_init(&run_queue); + ao_list_init(&alarm_queue); + for (i = 0; i < SLEEP_HASH_SIZE; i++) + ao_list_init(&sleep_queue[i]); +} + +#if DEBUG +static uint8_t +ao_task_validate_queue(struct ao_task *task) +{ + uint32_t flags; + struct ao_task *m; + uint8_t ret = 0; + struct ao_list *queue; + + flags = ao_arch_irqsave(); + if (task->wchan) { + queue = ao_task_sleep_queue(task->wchan); + ret |= 2; + } else { + queue = &run_queue; + ret |= 4; + } + ao_list_for_each_entry(m, queue, struct ao_task, queue) { + if (m == task) { + ret |= 1; + break; + } + } + ao_arch_irqrestore(flags); + return ret; +} + +static uint8_t +ao_task_validate_alarm(struct ao_task *task) +{ + uint32_t flags; + struct ao_task *m; + uint8_t ret = 0; + + flags = ao_arch_irqsave(); + if (task->alarm == 0) + return 0xff; + ao_list_for_each_entry(m, &alarm_queue, struct ao_task, alarm_queue) { + if (m == task) + ret |= 1; + else { + if (!(ret&1)) { + if ((int16_t) (m->alarm - task->alarm) > 0) + ret |= 2; + } else { + if ((int16_t) (task->alarm - m->alarm) > 0) + ret |= 4; + } + } + } + ao_arch_irqrestore(flags); + return ret; +} + + +static void +ao_task_validate(void) +{ + uint8_t i; + struct ao_task *task; + uint8_t ret; + + for (i = 0; i < ao_num_tasks; i++) { + task = ao_tasks[i]; + ret = ao_task_validate_queue(task); + if (!(ret & 1)) { + if (ret & 2) + printf ("sleeping task not on sleep queue %s %08x\n", + task->name, task->wchan); + else + printf ("running task not on run queue %s\n", + task->name); + } + ret = ao_task_validate_alarm(task); + if (ret != 0xff) { + if (!(ret & 1)) + printf ("alarm task not on alarm queue %s %d\n", + task->name, task->alarm); + if (ret & 2) + printf ("alarm queue has sooner entries after %s %d\n", + task->name, task->alarm); + if (ret & 4) + printf ("alarm queue has later entries before %s %d\n", + task->name, task->alarm); + } + } +} +#else +#define ao_task_validate() +#endif + +#else +#define ao_task_to_run_queue(task) +#define ao_task_to_alarm_queue(task) +#endif + void ao_add_task(__xdata struct ao_task * task, void (*start)(void), __code char *name) __reentrant { @@ -63,7 +287,6 @@ ao_add_task(__xdata struct ao_task * task, void (*start)(void), __code char *nam if (t == ao_num_tasks) break; } - ao_tasks[ao_num_tasks++] = task; task->task_id = task_id; task->name = name; task->wchan = NULL; @@ -72,18 +295,29 @@ ao_add_task(__xdata struct ao_task * task, void (*start)(void), __code char *nam * to the start of the task */ ao_arch_init_stack(task, start); + ao_arch_critical( +#if HAS_TASK_QUEUE + ao_task_init_queue(task); + ao_task_to_run_queue(task); +#endif + ao_tasks[ao_num_tasks] = task; + ao_num_tasks++; + ); } -__xdata uint8_t ao_idle; - /* Task switching function. This must not use any stack variables */ void ao_yield(void) ao_arch_naked_define { ao_arch_save_regs(); +#if HAS_TASK_QUEUE + if (ao_cur_task == NULL) + ao_cur_task = ao_tasks[ao_num_tasks-1]; +#else if (ao_cur_task_index == AO_NO_TASK_INDEX) ao_cur_task_index = ao_num_tasks-1; +#endif else { #if HAS_SAMPLE_PROFILE @@ -104,6 +338,24 @@ ao_yield(void) ao_arch_naked_define /* Find a task to run. If there isn't any runnable task, * this loop will run forever, which is just fine */ +#if HAS_TASK_QUEUE + if (ao_cur_task->wchan == NULL) { + uint32_t flags; + flags = ao_arch_irqsave(); + ao_task_to_run_queue(ao_cur_task); + ao_arch_irqrestore(flags); + } + ao_cur_task = NULL; + + for (;;) { + ao_arch_memory_barrier(); + if (!ao_list_is_empty(&run_queue)) + break; + ao_arch_cpu_idle(); + } + + ao_cur_task = ao_list_first_entry(&run_queue, struct ao_task, queue); +#else { __pdata uint8_t ao_last_task_index = ao_cur_task_index; for (;;) { @@ -127,14 +379,15 @@ ao_yield(void) ao_arch_naked_define ao_arch_cpu_idle(); } #if HAS_SAMPLE_PROFILE - ao_cur_task->start = ao_sample_profile_timer_value(); + ao_cur_task->start = ao_sample_profile_timer_value(); #endif } +#endif #if HAS_STACK_GUARD ao_mpu_stack_guard(ao_cur_task->stack); #endif #if AO_CHECK_STACK - cli(); + ao_arch_block_interrupts(); in_yield = 0; #endif ao_arch_restore_stack(); @@ -143,7 +396,15 @@ ao_yield(void) ao_arch_naked_define uint8_t ao_sleep(__xdata void *wchan) { +#if HAS_TASK_QUEUE + uint32_t flags; + flags = ao_arch_irqsave(); +#endif ao_cur_task->wchan = wchan; +#if HAS_TASK_QUEUE + ao_task_to_sleep_queue(ao_cur_task, wchan); + ao_arch_irqrestore(flags); +#endif ao_yield(); if (ao_cur_task->wchan) { ao_cur_task->wchan = NULL; @@ -156,28 +417,62 @@ ao_sleep(__xdata void *wchan) void ao_wakeup(__xdata void *wchan) { - uint8_t i; +#if HAS_TASK_QUEUE + struct ao_task *sleep, *next; + struct ao_list *sleep_queue; + uint32_t flags; - ao_check_stack(); + if (ao_num_tasks == 0) + return; + sleep_queue = ao_task_sleep_queue(wchan); + flags = ao_arch_irqsave(); + ao_list_for_each_entry_safe(sleep, next, sleep_queue, struct ao_task, queue) { + if (sleep->wchan == wchan) { + sleep->wchan = NULL; + ao_task_to_run_queue(sleep); + } + } + 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(); } void ao_alarm(uint16_t delay) { +#if HAS_TASK_QUEUE + uint32_t flags; /* Make sure we sleep *at least* delay ticks, which means adding * one to account for the fact that we may be close to the next tick */ + flags = ao_arch_irqsave(); +#endif if (!(ao_cur_task->alarm = ao_time() + delay + 1)) ao_cur_task->alarm = 1; +#if HAS_TASK_QUEUE + ao_task_to_alarm_queue(ao_cur_task); + ao_arch_irqrestore(flags); +#endif } void ao_clear_alarm(void) { +#if HAS_TASK_QUEUE + uint32_t flags; + + flags = ao_arch_irqsave(); +#endif ao_cur_task->alarm = 0; +#if HAS_TASK_QUEUE + ao_task_from_alarm_queue(ao_cur_task); + ao_arch_irqrestore(flags); +#endif } static __xdata uint8_t ao_forever; @@ -193,14 +488,22 @@ ao_delay(uint16_t ticks) void ao_exit(void) { - ao_arch_critical( - uint8_t i; - ao_num_tasks--; - for (i = ao_cur_task_index; i < ao_num_tasks; i++) - ao_tasks[i] = ao_tasks[i+1]; - ao_cur_task_index = AO_NO_TASK_INDEX; - ao_yield(); - ); + uint8_t i; + ao_arch_block_interrupts(); + ao_num_tasks--; +#if HAS_TASK_QUEUE + for (i = 0; i < ao_num_tasks; i++) + if (ao_tasks[i] == ao_cur_task) + break; + ao_task_exit_queue(ao_cur_task); +#else + i = ao_cur_task_index; + ao_cur_task_index = AO_NO_TASK_INDEX; +#endif + for (; i < ao_num_tasks; i++) + ao_tasks[i] = ao_tasks[i+1]; + ao_cur_task = NULL; + ao_yield(); /* we'll never get back here */ } @@ -216,12 +519,17 @@ ao_task_info(void) task->name, (int) task->wchan); } +#if HAS_TASK_QUEUE + ao_task_validate(); +#endif } void ao_start_scheduler(void) { +#if !HAS_TASK_QUEUE ao_cur_task_index = AO_NO_TASK_INDEX; +#endif ao_cur_task = NULL; ao_yield(); } diff --git a/src/core/ao_task.h b/src/core/ao_task.h index 4319d632..b3f152a0 100644 --- a/src/core/ao_task.h +++ b/src/core/ao_task.h @@ -17,6 +17,9 @@ #ifndef _AO_TASK_H_ #define _AO_TASK_H_ +#if HAS_TASK_QUEUE +#include +#endif /* An AltOS task */ struct ao_task { @@ -25,6 +28,10 @@ struct ao_task { ao_arch_task_members /* any architecture-specific fields */ uint8_t task_id; /* unique id */ __code char *name; /* task name */ +#if HAS_TASK_QUEUE + struct ao_list queue; + struct ao_list alarm_queue; +#endif uint8_t stack[AO_STACK_SIZE]; /* saved stack */ #if HAS_SAMPLE_PROFILE uint32_t ticks; @@ -39,7 +46,6 @@ struct ao_task { extern __xdata struct ao_task * __xdata ao_tasks[AO_NUM_TASKS]; extern __data uint8_t ao_num_tasks; -extern __data uint8_t ao_cur_task_index; extern __xdata struct ao_task *__data ao_cur_task; /* @@ -74,6 +80,12 @@ ao_yield(void) ao_arch_naked_declare; void ao_add_task(__xdata struct ao_task * task, void (*start)(void), __code char *name) __reentrant; +#if HAS_TASK_QUEUE +/* Called on timer interrupt to check alarms */ +void +ao_task_check_alarm(uint16_t tick); +#endif + /* Terminate the current task */ void ao_exit(void); @@ -86,4 +98,11 @@ ao_task_info(void); void ao_start_scheduler(void); +#if HAS_TASK_QUEUE +void +ao_task_init(void); +#else +#define ao_task_init() +#endif + #endif diff --git a/src/megametrum-v0.1/ao_megametrum.c b/src/megametrum-v0.1/ao_megametrum.c index 43c2292d..cb1eb417 100644 --- a/src/megametrum-v0.1/ao_megametrum.c +++ b/src/megametrum-v0.1/ao_megametrum.c @@ -41,6 +41,7 @@ main(void) ao_mpu_init(); #endif + ao_task_init(); ao_serial_init(); ao_led_init(LEDS_AVAILABLE); ao_led_on(AO_LED_GREEN); diff --git a/src/megametrum-v0.1/ao_pins.h b/src/megametrum-v0.1/ao_pins.h index e4c8c8fb..5ae80ac5 100644 --- a/src/megametrum-v0.1/ao_pins.h +++ b/src/megametrum-v0.1/ao_pins.h @@ -18,6 +18,8 @@ #ifndef _AO_PINS_H_ #define _AO_PINS_H_ +#define HAS_TASK_QUEUE 1 + /* 8MHz High speed external crystal */ #define AO_HSE 8000000 diff --git a/src/stm/ao_timer.c b/src/stm/ao_timer.c index d82a803e..d69035f8 100644 --- a/src/stm/ao_timer.c +++ b/src/stm/ao_timer.c @@ -16,6 +16,7 @@ */ #include "ao.h" +#include volatile __data AO_TICK_TYPE ao_tick_count; @@ -42,6 +43,9 @@ void stm_tim6_isr(void) if (stm_tim6.sr & (1 << STM_TIM67_SR_UIF)) { stm_tim6.sr = 0; ++ao_tick_count; +#if HAS_TASK_QUEUE + ao_task_check_alarm((uint16_t) ao_tick_count); +#endif #if AO_DATA_ALL if (++ao_data_count == ao_data_interval) { ao_data_count = 0; -- cgit v1.2.3 From f221c78e6237e0a118ebe85c25e433fe16a7735d Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 25 Oct 2012 11:25:42 -0700 Subject: altos: Switch drivers to ao_arch_block/release_interrupts Stop using cli/sei, which are avr-specific Signed-off-by: Keith Packard --- src/core/ao_ignite.c | 4 ++-- src/drivers/ao_cc1120.c | 12 ++++++------ src/drivers/ao_ms5607.c | 12 +++--------- src/drivers/ao_radio_master.c | 8 ++++---- src/stm/ao_i2c_stm.c | 16 ++++++++-------- src/stm/ao_lcd_stm.c | 4 ++-- src/stm/ao_serial_stm.c | 32 ++++++++++++++++---------------- src/stm/ao_usb_stm.c | 12 ++++++------ 8 files changed, 47 insertions(+), 53 deletions(-) (limited to 'src/stm') diff --git a/src/core/ao_ignite.c b/src/core/ao_ignite.c index 693b7c7a..74bd0c5a 100644 --- a/src/core/ao_ignite.c +++ b/src/core/ao_ignite.c @@ -23,10 +23,10 @@ __xdata struct ao_ignition ao_ignition[2]; void ao_ignite(enum ao_igniter igniter) { - cli(); + ao_arch_block_interrupts(); ao_ignition[igniter].request = 1; ao_wakeup(&ao_ignition); - sei(); + ao_arch_release_interrupts(); } #ifndef AO_SENSE_DROGUE diff --git a/src/drivers/ao_cc1120.c b/src/drivers/ao_cc1120.c index 7428bead..bad313eb 100644 --- a/src/drivers/ao_cc1120.c +++ b/src/drivers/ao_cc1120.c @@ -469,10 +469,10 @@ ao_rdf_run(void) { ao_radio_start_tx(); - cli(); + ao_arch_block_interrupts(); while (!ao_radio_wake && !ao_radio_abort) ao_sleep(&ao_radio_wake); - sei(); + ao_arch_release_interrupts(); if (!ao_radio_wake) ao_radio_idle(); ao_radio_put(); @@ -603,10 +603,10 @@ ao_radio_send(const void *d, uint8_t size) do { ao_radio_wake = 0; - cli(); + ao_arch_block_interrupts(); while (!ao_radio_wake) ao_sleep(&ao_radio_wake); - sei(); + ao_arch_release_interrupts(); if (!encode_len) break; fifo_space = ao_radio_tx_fifo_space(); @@ -660,14 +660,14 @@ ao_radio_rx_isr(void) static uint16_t ao_radio_rx_wait(void) { - cli(); + ao_arch_block_interrupts(); rx_waiting = 1; while (rx_data_cur - rx_data_consumed < AO_FEC_DECODE_BLOCK && !ao_radio_abort) { ao_sleep(&ao_radio_wake); } rx_waiting = 0; - sei(); + ao_arch_release_interrupts(); if (ao_radio_abort) return 0; rx_data_consumed += AO_FEC_DECODE_BLOCK; diff --git a/src/drivers/ao_ms5607.c b/src/drivers/ao_ms5607.c index ce0bcf4b..55bea563 100644 --- a/src/drivers/ao_ms5607.c +++ b/src/drivers/ao_ms5607.c @@ -130,7 +130,6 @@ static uint32_t ao_ms5607_get_sample(uint8_t cmd) { uint8_t reply[3]; uint8_t read; - uint32_t loops; ao_ms5607_done = 0; @@ -142,15 +141,10 @@ ao_ms5607_get_sample(uint8_t cmd) { #if AO_MS5607_PRIVATE_PINS ao_spi_put(AO_MS5607_SPI_INDEX); #endif -// loops = 0; - cli(); - while (!ao_ms5607_done) { -// loops++; + ao_arch_block_interrupts(); + while (!ao_ms5607_done) ao_sleep((void *) &ao_ms5607_done); - } - sei(); -// if (loops > 1) -// printf ("ms5607 loops %d\n", loops); + ao_arch_release_interrupts(); #if AO_MS5607_PRIVATE_PINS stm_gpio_set(AO_MS5607_CS_PORT, AO_MS5607_CS_PIN, 1); #else diff --git a/src/drivers/ao_radio_master.c b/src/drivers/ao_radio_master.c index 4a37ace0..1e0050c8 100644 --- a/src/drivers/ao_radio_master.c +++ b/src/drivers/ao_radio_master.c @@ -75,7 +75,7 @@ ao_radio_master_send(void) */ PRINTD("Waiting radio ready\n"); - cli(); + ao_arch_block_interrupts(); ao_radio_ready = ao_gpio_get(AO_RADIO_INT_PORT, AO_RADIO_INT_PIN, AO_RADIO_INT); ret = 0; @@ -84,7 +84,7 @@ ao_radio_master_send(void) if (ret) break; } - sei(); + ao_arch_release_interrupts(); if (ret) return 0; @@ -99,11 +99,11 @@ ao_radio_master_send(void) AO_RADIO_SPI_BUS); ao_radio_master_stop(); PRINTD("waiting for send done %d\n", ao_radio_done); - cli(); + ao_arch_block_interrupts(); while (!ao_radio_done) if (ao_sleep((void *) &ao_radio_done)) break; - sei(); + ao_arch_release_interrupts(); PRINTD ("sent, radio done %d isr_0 %d isr_1 %d\n", ao_radio_done, isr_0_count, isr_1_count); return ao_radio_done; } diff --git a/src/stm/ao_i2c_stm.c b/src/stm/ao_i2c_stm.c index b6dd7056..779e2275 100644 --- a/src/stm/ao_i2c_stm.c +++ b/src/stm/ao_i2c_stm.c @@ -197,13 +197,13 @@ ao_i2c_start(uint8_t index, uint16_t addr) break; } ao_alarm(AO_MS_TO_TICKS(250)); - cli(); + ao_arch_block_interrupts(); stm_i2c->cr2 = AO_STM_I2C_CR2 | (1 << STM_I2C_CR2_ITEVTEN) | (1 << STM_I2C_CR2_ITERREN); ao_i2c_ev_isr(index); while (ao_i2c_state[index] == I2C_IDLE) if (ao_sleep(&ao_i2c_state[index])) break; - sei(); + ao_arch_release_interrupts(); ao_clear_alarm(); return ao_i2c_state[index] == I2C_RUNNING; } @@ -263,7 +263,7 @@ ao_i2c_send(void *block, uint16_t len, uint8_t index, uint8_t stop) ao_dma_start(tx_dma_index); ao_alarm(1 + len); - cli(); + ao_arch_block_interrupts(); while (!ao_dma_done[tx_dma_index]) if (ao_sleep(&ao_dma_done[tx_dma_index])) break; @@ -274,7 +274,7 @@ ao_i2c_send(void *block, uint16_t len, uint8_t index, uint8_t stop) if (ao_sleep(&ao_i2c_state[index])) break; stm_i2c->cr2 = AO_STM_I2C_CR2; - sei(); + ao_arch_release_interrupts(); if (stop) { stm_i2c->cr1 = AO_STM_I2C_CR1 | (1 << STM_I2C_CR1_STOP); ao_i2c_wait_stop(index); @@ -328,11 +328,11 @@ ao_i2c_recv(void *block, uint16_t len, uint8_t index, uint8_t stop) stm_i2c->cr1 = AO_STM_I2C_CR1 | (1 << STM_I2C_CR1_STOP); ao_alarm(1); - cli(); + ao_arch_block_interrupts(); while (ao_i2c_recv_len[index]) if (ao_sleep(&ao_i2c_recv_len[index])) break; - sei(); + ao_arch_release_interrupts(); ret = ao_i2c_recv_len[index] == 0; ao_clear_alarm(); } else { @@ -358,11 +358,11 @@ ao_i2c_recv(void *block, uint16_t len, uint8_t index, uint8_t stop) ao_dma_start(rx_dma_index); ao_alarm(len); - cli(); + ao_arch_block_interrupts(); while (!ao_dma_done[rx_dma_index]) if (ao_sleep(&ao_dma_done[rx_dma_index])) break; - sei(); + ao_arch_release_interrupts(); ao_clear_alarm(); ret = ao_dma_done[rx_dma_index]; ao_dma_done_transfer(rx_dma_index); diff --git a/src/stm/ao_lcd_stm.c b/src/stm/ao_lcd_stm.c index 0f9a8eb5..4f2a2242 100644 --- a/src/stm/ao_lcd_stm.c +++ b/src/stm/ao_lcd_stm.c @@ -253,12 +253,12 @@ ao_lcd_stm_fcr_sync(void) void ao_lcd_flush(void) { - cli(); + ao_arch_block_interrupts(); ao_lcd_update_active = 1; stm_lcd.sr = (1 << STM_LCD_SR_UDR); while (ao_lcd_update_active) ao_sleep(&ao_lcd_update_active); - sei(); + ao_arch_release_interrupts(); } void diff --git a/src/stm/ao_serial_stm.c b/src/stm/ao_serial_stm.c index 406da9fb..00409f4a 100644 --- a/src/stm/ao_serial_stm.c +++ b/src/stm/ao_serial_stm.c @@ -34,7 +34,7 @@ ao_debug_out(char c) } static void -ao_usart_tx_start(struct ao_stm_usart *usart) +_ao_usart_tx_start(struct ao_stm_usart *usart) { if (!ao_fifo_empty(usart->tx_fifo) && !usart->tx_started) { @@ -61,7 +61,7 @@ ao_usart_isr(struct ao_stm_usart *usart, int stdin) } if (sr & (1 << STM_USART_SR_TC)) { usart->tx_started = 0; - ao_usart_tx_start(usart); + _ao_usart_tx_start(usart); ao_wakeup(&usart->tx_fifo); } } @@ -70,11 +70,11 @@ char ao_usart_getchar(struct ao_stm_usart *usart) { char c; - cli(); + ao_arch_block_interrupts(); while (ao_fifo_empty(usart->rx_fifo)) ao_sleep(&usart->rx_fifo); ao_fifo_remove(usart->rx_fifo, c); - sei(); + ao_arch_release_interrupts(); return c; } @@ -82,34 +82,34 @@ char ao_usart_pollchar(struct ao_stm_usart *usart) { char c; - cli(); - if (ao_fifo_empty(usart->rx_fifo)) { - sei(); - return AO_READ_AGAIN; - } - ao_fifo_remove(usart->rx_fifo,c); - sei(); + + ao_arch_block_interrupts(); + if (ao_fifo_empty(usart->rx_fifo)) + c = AO_READ_AGAIN; + else + ao_fifo_remove(usart->rx_fifo,c); + ao_arch_release_interrupts(); return c; } void ao_usart_putchar(struct ao_stm_usart *usart, char c) { - cli(); + ao_arch_block_interrupts(); while (ao_fifo_full(usart->tx_fifo)) ao_sleep(&usart->tx_fifo); ao_fifo_insert(usart->tx_fifo, c); - ao_usart_tx_start(usart); - sei(); + _ao_usart_tx_start(usart); + ao_arch_release_interrupts(); } void ao_usart_drain(struct ao_stm_usart *usart) { - cli(); + ao_arch_block_interrupts(); while (!ao_fifo_empty(usart->tx_fifo)) ao_sleep(&usart->tx_fifo); - sei(); + ao_arch_release_interrupts(); } static const struct { diff --git a/src/stm/ao_usb_stm.c b/src/stm/ao_usb_stm.c index 8e7dacc5..d93a0c17 100644 --- a/src/stm/ao_usb_stm.c +++ b/src/stm/ao_usb_stm.c @@ -223,16 +223,16 @@ _ao_usb_set_stat_tx(int ep, uint32_t stat_tx) static void ao_usb_set_stat_tx(int ep, uint32_t stat_tx) { - cli(); + ao_arch_block_interrupts(); _ao_usb_set_stat_tx(ep, stat_tx); - sei(); + ao_arch_release_interrupts(); } static void ao_usb_set_stat_rx(int ep, uint32_t stat_rx) { uint32_t epr_write, epr_old; - cli(); + ao_arch_block_interrupts(); epr_write = epr_old = stm_usb.epr[ep]; epr_write &= STM_USB_EPR_PRESERVE_MASK; epr_write |= STM_USB_EPR_INVARIANT; @@ -240,7 +240,7 @@ ao_usb_set_stat_rx(int ep, uint32_t stat_rx) { STM_USB_EPR_STAT_RX_MASK << STM_USB_EPR_STAT_RX, stat_rx << STM_USB_EPR_STAT_RX); stm_usb.epr[ep] = epr_write; - sei(); + ao_arch_release_interrupts(); } /* @@ -251,7 +251,7 @@ static void ao_usb_init_ep(uint8_t ep, uint32_t addr, uint32_t type, uint32_t stat_rx, uint32_t stat_tx) { uint32_t epr; - cli(); + ao_arch_block_interrupts(); epr = stm_usb.epr[ep]; epr = ((0 << STM_USB_EPR_CTR_RX) | (epr & (1 << STM_USB_EPR_DTOG_RX)) | @@ -267,7 +267,7 @@ ao_usb_init_ep(uint8_t ep, uint32_t addr, uint32_t type, uint32_t stat_rx, uint3 (stat_tx << STM_USB_EPR_STAT_TX)) | (addr << STM_USB_EPR_EA)); stm_usb.epr[ep] = epr; - sei(); + ao_arch_release_interrupts(); debug ("writing epr[%d] 0x%08x wrote 0x%08x\n", ep, epr, stm_usb.epr[ep]); } -- cgit v1.2.3 From 9b978cd467f9128f3069765dd8fbf8abad3459a4 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 25 Oct 2012 13:38:13 -0700 Subject: altos: Clean up stm arch macros a bit. Turn a bunch of the macros into inline functions. Clean up the reboot method to use the stm_scb structure. Signed-off-by: Keith Packard --- src/stm/ao_arch.h | 112 ++---------------------------------------------- src/stm/ao_arch_funcs.h | 99 ++++++++++++++++++++++++++++++++++++++++++ src/stm/registers.ld | 2 + src/stm/stm32l.h | 30 +++++++++++++ 4 files changed, 134 insertions(+), 109 deletions(-) (limited to 'src/stm') diff --git a/src/stm/ao_arch.h b/src/stm/ao_arch.h index 0c3cfc91..e270199e 100644 --- a/src/stm/ao_arch.h +++ b/src/stm/ao_arch.h @@ -46,9 +46,9 @@ #define __interrupt(n) #define __at(n) -#define CORTEX_M3_AIRCR ((uint32_t *) 0xe000ed0c) - -#define ao_arch_reboot() (*((uint32_t *) 0xe000ed0c) = 0x05fa0004) +#define ao_arch_reboot() \ + (stm_scb.aircr = ((STM_SCB_AIRCR_VECTKEY_KEY << STM_SCB_AIRCR_VECTKEY) | \ + (1 << STM_SCB_AIRCR_SYSRESETREQ))) #define ao_arch_nop() asm("nop") @@ -77,118 +77,12 @@ extern const uint16_t ao_romconfig_check; extern const uint16_t ao_serial_number; extern const uint32_t ao_radio_cal; -#define ARM_PUSH32(stack, val) (*(--(stack)) = (val)) - #define ao_arch_task_members\ uint32_t *sp; /* saved stack pointer */ #define ao_arch_block_interrupts() asm("cpsid i") #define ao_arch_release_interrupts() asm("cpsie i") -#define cli() ao_arch_block_interrupts() -#define sei() ao_arch_release_interrupts() - -static uint32_t -ao_arch_irqsave(void) { - uint32_t primask; - asm("mrs %0,primask" : "=&r" (primask)); - ao_arch_block_interrupts(); - return primask; -} - -static void -ao_arch_irqrestore(uint32_t primask) { - asm("msr primask,%0" : : "r" (primask)); -} - -static void -ao_arch_memory_barrier() { - asm volatile("" ::: "memory"); -} - -#define ao_arch_init_stack(task, start) do { \ - uint32_t *sp = (uint32_t *) (task->stack + AO_STACK_SIZE); \ - uint32_t a = (uint32_t) start; \ - int i; \ - \ - /* Return address (goes into LR) */ \ - ARM_PUSH32(sp, a); \ - \ - /* Clear register values r0-r12 */ \ - i = 13; \ - while (i--) \ - ARM_PUSH32(sp, 0); \ - \ - /* APSR */ \ - ARM_PUSH32(sp, 0); \ - \ - /* PRIMASK with interrupts enabled */ \ - ARM_PUSH32(sp, 0); \ - \ - task->sp = sp; \ -} while (0); - -#define ao_arch_save_regs() do { \ - /* Save general registers */ \ - asm("push {r0-r12,lr}\n"); \ - \ - /* Save APSR */ \ - asm("mrs r0,apsr"); \ - asm("push {r0}"); \ - \ - /* Save PRIMASK */ \ - asm("mrs r0,primask"); \ - asm("push {r0}"); \ - \ - /* Enable interrupts */ \ - sei(); \ - } while (0) - -#define ao_arch_save_stack() do { \ - uint32_t *sp; \ - asm("mov %0,sp" : "=&r" (sp) ); \ - ao_cur_task->sp = (sp); \ - if ((uint8_t *) sp < &ao_cur_task->stack[0]) \ - ao_panic (AO_PANIC_STACK); \ - } while (0) - -#if 0 -#define ao_arch_isr_stack() do { \ - uint32_t *sp = (uint32_t *) 0x20004000; \ - asm("mov %0,sp" : "=&r" (sp) ); \ - } while (0) -#else -#define ao_arch_isr_stack() -#endif - - -#define ao_arch_cpu_idle() do { \ - asm(".global ao_idle_loc\n\twfi\nao_idle_loc:"); \ - } while (0) - -#define ao_arch_restore_stack() do { \ - uint32_t sp; \ - sp = (uint32_t) ao_cur_task->sp; \ - \ - /* Switch stacks */ \ - asm("mov sp, %0" : : "r" (sp) ); \ - \ - /* Restore PRIMASK */ \ - asm("pop {r0}"); \ - asm("msr primask,r0"); \ - \ - /* Restore APSR */ \ - asm("pop {r0}"); \ - asm("msr apsr,r0"); \ - \ - /* Restore general registers */ \ - asm("pop {r0-r12,lr}\n"); \ - \ - /* Return to calling function */ \ - asm("bx lr"); \ - } while(0) - -#define ao_arch_critical(b) do { cli(); do { b } while (0); sei(); } while (0) /* * For now, we're running at a weird frequency diff --git a/src/stm/ao_arch_funcs.h b/src/stm/ao_arch_funcs.h index e66d20d7..ca451a53 100644 --- a/src/stm/ao_arch_funcs.h +++ b/src/stm/ao_arch_funcs.h @@ -210,4 +210,103 @@ ao_i2c_recv(void *block, uint16_t len, uint8_t i2c_index, uint8_t stop); void ao_i2c_init(void); +#define ARM_PUSH32(stack, val) (*(--(stack)) = (val)) + +static inline uint32_t +ao_arch_irqsave(void) { + uint32_t primask; + asm("mrs %0,primask" : "=&r" (primask)); + ao_arch_block_interrupts(); + return primask; +} + +static inline void +ao_arch_irqrestore(uint32_t primask) { + asm("msr primask,%0" : : "r" (primask)); +} + +static inline void +ao_arch_memory_barrier() { + asm volatile("" ::: "memory"); +} + +static inline void +ao_arch_init_stack(struct ao_task *task, void *start) +{ + uint32_t *sp = (uint32_t *) (task->stack + AO_STACK_SIZE); + uint32_t a = (uint32_t) start; + int i; + + /* Return address (goes into LR) */ + ARM_PUSH32(sp, a); + + /* Clear register values r0-r12 */ + i = 13; + while (i--) + ARM_PUSH32(sp, 0); + + /* APSR */ + ARM_PUSH32(sp, 0); + + /* PRIMASK with interrupts enabled */ + ARM_PUSH32(sp, 0); + + task->sp = sp; +} + +static inline void ao_arch_save_regs(void) { + /* Save general registers */ + asm("push {r0-r12,lr}\n"); + + /* Save APSR */ + asm("mrs r0,apsr"); + asm("push {r0}"); + + /* Save PRIMASK */ + asm("mrs r0,primask"); + asm("push {r0}"); +} + +static inline void ao_arch_save_stack(void) { + uint32_t *sp; + asm("mov %0,sp" : "=&r" (sp) ); + ao_cur_task->sp = (sp); + if ((uint8_t *) sp < &ao_cur_task->stack[0]) + ao_panic (AO_PANIC_STACK); +} + +static inline void ao_arch_restore_stack(void) { + uint32_t sp; + sp = (uint32_t) ao_cur_task->sp; + + /* Switch stacks */ + asm("mov sp, %0" : : "r" (sp) ); + + /* Restore PRIMASK */ + asm("pop {r0}"); + asm("msr primask,r0"); + + /* Restore APSR */ + asm("pop {r0}"); + asm("msr apsr,r0"); + + /* Restore general registers */ + asm("pop {r0-r12,lr}\n"); + + /* Return to calling function */ + asm("bx lr"); +} + +#define ao_arch_isr_stack() + +#define ao_arch_cpu_idle() do { \ + asm(".global ao_idle_loc\n\twfi\nao_idle_loc:"); \ + } while (0) + +#define ao_arch_critical(b) do { \ + ao_arch_block_interrupts(); \ + do { b } while (0); \ + ao_arch_release_interrupts(); \ + } while (0) + #endif /* _AO_ARCH_FUNCS_H_ */ diff --git a/src/stm/registers.ld b/src/stm/registers.ld index f8b224a2..95a86e35 100644 --- a/src/stm/registers.ld +++ b/src/stm/registers.ld @@ -46,6 +46,8 @@ stm_tim2 = 0x40000000; stm_nvic = 0xe000e100; +stm_scb = 0xe000ed00; + stm_mpu = 0xe000ed90; /* calibration data in system memory */ diff --git a/src/stm/stm32l.h b/src/stm/stm32l.h index d953aee4..0dbfae39 100644 --- a/src/stm/stm32l.h +++ b/src/stm/stm32l.h @@ -901,6 +901,36 @@ stm_nvic_get_priority(int irq) { return (stm_nvic.ipr[IRQ_PRIO_REG(irq)] >> IRQ_PRIO_BIT(irq)) & IRQ_PRIO_MASK(0); } +struct stm_scb { + vuint32_t cpuid; + vuint32_t icsr; + vuint32_t vtor; + vuint32_t aircr; + + vuint32_t scr; + vuint32_t ccr; + vuint32_t shpr1; + vuint32_t shpr2; + + vuint32_t shpr3; + vuint32_t shcrs; + vuint32_t cfsr; + vuint32_t hfsr; + + uint32_t unused_30; + vuint32_t mmfar; + vuint32_t bfar; +}; + +extern struct stm_scb stm_scb; + +#define STM_SCB_AIRCR_VECTKEY 16 +#define STM_SCB_AIRCR_VECTKEY_KEY 0x05fa +#define STM_SCB_AIRCR_PRIGROUP 8 +#define STM_SCB_AIRCR_SYSRESETREQ 2 +#define STM_SCB_AIRCR_VECTCLRACTIVE 1 +#define STM_SCB_AIRCR_VECTRESET 0 + struct stm_mpu { vuint32_t typer; vuint32_t cr; -- cgit v1.2.3 From ccf0faa7d26d56deca7928b521d07be40504466a Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 25 Oct 2012 13:40:54 -0700 Subject: altos: Leave interrupts disabled while checking for task to run Otherwise, we run the risk of an interrupt waking a task after we've decided to idle the CPU. Signed-off-by: Keith Packard --- src/avr/ao_arch.h | 19 +++++++++++++++---- src/cc1111/ao_arch.h | 11 +++++++---- src/core/ao_task.c | 28 +++++++++++++--------------- src/stm/ao_arch_funcs.h | 4 +++- 4 files changed, 38 insertions(+), 24 deletions(-) (limited to 'src/stm') diff --git a/src/avr/ao_arch.h b/src/avr/ao_arch.h index c82612a8..d626e830 100644 --- a/src/avr/ao_arch.h +++ b/src/avr/ao_arch.h @@ -112,7 +112,6 @@ extern uint8_t ao_cpu_sleep_disable; asm("push r9" "\n\t" "push r8" "\n\t" "push r7" "\n\t" "push r6" "\n\t" "push r5"); \ asm("push r4" "\n\t" "push r3" "\n\t" "push r2" "\n\t" "push r1" "\n\t" "push r0"); \ asm("in r0, __SREG__" "\n\t" "push r0"); \ - sei(); \ } while (0) #define ao_arch_save_stack() do { \ @@ -124,16 +123,28 @@ extern uint8_t ao_cpu_sleep_disable; #define ao_arch_isr_stack() /* nothing */ -#define ao_arch_cpu_idle() do { \ - if (!ao_cpu_sleep_disable) \ +/* Idle the CPU (if possible) waiting for an interrupt. Enabling + * interrupts and sleeping the CPU must be adjacent to eliminate race + * conditions. In all cases, we execute a single nop with interrupts + * enabled + */ +#define ao_arch_wait_interrupt() do { \ + if (!ao_cpu_sleep_disable) { \ + sleep_enable(); \ + sei(); \ sleep_cpu(); \ + sleep_disable(); \ + } else { \ + sei(); \ + } \ + ao_arch_nop(); \ + cli(); \ } while (0) #define ao_arch_restore_stack() do { \ uint8_t sp_l, sp_h; \ sp_l = (uint16_t) ao_cur_task->sp; \ sp_h = ((uint16_t) ao_cur_task->sp) >> 8; \ - cli(); \ asm("out __SP_H__,%0" : : "r" (sp_h) ); \ asm("out __SP_L__,%0" : : "r" (sp_l) ); \ asm("pop r0" "\n\t" \ diff --git a/src/cc1111/ao_arch.h b/src/cc1111/ao_arch.h index 39468e06..9097557f 100644 --- a/src/cc1111/ao_arch.h +++ b/src/cc1111/ao_arch.h @@ -112,9 +112,7 @@ extern AO_ROMCONFIG_SYMBOL(0x00a6) uint32_t ao_radio_cal; /* Push ACC first, as when restoring the context it must be restored \ * last (it is used to set the IE register). */ \ push ACC \ - /* Store the IE register then enable interrupts. */ \ push _IEN0 \ - setb _EA \ push DPL \ push DPH \ push b \ @@ -150,11 +148,16 @@ extern AO_ROMCONFIG_SYMBOL(0x00a6) uint32_t ao_radio_cal; /* Empty the stack; might as well let interrupts have the whole thing */ #define ao_arch_isr_stack() (SP = AO_STACK_START - 1) -/* Idle the CPU, waking when an interrupt occurs */ -#define ao_arch_cpu_idle() (PCON = PCON_IDLE) #define ao_arch_block_interrupts() __asm clr _EA __endasm #define ao_arch_release_interrupts() __asm setb _EA __endasm +/* Idle the CPU, waking when an interrupt occurs */ +#define ao_arch_wait_interrupt() do { \ + ao_arch_release_interrupts(); \ + (PCON = PCON_IDLE); \ + ao_arch_block_interrupts(); \ + } while (0) + #define ao_arch_restore_stack() { \ uint8_t stack_len; \ __data uint8_t *stack_ptr; \ diff --git a/src/core/ao_task.c b/src/core/ao_task.c index a11979f0..985c37fa 100644 --- a/src/core/ao_task.c +++ b/src/core/ao_task.c @@ -331,6 +331,7 @@ ao_yield(void) ao_arch_naked_define } ao_arch_isr_stack(); + ao_arch_block_interrupts(); #if AO_CHECK_STACK in_yield = 1; @@ -339,21 +340,19 @@ ao_yield(void) ao_arch_naked_define * this loop will run forever, which is just fine */ #if HAS_TASK_QUEUE - if (ao_cur_task->wchan == NULL) { - uint32_t flags; - flags = ao_arch_irqsave(); + /* If the current task is running, move it to the + * end of the queue to allow other tasks a chance + */ + if (ao_cur_task->wchan == NULL) ao_task_to_run_queue(ao_cur_task); - ao_arch_irqrestore(flags); - } ao_cur_task = NULL; - for (;;) { ao_arch_memory_barrier(); if (!ao_list_is_empty(&run_queue)) break; - ao_arch_cpu_idle(); + /* Wait for interrupts when there's nothing ready */ + ao_arch_wait_interrupt(); } - ao_cur_task = ao_list_first_entry(&run_queue, struct ao_task, queue); #else { @@ -374,20 +373,19 @@ ao_yield(void) ao_arch_naked_define (int16_t) (ao_time() - ao_cur_task->alarm) >= 0) break; - /* Enter lower power mode when there isn't anything to do */ + /* Wait for interrupts when there's nothing ready */ if (ao_cur_task_index == ao_last_task_index) - ao_arch_cpu_idle(); + ao_arch_wait_interrupt(); } -#if HAS_SAMPLE_PROFILE - ao_cur_task->start = ao_sample_profile_timer_value(); -#endif } #endif +#if HAS_SAMPLE_PROFILE + ao_cur_task->start = ao_sample_profile_timer_value(); +#endif #if HAS_STACK_GUARD ao_mpu_stack_guard(ao_cur_task->stack); #endif #if AO_CHECK_STACK - ao_arch_block_interrupts(); in_yield = 0; #endif ao_arch_restore_stack(); @@ -519,7 +517,7 @@ ao_task_info(void) task->name, (int) task->wchan); } -#if HAS_TASK_QUEUE +#if HAS_TASK_QUEUE && DEBUG ao_task_validate(); #endif } diff --git a/src/stm/ao_arch_funcs.h b/src/stm/ao_arch_funcs.h index ca451a53..d6ab1465 100644 --- a/src/stm/ao_arch_funcs.h +++ b/src/stm/ao_arch_funcs.h @@ -299,8 +299,10 @@ static inline void ao_arch_restore_stack(void) { #define ao_arch_isr_stack() -#define ao_arch_cpu_idle() do { \ +#define ao_arch_wait_interrupt() do { \ asm(".global ao_idle_loc\n\twfi\nao_idle_loc:"); \ + ao_arch_release_interrupts(); \ + ao_arch_block_interrupts(); \ } while (0) #define ao_arch_critical(b) do { \ -- cgit v1.2.3 From e57ab2a7bfb69c0ef9b5b7fa8e53e20a500e7c6c Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 25 Oct 2012 13:42:10 -0700 Subject: altos: Provide ao_task_alarm_tick to reduce per-tick cost Cache the next wakeup time and check that before jumping to the task code. Signed-off-by: Keith Packard --- src/core/ao_task.c | 20 ++++++++++---------- src/core/ao_task.h | 1 + src/stm/ao_timer.c | 3 ++- 3 files changed, 13 insertions(+), 11 deletions(-) (limited to 'src/stm') diff --git a/src/core/ao_task.c b/src/core/ao_task.c index 985c37fa..0411fbdd 100644 --- a/src/core/ao_task.c +++ b/src/core/ao_task.c @@ -114,6 +114,8 @@ ao_task_validate_alarm_queue(void) #define ao_task_validate_alarm_queue() #endif +uint16_t ao_task_alarm_tick; + static void ao_task_to_alarm_queue(struct ao_task *task) { @@ -126,6 +128,7 @@ ao_task_to_alarm_queue(struct ao_task *task) } } ao_list_append(&task->alarm_queue, &alarm_queue); + ao_task_alarm_tick = ao_list_first_entry(&alarm_queue, struct ao_task, alarm_queue)->alarm; ao_task_validate_alarm_queue(); } @@ -133,6 +136,10 @@ static void ao_task_from_alarm_queue(struct ao_task *task) { ao_list_del(&task->alarm_queue); + if (ao_list_is_empty(&alarm_queue)) + ao_task_alarm_tick = 0; + else + ao_task_alarm_tick = ao_list_first_entry(&alarm_queue, struct ao_task, alarm_queue)->alarm; ao_task_validate_alarm_queue(); } @@ -154,10 +161,7 @@ void ao_task_check_alarm(uint16_t tick) { struct ao_task *alarm, *next; - int i; - if (ao_num_tasks == 0) - return; ao_list_for_each_entry_safe(alarm, next, &alarm_queue, struct ao_task, alarm_queue) { if ((int16_t) (tick - alarm->alarm) < 0) break; @@ -173,6 +177,7 @@ ao_task_init(void) uint8_t i; ao_list_init(&run_queue); ao_list_init(&alarm_queue); + ao_task_alarm_tick = 0; for (i = 0; i < SLEEP_HASH_SIZE; i++) ao_list_init(&sleep_queue[i]); } @@ -264,14 +269,9 @@ ao_task_validate(void) } } } -#else -#define ao_task_validate() -#endif +#endif /* DEBUG */ -#else -#define ao_task_to_run_queue(task) -#define ao_task_to_alarm_queue(task) -#endif +#endif /* HAS_TASK_QUEUE */ void ao_add_task(__xdata struct ao_task * task, void (*start)(void), __code char *name) __reentrant diff --git a/src/core/ao_task.h b/src/core/ao_task.h index b3f152a0..049f69a7 100644 --- a/src/core/ao_task.h +++ b/src/core/ao_task.h @@ -82,6 +82,7 @@ ao_add_task(__xdata struct ao_task * task, void (*start)(void), __code char *nam #if HAS_TASK_QUEUE /* Called on timer interrupt to check alarms */ +extern uint16_t ao_task_alarm_tick; void ao_task_check_alarm(uint16_t tick); #endif diff --git a/src/stm/ao_timer.c b/src/stm/ao_timer.c index d69035f8..e07625d8 100644 --- a/src/stm/ao_timer.c +++ b/src/stm/ao_timer.c @@ -44,7 +44,8 @@ void stm_tim6_isr(void) stm_tim6.sr = 0; ++ao_tick_count; #if HAS_TASK_QUEUE - ao_task_check_alarm((uint16_t) ao_tick_count); + if (ao_task_alarm_tick && (int16_t) (ao_tick_count - ao_task_alarm_tick) >= 0) + ao_task_check_alarm((uint16_t) ao_tick_count); #endif #if AO_DATA_ALL if (++ao_data_count == ao_data_interval) { -- cgit v1.2.3 From 86f8b92149d1027b1d6d6b1cae097cfe47b02090 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 1 Nov 2012 10:48:08 -0700 Subject: altos/stm: Support LEDs on multiple ports Split out the bits in a fairly simplistic fashion so that we support no more than 16 LEDs still. Signed-off-by: Keith Packard --- src/stm/ao_led.c | 62 ++++++++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 58 insertions(+), 4 deletions(-) (limited to 'src/stm') diff --git a/src/stm/ao_led.c b/src/stm/ao_led.c index ee313b6f..0acab106 100644 --- a/src/stm/ao_led.c +++ b/src/stm/ao_led.c @@ -22,13 +22,31 @@ __pdata uint16_t ao_led_enable; void ao_led_on(uint16_t colors) { +#ifdef LED_PORT LED_PORT->bsrr = (colors & ao_led_enable); +#else +#ifdef LED_PORT_0 + LED_PORT_0->bsrr = ((colors & ao_led_enable) & LED_PORT_0_MASK) << LED_PORT_0_SHIFT; +#endif +#ifdef LED_PORT_1 + LED_PORT_1->bsrr = ((colors & ao_led_enable) & LED_PORT_1_MASK) << LED_PORT_1_SHIFT; +#endif +#endif } void ao_led_off(uint16_t colors) { +#ifdef LED_PORT LED_PORT->bsrr = (uint32_t) (colors & ao_led_enable) << 16; +#else +#ifdef LED_PORT_0 + LED_PORT_0->bsrr = ((uint32_t) (colors & ao_led_enable) & LED_PORT_0_MASK) << (LED_PORT_0_SHIFT + 16); +#endif +#ifdef LED_PORT_1 + LED_PORT_1->bsrr = ((uint32_t) (colors & ao_led_enable) & LED_PORT_1_MASK) << (LED_PORT_1_SHIFT + 16); +#endif +#endif } void @@ -37,13 +55,23 @@ ao_led_set(uint16_t colors) uint16_t on = colors & ao_led_enable; uint16_t off = ~colors & ao_led_enable; - LED_PORT->bsrr = off << 16 | on; + ao_led_off(off); + ao_led_on(on); } void ao_led_toggle(uint16_t colors) { +#ifdef LED_PORT LED_PORT->odr ^= (colors & ao_led_enable); +#else +#ifdef LED_PORT_0 + LED_PORT_0->odr ^= ((colors & ao_led_enable) & LED_PORT_0_MASK) << LED_PORT_0_SHIFT; +#endif +#ifdef LED_PORT_1 + LED_PORT_1->odr ^= ((colors & ao_led_enable) & LED_PORT_1_MASK) << LED_PORT_1_SHIFT; +#endif +#endif } void @@ -54,18 +82,44 @@ ao_led_for(uint16_t colors, uint16_t ticks) __reentrant ao_led_off(colors); } +#define init_led_pin(port, bit) do { \ + stm_moder_set(port, bit, STM_MODER_OUTPUT); \ + stm_otyper_set(port, bit, STM_OTYPER_PUSH_PULL); \ + } while (0) + void ao_led_init(uint16_t enable) { int bit; - stm_rcc.ahbenr |= (1 << LED_PORT_ENABLE); ao_led_enable = enable; +#ifdef LED_PORT + stm_rcc.ahbenr |= (1 << LED_PORT_ENABLE); LED_PORT->odr &= ~enable; +#else +#ifdef LED_PORT_0 + stm_rcc.ahbenr |= (1 << LED_PORT_0_ENABLE); + LED_PORT_0->odr &= ~((enable & ao_led_enable) & LED_PORT_0_MASK) << LED_PORT_0_SHIFT; +#endif +#ifdef LED_PORT_1 + stm_rcc.ahbenr |= (1 << LED_PORT_1_ENABLE); + LED_PORT_1->odr &= ~((enable & ao_led_enable) & LED_PORT_1_MASK) << LED_PORT_1_SHIFT; +#endif +#endif for (bit = 0; bit < 16; bit++) { if (enable & (1 << bit)) { - stm_moder_set(LED_PORT, bit, STM_MODER_OUTPUT); - stm_otyper_set(LED_PORT, bit, STM_OTYPER_PUSH_PULL); +#ifdef LED_PORT + init_led_pin(LED_PORT, bit); +#else +#ifdef LED_PORT_0 + if (LED_PORT_0_MASK & (1 << bit)) + init_led_pin(LED_PORT_0, bit + LED_PORT_0_SHIFT); +#endif +#ifdef LED_PORT_1 + if (LED_PORT_1_MASK & (1 << bit)) + init_led_pin(LED_PORT_1, bit + LED_PORT_1_SHIFT); +#endif +#endif } } } -- cgit v1.2.3 From 0b65402361f36a0c722977bcb63edb26fda0db28 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 30 Nov 2012 16:01:07 -0800 Subject: altos: Make stdio 8-bit clean by making pollchar return int We were stealing one value (0xff) in the return value from pollchar to indicate 'not ready yet'. Instead of doing that, use the integer value -1 and have pollchar return an int instead of a char. That necessitated cleaning a few other bits to make sure that 0xff wouldn't get promoted to -1 on accident. Signed-off-by: Keith Packard --- src/avr/ao_usb_avr.c | 10 +++++----- src/cc1111/ao_serial.c | 8 ++++---- src/cc1111/ao_usb.c | 12 ++++++------ src/core/ao.h | 6 +++--- src/core/ao_packet.h | 2 +- src/core/ao_serial.h | 28 ++++++++++++++++++++++++++-- src/core/ao_stdio.c | 2 +- src/core/ao_usb.h | 2 +- src/drivers/ao_packet.c | 6 +++--- src/stm/ao_arch.h | 36 ------------------------------------ src/stm/ao_arch_funcs.h | 20 ++++++++++++++++++++ src/stm/ao_serial_stm.c | 24 ++++++++++-------------- src/stm/ao_usb_stm.c | 10 +++++----- 13 files changed, 85 insertions(+), 81 deletions(-) (limited to 'src/stm') diff --git a/src/avr/ao_usb_avr.c b/src/avr/ao_usb_avr.c index 9ba407af..2ef546c9 100644 --- a/src/avr/ao_usb_avr.c +++ b/src/avr/ao_usb_avr.c @@ -480,10 +480,10 @@ ao_usb_putchar(char c) __critical __reentrant ao_usb_in_flushed = 0; } -static char +static int _ao_usb_pollchar(void) { - char c; + uint8_t c; uint8_t intx; if (!ao_usb_running) @@ -517,10 +517,10 @@ _ao_usb_pollchar(void) return c; } -char +int ao_usb_pollchar(void) { - char c; + int c; cli(); c = _ao_usb_pollchar(); sei(); @@ -530,7 +530,7 @@ ao_usb_pollchar(void) char ao_usb_getchar(void) __critical { - char c; + int c; cli(); while ((c = _ao_usb_pollchar()) == AO_READ_AGAIN) diff --git a/src/cc1111/ao_serial.c b/src/cc1111/ao_serial.c index 48383802..2a93bf52 100644 --- a/src/cc1111/ao_serial.c +++ b/src/cc1111/ao_serial.c @@ -85,10 +85,10 @@ ao_serial0_getchar(void) __critical } #if USE_SERIAL_0_STDIN -char +int ao_serial0_pollchar(void) __critical { - char c; + uint8_t c; if (ao_fifo_empty(ao_serial0_rx_fifo)) return AO_READ_AGAIN; ao_fifo_remove(ao_serial0_rx_fifo,c); @@ -173,10 +173,10 @@ ao_serial1_getchar(void) __critical } #if USE_SERIAL_1_STDIN -char +int ao_serial1_pollchar(void) __critical { - char c; + uint8_t c; if (ao_fifo_empty(ao_serial1_rx_fifo)) return AO_READ_AGAIN; ao_fifo_remove(ao_serial1_rx_fifo,c); diff --git a/src/cc1111/ao_usb.c b/src/cc1111/ao_usb.c index ce26e808..81e9074e 100644 --- a/src/cc1111/ao_usb.c +++ b/src/cc1111/ao_usb.c @@ -382,19 +382,19 @@ ao_usb_putchar(char c) __critical __reentrant ao_usb_in_send(); } -char +int ao_usb_pollchar(void) __critical { - char c; + uint8_t c; if (ao_usb_out_bytes == 0) { USBINDEX = AO_USB_OUT_EP; if ((USBCSOL & USBCSOL_OUTPKT_RDY) == 0) - return AO_READ_AGAIN; + return -1; ao_usb_out_bytes = (USBCNTH << 8) | USBCNTL; if (ao_usb_out_bytes == 0) { USBINDEX = AO_USB_OUT_EP; USBCSOL &= ~USBCSOL_OUTPKT_RDY; - return AO_READ_AGAIN; + return -1; } } --ao_usb_out_bytes; @@ -409,9 +409,9 @@ ao_usb_pollchar(void) __critical char ao_usb_getchar(void) __critical { - char c; + int c; - while ((c = ao_usb_pollchar()) == AO_READ_AGAIN) + while ((c = ao_usb_pollchar()) == -1) ao_sleep(&ao_stdin_ready); return c; } diff --git a/src/core/ao.h b/src/core/ao.h index 1aff3d49..54018b37 100644 --- a/src/core/ao.h +++ b/src/core/ao.h @@ -599,10 +599,10 @@ ao_monitor_init(void) __reentrant; * ao_stdio.c */ -#define AO_READ_AGAIN ((char) -1) +#define AO_READ_AGAIN (-1) struct ao_stdio { - char (*pollchar)(void); + int (*pollchar)(void); void (*putchar)(char c) __reentrant; void (*flush)(void); uint8_t echo; @@ -621,7 +621,7 @@ uint8_t ao_echo(void); int8_t -ao_add_stdio(char (*pollchar)(void), +ao_add_stdio(int (*pollchar)(void), void (*putchar)(char) __reentrant, void (*flush)(void)) __reentrant; diff --git a/src/core/ao_packet.h b/src/core/ao_packet.h index 0eafd3b2..08b184d6 100644 --- a/src/core/ao_packet.h +++ b/src/core/ao_packet.h @@ -62,7 +62,7 @@ ao_packet_flush(void); void ao_packet_putchar(char c) __reentrant; -char +int ao_packet_pollchar(void); #if PACKET_HAS_MASTER diff --git a/src/core/ao_serial.h b/src/core/ao_serial.h index 53aa8a89..a799bf2c 100644 --- a/src/core/ao_serial.h +++ b/src/core/ao_serial.h @@ -22,6 +22,7 @@ #define AO_SERIAL_SPEED_9600 1 #define AO_SERIAL_SPEED_19200 2 #define AO_SERIAL_SPEED_57600 3 +#define AO_SERIAL_SPEED_115200 4 #if HAS_SERIAL_0 extern volatile __xdata struct ao_fifo ao_serial0_rx_fifo; @@ -30,6 +31,9 @@ extern volatile __xdata struct ao_fifo ao_serial0_tx_fifo; char ao_serial0_getchar(void); +int +ao_serial0_pollchar(void); + void ao_serial0_putchar(char c); @@ -47,7 +51,7 @@ extern volatile __xdata struct ao_fifo ao_serial1_tx_fifo; char ao_serial1_getchar(void); -char +int ao_serial1_pollchar(void); void @@ -67,7 +71,7 @@ extern volatile __xdata struct ao_fifo ao_serial2_tx_fifo; char ao_serial2_getchar(void); -char +int ao_serial2_pollchar(void); void @@ -80,6 +84,26 @@ void ao_serial2_set_speed(uint8_t speed); #endif +#if HAS_SERIAL_3 +extern volatile __xdata struct ao_fifo ao_serial3_rx_fifo; +extern volatile __xdata struct ao_fifo ao_serial3_tx_fifo; + +char +ao_serial3_getchar(void); + +int +ao_serial3_pollchar(void); + +void +ao_serial3_putchar(char c); + +void +ao_serial3_drain(void); + +void +ao_serial3_set_speed(uint8_t speed); +#endif + void ao_serial_init(void); diff --git a/src/core/ao_stdio.c b/src/core/ao_stdio.c index 8cf66a23..4a832487 100644 --- a/src/core/ao_stdio.c +++ b/src/core/ao_stdio.c @@ -123,7 +123,7 @@ ao_echo(void) } int8_t -ao_add_stdio(char (*pollchar)(void), +ao_add_stdio(int (*pollchar)(void), void (*putchar)(char), void (*flush)(void)) __reentrant { diff --git a/src/core/ao_usb.h b/src/core/ao_usb.h index e051db93..4476ee6b 100644 --- a/src/core/ao_usb.h +++ b/src/core/ao_usb.h @@ -33,7 +33,7 @@ ao_usb_getchar(void); /* Poll for a charcter on the USB input queue. * returns AO_READ_AGAIN if none are available */ -char +int ao_usb_pollchar(void); /* Flush the USB output queue */ diff --git a/src/drivers/ao_packet.c b/src/drivers/ao_packet.c index 3c1e7a18..91319923 100644 --- a/src/drivers/ao_packet.c +++ b/src/drivers/ao_packet.c @@ -21,8 +21,8 @@ __xdata struct ao_packet_recv ao_rx_packet; __xdata struct ao_packet ao_tx_packet; __pdata uint8_t ao_packet_rx_len, ao_packet_rx_used, ao_packet_tx_used; -static __xdata char tx_data[AO_PACKET_MAX]; -static __xdata char rx_data[AO_PACKET_MAX]; +static __xdata uint8_t tx_data[AO_PACKET_MAX]; +static __xdata uint8_t rx_data[AO_PACKET_MAX]; static __pdata uint8_t rx_seq; __xdata struct ao_task ao_packet_task; @@ -169,7 +169,7 @@ ao_packet_putchar(char c) __reentrant tx_data[ao_packet_tx_used++] = c; } -char +int ao_packet_pollchar(void) { /* No need to block interrupts, all variables here diff --git a/src/stm/ao_arch.h b/src/stm/ao_arch.h index e270199e..007f7e2e 100644 --- a/src/stm/ao_arch.h +++ b/src/stm/ao_arch.h @@ -123,42 +123,6 @@ void ao_lcd_font_init(void); void ao_lcd_font_string(char *s); -char -ao_serial1_getchar(void); - -void -ao_serial1_putchar(char c); - -char -ao_serial1_pollchar(void); - -void -ao_serial1_set_speed(uint8_t speed); - -char -ao_serial2_getchar(void); - -void -ao_serial2_putchar(char c); - -char -ao_serial2_pollchar(void); - -void -ao_serial2_set_speed(uint8_t speed); - -char -ao_serial3_getchar(void); - -void -ao_serial3_putchar(char c); - -char -ao_serial3_pollchar(void); - -void -ao_serial3_set_speed(uint8_t speed); - extern const uint32_t ao_radio_cal; void diff --git a/src/stm/ao_arch_funcs.h b/src/stm/ao_arch_funcs.h index d6ab1465..87bbe73e 100644 --- a/src/stm/ao_arch_funcs.h +++ b/src/stm/ao_arch_funcs.h @@ -210,6 +210,26 @@ ao_i2c_recv(void *block, uint16_t len, uint8_t i2c_index, uint8_t stop); void ao_i2c_init(void); +/* 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; +}; + +#if HAS_SERIAL_1 +extern struct ao_stm_usart ao_stm_usart1; +#endif + +#if HAS_SERIAL_2 +extern struct ao_stm_usart ao_stm_usart2; +#endif + +#if HAS_SERIAL_3 +extern struct ao_stm_usart ao_stm_usart3; +#endif + #define ARM_PUSH32(stack, val) (*(--(stack)) = (val)) static inline uint32_t diff --git a/src/stm/ao_serial_stm.c b/src/stm/ao_serial_stm.c index 00409f4a..94138edc 100644 --- a/src/stm/ao_serial_stm.c +++ b/src/stm/ao_serial_stm.c @@ -17,13 +17,6 @@ #include -struct ao_stm_usart { - struct ao_fifo rx_fifo; - struct ao_fifo tx_fifo; - struct stm_usart *reg; - uint8_t tx_started; -}; - void ao_debug_out(char c) { @@ -78,16 +71,19 @@ ao_usart_getchar(struct ao_stm_usart *usart) return c; } -char +int ao_usart_pollchar(struct ao_stm_usart *usart) { - char c; + int c; ao_arch_block_interrupts(); if (ao_fifo_empty(usart->rx_fifo)) c = AO_READ_AGAIN; - else - ao_fifo_remove(usart->rx_fifo,c); + else { + uint8_t u; + ao_fifo_remove(usart->rx_fifo,u); + c = u; + } ao_arch_release_interrupts(); return c; } @@ -201,7 +197,7 @@ ao_serial1_putchar(char c) ao_usart_putchar(&ao_stm_usart1, c); } -char +int ao_serial1_pollchar(void) { return ao_usart_pollchar(&ao_stm_usart1); @@ -232,7 +228,7 @@ ao_serial2_putchar(char c) ao_usart_putchar(&ao_stm_usart2, c); } -char +int ao_serial2_pollchar(void) { return ao_usart_pollchar(&ao_stm_usart2); @@ -263,7 +259,7 @@ ao_serial3_putchar(char c) ao_usart_putchar(&ao_stm_usart3, c); } -char +int ao_serial3_pollchar(void) { return ao_usart_pollchar(&ao_stm_usart3); diff --git a/src/stm/ao_usb_stm.c b/src/stm/ao_usb_stm.c index d93a0c17..9379e5cd 100644 --- a/src/stm/ao_usb_stm.c +++ b/src/stm/ao_usb_stm.c @@ -873,10 +873,10 @@ _ao_usb_out_recv(void) ao_usb_set_stat_rx(AO_USB_OUT_EPR, STM_USB_EPR_STAT_RX_VALID); } -static char +static int _ao_usb_pollchar(void) { - char c; + uint8_t c; if (!ao_usb_running) return AO_READ_AGAIN; @@ -896,10 +896,10 @@ _ao_usb_pollchar(void) return c; } -char +int ao_usb_pollchar(void) { - char c; + int c; ao_arch_block_interrupts(); c = _ao_usb_pollchar(); ao_arch_release_interrupts(); @@ -909,7 +909,7 @@ ao_usb_pollchar(void) char ao_usb_getchar(void) { - char c; + int c; ao_arch_block_interrupts(); while ((c = _ao_usb_pollchar()) == AO_READ_AGAIN) -- cgit v1.2.3 From 7db14905af5cbbfa47d1a2026cce6aea9e5aae7a Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 30 Nov 2012 16:03:45 -0800 Subject: altos: Add support for 115200 baud serial rates Necessary for flashing skytraq chips Signed-off-by: Keith Packard --- src/cc1111/ao_serial.c | 10 ++++++++-- src/stm/ao_serial_stm.c | 5 ++++- src/test/ao_gps_test.c | 8 +++++++- src/test/ao_gps_test_skytraq.c | 10 +++++++++- 4 files changed, 28 insertions(+), 5 deletions(-) (limited to 'src/stm') diff --git a/src/cc1111/ao_serial.c b/src/cc1111/ao_serial.c index 2a93bf52..8913a9b0 100644 --- a/src/cc1111/ao_serial.c +++ b/src/cc1111/ao_serial.c @@ -34,8 +34,14 @@ const __code struct ao_serial_speed ao_serial_speeds[] = { /* .baud = */ 59, /* .gcr = */ (11 << UxGCR_BAUD_E_SHIFT) | UxGCR_ORDER_LSB }, + /* [AO_SERIAL_SPEED_115200] = */ { + /* .baud = */ 59, + /* .gcr = */ (12 << UxGCR_BAUD_E_SHIFT) | UxGCR_ORDER_LSB + }, }; +#define AO_SERIAL_SPEED_MAX AO_SERIAL_SPEED_115200 + #if HAS_SERIAL_0 volatile __xdata struct ao_fifo ao_serial0_rx_fifo; @@ -116,7 +122,7 @@ void ao_serial0_set_speed(uint8_t speed) { ao_serial0_drain(); - if (speed > AO_SERIAL_SPEED_57600) + if (speed > AO_SERIAL_SPEED_MAX) return; U0UCR |= UxUCR_FLUSH; U0BAUD = ao_serial_speeds[speed].baud; @@ -204,7 +210,7 @@ void ao_serial1_set_speed(uint8_t speed) { ao_serial1_drain(); - if (speed > AO_SERIAL_SPEED_57600) + if (speed > AO_SERIAL_SPEED_MAX) return; U1UCR |= UxUCR_FLUSH; U1BAUD = ao_serial_speeds[speed].baud; diff --git a/src/stm/ao_serial_stm.c b/src/stm/ao_serial_stm.c index 94138edc..ce33f97e 100644 --- a/src/stm/ao_serial_stm.c +++ b/src/stm/ao_serial_stm.c @@ -123,12 +123,15 @@ static const struct { [AO_SERIAL_SPEED_57600] = { AO_PCLK1 / 57600 }, + [AO_SERIAL_SPEED_115200] = { + AO_PCLK1 / 115200 + }, }; void ao_usart_set_speed(struct ao_stm_usart *usart, uint8_t speed) { - if (speed > AO_SERIAL_SPEED_57600) + if (speed > AO_SERIAL_SPEED_115200) return; usart->reg->brr = ao_usart_speeds[speed].brr; } diff --git a/src/test/ao_gps_test.c b/src/test/ao_gps_test.c index d75a12ec..3844a326 100644 --- a/src/test/ao_gps_test.c +++ b/src/test/ao_gps_test.c @@ -88,6 +88,7 @@ ao_mutex_put(uint8_t *mutex) static int ao_gps_fd; +#if 0 static void ao_dbg_char(char c) { @@ -103,6 +104,7 @@ ao_dbg_char(char c) } write(1, line, strlen(line)); } +#endif #define QUEUE_LEN 4096 @@ -391,6 +393,7 @@ ao_serial1_putchar(char c) #define AO_SERIAL_SPEED_4800 0 #define AO_SERIAL_SPEED_57600 1 +#define AO_SERIAL_SPEED_115200 2 static void ao_serial1_set_speed(uint8_t speed) @@ -407,6 +410,9 @@ ao_serial1_set_speed(uint8_t speed) case AO_SERIAL_SPEED_57600: cfsetspeed(&termios, B57600); break; + case AO_SERIAL_SPEED_115200: + cfsetspeed(&termios, B115200); + break; } tcsetattr(fd, TCSAFLUSH, &termios); tcflush(fd, TCIFLUSH); @@ -420,7 +426,6 @@ ao_serial1_set_speed(uint8_t speed) void ao_dump_state(void *wchan) { - double lat, lon; int i; if (wchan == &ao_gps_data) ao_gps_print(&ao_gps_data); @@ -510,4 +515,5 @@ main (int argc, char **argv) } ao_gps_setup(); ao_gps(); + return 0; } diff --git a/src/test/ao_gps_test_skytraq.c b/src/test/ao_gps_test_skytraq.c index 846daa94..81008b39 100644 --- a/src/test/ao_gps_test_skytraq.c +++ b/src/test/ao_gps_test_skytraq.c @@ -397,6 +397,7 @@ ao_serial1_putchar(char c) #define AO_SERIAL_SPEED_4800 0 #define AO_SERIAL_SPEED_9600 1 #define AO_SERIAL_SPEED_57600 2 +#define AO_SERIAL_SPEED_115200 3 static void ao_serial1_set_speed(uint8_t speed) @@ -411,11 +412,14 @@ ao_serial1_set_speed(uint8_t speed) cfsetspeed(&termios, B4800); break; case AO_SERIAL_SPEED_9600: - cfsetspeed(&termios, B38400); + cfsetspeed(&termios, B9600); break; case AO_SERIAL_SPEED_57600: cfsetspeed(&termios, B57600); break; + case AO_SERIAL_SPEED_115200: + cfsetspeed(&termios, B115200); + break; } tcsetattr(fd, TCSAFLUSH, &termios); tcflush(fd, TCIFLUSH); @@ -423,6 +427,10 @@ ao_serial1_set_speed(uint8_t speed) #define ao_time() 0 +uint8_t ao_task_minimize_latency; + +#define ao_usb_getchar() 0 + #include "ao_gps_print.c" #include "ao_gps_skytraq.c" -- cgit v1.2.3 From 7883744526156879ad63256ab12d959df56d5252 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 12 Jan 2013 20:11:38 -0800 Subject: altos: Initial telescience bits These might do something, and should at least bring up USB Signed-off-by: Keith Packard --- src/stm/ao_spi_stm_slave.c | 339 ++++++++++++++++++++++++++++++++++ src/telescience-v0.2/.gitignore | 2 + src/telescience-v0.2/Makefile | 85 +++++++++ src/telescience-v0.2/ao_pins.h | 141 ++++++++++++++ src/telescience-v0.2/ao_telescience.c | 51 +++++ 5 files changed, 618 insertions(+) create mode 100644 src/stm/ao_spi_stm_slave.c create mode 100644 src/telescience-v0.2/.gitignore create mode 100644 src/telescience-v0.2/Makefile create mode 100644 src/telescience-v0.2/ao_pins.h create mode 100644 src/telescience-v0.2/ao_telescience.c (limited to 'src/stm') diff --git a/src/stm/ao_spi_stm_slave.c b/src/stm/ao_spi_stm_slave.c new file mode 100644 index 00000000..98022442 --- /dev/null +++ b/src/stm/ao_spi_stm_slave.c @@ -0,0 +1,339 @@ +/* + * Copyright © 2012 Keith Packard + * + * 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 + +struct ao_spi_stm_slave_info { + uint8_t miso_dma_index; + uint8_t mosi_dma_index; + struct stm_spi *stm_spi; +}; + +static uint8_t ao_spi_slave_mutex[STM_NUM_SPI]; +static uint8_t ao_spi_slave_index[STM_NUM_SPI]; + +static const struct ao_spi_stm_slave_info ao_spi_stm_slave_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; + +void +ao_spi_slave_send(void *block, uint16_t len) +{ + struct stm_spi *stm_spi = ao_spi_stm_slave_info[AO_SPI_INDEX(SPI_SLAVE_INDEX)].stm_spi; + uint8_t mosi_dma_index = ao_spi_stm_slave_info[AO_SPI_INDEX(SPI_SLAVE_INDEX)].mosi_dma_index; + uint8_t miso_dma_index = ao_spi_stm_slave_info[AO_SPI_INDEX(SPI_SLAVE_INDEX)].miso_dma_index; + + /* Set up the transmit DMA to deliver data */ + ao_dma_set_transfer(mosi_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_MEM_TO_PER << STM_DMA_CCR_DIR)); + + /* 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)); + stm_spi->cr2 = ((0 << STM_SPI_CR2_TXEIE) | + (0 << STM_SPI_CR2_RXNEIE) | + (0 << STM_SPI_CR2_ERRIE) | + (0 << STM_SPI_CR2_SSOE) | + (1 << STM_SPI_CR2_TXDMAEN) | + (1 << STM_SPI_CR2_RXDMAEN)); + 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); +} + + +uint8_t +ao_spi_slave_recv(void *block, uint16_t len) +{ + struct stm_spi *stm_spi = ao_spi_stm_slave_info[AO_SPI_INDEX(SPI_SLAVE_INDEX)].stm_spi; + uint8_t mosi_dma_index = ao_spi_stm_slave_info[AO_SPI_INDEX(SPI_SLAVE_INDEX)].mosi_dma_index; + uint8_t miso_dma_index = ao_spi_stm_slave_info[AO_SPI_INDEX(SPI_SLAVE_INDEX)].miso_dma_index; + + /* 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)); + + /* 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)); + + stm_spi->cr2 = ((0 << STM_SPI_CR2_TXEIE) | + (0 << STM_SPI_CR2_RXNEIE) | + (0 << STM_SPI_CR2_ERRIE) | + (0 << STM_SPI_CR2_SSOE) | + (1 << STM_SPI_CR2_TXDMAEN) | + (1 << STM_SPI_CR2_RXDMAEN)); + 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_slave_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; + case AO_SPI_1_PE13_PE14_PE15: + stm_gpio_set(&stm_gpioe, 13, 1); + stm_moder_set(&stm_gpioe, 13, STM_MODER_OUTPUT); + stm_moder_set(&stm_gpioe, 14, STM_MODER_INPUT); + stm_moder_set(&stm_gpioe, 15, 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; + case AO_SPI_2_PD1_PD3_PD4: + stm_gpio_set(&stm_gpiod, 1, 1); + stm_moder_set(&stm_gpiod, 1, STM_MODER_OUTPUT); + stm_moder_set(&stm_gpiod, 3, STM_MODER_INPUT); + stm_moder_set(&stm_gpiod, 4, STM_MODER_OUTPUT); + break; + } + break; + } +} + +static void +ao_spi_slave_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_AF5); + stm_afr_set(&stm_gpioa, 6, STM_AFR_AF5); + stm_afr_set(&stm_gpioa, 7, STM_AFR_AF5); + break; + case AO_SPI_1_PB3_PB4_PB5: + stm_afr_set(&stm_gpiob, 3, STM_AFR_AF5); + stm_afr_set(&stm_gpiob, 4, STM_AFR_AF5); + stm_afr_set(&stm_gpiob, 5, STM_AFR_AF5); + break; + case AO_SPI_1_PE13_PE14_PE15: + stm_afr_set(&stm_gpioe, 13, STM_AFR_AF5); + stm_afr_set(&stm_gpioe, 14, STM_AFR_AF5); + stm_afr_set(&stm_gpioe, 15, STM_AFR_AF5); + 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_AF5); + stm_afr_set(&stm_gpiob, 14, STM_AFR_AF5); + stm_afr_set(&stm_gpiob, 15, STM_AFR_AF5); + break; + case AO_SPI_2_PD1_PD3_PD4: + stm_afr_set(&stm_gpiod, 1, STM_AFR_AF5); + stm_afr_set(&stm_gpiod, 3, STM_AFR_AF5); + stm_afr_set(&stm_gpiod, 4, STM_AFR_AF5); + break; + } + break; + } +} + +void +ao_spi_slave_get(uint8_t spi_index, uint32_t speed) +{ + uint8_t id = AO_SPI_INDEX(spi_index); + struct stm_spi *stm_spi = ao_spi_stm_slave_info[id].stm_spi; + + ao_mutex_get(&ao_spi_slave_mutex[id]); + 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_DFF) | + (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_slave_index[id]) { + + /* Disable old config + */ + ao_spi_slave_disable_index(ao_spi_slave_index[id]); + + /* Enable new config + */ + ao_spi_slave_enable_index(spi_index); + + /* Remember current config + */ + ao_spi_slave_index[id] = spi_index; + } +} + +void +ao_spi_slave_put(uint8_t spi_index) +{ + uint8_t id = AO_SPI_INDEX(spi_index); + struct stm_spi *stm_spi = ao_spi_stm_slave_info[id].stm_spi; + + stm_spi->cr1 = 0; + ao_mutex_put(&ao_spi_slave_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_slave_info[id].stm_spi; + + ao_spi_slave_disable_index(spi_index); + + stm_spi->cr1 = 0; + (void) stm_spi->sr; + 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)); +} + +void +ao_spi_slave_init(void) +{ +#if HAS_SPI_SLAVE_1 +# if SPI_1_PA5_PA6_PA7 + stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_GPIOAEN); +# endif +# if SPI_1_PB3_PB4_PB5 + stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_GPIOBEN); +# endif +# if SPI_1_PE13_PE14_PE15 + stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_GPIOEEN); +# endif + stm_rcc.apb2enr |= (1 << STM_RCC_APB2ENR_SPI1EN); + ao_spi_slave_index[0] = AO_SPI_CONFIG_NONE; + ao_spi_channel_init(0); +#endif + +#if HAS_SPI_SLAVE_2 +# if SPI_2_PB13_PB14_PB15 + stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_GPIOBEN); +# endif +# if SPI_2_PD1_PD3_PD4 + stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_GPIODEN); +# endif + stm_rcc.apb1enr |= (1 << STM_RCC_APB1ENR_SPI2EN); + ao_spi_slave_index[1] = AO_SPI_CONFIG_NONE; + ao_spi_channel_init(1); +#endif +} diff --git a/src/telescience-v0.2/.gitignore b/src/telescience-v0.2/.gitignore new file mode 100644 index 00000000..cc1f8b73 --- /dev/null +++ b/src/telescience-v0.2/.gitignore @@ -0,0 +1,2 @@ +ao_product.h +telescience-*.elf diff --git a/src/telescience-v0.2/Makefile b/src/telescience-v0.2/Makefile new file mode 100644 index 00000000..fbeeb75c --- /dev/null +++ b/src/telescience-v0.2/Makefile @@ -0,0 +1,85 @@ +# +# AltOS build +# +# + +include ../stm/Makefile.defs + +INC = \ + ao.h \ + ao_arch.h \ + ao_arch_funcs.h \ + ao_pins.h \ + ao_product.h \ + ao_cc1120_CC1120.h \ + ao_task.h \ + ao_whiten.h \ + stm32l.h \ + Makefile + +#PROFILE=ao_profile.c +#PROFILE_DEF=-DAO_PROFILE=1 + +#SAMPLE_PROFILE=ao_sample_profile.c \ +# ao_sample_profile_timer.c +#SAMPLE_PROFILE_DEF=-DHAS_SAMPLE_PROFILE=1 + +#STACK_GUARD=ao_mpu_stm.c +#STACK_GUARD_DEF=-DHAS_STACK_GUARD=1 + +ALTOS_SRC = \ + 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_dma_stm.c \ + ao_spi_stm.c \ + ao_usb_stm.c \ + ao_adc_stm.c \ + ao_data.c \ + ao_exti_stm.c \ + ao_storage.c \ + ao_m25.c \ + ao_science_slave.c \ + ao_spi_stm_slave.c \ + ao_log_telescience.c \ + ao_log_single.c + +PRODUCT=TeleScience-v0.2 +PRODUCT_DEF=-DTELESCIENCE +IDPRODUCT=0x0011 + +CFLAGS = $(PRODUCT_DEF) $(STM_CFLAGS) $(PROFILE_DEF) $(SAMPLE_PROFILE_DEF) $(STACK_GUARD_DEF) -Os -g + +PROGNAME=telescience-v0.2 +PROG=$(PROGNAME)-$(VERSION).elf + +SRC=$(ALTOS_SRC) ao_telescience.c +OBJ=$(SRC:.c=.o) + +all: $(PROG) + +$(PROG): Makefile $(OBJ) altos.ld + $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(OBJ) $(SAT_CLIB) -lgcc + +$(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 + rm -f ao_product.h + +install: + +uninstall: diff --git a/src/telescience-v0.2/ao_pins.h b/src/telescience-v0.2/ao_pins.h new file mode 100644 index 00000000..cb86fcb6 --- /dev/null +++ b/src/telescience-v0.2/ao_pins.h @@ -0,0 +1,141 @@ +/* + * Copyright © 2012 Keith Packard + * + * 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_TASK_QUEUE 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) + +/* 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_SERIAL_1 0 +#define USE_SERIAL_1_STDIN 0 +#define SERIAL_1_PB6_PB7 0 +#define SERIAL_1_PA9_PA10 1 + +#define HAS_SERIAL_2 0 +#define USE_SERIAL_2_STDIN 0 +#define SERIAL_2_PA2_PA3 0 +#define SERIAL_2_PD5_PD6 0 + +#define HAS_SERIAL_3 0 +#define USE_SERIAL_3_STDIN 0 +#define SERIAL_3_PB10_PB11 0 +#define SERIAL_3_PC10_PC11 1 +#define SERIAL_3_PD8_PD9 0 + +#define HAS_EEPROM 1 +#define USE_INTERNAL_FLASH 0 +#define HAS_USB 1 +#define HAS_BEEP 0 +#define HAS_RADIO 0 +#define HAS_TELEMETRY 0 +#define PACKET_HAS_SLAVE 0 + +#define HAS_SPI_1 1 +#define SPI_1_PA5_PA6_PA7 1 +#define SPI_1_PB3_PB4_PB5 0 +#define SPI_1_PE13_PE14_PE15 0 + +#define HAS_SPI_2 1 +#define SPI_2_PB13_PB14_PB15 1 +#define SPI_2_PD1_PD3_PD4 0 + +#define SPI_2_PORT (&stm_gpiob) +#define SPI_2_SCK_PIN 13 +#define SPI_2_MISO_PIN 14 +#define SPI_2_MOSI_PIN 15 +#define SPI_SLAVE_INDEX 1 + +#define HAS_I2C_1 0 +#define I2C_1_PB8_PB9 0 + +#define HAS_I2C_2 0 +#define I2C_2_PB10_PB11 0 + +#define LOW_LEVEL_DEBUG 0 + +#define LED_PORT_0_ENABLE STM_RCC_AHBENR_GPIOAEN + +#define LED_PORT_0 (&stm_gpioa) +#define LED_PORT_0_MASK (0xff) +#define LED_PORT_0_SHIFT 0 +#define LED_PIN_RED 8 +#define LED_PIN_GREEN 9 +#define AO_LED_RED (1 << LED_PIN_RED) +#define AO_LED_GREEN (1 << LED_PIN_GREEN) + +#define LEDS_AVAILABLE (AO_LED_RED | AO_LED_GREEN) + +#define HAS_GPS 0 +#define HAS_FLIGHT 0 +#define HAS_ADC 1 +#define HAS_LOG 1 + +/* + * SPI Flash memory + */ + +#define M25_MAX_CHIPS 1 +#define AO_M25_SPI_CS_PORT (&stm_gpioa) +#define AO_M25_SPI_CS_MASK (1 << 3) +#define AO_M25_SPI_BUS AO_SPI_2_PB13_PB14_PB15 + +/* + * ADC + */ + +#define AO_DATA_RING 32 +#define AO_ADC_NUM 1 + +struct ao_adc { + int16_t adc[AO_ADC_NUM]; +}; + +#define AO_ADC_TEMP 16 + +#define AO_ADC_RCC_AHBENR 0 + +#define AO_NUM_ADC_PIN 0 + +#define AO_NUM_ADC 1 + +#define AO_ADC_SQ1 AO_ADC_TEMP + + +#endif /* _AO_PINS_H_ */ diff --git a/src/telescience-v0.2/ao_telescience.c b/src/telescience-v0.2/ao_telescience.c new file mode 100644 index 00000000..2fb3186a --- /dev/null +++ b/src/telescience-v0.2/ao_telescience.c @@ -0,0 +1,51 @@ +/* + * Copyright © 2012 Keith Packard + * + * 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 +#include +#include +#include + +int +main(void) +{ + ao_clock_init(); + +#if HAS_STACK_GUARD + ao_mpu_init(); +#endif + + ao_task_init(); + ao_led_init(LEDS_AVAILABLE); + ao_led_on(AO_LED_GREEN); + ao_timer_init(); + + ao_spi_init(); + ao_spi_slave_init(); + ao_dma_init(); + ao_exti_init(); + + ao_cmd_init(); + + ao_usb_init(); + ao_config_init(); + + ao_storage_init(); + + ao_start_scheduler(); + return 0; +} -- cgit v1.2.3 From 8d885616e2e522b8aea5e7d5398f16d330a0cffa Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 13 Jan 2013 20:48:47 -0800 Subject: altos: Set STM GPIO output speed for SPI pins correctly The GPIO pin settings affect the output impedence, and hence the maximum speed for SPI. Cranking these to suitable values allows SPI to run at full speed. Signed-off-by: Keith Packard --- src/megadongle-v0.1/ao_pins.h | 1 + src/megametrum-v0.1/ao_pins.h | 2 ++ src/stm-demo/ao_pins.h | 1 + src/stm/ao_spi_stm.c | 15 +++++++++++++++ src/telelco-v0.1/ao_pins.h | 7 ++++--- src/telescience-v0.2/ao_pins.h | 7 +++++-- 6 files changed, 28 insertions(+), 5 deletions(-) (limited to 'src/stm') diff --git a/src/megadongle-v0.1/ao_pins.h b/src/megadongle-v0.1/ao_pins.h index c766a48c..d460a490 100644 --- a/src/megadongle-v0.1/ao_pins.h +++ b/src/megadongle-v0.1/ao_pins.h @@ -78,6 +78,7 @@ #define HAS_SPI_2 1 #define SPI_2_PB13_PB14_PB15 1 /* Flash, Companion */ #define SPI_2_PD1_PD3_PD4 0 +#define SPI_2_OSPEEDR STM_OSPEEDR_10MHz #define SPI_2_PORT (&stm_gpiob) #define SPI_2_SCK_PIN 13 diff --git a/src/megametrum-v0.1/ao_pins.h b/src/megametrum-v0.1/ao_pins.h index 64da41a9..4c645871 100644 --- a/src/megametrum-v0.1/ao_pins.h +++ b/src/megametrum-v0.1/ao_pins.h @@ -76,10 +76,12 @@ #define SPI_1_PA5_PA6_PA7 1 /* Barometer */ #define SPI_1_PB3_PB4_PB5 0 #define SPI_1_PE13_PE14_PE15 1 /* Accelerometer */ +#define SPI_1_OSPEEDR STM_OSPEEDR_10MHz #define HAS_SPI_2 1 #define SPI_2_PB13_PB14_PB15 1 /* Flash, Companion */ #define SPI_2_PD1_PD3_PD4 0 +#define SPI_2_OSPEEDR STM_OSPEEDR_10MHz #define SPI_2_PORT (&stm_gpiob) #define SPI_2_SCK_PIN 13 diff --git a/src/stm-demo/ao_pins.h b/src/stm-demo/ao_pins.h index c9c7446e..07b4a19d 100644 --- a/src/stm-demo/ao_pins.h +++ b/src/stm-demo/ao_pins.h @@ -60,6 +60,7 @@ #define HAS_SPI_1 1 #define SPI_1_PB3_PB4_PB5 1 +#define SPI_1_OSPEEDR STM_OSPEEDR_10MHz #define HAS_SPI_2 0 diff --git a/src/stm/ao_spi_stm.c b/src/stm/ao_spi_stm.c index 599d7ee0..7b4af964 100644 --- a/src/stm/ao_spi_stm.c +++ b/src/stm/ao_spi_stm.c @@ -425,12 +425,21 @@ ao_spi_init(void) #if HAS_SPI_1 # if SPI_1_PA5_PA6_PA7 stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_GPIOAEN); + 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_GPIOBEN); + 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 # if SPI_1_PE13_PE14_PE15 stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_GPIOEEN); + stm_ospeedr_set(&stm_gpioe, 13, SPI_1_OSPEEDR); + stm_ospeedr_set(&stm_gpioe, 14, SPI_1_OSPEEDR); + stm_ospeedr_set(&stm_gpioe, 15, SPI_1_OSPEEDR); # endif stm_rcc.apb2enr |= (1 << STM_RCC_APB2ENR_SPI1EN); ao_spi_index[0] = AO_SPI_CONFIG_NONE; @@ -440,9 +449,15 @@ ao_spi_init(void) #if HAS_SPI_2 # if SPI_2_PB13_PB14_PB15 stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_GPIOBEN); + 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 # if SPI_2_PD1_PD3_PD4 stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_GPIODEN); + stm_ospeedr_set(&stm_gpiod, 1, SPI_2_OSPEEDR); + stm_ospeedr_set(&stm_gpiod, 3, SPI_2_OSPEEDR); + stm_ospeedr_set(&stm_gpiod, 4, SPI_2_OSPEEDR); # endif stm_rcc.apb1enr |= (1 << STM_RCC_APB1ENR_SPI2EN); ao_spi_index[1] = AO_SPI_CONFIG_NONE; diff --git a/src/telelco-v0.1/ao_pins.h b/src/telelco-v0.1/ao_pins.h index 60cf018f..970f9bd1 100644 --- a/src/telelco-v0.1/ao_pins.h +++ b/src/telelco-v0.1/ao_pins.h @@ -49,18 +49,19 @@ #define HAS_TELEMETRY 0 #define HAS_AES 1 -#define HAS_SPI_1 1 -#define SPI_1_PA5_PA6_PA7 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 +#define HAS_SPI_2 1 /* CC1111 */ #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 diff --git a/src/telescience-v0.2/ao_pins.h b/src/telescience-v0.2/ao_pins.h index cb86fcb6..7b974506 100644 --- a/src/telescience-v0.2/ao_pins.h +++ b/src/telescience-v0.2/ao_pins.h @@ -67,14 +67,17 @@ #define HAS_TELEMETRY 0 #define PACKET_HAS_SLAVE 0 -#define HAS_SPI_1 1 -#define SPI_1_PA5_PA6_PA7 1 +#define HAS_SPI_1 0 +#define HAS_SPI_SLAVE_1 1 +#define SPI_1_PA5_PA6_PA7 1 #define SPI_1_PB3_PB4_PB5 0 #define SPI_1_PE13_PE14_PE15 0 +#define SPI_1_OSPEEDR STM_OSPEEDR_10MHz #define HAS_SPI_2 1 #define SPI_2_PB13_PB14_PB15 1 #define SPI_2_PD1_PD3_PD4 0 +#define SPI_2_OSPEEDR STM_OSPEEDR_10MHz #define SPI_2_PORT (&stm_gpiob) #define SPI_2_SCK_PIN 13 -- cgit v1.2.3 From a866431e9a063830b407f749ff97a730831e5e4e Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 13 Jan 2013 20:50:10 -0800 Subject: altos: Crank fast SPI on STM to 8MHz With the GPIO pins set to 10MHz now, we can run SPI at the maximum possible speed (8MHz). Signed-off-by: Keith Packard --- src/stm/ao_arch_funcs.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/stm') diff --git a/src/stm/ao_arch_funcs.h b/src/stm/ao_arch_funcs.h index 87bbe73e..d1779307 100644 --- a/src/stm/ao_arch_funcs.h +++ b/src/stm/ao_arch_funcs.h @@ -23,7 +23,7 @@ /* PCLK is set to 16MHz (HCLK 32MHz, APB prescaler 2) */ -#define AO_SPI_SPEED_8MHz STM_SPI_CR1_BR_PCLK_2 /* This doesn't appear to work */ +#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 @@ -32,7 +32,7 @@ #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_FAST AO_SPI_SPEED_4MHz +#define AO_SPI_SPEED_FAST AO_SPI_SPEED_8MHz /* Companion bus wants something no faster than 200kHz */ -- cgit v1.2.3 From 25435dcbc6416935aa432fc090ea977bfff5d153 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 24 Feb 2013 00:19:49 -0800 Subject: altos/stm: Add more bits to NVIC register definitions This cleans up a few values, adds more comments and a few more NVIC fields. Signed-off-by: Keith Packard --- src/stm/stm32l.h | 35 +++++++++++++++++++++++------------ 1 file changed, 23 insertions(+), 12 deletions(-) (limited to 'src/stm') diff --git a/src/stm/stm32l.h b/src/stm/stm32l.h index 0dbfae39..1d636037 100644 --- a/src/stm/stm32l.h +++ b/src/stm/stm32l.h @@ -811,30 +811,41 @@ extern struct stm_lcd stm_lcd; #define STM_LCD_CLR_UDDC (3) #define STM_LCD_CLR_SOFC (1) +/* The NVIC starts at 0xe000e100, so add that to the offsets to find the absolute address */ + struct stm_nvic { - vuint32_t iser[3]; /* 0x000 */ + vuint32_t iser[8]; /* 0x000 0xe000e100 Set Enable Register */ + + uint8_t _unused020[0x080 - 0x020]; + + vuint32_t icer[8]; /* 0x080 0xe000e180 Clear Enable Register */ - uint8_t _unused00c[0x080 - 0x00c]; + uint8_t _unused0a0[0x100 - 0x0a0]; - vuint32_t icer[3]; /* 0x080 */ + vuint32_t ispr[8]; /* 0x100 0xe000e200 Set Pending Register */ - uint8_t _unused08c[0x100 - 0x08c]; + uint8_t _unused120[0x180 - 0x120]; - vuint32_t ispr[3]; /* 0x100 */ + vuint32_t icpr[8]; /* 0x180 0xe000e280 Clear Pending Register */ - uint8_t _unused10c[0x180 - 0x10c]; + uint8_t _unused1a0[0x200 - 0x1a0]; - vuint32_t icpr[3]; /* 0x180 */ + vuint32_t iabr[8]; /* 0x200 0xe000e300 Active Bit Register */ - uint8_t _unused18c[0x200 - 0x18c]; + uint8_t _unused220[0x300 - 0x220]; - vuint32_t iabr[3]; /* 0x200 */ + vuint32_t ipr[60]; /* 0x300 0xe000e400 Priority Register */ - uint8_t _unused20c[0x300 - 0x20c]; + uint8_t _unused3f0[0xc00 - 0x3f0]; - vuint32_t ipr[21]; /* 0x300 */ + vuint32_t cpuid_base; /* 0xc00 0xe000ed00 CPUID Base Register */ + vuint32_t ics; /* 0xc04 0xe000ed04 Interrupt Control State Register */ + vuint32_t vto; /* 0xc08 0xe000ed08 Vector Table Offset Register */ + vuint32_t ai_rc; /* 0xc0c 0xe000ed0c Application Interrupt/Reset Control Register */ + vuint32_t sc; /* 0xc10 0xe000ed10 System Control Register */ + vuint32_t cc; /* 0xc14 0xe000ed14 Configuration Control Register */ - uint8_t _unused324[0xe00 - 0x324]; + uint8_t _unusedc18[0xe00 - 0xc18]; vuint32_t stir; /* 0xe00 */ }; -- cgit v1.2.3 From 4d187460bdcb97bf6d0a3550e4e03c4c223e4cc1 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 26 Mar 2013 14:26:38 -0700 Subject: altos/stm: Ensure SPI always sends 0xff during receive SD cards require 0xff when fetching data Signed-off-by: Keith Packard --- src/stm/ao_spi_stm.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src/stm') diff --git a/src/stm/ao_spi_stm.c b/src/stm/ao_spi_stm.c index 7b4af964..56329c24 100644 --- a/src/stm/ao_spi_stm.c +++ b/src/stm/ao_spi_stm.c @@ -160,6 +160,8 @@ ao_spi_recv(void *block, uint16_t len, uint8_t spi_index) 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, -- cgit v1.2.3 From 985cd22b941415b1ae2709ae1ab6b60c3d815ec1 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 27 Mar 2013 18:43:42 -0700 Subject: altos: Use FTDW, clear DATA bit. Disable backup write protection The newer(?) chips in telegps didn't like the previous programming scheme, so go back to fixed time for write, which does an implicit erase before every write. Also clear the DATA bit, which is only needed for double word erase/programming. Signed-off-by: Keith Packard --- src/stm/ao_eeprom_stm.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) (limited to 'src/stm') diff --git a/src/stm/ao_eeprom_stm.c b/src/stm/ao_eeprom_stm.c index 5a75a97d..58783f1a 100644 --- a/src/stm/ao_eeprom_stm.c +++ b/src/stm/ao_eeprom_stm.c @@ -55,10 +55,16 @@ ao_storage_erase(ao_pos_t pos) __reentrant static void ao_intflash_unlock(void) { + /* Disable backup write protection */ + stm_pwr.cr |= (1 << STM_PWR_CR_DBP); + /* Unlock Data EEPROM and FLASH_PECR register */ stm_flash.pekeyr = STM_FLASH_PEKEYR_PEKEY1; stm_flash.pekeyr = STM_FLASH_PEKEYR_PEKEY2; + if (stm_flash.pecr & (1 << STM_FLASH_PECR_PELOCK)) + printf ("eeprom unlock failed\n"); + /* Configure the FTDW bit (FLASH_PECR[8]) to execute * word write, whatever the previous value of the word * being written to @@ -68,8 +74,8 @@ ao_intflash_unlock(void) (0 << STM_FLASH_PECR_EOPIE) | (0 << STM_FLASH_PECR_FPRG) | (0 << STM_FLASH_PECR_ERASE) | - (0 << STM_FLASH_PECR_FTDW) | - (1 << STM_FLASH_PECR_DATA) | + (1 << STM_FLASH_PECR_FTDW) | + (0 << STM_FLASH_PECR_DATA) | (0 << STM_FLASH_PECR_PROG) | (0 << STM_FLASH_PECR_OPTLOCK) | (0 << STM_FLASH_PECR_PRGLOCK) | @@ -97,15 +103,9 @@ ao_intflash_write32(uint16_t pos, uint32_t w) addr = (uint32_t *) (stm_eeprom + pos); - /* Erase previous word */ - *addr = 0; + /* Write a word to a valid address in the data EEPROM */ + *addr = w; ao_intflash_wait(); - - if (w) { - /* Write a word to a valid address in the data EEPROM */ - *addr = w; - ao_intflash_wait(); - } } static void -- cgit v1.2.3 From 4f1f3e836393304434130d362771a39f6f8f859a Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 24 Mar 2013 15:00:20 -0700 Subject: altos: Do not release interrupts from any pollchar function getchar relies on interrupts being blocked across the pollchar calls and into the sleep call or it may go to sleep with data pending. This prefixes all pollchar functions with _ to indicate that they are to be called with interrupts blocked and eliminates all interrupt manipulation calls from within the pollchar functions. Signed-off-by: Keith Packard --- src/avr/ao_serial_avr.c | 43 +++++++++++++++++----------------- src/avr/ao_usb_avr.c | 42 ++++++++++++++-------------------- src/cc1111/ao_serial.c | 8 +++---- src/cc1111/ao_usb.c | 14 +++++++----- src/core/ao.h | 2 +- src/core/ao_packet.h | 2 +- src/core/ao_serial.h | 8 +++---- src/core/ao_stdio.c | 31 +++++++++++++------------ src/drivers/ao_btm.c | 52 +++++++++++++++++++++++++++--------------- src/drivers/ao_packet.c | 6 ++--- src/drivers/ao_packet_master.c | 7 +++++- src/drivers/ao_packet_slave.c | 2 +- src/stm/ao_serial_stm.c | 45 +++++++++++++++++------------------- src/stm/ao_usb_stm.c | 23 ++++++++----------- 14 files changed, 144 insertions(+), 141 deletions(-) (limited to 'src/stm') diff --git a/src/avr/ao_serial_avr.c b/src/avr/ao_serial_avr.c index dcee246c..e0f813d5 100644 --- a/src/avr/ao_serial_avr.c +++ b/src/avr/ao_serial_avr.c @@ -59,52 +59,51 @@ ISR(USART1_UDRE_vect) ao_wakeup(&ao_serial1_tx_fifo); } -char -ao_serial1_getchar(void) __critical -{ - char c; - cli(); - while (ao_fifo_empty(ao_serial1_rx_fifo)) - ao_sleep(&ao_serial1_rx_fifo); - ao_fifo_remove(ao_serial1_rx_fifo, c); - sei(); - return c; -} - #if USE_SERIAL_1_STDIN -char -ao_serial1_pollchar(void) __critical +int +_ao_serial1_pollchar(void) { char c; - cli(); if (ao_fifo_empty(ao_serial1_rx_fifo)) { sei(); return AO_READ_AGAIN; } ao_fifo_remove(ao_serial1_rx_fifo,c); - sei(); return c; } #endif +char +ao_serial1_getchar(void) __critical +{ + char c; + + ao_arch_block_interrupts(); + while (ao_fifo_empty(ao_serial1_rx_fifo)) + ao_sleep(&ao_serial1_rx_fifo); + ao_fifo_remove(ao_serial1_rx_fifo, c); + ao_arch_release_interrupts(); + return c; +} + void -ao_serial1_putchar(char c) __critical +ao_serial1_putchar(char c) { - cli(); + ao_arch_block_interrupts(); while (ao_fifo_full(ao_serial1_tx_fifo)) ao_sleep(&ao_serial1_tx_fifo); ao_fifo_insert(ao_serial1_tx_fifo, c); ao_serial_tx1_start(); - sei(); + ao_arch_release_interrupts(); } void ao_serial1_drain(void) __critical { - cli(); + ao_arch_block_interrupts(); while (!ao_fifo_empty(ao_serial1_tx_fifo)) ao_sleep(&ao_serial1_tx_fifo); - sei(); + ao_arch_release_interrupts(); } static const struct { @@ -155,7 +154,7 @@ ao_serial_init(void) (1 << RXCIE1) | /* Enable receive interrupts */ (1 << UDRIE1)); /* Enable transmit empty interrupts */ #if USE_SERIAL_1_STDIN - ao_add_stdio(ao_serial1_pollchar, + ao_add_stdio(_ao_serial1_pollchar, ao_serial1_putchar, NULL); #endif diff --git a/src/avr/ao_usb_avr.c b/src/avr/ao_usb_avr.c index 2ef546c9..bd75b17d 100644 --- a/src/avr/ao_usb_avr.c +++ b/src/avr/ao_usb_avr.c @@ -411,7 +411,7 @@ ao_usb_ep0(void) /* Wait for a free IN buffer */ static void -ao_usb_in_wait(void) +_ao_usb_in_wait(void) { for (;;) { /* Check if the current buffer is writable */ @@ -419,7 +419,6 @@ ao_usb_in_wait(void) if (UEINTX & (1 << RWAL)) break; - cli(); /* Wait for an IN buffer to be ready */ for (;;) { UENUM = AO_USB_IN_EP; @@ -430,24 +429,24 @@ ao_usb_in_wait(void) } /* Ack the interrupt */ UEINTX &= ~(1 << TXINI); - sei(); } } /* Queue the current IN buffer for transmission */ static void -ao_usb_in_send(void) +_ao_usb_in_send(void) { UENUM = AO_USB_IN_EP; UEINTX &= ~(1 << FIFOCON); } void -ao_usb_flush(void) __critical +ao_usb_flush(void) { if (!ao_usb_running) return; + ao_arch_block_interrupts(); /* Anytime we've sent a character since * the last time we flushed, we'll need * to send a packet -- the only other time @@ -457,18 +456,20 @@ ao_usb_flush(void) __critical */ if (!ao_usb_in_flushed) { ao_usb_in_flushed = 1; - ao_usb_in_wait(); - ao_usb_in_send(); + _ao_usb_in_wait(); + _ao_usb_in_send(); } + ao_arch_release_interrupts(); } void -ao_usb_putchar(char c) __critical __reentrant +ao_usb_putchar(char c) { if (!ao_usb_running) return; - ao_usb_in_wait(); + ao_arch_block_interrupts(); + _ao_usb_in_wait(); /* Queue a byte */ UENUM = AO_USB_IN_EP; @@ -476,11 +477,12 @@ ao_usb_putchar(char c) __critical __reentrant /* Send the packet when full */ if ((UEINTX & (1 << RWAL)) == 0) - ao_usb_in_send(); + _ao_usb_in_send(); ao_usb_in_flushed = 0; + ao_arch_release_interrupts(); } -static int +int _ao_usb_pollchar(void) { uint8_t c; @@ -517,25 +519,15 @@ _ao_usb_pollchar(void) return c; } -int -ao_usb_pollchar(void) -{ - int c; - cli(); - c = _ao_usb_pollchar(); - sei(); - return c; -} - char -ao_usb_getchar(void) __critical +ao_usb_getchar(void) { int c; - cli(); + ao_arch_block_interrupts(); while ((c = _ao_usb_pollchar()) == AO_READ_AGAIN) ao_sleep(&ao_stdin_ready); - sei(); + ao_arch_release_interrupts(); return c; } @@ -668,5 +660,5 @@ ao_usb_init(void) #if USB_DEBUG ao_add_task(&ao_usb_echo_task, ao_usb_echo, "usb echo"); #endif - ao_add_stdio(ao_usb_pollchar, ao_usb_putchar, ao_usb_flush); + ao_add_stdio(_ao_usb_pollchar, ao_usb_putchar, ao_usb_flush); } diff --git a/src/cc1111/ao_serial.c b/src/cc1111/ao_serial.c index 8913a9b0..81727836 100644 --- a/src/cc1111/ao_serial.c +++ b/src/cc1111/ao_serial.c @@ -92,7 +92,7 @@ ao_serial0_getchar(void) __critical #if USE_SERIAL_0_STDIN int -ao_serial0_pollchar(void) __critical +_ao_serial0_pollchar(void) { uint8_t c; if (ao_fifo_empty(ao_serial0_rx_fifo)) @@ -180,7 +180,7 @@ ao_serial1_getchar(void) __critical #if USE_SERIAL_1_STDIN int -ao_serial1_pollchar(void) __critical +_ao_serial1_pollchar(void) { uint8_t c; if (ao_fifo_empty(ao_serial1_rx_fifo)) @@ -271,7 +271,7 @@ ao_serial_init(void) IEN0 |= IEN0_URX0IE; IEN2 |= IEN2_UTX0IE; #if USE_SERIAL_0_STDIN && !DELAY_SERIAL_0_STDIN - ao_add_stdio(ao_serial0_pollchar, + ao_add_stdio(_ao_serial0_pollchar, ao_serial0_putchar, NULL); #endif @@ -327,7 +327,7 @@ ao_serial_init(void) IEN2 |= IEN2_UTX1IE; #if USE_SERIAL_1_STDIN && !DELAY_SERIAL_1_STDIN - ao_add_stdio(ao_serial1_pollchar, + ao_add_stdio(_ao_serial1_pollchar, ao_serial1_putchar, NULL); #endif diff --git a/src/cc1111/ao_usb.c b/src/cc1111/ao_usb.c index f66e807c..8bd2efdf 100644 --- a/src/cc1111/ao_usb.c +++ b/src/cc1111/ao_usb.c @@ -383,18 +383,18 @@ ao_usb_putchar(char c) __critical __reentrant } int -ao_usb_pollchar(void) __critical +_ao_usb_pollchar(void) { uint8_t c; if (ao_usb_out_bytes == 0) { USBINDEX = AO_USB_OUT_EP; if ((USBCSOL & USBCSOL_OUTPKT_RDY) == 0) - return -1; + return AO_READ_AGAIN; ao_usb_out_bytes = (USBCNTH << 8) | USBCNTL; if (ao_usb_out_bytes == 0) { USBINDEX = AO_USB_OUT_EP; USBCSOL &= ~USBCSOL_OUTPKT_RDY; - return -1; + return AO_READ_AGAIN; } } --ao_usb_out_bytes; @@ -407,12 +407,14 @@ ao_usb_pollchar(void) __critical } char -ao_usb_getchar(void) __critical +ao_usb_getchar(void) { int c; - while ((c = ao_usb_pollchar()) == AO_READ_AGAIN) + ao_arch_block_interrupts(); + while ((c = _ao_usb_pollchar()) == AO_READ_AGAIN) ao_sleep(&ao_stdin_ready); + ao_arch_release_interrupts(); return c; } @@ -459,5 +461,5 @@ ao_usb_init(void) ao_usb_enable(); ao_add_task(&ao_usb_task, ao_usb_ep0, "usb"); - ao_add_stdio(ao_usb_pollchar, ao_usb_putchar, ao_usb_flush); + ao_add_stdio(_ao_usb_pollchar, ao_usb_putchar, ao_usb_flush); } diff --git a/src/core/ao.h b/src/core/ao.h index e3161b4c..6c790f69 100644 --- a/src/core/ao.h +++ b/src/core/ao.h @@ -638,7 +638,7 @@ ao_monitor_init(void) __reentrant; #define AO_READ_AGAIN (-1) struct ao_stdio { - int (*pollchar)(void); + int (*_pollchar)(void); /* Called with interrupts blocked */ void (*putchar)(char c) __reentrant; void (*flush)(void); uint8_t echo; diff --git a/src/core/ao_packet.h b/src/core/ao_packet.h index 08b184d6..6d121bb9 100644 --- a/src/core/ao_packet.h +++ b/src/core/ao_packet.h @@ -63,7 +63,7 @@ void ao_packet_putchar(char c) __reentrant; int -ao_packet_pollchar(void); +_ao_packet_pollchar(void); #if PACKET_HAS_MASTER /* ao_packet_master.c */ diff --git a/src/core/ao_serial.h b/src/core/ao_serial.h index a799bf2c..baf213c0 100644 --- a/src/core/ao_serial.h +++ b/src/core/ao_serial.h @@ -32,7 +32,7 @@ char ao_serial0_getchar(void); int -ao_serial0_pollchar(void); +_ao_serial0_pollchar(void); void ao_serial0_putchar(char c); @@ -52,7 +52,7 @@ char ao_serial1_getchar(void); int -ao_serial1_pollchar(void); +_ao_serial1_pollchar(void); void ao_serial1_putchar(char c); @@ -72,7 +72,7 @@ char ao_serial2_getchar(void); int -ao_serial2_pollchar(void); +_ao_serial2_pollchar(void); void ao_serial2_putchar(char c); @@ -92,7 +92,7 @@ char ao_serial3_getchar(void); int -ao_serial3_pollchar(void); +_ao_serial3_pollchar(void); void ao_serial3_putchar(char c); diff --git a/src/core/ao_stdio.c b/src/core/ao_stdio.c index 1748dfe8..977d74b1 100644 --- a/src/core/ao_stdio.c +++ b/src/core/ao_stdio.c @@ -99,20 +99,21 @@ char getchar(void) __reentrant { int c; - ao_arch_critical( - int8_t stdio = ao_cur_stdio; + int8_t stdio; - for (;;) { - c = ao_stdios[stdio].pollchar(); - if (c != AO_READ_AGAIN) - break; - if (++stdio == ao_num_stdios) - stdio = 0; - if (stdio == ao_cur_stdio) - ao_sleep(&ao_stdin_ready); - } - ao_cur_stdio = stdio; - ); + ao_arch_block_interrupts(); + stdio = ao_cur_stdio; + for (;;) { + c = ao_stdios[stdio]._pollchar(); + if (c != AO_READ_AGAIN) + break; + if (++stdio == ao_num_stdios) + stdio = 0; + if (stdio == ao_cur_stdio) + ao_sleep(&ao_stdin_ready); + } + ao_cur_stdio = stdio; + ao_arch_release_interrupts(); return c; } @@ -123,13 +124,13 @@ ao_echo(void) } int8_t -ao_add_stdio(int (*pollchar)(void), +ao_add_stdio(int (*_pollchar)(void), void (*putchar)(char), void (*flush)(void)) __reentrant { if (ao_num_stdios == AO_NUM_STDIOS) ao_panic(AO_PANIC_STDIO); - ao_stdios[ao_num_stdios].pollchar = pollchar; + ao_stdios[ao_num_stdios]._pollchar = _pollchar; ao_stdios[ao_num_stdios].putchar = putchar; ao_stdios[ao_num_stdios].flush = flush; ao_stdios[ao_num_stdios].echo = 1; diff --git a/src/drivers/ao_btm.c b/src/drivers/ao_btm.c index c862200a..de1f31a3 100644 --- a/src/drivers/ao_btm.c +++ b/src/drivers/ao_btm.c @@ -19,9 +19,10 @@ #ifndef ao_serial_btm_getchar #define ao_serial_btm_putchar ao_serial1_putchar -#define ao_serial_btm_pollchar ao_serial1_pollchar +#define _ao_serial_btm_pollchar _ao_serial1_pollchar #define ao_serial_btm_set_speed ao_serial1_set_speed #define ao_serial_btm_drain ao_serial1_drain +#define ao_serial_btm_rx_fifo ao_serial1_rx_fifo #endif int8_t ao_btm_stdio; @@ -111,6 +112,30 @@ __code struct ao_cmds ao_btm_cmds[] = { #define AO_BTM_MAX_REPLY 16 __xdata char ao_btm_reply[AO_BTM_MAX_REPLY]; +/* + * Read one bluetooth character. + * Returns AO_READ_AGAIN if no character arrives within 10ms + */ + +static int +ao_btm_getchar(void) +{ + int c; + + ao_arch_block_interrupts(); + while ((c = _ao_serial_btm_pollchar()) == AO_READ_AGAIN) { + ao_alarm(AO_MS_TO_TICKS(10)); + c = ao_sleep(&ao_serial_btm_rx_fifo); + ao_clear_alarm(); + if (c) { + c = AO_READ_AGAIN; + break; + } + } + ao_arch_release_interrupts(); + return c; +} + /* * Read a line of data from the serial port, truncating * it after a few characters. @@ -122,24 +147,13 @@ ao_btm_get_line(void) uint8_t ao_btm_reply_len = 0; int c; - for (;;) { - - while ((c = ao_serial_btm_pollchar()) != AO_READ_AGAIN) { - ao_btm_log_in_char(c); - if (ao_btm_reply_len < sizeof (ao_btm_reply)) - ao_btm_reply[ao_btm_reply_len++] = c; - if (c == '\r' || c == '\n') - goto done; - } - for (c = 0; c < 10; c++) { - ao_delay(AO_MS_TO_TICKS(10)); - if (!ao_fifo_empty(ao_serial1_rx_fifo)) - break; - } - if (c == 10) - goto done; + while ((c = ao_btm_getchar()) != AO_READ_AGAIN) { + ao_btm_log_in_char(c); + if (ao_btm_reply_len < sizeof (ao_btm_reply)) + ao_btm_reply[ao_btm_reply_len++] = c; + if (c == '\r' || c == '\n') + break; } -done: for (c = ao_btm_reply_len; c < sizeof (ao_btm_reply);) ao_btm_reply[c++] = '\0'; return ao_btm_reply_len; @@ -279,7 +293,7 @@ ao_btm(void) /* Turn off status reporting */ ao_btm_cmd("ATQ1\r"); - ao_btm_stdio = ao_add_stdio(ao_serial_btm_pollchar, + ao_btm_stdio = ao_add_stdio(_ao_serial_btm_pollchar, ao_serial_btm_putchar, NULL); ao_btm_echo(0); diff --git a/src/drivers/ao_packet.c b/src/drivers/ao_packet.c index 91319923..5a507478 100644 --- a/src/drivers/ao_packet.c +++ b/src/drivers/ao_packet.c @@ -169,12 +169,10 @@ ao_packet_putchar(char c) __reentrant tx_data[ao_packet_tx_used++] = c; } +/* May be called with interrupts blocked */ int -ao_packet_pollchar(void) +_ao_packet_pollchar(void) { - /* No need to block interrupts, all variables here - * are only manipulated in task context - */ if (!ao_packet_enable) return AO_READ_AGAIN; diff --git a/src/drivers/ao_packet_master.c b/src/drivers/ao_packet_master.c index 023c788b..4c0dc573 100644 --- a/src/drivers/ao_packet_master.c +++ b/src/drivers/ao_packet_master.c @@ -21,7 +21,12 @@ static char ao_packet_getchar(void) { int c; - while ((c = ao_packet_pollchar()) == AO_READ_AGAIN) { + + /* No need to block interrupts in this function as + * all packet variables are only modified from task + * context, not an interrupt handler + */ + while ((c = _ao_packet_pollchar()) == AO_READ_AGAIN) { if (!ao_packet_enable) break; if (ao_packet_master_sleeping) diff --git a/src/drivers/ao_packet_slave.c b/src/drivers/ao_packet_slave.c index e45775cb..e75df0d6 100644 --- a/src/drivers/ao_packet_slave.c +++ b/src/drivers/ao_packet_slave.c @@ -59,7 +59,7 @@ ao_packet_slave_stop(void) void ao_packet_slave_init(uint8_t enable) { - ao_add_stdio(ao_packet_pollchar, + ao_add_stdio(_ao_packet_pollchar, ao_packet_putchar, NULL); if (enable) diff --git a/src/stm/ao_serial_stm.c b/src/stm/ao_serial_stm.c index ce33f97e..2133c584 100644 --- a/src/stm/ao_serial_stm.c +++ b/src/stm/ao_serial_stm.c @@ -59,24 +59,11 @@ ao_usart_isr(struct ao_stm_usart *usart, int stdin) } } -char -ao_usart_getchar(struct ao_stm_usart *usart) -{ - char c; - ao_arch_block_interrupts(); - while (ao_fifo_empty(usart->rx_fifo)) - ao_sleep(&usart->rx_fifo); - ao_fifo_remove(usart->rx_fifo, c); - ao_arch_release_interrupts(); - return c; -} - int -ao_usart_pollchar(struct ao_stm_usart *usart) +_ao_usart_pollchar(struct ao_stm_usart *usart) { int c; - ao_arch_block_interrupts(); if (ao_fifo_empty(usart->rx_fifo)) c = AO_READ_AGAIN; else { @@ -84,10 +71,20 @@ ao_usart_pollchar(struct ao_stm_usart *usart) ao_fifo_remove(usart->rx_fifo,u); c = u; } - ao_arch_release_interrupts(); return c; } +char +ao_usart_getchar(struct ao_stm_usart *usart) +{ + int c; + ao_arch_block_interrupts(); + while ((c = _ao_usart_pollchar(usart)) == AO_READ_AGAIN) + ao_sleep(&usart->rx_fifo); + ao_arch_release_interrupts(); + return (char) c; +} + void ao_usart_putchar(struct ao_stm_usart *usart, char c) { @@ -201,9 +198,9 @@ ao_serial1_putchar(char c) } int -ao_serial1_pollchar(void) +_ao_serial1_pollchar(void) { - return ao_usart_pollchar(&ao_stm_usart1); + return _ao_usart_pollchar(&ao_stm_usart1); } void @@ -232,9 +229,9 @@ ao_serial2_putchar(char c) } int -ao_serial2_pollchar(void) +_ao_serial2_pollchar(void) { - return ao_usart_pollchar(&ao_stm_usart2); + return _ao_usart_pollchar(&ao_stm_usart2); } void @@ -263,9 +260,9 @@ ao_serial3_putchar(char c) } int -ao_serial3_pollchar(void) +_ao_serial3_pollchar(void) { - return ao_usart_pollchar(&ao_stm_usart3); + return _ao_usart_pollchar(&ao_stm_usart3); } void @@ -309,7 +306,7 @@ ao_serial_init(void) stm_nvic_set_enable(STM_ISR_USART1_POS); stm_nvic_set_priority(STM_ISR_USART1_POS, 4); #if USE_SERIAL_1_STDIN - ao_add_stdio(ao_serial1_pollchar, + ao_add_stdio(_ao_serial1_pollchar, ao_serial1_putchar, NULL); #endif @@ -346,7 +343,7 @@ ao_serial_init(void) stm_nvic_set_enable(STM_ISR_USART2_POS); stm_nvic_set_priority(STM_ISR_USART2_POS, 4); #if USE_SERIAL_2_STDIN - ao_add_stdio(ao_serial2_pollchar, + ao_add_stdio(_ao_serial2_pollchar, ao_serial2_putchar, NULL); #endif @@ -390,7 +387,7 @@ ao_serial_init(void) stm_nvic_set_enable(STM_ISR_USART3_POS); stm_nvic_set_priority(STM_ISR_USART3_POS, 4); #if USE_SERIAL_3_STDIN - ao_add_stdio(ao_serial3_pollchar, + ao_add_stdio(_ao_serial3_pollchar, ao_serial3_putchar, NULL); #endif diff --git a/src/stm/ao_usb_stm.c b/src/stm/ao_usb_stm.c index 9379e5cd..dfa58c42 100644 --- a/src/stm/ao_usb_stm.c +++ b/src/stm/ao_usb_stm.c @@ -229,10 +229,9 @@ ao_usb_set_stat_tx(int ep, uint32_t stat_tx) } static void -ao_usb_set_stat_rx(int ep, uint32_t stat_rx) { +_ao_usb_set_stat_rx(int ep, uint32_t stat_rx) { uint32_t epr_write, epr_old; - ao_arch_block_interrupts(); epr_write = epr_old = stm_usb.epr[ep]; epr_write &= STM_USB_EPR_PRESERVE_MASK; epr_write |= STM_USB_EPR_INVARIANT; @@ -240,6 +239,12 @@ ao_usb_set_stat_rx(int ep, uint32_t stat_rx) { STM_USB_EPR_STAT_RX_MASK << STM_USB_EPR_STAT_RX, stat_rx << STM_USB_EPR_STAT_RX); stm_usb.epr[ep] = epr_write; +} + +static void +ao_usb_set_stat_rx(int ep, uint32_t stat_rx) { + ao_arch_block_interrupts(); + _ao_usb_set_stat_rx(ep, stat_rx); ao_arch_release_interrupts(); } @@ -870,10 +875,10 @@ _ao_usb_out_recv(void) ao_usb_rx_pos = 0; /* ACK the packet */ - ao_usb_set_stat_rx(AO_USB_OUT_EPR, STM_USB_EPR_STAT_RX_VALID); + _ao_usb_set_stat_rx(AO_USB_OUT_EPR, STM_USB_EPR_STAT_RX_VALID); } -static int +int _ao_usb_pollchar(void) { uint8_t c; @@ -896,16 +901,6 @@ _ao_usb_pollchar(void) return c; } -int -ao_usb_pollchar(void) -{ - int c; - ao_arch_block_interrupts(); - c = _ao_usb_pollchar(); - ao_arch_release_interrupts(); - return c; -} - char ao_usb_getchar(void) { -- cgit v1.2.3 From de199601a177fc2d45ad9bd7357111111844d40a Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 24 Mar 2013 15:03:59 -0700 Subject: altos/stm: Add debugging mechanism to STM USB driver This adds a pile of debugging hooks to the USB driver to try and isolate various lockup-related issues. It's all disabled by default, of course. Signed-off-by: Keith Packard --- src/stm/ao_usb_stm.c | 109 +++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 101 insertions(+), 8 deletions(-) (limited to 'src/stm') diff --git a/src/stm/ao_usb_stm.c b/src/stm/ao_usb_stm.c index dfa58c42..44f49dfa 100644 --- a/src/stm/ao_usb_stm.c +++ b/src/stm/ao_usb_stm.c @@ -200,6 +200,29 @@ ao_usb_set_address(uint8_t address) (1 << STM_USB_EPR_EP_KIND) | \ (STM_USB_EPR_EA_MASK << STM_USB_EPR_EA)) +#define TX_DBG 0 +#define RX_DBG 0 + +#if TX_DBG +#define _tx_dbg0(msg) _dbg(__LINE__,msg,0) +#define _tx_dbg1(msg,value) _dbg(__LINE__,msg,value) +#else +#define _tx_dbg0(msg) +#define _tx_dbg1(msg,value) +#endif + +#if RX_DBG +#define _rx_dbg0(msg) _dbg(__LINE__,msg,0) +#define _rx_dbg1(msg,value) _dbg(__LINE__,msg,value) +#else +#define _rx_dbg0(msg) +#define _rx_dbg1(msg,value) +#endif + +#if TX_DBG || RX_DBG +static void _dbg(int line, char *msg, uint32_t value); +#endif + /* * Set the state of the specified endpoint register to a new * value. This is tricky because the bits toggle where the new @@ -211,6 +234,7 @@ _ao_usb_set_stat_tx(int ep, uint32_t stat_tx) { uint32_t epr_write, epr_old; + _tx_dbg1("set_stat_tx top", stat_tx); epr_old = epr_write = stm_usb.epr[ep]; epr_write &= STM_USB_EPR_PRESERVE_MASK; epr_write |= STM_USB_EPR_INVARIANT; @@ -218,6 +242,7 @@ _ao_usb_set_stat_tx(int ep, uint32_t stat_tx) STM_USB_EPR_STAT_TX_MASK << STM_USB_EPR_STAT_TX, stat_tx << STM_USB_EPR_STAT_TX); stm_usb.epr[ep] = epr_write; + _tx_dbg1("set_stat_tx bottom", epr_write); } static void @@ -338,7 +363,7 @@ ao_usb_set_configuration(void) STM_USB_EPR_EP_TYPE_INTERRUPT, STM_USB_EPR_STAT_RX_DISABLED, STM_USB_EPR_STAT_TX_NAK); - + /* Set up the OUT end point */ ao_usb_bdt[AO_USB_OUT_EPR].single.addr_rx = ao_usb_sram_addr; ao_usb_bdt[AO_USB_OUT_EPR].single.count_rx = ((1 << STM_USB_BDT_COUNT_RX_BL_SIZE) | @@ -351,7 +376,7 @@ ao_usb_set_configuration(void) STM_USB_EPR_EP_TYPE_BULK, STM_USB_EPR_STAT_RX_VALID, STM_USB_EPR_STAT_TX_DISABLED); - + /* Set up the IN end point */ ao_usb_bdt[AO_USB_IN_EPR].single.addr_tx = ao_usb_sram_addr; ao_usb_bdt[AO_USB_IN_EPR].single.count_tx = 0; @@ -409,12 +434,16 @@ stm_usb_lp_isr(void) case AO_USB_OUT_EPR: ++out_count; if (ao_usb_epr_ctr_rx(epr)) { + _rx_dbg1("RX ISR", epr); ao_usb_out_avail = 1; + _rx_dbg0("out avail set"); ao_wakeup(&ao_stdin_ready); + _rx_dbg0("stdin awoken"); } break; case AO_USB_IN_EPR: ++in_count; + _tx_dbg1("TX ISR", epr); if (ao_usb_epr_ctr_tx(epr)) { ao_usb_in_pending = 0; ao_wakeup(&ao_usb_in_pending); @@ -758,7 +787,7 @@ ao_usb_ep0(void) ao_sleep(&ao_usb_ep0_receive); ao_usb_ep0_receive = 0; ); - + if (receive & AO_USB_EP0_GOT_RESET) { debug ("\treset\n"); ao_usb_set_ep0(); @@ -796,6 +825,7 @@ ao_usb_ep0(void) static void ao_usb_in_send(void) { + _tx_dbg0("in_send start"); debug ("send %d\n", ao_usb_tx_count); ao_usb_in_pending = 1; ao_usb_write(ao_usb_tx_buffer, ao_usb_in_tx_buffer, 0, ao_usb_tx_count); @@ -813,9 +843,11 @@ _ao_usb_in_wait(void) if (ao_usb_tx_count < AO_USB_IN_SIZE) break; + _tx_dbg0("in_wait top"); /* Wait for an IN buffer to be ready */ while (ao_usb_in_pending) ao_sleep(&ao_usb_in_pending); + _tx_dbg0("in_wait bottom"); } } @@ -856,18 +888,23 @@ ao_usb_putchar(char c) ao_usb_tx_buffer[ao_usb_tx_count++] = (uint8_t) c; /* Send the packet when full */ - if (ao_usb_tx_count == AO_USB_IN_SIZE) - ao_usb_in_send(); + if (ao_usb_tx_count == AO_USB_IN_SIZE) { + _tx_dbg0("putchar full"); + _ao_usb_in_send(); + _tx_dbg0("putchar flushed"); + } ao_arch_release_interrupts(); } static void _ao_usb_out_recv(void) { + _rx_dbg0("out_recv top"); ao_usb_out_avail = 0; ao_usb_rx_count = ao_usb_bdt[AO_USB_OUT_EPR].single.count_rx & STM_USB_BDT_COUNT_RX_COUNT_RX_MASK; + _rx_dbg1("out_recv count", ao_usb_rx_count); debug ("recv %d\n", ao_usb_rx_count); debug_data("Fill OUT len %d:", ao_usb_rx_count); ao_usb_read(ao_usb_rx_buffer, ao_usb_out_rx_buffer, 0, ao_usb_rx_count); @@ -890,9 +927,12 @@ _ao_usb_pollchar(void) if (ao_usb_rx_pos != ao_usb_rx_count) break; + _rx_dbg0("poll check"); /* Check to see if a packet has arrived */ - if (!ao_usb_out_avail) + if (!ao_usb_out_avail) { + _rx_dbg0("poll none"); return AO_READ_AGAIN; + } _ao_usb_out_recv(); } @@ -966,7 +1006,7 @@ ao_usb_enable(void) /* Clear any spurious interrupts */ stm_usb.istr = 0; - + debug ("ao_usb_enable\n"); /* Enable interrupts */ @@ -1036,6 +1076,59 @@ ao_usb_init(void) ao_cmd_register(&ao_usb_cmds[0]); #endif #if !USB_ECHO - ao_add_stdio(ao_usb_pollchar, ao_usb_putchar, ao_usb_flush); + ao_add_stdio(_ao_usb_pollchar, ao_usb_putchar, ao_usb_flush); +#endif +} + +#if TX_DBG || RX_DBG + +struct ao_usb_dbg { + int line; + char *msg; + uint32_t value; + uint32_t primask; +#if TX_DBG + uint16_t in_count; + uint32_t in_epr; + uint32_t in_pending; + uint32_t tx_count; + uint32_t in_flushed; +#endif +#if RX_DBG + uint8_t rx_count; + uint8_t rx_pos; + uint8_t out_avail; + uint32_t out_epr; +#endif +}; + +#define NUM_USB_DBG 128 + +static struct ao_usb_dbg dbg[128]; +static int dbg_i; + +static void _dbg(int line, char *msg, uint32_t value) +{ + uint32_t primask; + dbg[dbg_i].line = line; + dbg[dbg_i].msg = msg; + dbg[dbg_i].value = value; + asm("mrs %0,primask" : "=&r" (primask)); + dbg[dbg_i].primask = primask; +#if TX_DBG + dbg[dbg_i].in_count = in_count; + dbg[dbg_i].in_epr = stm_usb.epr[AO_USB_IN_EPR]; + dbg[dbg_i].in_pending = ao_usb_in_pending; + dbg[dbg_i].tx_count = ao_usb_tx_count; + dbg[dbg_i].in_flushed = ao_usb_in_flushed; +#endif +#if RX_DBG + dbg[dbg_i].rx_count = ao_usb_rx_count; + dbg[dbg_i].rx_pos = ao_usb_rx_pos; + dbg[dbg_i].out_avail = ao_usb_out_avail; + dbg[dbg_i].out_epr = stm_usb.epr[AO_USB_OUT_EPR]; #endif + if (++dbg_i == NUM_USB_DBG) + dbg_i = 0; } +#endif -- cgit v1.2.3 From 8b2f211758dfa97230a730b8c4b31e0e711c19c9 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 24 Mar 2013 15:04:57 -0700 Subject: altos/stm: Always check for idle IN buffer before sending Unlike the AVR and CC1111 USB drivers, the STM usb driver queues IN bytes in a local buffer instead of in the driver; this means that the driver is queuing bytes while the previous IN packet is queued for the host, which allows for overlapping execution. It also means that when the local buffer is full, we must check to see if the host has picked up the previous IN packet before trying to queue another IN packet for transmission. This is done by always waiting for the IN buffer to be ready before sending data. Signed-off-by: Keith Packard --- src/stm/ao_usb_stm.c | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) (limited to 'src/stm') diff --git a/src/stm/ao_usb_stm.c b/src/stm/ao_usb_stm.c index 44f49dfa..e29abc87 100644 --- a/src/stm/ao_usb_stm.c +++ b/src/stm/ao_usb_stm.c @@ -823,15 +823,20 @@ ao_usb_ep0(void) /* Queue the current IN buffer for transmission */ static void -ao_usb_in_send(void) +_ao_usb_in_send(void) { _tx_dbg0("in_send start"); debug ("send %d\n", ao_usb_tx_count); + while (ao_usb_in_pending) + ao_sleep(&ao_usb_in_pending); ao_usb_in_pending = 1; + if (ao_usb_tx_count != AO_USB_IN_SIZE) + ao_usb_in_flushed = 1; ao_usb_write(ao_usb_tx_buffer, ao_usb_in_tx_buffer, 0, ao_usb_tx_count); ao_usb_bdt[AO_USB_IN_EPR].single.count_tx = ao_usb_tx_count; - ao_usb_set_stat_tx(AO_USB_IN_EPR, STM_USB_EPR_STAT_TX_VALID); ao_usb_tx_count = 0; + _ao_usb_set_stat_tx(AO_USB_IN_EPR, STM_USB_EPR_STAT_TX_VALID); + _tx_dbg0("in_send end"); } /* Wait for a free IN buffer. Interrupts are blocked */ @@ -865,12 +870,10 @@ ao_usb_flush(void) * want to send an empty packet */ ao_arch_block_interrupts(); - if (!ao_usb_in_flushed) { - ao_usb_in_flushed = 1; - /* Wait for an IN buffer to be ready */ - while (ao_usb_in_pending) - ao_sleep(&ao_usb_in_pending); - ao_usb_in_send(); + while (!ao_usb_in_flushed) { + _tx_dbg0("flush top"); + _ao_usb_in_send(); + _tx_dbg0("flush end"); } ao_arch_release_interrupts(); } -- cgit v1.2.3 From 398c02b945a58634c8932f07df2c2be8438da7d1 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 9 Apr 2013 00:28:05 -0700 Subject: altoslib/altosui: Carry receiver status around in AltosListenerState This moves the crc_errors into the new structure and adds a receiver battery voltage value there as well. Now the receiver status can be monitored separately from the flight status. That also means that code receiving state updates should be prepared to accept missing listener or flight state values. Signed-off-by: Keith Packard --- altoslib/AltosConfigData.java | 6 + altoslib/AltosFlightReader.java | 4 + altoslib/AltosGPS.java | 57 +++++----- altoslib/AltosIdleMonitor.java | 6 +- altoslib/AltosLink.java | 57 ++++++++++ altoslib/AltosListenerState.java | 28 +++++ altoslib/AltosRecord.java | 24 ++-- altoslib/AltosSensorMM.java | 122 +++++++++----------- altoslib/AltosSensorTM.java | 80 ++++++------- altoslib/AltosState.java | 21 +++- altoslib/AltosTelemetryReader.java | 8 ++ altoslib/Makefile.am | 1 + altosui/AltosAscent.java | 36 +++--- altosui/AltosCompanionInfo.java | 2 +- altosui/AltosDescent.java | 48 ++++---- altosui/AltosDisplayThread.java | 55 ++++----- altosui/AltosFlightDisplay.java | 2 +- altosui/AltosFlightStatus.java | 38 ++++--- altosui/AltosFlightStatusUpdate.java | 12 +- altosui/AltosFlightUI.java | 31 ++--- altosui/AltosGraphUI.java | 2 +- altosui/AltosIdleMonitorUI.java | 10 +- altosui/AltosInfoTable.java | 213 ++++++++++++++++++----------------- altosui/AltosLanded.java | 32 +++--- altosui/AltosPad.java | 199 +++++++++++++++++++------------- altosui/AltosSiteMap.java | 6 +- altosui/AltosSiteMapTile.java | 2 +- src/core/ao.h | 2 +- src/stm/ao_timer.c | 11 +- 29 files changed, 632 insertions(+), 483 deletions(-) create mode 100644 altoslib/AltosListenerState.java (limited to 'src/stm') diff --git a/altoslib/AltosConfigData.java b/altoslib/AltosConfigData.java index 45b95646..57605607 100644 --- a/altoslib/AltosConfigData.java +++ b/altoslib/AltosConfigData.java @@ -135,6 +135,12 @@ public class AltosConfigData implements Iterable { } } + public boolean has_monitor_battery() { + if (product.startsWith("TeleBT")) + return true; + return false; + } + int[] parse_version(String v) { String[] parts = v.split("\\."); int r[] = new int[parts.length]; diff --git a/altoslib/AltosFlightReader.java b/altoslib/AltosFlightReader.java index 3039b4dc..34526658 100644 --- a/altoslib/AltosFlightReader.java +++ b/altoslib/AltosFlightReader.java @@ -45,4 +45,8 @@ public class AltosFlightReader { public boolean supports_telemetry(int telemetry) { return false; } public File backing_file() { return null; } + + public boolean has_monitor_battery() { return false; } + + public double monitor_battery() { return AltosRecord.MISSING; } } diff --git a/altoslib/AltosGPS.java b/altoslib/AltosGPS.java index 068d8c9c..f23842f3 100644 --- a/altoslib/AltosGPS.java +++ b/altoslib/AltosGPS.java @@ -217,33 +217,38 @@ public class AltosGPS { } public AltosGPS(AltosGPS old) { - nsat = old.nsat; - locked = old.locked; - connected = old.connected; - lat = old.lat; /* degrees (+N -S) */ - lon = old.lon; /* degrees (+E -W) */ - alt = old.alt; /* m */ - year = old.year; - month = old.month; - day = old.day; - hour = old.hour; - minute = old.minute; - second = old.second; - - ground_speed = old.ground_speed; /* m/s */ - course = old.course; /* degrees */ - climb_rate = old.climb_rate; /* m/s */ - hdop = old.hdop; /* unitless? */ - h_error = old.h_error; /* m */ - v_error = old.v_error; /* m */ - - if (old.cc_gps_sat != null) { - cc_gps_sat = new AltosGPSSat[old.cc_gps_sat.length]; - for (int i = 0; i < old.cc_gps_sat.length; i++) { - cc_gps_sat[i] = new AltosGPSSat(); - cc_gps_sat[i].svid = old.cc_gps_sat[i].svid; - cc_gps_sat[i].c_n0 = old.cc_gps_sat[i].c_n0; + if (old != null) { + nsat = old.nsat; + locked = old.locked; + connected = old.connected; + lat = old.lat; /* degrees (+N -S) */ + lon = old.lon; /* degrees (+E -W) */ + alt = old.alt; /* m */ + year = old.year; + month = old.month; + day = old.day; + hour = old.hour; + minute = old.minute; + second = old.second; + + ground_speed = old.ground_speed; /* m/s */ + course = old.course; /* degrees */ + climb_rate = old.climb_rate; /* m/s */ + hdop = old.hdop; /* unitless? */ + h_error = old.h_error; /* m */ + v_error = old.v_error; /* m */ + + if (old.cc_gps_sat != null) { + cc_gps_sat = new AltosGPSSat[old.cc_gps_sat.length]; + for (int i = 0; i < old.cc_gps_sat.length; i++) { + cc_gps_sat[i] = new AltosGPSSat(); + cc_gps_sat[i].svid = old.cc_gps_sat[i].svid; + cc_gps_sat[i].c_n0 = old.cc_gps_sat[i].c_n0; + } } + } else { + ClearGPSTime(); + cc_gps_sat = null; } } } diff --git a/altoslib/AltosIdleMonitor.java b/altoslib/AltosIdleMonitor.java index f2f75bbb..ec51b9c1 100644 --- a/altoslib/AltosIdleMonitor.java +++ b/altoslib/AltosIdleMonitor.java @@ -116,8 +116,10 @@ public class AltosIdleMonitor extends Thread { } finally { if (remote) { link.stop_remote(); - if (record != null) - record.rssi = AltosRSSI(); + if (record != null) { + record.rssi = link.rssi(); + record.monitor_battery = link.monitor_battery(); + } } else { if (record != null) record.rssi = 0; diff --git a/altoslib/AltosLink.java b/altoslib/AltosLink.java index 9eb25ce0..159ebfe1 100644 --- a/altoslib/AltosLink.java +++ b/altoslib/AltosLink.java @@ -364,6 +364,63 @@ public abstract class AltosLink implements Runnable { remote = false; } + public int rssi() throws TimeoutException, InterruptedException { + if (remote) + return 0; + printf("s\n"); + String line = get_reply_no_dialog(5000); + if (line == null) + throw new TimeoutException(); + String[] items = line.split("\\s+"); + if (items.length < 2) + return 0; + if (!items[0].equals("RSSI:")) + return 0; + int rssi = Integer.parseInt(items[1]); + return rssi; + } + + public String[] adc() throws TimeoutException, InterruptedException { + printf("a\n"); + for (;;) { + String line = get_reply_no_dialog(5000); + if (line == null) { + throw new TimeoutException(); + } + if (!line.startsWith("tick:")) + continue; + String[] items = line.split("\\s+"); + return items; + } + } + + public boolean has_monitor_battery() { + return config_data.has_monitor_battery(); + } + + public double monitor_battery() { + int monitor_batt = AltosRecord.MISSING; + + if (config_data.has_monitor_battery()) { + try { + String[] items = adc(); + for (int i = 0; i < items.length;) { + if (items[i].equals("batt")) { + monitor_batt = Integer.parseInt(items[i+1]); + i += 2; + continue; + } + i++; + } + } catch (InterruptedException ie) { + } catch (TimeoutException te) { + } + } + if (monitor_batt == AltosRecord.MISSING) + return AltosRecord.MISSING; + return AltosConvert.cc_battery_to_voltage(monitor_batt); + } + public AltosLink() { callsign = ""; } diff --git a/altoslib/AltosListenerState.java b/altoslib/AltosListenerState.java new file mode 100644 index 00000000..2fb4673e --- /dev/null +++ b/altoslib/AltosListenerState.java @@ -0,0 +1,28 @@ +/* + * Copyright © 2013 Keith Packard + * + * 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. + */ + +package org.altusmetrum.altoslib_1; + +public class AltosListenerState { + public int crc_errors; + public double battery; + + public AltosListenerState() { + crc_errors = 0; + battery = AltosRecord.MISSING; + } +} diff --git a/altoslib/AltosRecord.java b/altoslib/AltosRecord.java index f8c44cc5..7046b9f1 100644 --- a/altoslib/AltosRecord.java +++ b/altoslib/AltosRecord.java @@ -17,7 +17,7 @@ package org.altusmetrum.altoslib_1; -public abstract class AltosRecord implements Comparable , Cloneable { +public class AltosRecord implements Comparable , Cloneable { public static final int seen_flight = 1; public static final int seen_sensor = 2; @@ -75,15 +75,17 @@ public abstract class AltosRecord implements Comparable , Cloneable * temperature: °C */ - abstract public double pressure(); - abstract public double ground_pressure(); - abstract public double acceleration(); + public double pressure() { return MISSING; } + public double ground_pressure() { return MISSING; } + public double acceleration() { return MISSING; } public double altitude() { double p = pressure(); - if (p == MISSING) + if (p == MISSING) { + System.out.printf ("altitude missing\n"); return MISSING; + } return AltosConvert.pressure_to_altitude(p); } @@ -126,7 +128,11 @@ public abstract class AltosRecord implements Comparable , Cloneable return tick - o.tick; } - abstract public AltosRecord clone(); + public AltosRecord clone() { + AltosRecord n = new AltosRecord(); + n.copy(this); + return n; + } public void copy(AltosRecord old) { seen = old.seen; @@ -150,13 +156,13 @@ public abstract class AltosRecord implements Comparable , Cloneable seen = 0; version = 0; callsign = "N0CALL"; - serial = 0; - flight = 0; + serial = MISSING; + flight = MISSING; rssi = 0; status = 0; state = AltosLib.ao_flight_startup; tick = 0; - gps = new AltosGPS(); + gps = null; new_gps = false; companion = null; diff --git a/altoslib/AltosSensorMM.java b/altoslib/AltosSensorMM.java index 8372d047..6d1b61c0 100644 --- a/altoslib/AltosSensorMM.java +++ b/altoslib/AltosSensorMM.java @@ -28,75 +28,65 @@ class AltosSensorMM { int accel_ref; public AltosSensorMM(AltosLink link) throws InterruptedException, TimeoutException { - link.printf("a\n"); - for (;;) { - String line = link.get_reply_no_dialog(5000); - if (line == null) { - throw new TimeoutException(); + String[] items = link.adc(); + sense = new int[6]; + for (int i = 0; i < items.length;) { + if (items[i].equals("tick:")) { + tick = Integer.parseInt(items[i+1]); + i += 2; + continue; + } + if (items[i].equals("0:")) { + sense[0] = Integer.parseInt(items[i+1]); + i += 2; + continue; + } + if (items[i].equals("1:")) { + sense[1] = Integer.parseInt(items[i+1]); + i += 2; + continue; + } + if (items[i].equals("2:")) { + sense[2] = Integer.parseInt(items[i+1]); + i += 2; + continue; + } + if (items[i].equals("3:")) { + sense[3] = Integer.parseInt(items[i+1]); + i += 2; + continue; + } + if (items[i].equals("4:")) { + sense[4] = Integer.parseInt(items[i+1]); + i += 2; + continue; + } + if (items[i].equals("5:")) { + sense[5] = Integer.parseInt(items[i+1]); + i += 2; + continue; + } + if (items[i].equals("6:")) { + v_batt = Integer.parseInt(items[i+1]); + i += 2; + continue; + } + if (items[i].equals("7:")) { + v_pyro = Integer.parseInt(items[i+1]); + i += 2; + continue; + } + if (items[i].equals("8:")) { + accel = Integer.parseInt(items[i+1]); + i += 2; + continue; } - if (!line.startsWith("tick:")) + if (items[i].equals("9:")) { + accel_ref = Integer.parseInt(items[i+1]); + i += 2; continue; - String[] items = line.split("\\s+"); - sense = new int[6]; - for (int i = 0; i < items.length;) { - if (items[i].equals("tick:")) { - tick = Integer.parseInt(items[i+1]); - i += 2; - continue; - } - if (items[i].equals("0:")) { - sense[0] = Integer.parseInt(items[i+1]); - i += 2; - continue; - } - if (items[i].equals("1:")) { - sense[1] = Integer.parseInt(items[i+1]); - i += 2; - continue; - } - if (items[i].equals("2:")) { - sense[2] = Integer.parseInt(items[i+1]); - i += 2; - continue; - } - if (items[i].equals("3:")) { - sense[3] = Integer.parseInt(items[i+1]); - i += 2; - continue; - } - if (items[i].equals("4:")) { - sense[4] = Integer.parseInt(items[i+1]); - i += 2; - continue; - } - if (items[i].equals("5:")) { - sense[5] = Integer.parseInt(items[i+1]); - i += 2; - continue; - } - if (items[i].equals("6:")) { - v_batt = Integer.parseInt(items[i+1]); - i += 2; - continue; - } - if (items[i].equals("7:")) { - v_pyro = Integer.parseInt(items[i+1]); - i += 2; - continue; - } - if (items[i].equals("8:")) { - accel = Integer.parseInt(items[i+1]); - i += 2; - continue; - } - if (items[i].equals("9:")) { - accel_ref = Integer.parseInt(items[i+1]); - i += 2; - continue; - } - i++; } - break; + i++; } } } diff --git a/altoslib/AltosSensorTM.java b/altoslib/AltosSensorTM.java index f5fa83a5..754dc5bb 100644 --- a/altoslib/AltosSensorTM.java +++ b/altoslib/AltosSensorTM.java @@ -23,54 +23,44 @@ class AltosSensorTM extends AltosRecordTM { public AltosSensorTM(AltosLink link, AltosConfigData config_data) throws InterruptedException, TimeoutException { super(); - link.printf("a\n"); - for (;;) { - String line = link.get_reply_no_dialog(5000); - if (line == null) { - throw new TimeoutException(); + String[] items = link.adc(); + for (int i = 0; i < items.length;) { + if (items[i].equals("tick:")) { + tick = Integer.parseInt(items[i+1]); + i += 2; + continue; + } + if (items[i].equals("accel:")) { + accel = Integer.parseInt(items[i+1]); + i += 2; + continue; + } + if (items[i].equals("pres:")) { + pres = Integer.parseInt(items[i+1]); + i += 2; + continue; + } + if (items[i].equals("temp:")) { + temp = Integer.parseInt(items[i+1]); + i += 2; + continue; + } + if (items[i].equals("batt:")) { + batt = Integer.parseInt(items[i+1]); + i += 2; + continue; + } + if (items[i].equals("drogue:")) { + drogue = Integer.parseInt(items[i+1]); + i += 2; + continue; } - if (!line.startsWith("tick:")) + if (items[i].equals("main:")) { + main = Integer.parseInt(items[i+1]); + i += 2; continue; - String[] items = line.split("\\s+"); - for (int i = 0; i < items.length;) { - if (items[i].equals("tick:")) { - tick = Integer.parseInt(items[i+1]); - i += 2; - continue; - } - if (items[i].equals("accel:")) { - accel = Integer.parseInt(items[i+1]); - i += 2; - continue; - } - if (items[i].equals("pres:")) { - pres = Integer.parseInt(items[i+1]); - i += 2; - continue; - } - if (items[i].equals("temp:")) { - temp = Integer.parseInt(items[i+1]); - i += 2; - continue; - } - if (items[i].equals("batt:")) { - batt = Integer.parseInt(items[i+1]); - i += 2; - continue; - } - if (items[i].equals("drogue:")) { - drogue = Integer.parseInt(items[i+1]); - i += 2; - continue; - } - if (items[i].equals("main:")) { - main = Integer.parseInt(items[i+1]); - i += 2; - continue; - } - i++; } - break; + i++; } ground_accel = config_data.accel_cal_plus; ground_pres = pres; diff --git a/altoslib/AltosState.java b/altoslib/AltosState.java index 8a3bbd4c..f1bcb1c1 100644 --- a/altoslib/AltosState.java +++ b/altoslib/AltosState.java @@ -155,30 +155,41 @@ public class AltosState { /* compute barometric speed */ double height_change = height - prev_state.height; + + double prev_baro_speed = prev_state.baro_speed; + if (prev_baro_speed == AltosRecord.MISSING) + prev_baro_speed = 0; + if (time_change > 0) - baro_speed = (prev_state.baro_speed * 3 + (height_change / time_change)) / 4.0; + baro_speed = (prev_baro_speed * 3 + (height_change / time_change)) / 4.0; else baro_speed = prev_state.baro_speed; + double prev_accel_speed = prev_state.accel_speed; + + if (prev_accel_speed == AltosRecord.MISSING) + prev_accel_speed = 0; + if (acceleration == AltosRecord.MISSING) { /* Fill in mising acceleration value */ accel_speed = baro_speed; - if (time_change > 0) - acceleration = (accel_speed - prev_state.accel_speed) / time_change; + + if (time_change > 0 && accel_speed != AltosRecord.MISSING) + acceleration = (accel_speed - prev_accel_speed) / time_change; else acceleration = prev_state.acceleration; } else { /* compute accelerometer speed */ - accel_speed = prev_state.accel_speed + acceleration * time_change; + accel_speed = prev_accel_speed + acceleration * time_change; } } - } else { npad = 0; ngps = 0; gps = null; baro_speed = AltosRecord.MISSING; accel_speed = AltosRecord.MISSING; + pad_alt = AltosRecord.MISSING; max_baro_speed = 0; max_accel_speed = 0; max_height = 0; diff --git a/altoslib/AltosTelemetryReader.java b/altoslib/AltosTelemetryReader.java index f365b821..b4293c73 100644 --- a/altoslib/AltosTelemetryReader.java +++ b/altoslib/AltosTelemetryReader.java @@ -107,6 +107,14 @@ public class AltosTelemetryReader extends AltosFlightReader { return log.file(); } + public boolean has_monitor_battery() { + return link.has_monitor_battery(); + } + + public double monitor_battery() { + return link.monitor_battery(); + } + public AltosTelemetryReader (AltosLink in_link) throws IOException, InterruptedException, TimeoutException { link = in_link; diff --git a/altoslib/Makefile.am b/altoslib/Makefile.am index 8e5701ad..30a9d954 100644 --- a/altoslib/Makefile.am +++ b/altoslib/Makefile.am @@ -37,6 +37,7 @@ altoslib_JAVA = \ AltosIMUQuery.java \ AltosLine.java \ AltosLink.java \ + AltosListenerState.java \ AltosLog.java \ AltosMs5607.java \ AltosMs5607Query.java \ diff --git a/altosui/AltosAscent.java b/altosui/AltosAscent.java index 80a5b759..4da4d591 100644 --- a/altosui/AltosAscent.java +++ b/altosui/AltosAscent.java @@ -42,7 +42,7 @@ public class AltosAscent extends JComponent implements AltosFlightDisplay { label.setVisible(false); } - void show(AltosState state, int crc_errors) {} + void show(AltosState state, AltosListenerState listener_state) {} void show(String s) { show(); @@ -107,7 +107,7 @@ public class AltosAscent extends JComponent implements AltosFlightDisplay { public class AscentValue { JLabel label; JTextField value; - void show(AltosState state, int crc_errors) {} + void show(AltosState state, AltosListenerState listener_state) {} void reset() { value.setText(""); @@ -174,7 +174,7 @@ public class AltosAscent extends JComponent implements AltosFlightDisplay { JTextField max_value; double max; - void show(AltosState state, int crc_errors) {} + void show(AltosState state, AltosListenerState listener_state) {} void reset() { value.setText(""); @@ -239,7 +239,7 @@ public class AltosAscent extends JComponent implements AltosFlightDisplay { class Height extends AscentValueHold { - void show (AltosState state, int crc_errors) { + void show (AltosState state, AltosListenerState listener_state) { show(AltosConvert.height, state.height); } public Height (GridBagLayout layout, int y) { @@ -250,7 +250,7 @@ public class AltosAscent extends JComponent implements AltosFlightDisplay { Height height; class Speed extends AscentValueHold { - void show (AltosState state, int crc_errors) { + void show (AltosState state, AltosListenerState listener_state) { double speed = state.accel_speed; if (!state.ascent) speed = state.baro_speed; @@ -264,7 +264,7 @@ public class AltosAscent extends JComponent implements AltosFlightDisplay { Speed speed; class Accel extends AscentValueHold { - void show (AltosState state, int crc_errors) { + void show (AltosState state, AltosListenerState listener_state) { show(AltosConvert.accel, state.acceleration); } public Accel (GridBagLayout layout, int y) { @@ -286,7 +286,7 @@ public class AltosAscent extends JComponent implements AltosFlightDisplay { } class Apogee extends AscentStatus { - void show (AltosState state, int crc_errors) { + void show (AltosState state, AltosListenerState listener_state) { show("%4.2f V", state.drogue_sense); lights.set(state.drogue_sense > 3.2); } @@ -298,7 +298,7 @@ public class AltosAscent extends JComponent implements AltosFlightDisplay { Apogee apogee; class Main extends AscentStatus { - void show (AltosState state, int crc_errors) { + void show (AltosState state, AltosListenerState listener_state) { show("%4.2f V", state.main_sense); lights.set(state.main_sense > 3.2); } @@ -310,7 +310,7 @@ public class AltosAscent extends JComponent implements AltosFlightDisplay { Main main; class Lat extends AscentValue { - void show (AltosState state, int crc_errors) { + void show (AltosState state, AltosListenerState listener_state) { if (state.gps != null) show(pos(state.gps.lat,"N", "S")); else @@ -324,7 +324,7 @@ public class AltosAscent extends JComponent implements AltosFlightDisplay { Lat lat; class Lon extends AscentValue { - void show (AltosState state, int crc_errors) { + void show (AltosState state, AltosListenerState listener_state) { if (state.gps != null) show(pos(state.gps.lon,"E", "W")); else @@ -359,25 +359,25 @@ public class AltosAscent extends JComponent implements AltosFlightDisplay { accel.set_font(); } - public void show(AltosState state, int crc_errors) { + public void show(AltosState state, AltosListenerState listener_state) { if (state.gps != null && state.gps.connected) { - lat.show(state, crc_errors); - lon.show(state, crc_errors); + lat.show(state, listener_state); + lon.show(state, listener_state); } else { lat.hide(); lon.hide(); } - height.show(state, crc_errors); + height.show(state, listener_state); if (state.main_sense != AltosRecord.MISSING) - main.show(state, crc_errors); + main.show(state, listener_state); else main.hide(); if (state.drogue_sense != AltosRecord.MISSING) - apogee.show(state, crc_errors); + apogee.show(state, listener_state); else apogee.hide(); - speed.show(state, crc_errors); - accel.show(state, crc_errors); + speed.show(state, listener_state); + accel.show(state, listener_state); } public void labels(GridBagLayout layout, int y) { diff --git a/altosui/AltosCompanionInfo.java b/altosui/AltosCompanionInfo.java index 7dd36aec..ebe1d1f9 100644 --- a/altosui/AltosCompanionInfo.java +++ b/altosui/AltosCompanionInfo.java @@ -83,7 +83,7 @@ public class AltosCompanionInfo extends JTable { } } - public void show(AltosState state, int crc_errors) { + public void show(AltosState state, AltosListenerState listener_state) { if (state == null) return; if (state.data.companion != null) diff --git a/altosui/AltosDescent.java b/altosui/AltosDescent.java index 9838f46b..29d33ddc 100644 --- a/altosui/AltosDescent.java +++ b/altosui/AltosDescent.java @@ -29,7 +29,7 @@ public class AltosDescent extends JComponent implements AltosFlightDisplay { JTextField value; AltosLights lights; - abstract void show(AltosState state, int crc_errors); + abstract void show(AltosState state, AltosListenerState listener_state); void show() { label.setVisible(true); @@ -108,7 +108,7 @@ public class AltosDescent extends JComponent implements AltosFlightDisplay { value.setText(""); } - abstract void show(AltosState state, int crc_errors); + abstract void show(AltosState state, AltosListenerState listener_state); void show() { label.setVisible(true); @@ -192,7 +192,7 @@ public class AltosDescent extends JComponent implements AltosFlightDisplay { value2.setFont(Altos.value_font); } - abstract void show(AltosState state, int crc_errors); + abstract void show(AltosState state, AltosListenerState listener_state); void show(String v1, String v2) { show(); @@ -244,7 +244,7 @@ public class AltosDescent extends JComponent implements AltosFlightDisplay { } class Height extends DescentValue { - void show (AltosState state, int crc_errors) { + void show (AltosState state, AltosListenerState listener_state) { show(AltosConvert.height, state.height); } public Height (GridBagLayout layout, int x, int y) { @@ -255,7 +255,7 @@ public class AltosDescent extends JComponent implements AltosFlightDisplay { Height height; class Speed extends DescentValue { - void show (AltosState state, int crc_errors) { + void show (AltosState state, AltosListenerState listener_state) { double speed = state.accel_speed; if (!state.ascent) speed = state.baro_speed; @@ -280,7 +280,7 @@ public class AltosDescent extends JComponent implements AltosFlightDisplay { } class Lat extends DescentValue { - void show (AltosState state, int crc_errors) { + void show (AltosState state, AltosListenerState listener_state) { if (state.gps != null && state.gps.connected) show(pos(state.gps.lat,"N", "S")); else @@ -294,7 +294,7 @@ public class AltosDescent extends JComponent implements AltosFlightDisplay { Lat lat; class Lon extends DescentValue { - void show (AltosState state, int crc_errors) { + void show (AltosState state, AltosListenerState listener_state) { if (state.gps != null && state.gps.connected) show(pos(state.gps.lon,"W", "E")); else @@ -308,7 +308,7 @@ public class AltosDescent extends JComponent implements AltosFlightDisplay { Lon lon; class Distance extends DescentValue { - void show(AltosState state, int crc_errors) { + void show(AltosState state, AltosListenerState listener_state) { if (state.from_pad != null) show(AltosConvert.distance, state.from_pad.distance); else @@ -324,7 +324,7 @@ public class AltosDescent extends JComponent implements AltosFlightDisplay { class Apogee extends DescentStatus { - void show (AltosState state, int crc_errors) { + void show (AltosState state, AltosListenerState listener_state) { show("%4.2f V", state.drogue_sense); lights.set(state.drogue_sense > 3.2); } @@ -336,7 +336,7 @@ public class AltosDescent extends JComponent implements AltosFlightDisplay { Apogee apogee; class Main extends DescentStatus { - void show (AltosState state, int crc_errors) { + void show (AltosState state, AltosListenerState listener_state) { show("%4.2f V", state.main_sense); lights.set(state.main_sense > 3.2); } @@ -348,7 +348,7 @@ public class AltosDescent extends JComponent implements AltosFlightDisplay { Main main; class Bearing extends DescentDualValue { - void show (AltosState state, int crc_errors) { + void show (AltosState state, AltosListenerState listener_state) { if (state.from_pad != null) { show( String.format("%3.0f°", state.from_pad.bearing), state.from_pad.bearing_words( @@ -365,7 +365,7 @@ public class AltosDescent extends JComponent implements AltosFlightDisplay { Bearing bearing; class Range extends DescentValue { - void show (AltosState state, int crc_errors) { + void show (AltosState state, AltosListenerState listener_state) { show(AltosConvert.distance, state.range); } public Range (GridBagLayout layout, int x, int y) { @@ -376,7 +376,7 @@ public class AltosDescent extends JComponent implements AltosFlightDisplay { Range range; class Elevation extends DescentValue { - void show (AltosState state, int crc_errors) { + void show (AltosState state, AltosListenerState listener_state) { show("%3.0f°", state.elevation); } public Elevation (GridBagLayout layout, int x, int y) { @@ -412,16 +412,16 @@ public class AltosDescent extends JComponent implements AltosFlightDisplay { apogee.set_font(); } - public void show(AltosState state, int crc_errors) { - height.show(state, crc_errors); - speed.show(state, crc_errors); + public void show(AltosState state, AltosListenerState listener_state) { + height.show(state, listener_state); + speed.show(state, listener_state); if (state.gps != null && state.gps.connected) { - bearing.show(state, crc_errors); - range.show(state, crc_errors); - distance.show(state, crc_errors); - elevation.show(state, crc_errors); - lat.show(state, crc_errors); - lon.show(state, crc_errors); + bearing.show(state, listener_state); + range.show(state, listener_state); + distance.show(state, listener_state); + elevation.show(state, listener_state); + lat.show(state, listener_state); + lon.show(state, listener_state); } else { bearing.hide(); range.hide(); @@ -431,11 +431,11 @@ public class AltosDescent extends JComponent implements AltosFlightDisplay { lon.hide(); } if (state.main_sense != AltosRecord.MISSING) - main.show(state, crc_errors); + main.show(state, listener_state); else main.hide(); if (state.drogue_sense != AltosRecord.MISSING) - apogee.show(state, crc_errors); + apogee.show(state, listener_state); else apogee.hide(); } diff --git a/altosui/AltosDisplayThread.java b/altosui/AltosDisplayThread.java index 6f8aa9ee..095bed99 100644 --- a/altosui/AltosDisplayThread.java +++ b/altosui/AltosDisplayThread.java @@ -29,21 +29,17 @@ public class AltosDisplayThread extends Thread { IdleThread idle_thread; AltosVoice voice; AltosFlightReader reader; - int crc_errors; + AltosState old_state, state; + AltosListenerState listener_state; AltosFlightDisplay display; - void show_internal(AltosState state, int crc_errors) { - if (state != null) - display.show(state, crc_errors); - } - - void show_safely(AltosState in_state, int in_crc_errors) { - final AltosState state = in_state; - final int crc_errors = in_crc_errors; + synchronized void show_safely() { + final AltosState my_state = state; + final AltosListenerState my_listener_state = listener_state; Runnable r = new Runnable() { public void run() { try { - show_internal(state, crc_errors); + display.show(my_state, my_listener_state); } catch (Exception ex) { } } @@ -73,7 +69,6 @@ public class AltosDisplayThread extends Thread { class IdleThread extends Thread { boolean started; - private AltosState state; int reported_landing; int report_interval; long report_time; @@ -129,7 +124,7 @@ public class AltosDisplayThread extends Thread { ++reported_landing; if (state.state != Altos.ao_flight_landed) { state.state = Altos.ao_flight_landed; - show_safely(state, 0); + show_safely(); } } } @@ -145,6 +140,10 @@ public class AltosDisplayThread extends Thread { public void run () { try { for (;;) { + if (reader.has_monitor_battery()) { + listener_state.battery = reader.monitor_battery(); + show_safely(); + } set_report_time(); for (;;) { voice.drain(); @@ -155,6 +154,7 @@ public class AltosDisplayThread extends Thread { wait(sleep_time); } } + report(false); } } catch (InterruptedException ie) { @@ -164,18 +164,7 @@ public class AltosDisplayThread extends Thread { } } - public synchronized void notice(AltosState new_state, boolean spoken) { - AltosState old_state = state; - state = new_state; - if (!started && state.state > Altos.ao_flight_pad) { - started = true; - start(); - } - - if (state.state < Altos.ao_flight_drogue) - report_interval = 10000; - else - report_interval = 20000; + public synchronized void notice(boolean spoken) { if (old_state != null && old_state.state != state.state) { report_time = now(); this.notify(); @@ -184,13 +173,12 @@ public class AltosDisplayThread extends Thread { } public IdleThread() { - state = null; reported_landing = 0; report_interval = 10000; } } - boolean tell(AltosState state, AltosState old_state) { + synchronized boolean tell() { boolean ret = false; if (old_state == null || old_state.state != state.state) { voice.speak(state.data.state()); @@ -222,12 +210,10 @@ public class AltosDisplayThread extends Thread { public void run() { boolean interrupted = false; - //String line; - AltosState state = null; - AltosState old_state = null; boolean told; idle_thread = new IdleThread(); + idle_thread.start(); try { for (;;) { @@ -238,14 +224,14 @@ public class AltosDisplayThread extends Thread { old_state = state; state = new AltosState(record, state); reader.update(state); - show_safely(state, crc_errors); - told = tell(state, old_state); - idle_thread.notice(state, told); + show_safely(); + told = tell(); + idle_thread.notice(told); } catch (ParseException pp) { System.out.printf("Parse error: %d \"%s\"\n", pp.getErrorOffset(), pp.getMessage()); } catch (AltosCRCException ce) { - ++crc_errors; - show_safely(state, crc_errors); + ++listener_state.crc_errors; + show_safely(); } } } catch (InterruptedException ee) { @@ -264,6 +250,7 @@ public class AltosDisplayThread extends Thread { } public AltosDisplayThread(Frame in_parent, AltosVoice in_voice, AltosFlightDisplay in_display, AltosFlightReader in_reader) { + listener_state = new AltosListenerState(); parent = in_parent; voice = in_voice; display = in_display; diff --git a/altosui/AltosFlightDisplay.java b/altosui/AltosFlightDisplay.java index d1ed7d2f..4f4c158e 100644 --- a/altosui/AltosFlightDisplay.java +++ b/altosui/AltosFlightDisplay.java @@ -22,7 +22,7 @@ import org.altusmetrum.altoslib_1.*; public interface AltosFlightDisplay { void reset(); - void show(AltosState state, int crc_errors); + void show(AltosState state, AltosListenerState listener_state); void set_font(); } diff --git a/altosui/AltosFlightStatus.java b/altosui/AltosFlightStatus.java index 20539a9f..d2910414 100644 --- a/altosui/AltosFlightStatus.java +++ b/altosui/AltosFlightStatus.java @@ -28,7 +28,7 @@ public class AltosFlightStatus extends JComponent implements AltosFlightDisplay JLabel label; JTextField value; - void show(AltosState state, int crc_errors) {} + void show(AltosState state, AltosListenerState listener_state) {} void reset() { value.setText(""); @@ -64,7 +64,7 @@ public class AltosFlightStatus extends JComponent implements AltosFlightDisplay } class Call extends FlightValue { - void show(AltosState state, int crc_errors) { + void show(AltosState state, AltosListenerState listener_state) { value.setText(state.data.callsign); } public Call (GridBagLayout layout, int x) { @@ -75,8 +75,11 @@ public class AltosFlightStatus extends JComponent implements AltosFlightDisplay Call call; class Serial extends FlightValue { - void show(AltosState state, int crc_errors) { - value.setText(String.format("%d", state.data.serial)); + void show(AltosState state, AltosListenerState listener_state) { + if (state.data.serial == AltosRecord.MISSING) + value.setText("none"); + else + value.setText(String.format("%d", state.data.serial)); } public Serial (GridBagLayout layout, int x) { super (layout, x, "Serial"); @@ -86,8 +89,11 @@ public class AltosFlightStatus extends JComponent implements AltosFlightDisplay Serial serial; class Flight extends FlightValue { - void show(AltosState state, int crc_errors) { - value.setText(String.format("%d", state.data.flight)); + void show(AltosState state, AltosListenerState listener_state) { + if (state.data.flight == AltosRecord.MISSING) + value.setText("none"); + else + value.setText(String.format("%d", state.data.flight)); } public Flight (GridBagLayout layout, int x) { super (layout, x, "Flight"); @@ -97,7 +103,7 @@ public class AltosFlightStatus extends JComponent implements AltosFlightDisplay Flight flight; class FlightState extends FlightValue { - void show(AltosState state, int crc_errors) { + void show(AltosState state, AltosListenerState listener_state) { value.setText(state.data.state()); } public FlightState (GridBagLayout layout, int x) { @@ -108,7 +114,7 @@ public class AltosFlightStatus extends JComponent implements AltosFlightDisplay FlightState flight_state; class RSSI extends FlightValue { - void show(AltosState state, int crc_errors) { + void show(AltosState state, AltosListenerState listener_state) { value.setText(String.format("%d", state.data.rssi)); } public RSSI (GridBagLayout layout, int x) { @@ -119,7 +125,7 @@ public class AltosFlightStatus extends JComponent implements AltosFlightDisplay RSSI rssi; class LastPacket extends FlightValue { - void show(AltosState state, int crc_errors) { + void show(AltosState state, AltosListenerState listener_state) { long secs = (System.currentTimeMillis() - state.report_time + 500) / 1000; value.setText(String.format("%d", secs)); } @@ -148,13 +154,13 @@ public class AltosFlightStatus extends JComponent implements AltosFlightDisplay last_packet.set_font(); } - public void show (AltosState state, int crc_errors) { - call.show(state, crc_errors); - serial.show(state, crc_errors); - flight.show(state, crc_errors); - flight_state.show(state, crc_errors); - rssi.show(state, crc_errors); - last_packet.show(state, crc_errors); + public void show (AltosState state, AltosListenerState listener_state) { + call.show(state, listener_state); + serial.show(state, listener_state); + flight.show(state, listener_state); + flight_state.show(state, listener_state); + rssi.show(state, listener_state); + last_packet.show(state, listener_state); } public int height() { diff --git a/altosui/AltosFlightStatusUpdate.java b/altosui/AltosFlightStatusUpdate.java index bf679b85..962a08f7 100644 --- a/altosui/AltosFlightStatusUpdate.java +++ b/altosui/AltosFlightStatusUpdate.java @@ -22,12 +22,16 @@ import org.altusmetrum.altoslib_1.*; public class AltosFlightStatusUpdate implements ActionListener { - public AltosState saved_state; - AltosFlightStatus flightStatus; + public AltosState saved_state; + public AltosListenerState saved_listener_state; + AltosFlightStatus flightStatus; public void actionPerformed (ActionEvent e) { - if (saved_state != null) - flightStatus.show(saved_state, 0); + if (saved_state != null) { + if (saved_listener_state == null) + saved_listener_state = new AltosListenerState(); + flightStatus.show(saved_state, saved_listener_state); + } } public AltosFlightStatusUpdate (AltosFlightStatus in_flightStatus) { diff --git a/altosui/AltosFlightUI.java b/altosui/AltosFlightUI.java index c04a4357..6b258f2e 100644 --- a/altosui/AltosFlightUI.java +++ b/altosui/AltosFlightUI.java @@ -98,11 +98,15 @@ public class AltosFlightUI extends AltosUIFrame implements AltosFlightDisplay, A AltosFlightStatusUpdate status_update; - public void show(AltosState state, int crc_errors) { + public void show(AltosState state, AltosListenerState listener_state) { status_update.saved_state = state; - JComponent tab = which_tab(state); - try { - pad.show(state, crc_errors); + + if (state == null) { + System.out.printf ("no state provided\n"); + state = new AltosState(new AltosRecord()); + } + + pad.show(state, listener_state); if (state.state != Altos.ao_flight_startup) { if (!has_state) { @@ -114,25 +118,26 @@ public class AltosFlightUI extends AltosUIFrame implements AltosFlightDisplay, A } } - ascent.show(state, crc_errors); - descent.show(state, crc_errors); - landed.show(state, crc_errors); + ascent.show(state, listener_state); + descent.show(state, listener_state); + landed.show(state, listener_state); + JComponent tab = which_tab(state); if (tab != cur_tab) { if (cur_tab == pane.getSelectedComponent()) { pane.setSelectedComponent(tab); } cur_tab = tab; } - flightStatus.show(state, crc_errors); - flightInfo.show(state, crc_errors); + flightStatus.show(state, listener_state); + flightInfo.show(state, listener_state); if (state.data.companion != null) { if (!has_companion) { pane.add("Companion", companion); has_companion= true; } - companion.show(state, crc_errors); + companion.show(state, listener_state); } else { if (has_companion) { pane.remove(companion); @@ -144,17 +149,13 @@ public class AltosFlightUI extends AltosUIFrame implements AltosFlightDisplay, A pane.add("Site Map", sitemap); has_map = true; } - sitemap.show(state, crc_errors); + sitemap.show(state, listener_state); } else { if (has_map) { pane.remove(sitemap); has_map = false; } } - } catch (Exception e) { - System.out.print("Show exception " + e + "\n"); - e.printStackTrace(); - } } public void set_exit_on_close() { diff --git a/altosui/AltosGraphUI.java b/altosui/AltosGraphUI.java index f6e57e7e..d8b8f6dd 100644 --- a/altosui/AltosGraphUI.java +++ b/altosui/AltosGraphUI.java @@ -35,7 +35,7 @@ public class AltosGraphUI extends AltosUIFrame if (state.gps != null && state.gps.locked && state.gps.nsat >= 4) { if (map == null) map = new AltosSiteMap(); - map.show(state, 0); + map.show(state, null); has_gps = true; } } diff --git a/altosui/AltosIdleMonitorUI.java b/altosui/AltosIdleMonitorUI.java index 8c883eeb..1ef30f0a 100644 --- a/altosui/AltosIdleMonitorUI.java +++ b/altosui/AltosIdleMonitorUI.java @@ -63,12 +63,12 @@ public class AltosIdleMonitorUI extends AltosUIFrame implements AltosFlightDispl AltosFlightStatusUpdate status_update; - public void show(AltosState state, int crc_errors) { + public void show(AltosState state, AltosListenerState listener_state) { status_update.saved_state = state; try { - pad.show(state, crc_errors); - flightStatus.show(state, crc_errors); - flightInfo.show(state, crc_errors); + pad.show(state, listener_state); + flightStatus.show(state, listener_state); + flightInfo.show(state, listener_state); } catch (Exception e) { System.out.print("Show exception" + e); } @@ -77,7 +77,7 @@ public class AltosIdleMonitorUI extends AltosUIFrame implements AltosFlightDispl public void update(final AltosState state) { Runnable r = new Runnable() { public void run() { - show(state, 0); + show(state, null); } }; SwingUtilities.invokeLater(r); diff --git a/altosui/AltosInfoTable.java b/altosui/AltosInfoTable.java index 1dce6daf..3d16faf2 100644 --- a/altosui/AltosInfoTable.java +++ b/altosui/AltosInfoTable.java @@ -104,111 +104,118 @@ public class AltosInfoTable extends JTable { model.clear(); } - public void show(AltosState state, int crc_errors) { - if (state == null) - return; + public void show(AltosState state, AltosListenerState listener_state) { info_reset(); - if (state.altitude != AltosRecord.MISSING) - info_add_row(0, "Altitude", "%6.0f m", state.altitude); - if (state.ground_altitude != AltosRecord.MISSING) - info_add_row(0, "Pad altitude", "%6.0f m", state.ground_altitude); - if (state.height != AltosRecord.MISSING) - info_add_row(0, "Height", "%6.0f m", state.height); - if (state.max_height != AltosRecord.MISSING) - info_add_row(0, "Max height", "%6.0f m", state.max_height); - if (state.acceleration != AltosRecord.MISSING) - info_add_row(0, "Acceleration", "%8.1f m/s²", state.acceleration); - if (state.max_acceleration != AltosRecord.MISSING) - info_add_row(0, "Max acceleration", "%8.1f m/s²", state.max_acceleration); - if (state.speed() != AltosRecord.MISSING) - info_add_row(0, "Speed", "%8.1f m/s", state.speed()); - if (state.max_speed() != AltosRecord.MISSING) - info_add_row(0, "Max Speed", "%8.1f m/s", state.max_accel_speed); - if (state.temperature != AltosRecord.MISSING) - info_add_row(0, "Temperature", "%9.2f °C", state.temperature); - if (state.battery != AltosRecord.MISSING) - info_add_row(0, "Battery", "%9.2f V", state.battery); - if (state.drogue_sense != AltosRecord.MISSING) - info_add_row(0, "Drogue", "%9.2f V", state.drogue_sense); - if (state.main_sense != AltosRecord.MISSING) - info_add_row(0, "Main", "%9.2f V", state.main_sense); - info_add_row(0, "CRC Errors", "%6d", crc_errors); - - if (state.gps == null || !state.gps.connected) { - info_add_row(1, "GPS", "not available"); - } else { - if (state.gps_ready) - info_add_row(1, "GPS state", "%s", "ready"); - else - info_add_row(1, "GPS state", "wait (%d)", - state.gps_waiting); - if (state.data.gps.locked) - info_add_row(1, "GPS", " locked"); - else if (state.data.gps.connected) - info_add_row(1, "GPS", " unlocked"); - else - info_add_row(1, "GPS", " missing"); - info_add_row(1, "Satellites", "%6d", state.data.gps.nsat); - info_add_deg(1, "Latitude", state.gps.lat, 'N', 'S'); - info_add_deg(1, "Longitude", state.gps.lon, 'E', 'W'); - info_add_row(1, "GPS altitude", "%6d", state.gps.alt); - info_add_row(1, "GPS height", "%6.0f", state.gps_height); - - /* The SkyTraq GPS doesn't report these values */ - /* - if (false) { - info_add_row(1, "GPS ground speed", "%8.1f m/s %3d°", - state.gps.ground_speed, - state.gps.course); - info_add_row(1, "GPS climb rate", "%8.1f m/s", - state.gps.climb_rate); - info_add_row(1, "GPS error", "%6d m(h)%3d m(v)", - state.gps.h_error, state.gps.v_error); - } - */ - - info_add_row(1, "GPS hdop", "%8.1f", state.gps.hdop); - - if (state.npad > 0) { - if (state.from_pad != null) { - info_add_row(1, "Distance from pad", "%6d m", - (int) (state.from_pad.distance + 0.5)); - info_add_row(1, "Direction from pad", "%6d°", - (int) (state.from_pad.bearing + 0.5)); - info_add_row(1, "Elevation from pad", "%6d°", - (int) (state.elevation + 0.5)); - info_add_row(1, "Range from pad", "%6d m", - (int) (state.range + 0.5)); - } else { - info_add_row(1, "Distance from pad", "unknown"); - info_add_row(1, "Direction from pad", "unknown"); - info_add_row(1, "Elevation from pad", "unknown"); - info_add_row(1, "Range from pad", "unknown"); + if (state != null) { + if (state.altitude != AltosRecord.MISSING) + info_add_row(0, "Altitude", "%6.0f m", state.altitude); + if (state.ground_altitude != AltosRecord.MISSING) + info_add_row(0, "Pad altitude", "%6.0f m", state.ground_altitude); + if (state.height != AltosRecord.MISSING) + info_add_row(0, "Height", "%6.0f m", state.height); + if (state.height != AltosRecord.MISSING) + info_add_row(0, "Max height", "%6.0f m", state.max_height); + if (state.acceleration != AltosRecord.MISSING) + info_add_row(0, "Acceleration", "%8.1f m/s²", state.acceleration); + if (state.acceleration != AltosRecord.MISSING) + info_add_row(0, "Max acceleration", "%8.1f m/s²", state.max_acceleration); + if (state.speed() != AltosRecord.MISSING) + info_add_row(0, "Speed", "%8.1f m/s", state.speed()); + if (state.speed() != AltosRecord.MISSING) + info_add_row(0, "Max Speed", "%8.1f m/s", state.max_accel_speed); + if (state.temperature != AltosRecord.MISSING) + info_add_row(0, "Temperature", "%9.2f °C", state.temperature); + if (state.battery != AltosRecord.MISSING) + info_add_row(0, "Battery", "%9.2f V", state.battery); + if (state.drogue_sense != AltosRecord.MISSING) + info_add_row(0, "Drogue", "%9.2f V", state.drogue_sense); + if (state.main_sense != AltosRecord.MISSING) + info_add_row(0, "Main", "%9.2f V", state.main_sense); + } + if (listener_state != null) { + info_add_row(0, "CRC Errors", "%6d", listener_state.crc_errors); + + if (listener_state.battery != AltosRecord.MISSING) + info_add_row(0, "Receiver Battery", "%9.2f", listener_state.battery); + } + + if (state != null) { + if (state.gps == null || !state.gps.connected) { + info_add_row(1, "GPS", "not available"); + } else { + if (state.gps_ready) + info_add_row(1, "GPS state", "%s", "ready"); + else + info_add_row(1, "GPS state", "wait (%d)", + state.gps_waiting); + if (state.data.gps.locked) + info_add_row(1, "GPS", " locked"); + else if (state.data.gps.connected) + info_add_row(1, "GPS", " unlocked"); + else + info_add_row(1, "GPS", " missing"); + info_add_row(1, "Satellites", "%6d", state.data.gps.nsat); + info_add_deg(1, "Latitude", state.gps.lat, 'N', 'S'); + info_add_deg(1, "Longitude", state.gps.lon, 'E', 'W'); + info_add_row(1, "GPS altitude", "%6d", state.gps.alt); + info_add_row(1, "GPS height", "%6.0f", state.gps_height); + + /* The SkyTraq GPS doesn't report these values */ + /* + if (false) { + info_add_row(1, "GPS ground speed", "%8.1f m/s %3d°", + state.gps.ground_speed, + state.gps.course); + info_add_row(1, "GPS climb rate", "%8.1f m/s", + state.gps.climb_rate); + info_add_row(1, "GPS error", "%6d m(h)%3d m(v)", + state.gps.h_error, state.gps.v_error); + } + */ + + info_add_row(1, "GPS hdop", "%8.1f", state.gps.hdop); + + if (state.npad > 0) { + if (state.from_pad != null) { + info_add_row(1, "Distance from pad", "%6d m", + (int) (state.from_pad.distance + 0.5)); + info_add_row(1, "Direction from pad", "%6d°", + (int) (state.from_pad.bearing + 0.5)); + info_add_row(1, "Elevation from pad", "%6d°", + (int) (state.elevation + 0.5)); + info_add_row(1, "Range from pad", "%6d m", + (int) (state.range + 0.5)); + } else { + info_add_row(1, "Distance from pad", "unknown"); + info_add_row(1, "Direction from pad", "unknown"); + info_add_row(1, "Elevation from pad", "unknown"); + info_add_row(1, "Range from pad", "unknown"); + } + info_add_deg(1, "Pad latitude", state.pad_lat, 'N', 'S'); + info_add_deg(1, "Pad longitude", state.pad_lon, 'E', 'W'); + info_add_row(1, "Pad GPS alt", "%6.0f m", state.pad_alt); } - info_add_deg(1, "Pad latitude", state.pad_lat, 'N', 'S'); - info_add_deg(1, "Pad longitude", state.pad_lon, 'E', 'W'); - info_add_row(1, "Pad GPS alt", "%6.0f m", state.pad_alt); - } - info_add_row(1, "GPS date", "%04d-%02d-%02d", - state.gps.year, - state.gps.month, - state.gps.day); - info_add_row(1, "GPS time", " %02d:%02d:%02d", - state.gps.hour, - state.gps.minute, - state.gps.second); - //int nsat_vis = 0; - int c; - - if (state.gps.cc_gps_sat == null) - info_add_row(2, "Satellites Visible", "%4d", 0); - else { - info_add_row(2, "Satellites Visible", "%4d", state.gps.cc_gps_sat.length); - for (c = 0; c < state.gps.cc_gps_sat.length; c++) { - info_add_row(2, "Satellite id,C/N0", - "%4d, %4d", - state.gps.cc_gps_sat[c].svid, - state.gps.cc_gps_sat[c].c_n0); + info_add_row(1, "GPS date", "%04d-%02d-%02d", + state.gps.year, + state.gps.month, + state.gps.day); + info_add_row(1, "GPS time", " %02d:%02d:%02d", + state.gps.hour, + state.gps.minute, + state.gps.second); + //int nsat_vis = 0; + int c; + + if (state.gps.cc_gps_sat == null) + info_add_row(2, "Satellites Visible", "%4d", 0); + else { + info_add_row(2, "Satellites Visible", "%4d", state.gps.cc_gps_sat.length); + for (c = 0; c < state.gps.cc_gps_sat.length; c++) { + info_add_row(2, "Satellite id,C/N0", + "%4d, %4d", + state.gps.cc_gps_sat[c].svid, + state.gps.cc_gps_sat[c].c_n0); + } } } } diff --git a/altosui/AltosLanded.java b/altosui/AltosLanded.java index a245dde3..1d209bda 100644 --- a/altosui/AltosLanded.java +++ b/altosui/AltosLanded.java @@ -29,7 +29,7 @@ public class AltosLanded extends JComponent implements AltosFlightDisplay, Actio public class LandedValue { JLabel label; JTextField value; - void show(AltosState state, int crc_errors) {} + void show(AltosState state, AltosListenerState listener_state) {} void reset() { value.setText(""); @@ -102,7 +102,7 @@ public class AltosLanded extends JComponent implements AltosFlightDisplay, Actio } class Lat extends LandedValue { - void show (AltosState state, int crc_errors) { + void show (AltosState state, AltosListenerState listener_state) { if (state.gps != null && state.gps.connected) show(pos(state.gps.lat,"N", "S")); else @@ -116,7 +116,7 @@ public class AltosLanded extends JComponent implements AltosFlightDisplay, Actio Lat lat; class Lon extends LandedValue { - void show (AltosState state, int crc_errors) { + void show (AltosState state, AltosListenerState listener_state) { show(); if (state.gps != null && state.gps.connected) show(pos(state.gps.lon,"E", "W")); @@ -131,7 +131,7 @@ public class AltosLanded extends JComponent implements AltosFlightDisplay, Actio Lon lon; class Bearing extends LandedValue { - void show (AltosState state, int crc_errors) { + void show (AltosState state, AltosListenerState listener_state) { show(); if (state.from_pad != null) show("%3.0f°", state.from_pad.bearing); @@ -146,7 +146,7 @@ public class AltosLanded extends JComponent implements AltosFlightDisplay, Actio Bearing bearing; class Distance extends LandedValue { - void show (AltosState state, int crc_errors) { + void show (AltosState state, AltosListenerState listener_state) { show(); if (state.from_pad != null) show(AltosConvert.distance, state.from_pad.distance); @@ -161,7 +161,7 @@ public class AltosLanded extends JComponent implements AltosFlightDisplay, Actio Distance distance; class Height extends LandedValue { - void show (AltosState state, int crc_errors) { + void show (AltosState state, AltosListenerState listener_state) { show(AltosConvert.height, state.max_height); } public Height (GridBagLayout layout, int y) { @@ -172,7 +172,7 @@ public class AltosLanded extends JComponent implements AltosFlightDisplay, Actio Height height; class Speed extends LandedValue { - void show (AltosState state, int crc_errors) { + void show (AltosState state, AltosListenerState listener_state) { show(AltosConvert.speed, state.max_speed()); } public Speed (GridBagLayout layout, int y) { @@ -183,7 +183,7 @@ public class AltosLanded extends JComponent implements AltosFlightDisplay, Actio Speed speed; class Accel extends LandedValue { - void show (AltosState state, int crc_errors) { + void show (AltosState state, AltosListenerState listener_state) { show(AltosConvert.accel, state.max_acceleration); } public Accel (GridBagLayout layout, int y) { @@ -213,21 +213,21 @@ public class AltosLanded extends JComponent implements AltosFlightDisplay, Actio accel.set_font(); } - public void show(AltosState state, int crc_errors) { + public void show(AltosState state, AltosListenerState listener_state) { if (state.gps != null && state.gps.connected) { - bearing.show(state, crc_errors); - distance.show(state, crc_errors); - lat.show(state, crc_errors); - lon.show(state, crc_errors); + bearing.show(state, listener_state); + distance.show(state, listener_state); + lat.show(state, listener_state); + lon.show(state, listener_state); } else { bearing.hide(); distance.hide(); lat.hide(); lon.hide(); } - height.show(state, crc_errors); - speed.show(state, crc_errors); - accel.show(state, crc_errors); + height.show(state, listener_state); + speed.show(state, listener_state); + accel.show(state, listener_state); if (reader.backing_file() != null) graph.setEnabled(true); } diff --git a/altosui/AltosPad.java b/altosui/AltosPad.java index eb08525c..e2316a13 100644 --- a/altosui/AltosPad.java +++ b/altosui/AltosPad.java @@ -29,7 +29,7 @@ public class AltosPad extends JComponent implements AltosFlightDisplay { JTextField value; AltosLights lights; - void show(AltosState state, int crc_errors) {} + void show(AltosState state, AltosListenerState listener_state) {} void reset() { value.setText(""); @@ -109,7 +109,7 @@ public class AltosPad extends JComponent implements AltosFlightDisplay { public class LaunchValue { JLabel label; JTextField value; - void show(AltosState state, int crc_errors) {} + void show(AltosState state, AltosListenerState listener_state) {} void show() { label.setVisible(true); @@ -175,8 +175,8 @@ public class AltosPad extends JComponent implements AltosFlightDisplay { } class Battery extends LaunchStatus { - void show (AltosState state, int crc_errors) { - if (state.battery == AltosRecord.MISSING) + void show (AltosState state, AltosListenerState listener_state) { + if (state == null || state.battery == AltosRecord.MISSING) hide(); else { show("%4.2f V", state.battery); @@ -191,9 +191,13 @@ public class AltosPad extends JComponent implements AltosFlightDisplay { Battery battery; class Apogee extends LaunchStatus { - void show (AltosState state, int crc_errors) { - show("%4.2f V", state.drogue_sense); - lights.set(state.drogue_sense > 3.2); + void show (AltosState state, AltosListenerState listener_state) { + if (state == null || state.drogue_sense == AltosRecord.MISSING) + hide(); + else { + show("%4.2f V", state.drogue_sense); + lights.set(state.drogue_sense > 3.2); + } } public Apogee (GridBagLayout layout, int y) { super(layout, y, "Apogee Igniter Voltage"); @@ -203,9 +207,13 @@ public class AltosPad extends JComponent implements AltosFlightDisplay { Apogee apogee; class Main extends LaunchStatus { - void show (AltosState state, int crc_errors) { - show("%4.2f V", state.main_sense); - lights.set(state.main_sense > 3.2); + void show (AltosState state, AltosListenerState listener_state) { + if (state == null || state.main_sense == AltosRecord.MISSING) + hide(); + else { + show("%4.2f V", state.main_sense); + lights.set(state.main_sense > 3.2); + } } public Main (GridBagLayout layout, int y) { super(layout, y, "Main Igniter Voltage"); @@ -215,18 +223,21 @@ public class AltosPad extends JComponent implements AltosFlightDisplay { Main main; class LoggingReady extends LaunchStatus { - void show (AltosState state, int crc_errors) { - if (state.data.flight != 0) { - if (state.data.state <= Altos.ao_flight_pad) - show("Ready to record"); - else if (state.data.state < Altos.ao_flight_landed) - show("Recording data"); - else - show("Recorded data"); + void show (AltosState state, AltosListenerState listener_state) { + if (state == null || state.data.flight == AltosRecord.MISSING) { + hide(); + } else { + if (state.data.flight != 0) { + if (state.data.state <= Altos.ao_flight_pad) + show("Ready to record"); + else if (state.data.state < Altos.ao_flight_landed) + show("Recording data"); + else + show("Recorded data"); + } else + show("Storage full"); + lights.set(state.data.flight != 0); } - else - show("Storage full"); - lights.set(state.data.flight != 0); } public LoggingReady (GridBagLayout layout, int y) { super(layout, y, "On-board Data Logging"); @@ -236,9 +247,13 @@ public class AltosPad extends JComponent implements AltosFlightDisplay { LoggingReady logging_ready; class GPSLocked extends LaunchStatus { - void show (AltosState state, int crc_errors) { - show("%4d sats", state.gps.nsat); - lights.set(state.gps.locked && state.gps.nsat >= 4); + void show (AltosState state, AltosListenerState listener_state) { + if (state == null || state.gps == null) + hide(); + else { + show("%4d sats", state.gps.nsat); + lights.set(state.gps.locked && state.gps.nsat >= 4); + } } public GPSLocked (GridBagLayout layout, int y) { super (layout, y, "GPS Locked"); @@ -248,12 +263,16 @@ public class AltosPad extends JComponent implements AltosFlightDisplay { GPSLocked gps_locked; class GPSReady extends LaunchStatus { - void show (AltosState state, int crc_errors) { - if (state.gps_ready) - show("Ready"); - else - show("Waiting %d", state.gps_waiting); - lights.set(state.gps_ready); + void show (AltosState state, AltosListenerState listener_state) { + if (state == null || state.gps == null) + hide(); + else { + if (state.gps_ready) + show("Ready"); + else + show("Waiting %d", state.gps_waiting); + lights.set(state.gps_ready); + } } public GPSReady (GridBagLayout layout, int y) { super (layout, y, "GPS Ready"); @@ -262,6 +281,22 @@ public class AltosPad extends JComponent implements AltosFlightDisplay { GPSReady gps_ready; + class ReceiverBattery extends LaunchStatus { + void show (AltosState state, AltosListenerState listener_state) { + if (listener_state == null || listener_state.battery == AltosRecord.MISSING) + hide(); + else { + show("%4.2f V", listener_state.battery); + lights.set(listener_state.battery > 3.7); + } + } + public ReceiverBattery (GridBagLayout layout, int y) { + super(layout, y, "Receiver Battery"); + } + } + + ReceiverBattery receiver_battery; + String pos(double p, String pos, String neg) { String h = pos; if (p < 0) { @@ -274,13 +309,17 @@ public class AltosPad extends JComponent implements AltosFlightDisplay { } class PadLat extends LaunchValue { - void show (AltosState state, int crc_errors) { - if (state.state < AltosLib.ao_flight_pad && state.gps != null) { - show(pos(state.gps.lat,"N", "S")); - set_label("Latitude"); - } else { - show(pos(state.pad_lat,"N", "S")); - set_label("Pad Latitude"); + void show (AltosState state, AltosListenerState listener_state) { + if (state == null || state.gps == null) { + hide(); + } else { + if (state.state < AltosLib.ao_flight_pad) { + show(pos(state.gps.lat,"N", "S")); + set_label("Latitude"); + } else { + show(pos(state.pad_lat,"N", "S")); + set_label("Pad Latitude"); + } } } public PadLat (GridBagLayout layout, int y) { @@ -291,13 +330,17 @@ public class AltosPad extends JComponent implements AltosFlightDisplay { PadLat pad_lat; class PadLon extends LaunchValue { - void show (AltosState state, int crc_errors) { - if (state.state < AltosLib.ao_flight_pad && state.gps != null) { - show(pos(state.gps.lon,"E", "W")); - set_label("Longitude"); - } else { - show(pos(state.pad_lon,"E", "W")); - set_label("Pad Longitude"); + void show (AltosState state, AltosListenerState listener_state) { + if (state == null || state.gps == null) { + hide(); + } else { + if (state.state < AltosLib.ao_flight_pad) { + show(pos(state.gps.lon,"E", "W")); + set_label("Longitude"); + } else { + show(pos(state.pad_lon,"E", "W")); + set_label("Pad Longitude"); + } } } public PadLon (GridBagLayout layout, int y) { @@ -308,16 +351,20 @@ public class AltosPad extends JComponent implements AltosFlightDisplay { PadLon pad_lon; class PadAlt extends LaunchValue { - void show (AltosState state, int crc_errors) { - if (state.state < AltosLib.ao_flight_pad && state.gps != null) { - show("%4.0f m", state.gps.alt); - set_label("Altitude"); - } else { - if (state.pad_alt == AltosRecord.MISSING) - hide(); - else { - show("%4.0f m", state.pad_alt); - set_label("Pad Altitude"); + void show (AltosState state, AltosListenerState listener_state) { + if (state == null) + hide(); + else { + if (state.state < AltosLib.ao_flight_pad && state.gps != null) { + show("%4.0f m", state.gps.alt); + set_label("Altitude"); + } else { + if (state.pad_alt == AltosRecord.MISSING) + hide(); + else { + show("%4.0f m", state.pad_alt); + set_label("Pad Altitude"); + } } } } @@ -335,6 +382,7 @@ public class AltosPad extends JComponent implements AltosFlightDisplay { logging_ready.reset(); gps_locked.reset(); gps_ready.reset(); + receiver_battery.reset(); pad_lat.reset(); pad_lon.reset(); pad_alt.reset(); @@ -347,34 +395,23 @@ public class AltosPad extends JComponent implements AltosFlightDisplay { logging_ready.set_font(); gps_locked.set_font(); gps_ready.set_font(); + receiver_battery.set_font(); pad_lat.set_font(); pad_lon.set_font(); pad_alt.set_font(); } - public void show(AltosState state, int crc_errors) { - battery.show(state, crc_errors); - if (state.drogue_sense == AltosRecord.MISSING) - apogee.hide(); - else - apogee.show(state, crc_errors); - if (state.main_sense == AltosRecord.MISSING) - main.hide(); - else - main.show(state, crc_errors); - logging_ready.show(state, crc_errors); - pad_alt.show(state, crc_errors); - if (state.gps != null && state.gps.connected) { - gps_locked.show(state, crc_errors); - gps_ready.show(state, crc_errors); - pad_lat.show(state, crc_errors); - pad_lon.show(state, crc_errors); - } else { - gps_locked.hide(); - gps_ready.hide(); - pad_lat.hide(); - pad_lon.hide(); - } + public void show(AltosState state, AltosListenerState listener_state) { + battery.show(state, listener_state); + apogee.show(state, listener_state); + main.show(state, listener_state); + logging_ready.show(state, listener_state); + pad_alt.show(state, listener_state); + receiver_battery.show(state, listener_state); + gps_locked.show(state, listener_state); + gps_ready.show(state, listener_state); + pad_lat.show(state, listener_state); + pad_lon.show(state, listener_state); } public AltosPad() { @@ -398,8 +435,10 @@ public class AltosPad extends JComponent implements AltosFlightDisplay { logging_ready = new LoggingReady(layout, 3); gps_locked = new GPSLocked(layout, 4); gps_ready = new GPSReady(layout, 5); - pad_lat = new PadLat(layout, 6); - pad_lon = new PadLon(layout, 7); - pad_alt = new PadAlt(layout, 8); + receiver_battery = new ReceiverBattery(layout, 6); + pad_lat = new PadLat(layout, 7); + pad_lon = new PadLon(layout, 8); + pad_alt = new PadAlt(layout, 9); + show(null, null); } } diff --git a/altosui/AltosSiteMap.java b/altosui/AltosSiteMap.java index f614eae6..5bf02e54 100644 --- a/altosui/AltosSiteMap.java +++ b/altosui/AltosSiteMap.java @@ -264,7 +264,7 @@ public class AltosSiteMap extends JScrollPane implements AltosFlightDisplay { initMaps(lat, lon); scrollRocketToVisible(pt(lat, lon)); } - public void show(final AltosState state, final int crc_errors) { + public void show(final AltosState state, final AltosListenerState listener_state) { // if insufficient gps data, nothing to update if (!state.gps.locked && state.gps.nsat < 4) return; @@ -294,7 +294,7 @@ public class AltosSiteMap extends JScrollPane implements AltosFlightDisplay { Point2D.Double ref, lref; ref = translatePoint(pt, tileCoordOffset(offset)); lref = translatePoint(last_pt, tileCoordOffset(offset)); - tile.show(state, crc_errors, lref, ref); + tile.show(state, listener_state, lref, ref); if (0 <= ref.x && ref.x < px_size) if (0 <= ref.y && ref.y < px_size) in_any = true; @@ -307,7 +307,7 @@ public class AltosSiteMap extends JScrollPane implements AltosFlightDisplay { lref = translatePoint(last_pt, tileCoordOffset(offset)); AltosSiteMapTile tile = createTile(offset); - tile.show(state, crc_errors, lref, ref); + tile.show(state, listener_state, lref, ref); initMap(offset); finishTileLater(tile, offset); } diff --git a/altosui/AltosSiteMapTile.java b/altosui/AltosSiteMapTile.java index 10e65bcd..365e4b6c 100644 --- a/altosui/AltosSiteMapTile.java +++ b/altosui/AltosSiteMapTile.java @@ -56,7 +56,7 @@ public class AltosSiteMapTile extends JLayeredPane { private boolean drawn_landed_circle = false; private boolean drawn_boost_circle = false; - public synchronized void show(AltosState state, int crc_errors, + public synchronized void show(AltosState state, AltosListenerState listener_state, Point2D.Double last_pt, Point2D.Double pt) { if (0 <= state.state && state.state < stateColors.length) { diff --git a/src/core/ao.h b/src/core/ao.h index 6c790f69..977e10b8 100644 --- a/src/core/ao.h +++ b/src/core/ao.h @@ -94,7 +94,7 @@ extern volatile __data AO_TICK_TYPE ao_tick_count; #define AO_SEC_TO_TICKS(s) ((s) * AO_HERTZ) /* Returns the current time in ticks */ -uint16_t +AO_TICK_TYPE ao_time(void); /* Suspend the current task until ticks time has passed */ diff --git a/src/stm/ao_timer.c b/src/stm/ao_timer.c index e07625d8..8b7c2327 100644 --- a/src/stm/ao_timer.c +++ b/src/stm/ao_timer.c @@ -18,15 +18,12 @@ #include "ao.h" #include -volatile __data AO_TICK_TYPE ao_tick_count; +volatile AO_TICK_TYPE ao_tick_count; -uint16_t ao_time(void) +AO_TICK_TYPE +ao_time(void) { - uint16_t v; - ao_arch_critical( - v = ao_tick_count; - ); - return v; + return ao_tick_count; } #if AO_DATA_ALL -- cgit v1.2.3 From 8c05f608c8f103649c1e5ec0d5742621e233af78 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 22 Apr 2013 11:06:36 -0500 Subject: Move cortex toolchain to /opt/cortex Signed-off-by: Keith Packard --- src/stm-bringup/Makefile | 4 ++-- src/stm/Makefile.defs | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'src/stm') diff --git a/src/stm-bringup/Makefile b/src/stm-bringup/Makefile index 5cc94bd9..1bc5aaad 100644 --- a/src/stm-bringup/Makefile +++ b/src/stm-bringup/Makefile @@ -8,8 +8,8 @@ endif CC=arm-none-eabi-gcc OBJCOPY=arm-none-eabi-objcopy -PDCLIB=/home/keithp/sat -C_LIB=$(PDCLIB)/lib/pdclib.a +PDCLIB=/opt/cortex +C_LIB=$(PDCLIB)/lib/pdclib-cortex-m3.a C_INC=-I$(PDCLIB)/include DEF_CFLAGS=-g -std=gnu99 -Os -mlittle-endian -mthumb -ffreestanding -nostdlib -I. -I../../src/stm $(C_INC) diff --git a/src/stm/Makefile.defs b/src/stm/Makefile.defs index 04404cdc..1480f0b3 100644 --- a/src/stm/Makefile.defs +++ b/src/stm/Makefile.defs @@ -8,8 +8,8 @@ vpath matrix.5c ../kalman vpath ao-make-product.5c ../util CC=arm-none-eabi-gcc -SAT=/home/keithp/sat -SAT_CLIB=$(SAT)/lib/pdclib.a +SAT=/opt/cortex +SAT_CLIB=$(SAT)/lib/pdclib-cortex-m3.a SAT_CFLAGS=-I$(SAT)/include ifndef VERSION -- cgit v1.2.3 From aa7eac32adf4c2cdf441991d02411758f2682d1e Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Mon, 22 Apr 2013 13:00:26 -0600 Subject: name change from MegaMetrum to TeleMega --- altoslib/AltosConfigData.java | 2 +- altoslib/AltosIdleMonitor.java | 4 +- altoslib/AltosLib.java | 6 +- altosui/AltosDataChooser.java | 2 +- altosui/AltosEepromDownload.java | 2 +- altosui/Makefile.am | 2 +- altosui/altos-windows.nsi.in | 2 +- altosuilib/AltosUSBDevice.java | 6 +- ao-bringup/megametrum.cfg | 4 - ao-bringup/megametrum.gdb | 2 - ao-bringup/telemega.cfg | 4 + ao-bringup/telemega.gdb | 2 + debian/docs | 2 +- doc/altos.xsl | 2 +- doc/megametrum-outline.pdf | Bin 4349 -> 0 bytes doc/megametrum-outline.svg | 244 ------------------------ doc/release-notes-1.2.xsl | 2 +- src/Makefile | 2 +- src/core/ao_fec_rx.c | 2 +- src/core/ao_log.h | 2 +- src/core/ao_log_mega.c | 2 +- src/core/ao_telemetry.c | 2 +- src/drivers/ao_companion.c | 2 +- src/megametrum-v0.1/.gitignore | 2 - src/megametrum-v0.1/Makefile | 131 ------------- src/megametrum-v0.1/ao_megametrum.c | 100 ---------- src/megametrum-v0.1/ao_pins.h | 359 ------------------------------------ src/megametrum-v0.1/stlink-pins | 57 ------ src/stm/ao_i2c_stm.c | 2 +- src/telelco-v0.1/Makefile | 2 +- src/test/Makefile | 2 +- src/test/ao_flight_test.c | 22 +-- telemetrum.inf | 8 +- 33 files changed, 46 insertions(+), 939 deletions(-) delete mode 100644 ao-bringup/megametrum.cfg delete mode 100644 ao-bringup/megametrum.gdb create mode 100644 ao-bringup/telemega.cfg create mode 100644 ao-bringup/telemega.gdb delete mode 100644 doc/megametrum-outline.pdf delete mode 100644 doc/megametrum-outline.svg delete mode 100644 src/megametrum-v0.1/.gitignore delete mode 100644 src/megametrum-v0.1/Makefile delete mode 100644 src/megametrum-v0.1/ao_megametrum.c delete mode 100644 src/megametrum-v0.1/ao_pins.h delete mode 100644 src/megametrum-v0.1/stlink-pins (limited to 'src/stm') diff --git a/altoslib/AltosConfigData.java b/altoslib/AltosConfigData.java index 57605607..2ca5a7a5 100644 --- a/altoslib/AltosConfigData.java +++ b/altoslib/AltosConfigData.java @@ -504,7 +504,7 @@ public class AltosConfigData implements Iterable { switch (log_format) { case AltosLib.AO_LOG_FORMAT_FULL: case AltosLib.AO_LOG_FORMAT_TINY: - case AltosLib.AO_LOG_FORMAT_MEGAMETRUM: + case AltosLib.AO_LOG_FORMAT_TELEMEGA: link.printf("l\n"); read_link(link, "done"); default: diff --git a/altoslib/AltosIdleMonitor.java b/altoslib/AltosIdleMonitor.java index c379547f..2e4ddef2 100644 --- a/altoslib/AltosIdleMonitor.java +++ b/altoslib/AltosIdleMonitor.java @@ -52,11 +52,11 @@ public class AltosIdleMonitor extends Thread { } boolean has_sensor_mm(AltosConfigData config_data) { - return config_data.product.startsWith("MegaMetrum"); + return config_data.product.startsWith("TeleMega"); } boolean has_gps(AltosConfigData config_data) { - return config_data.product.startsWith("TeleMetrum") || config_data.product.startsWith("MegaMetrum"); + return config_data.product.startsWith("TeleMetrum") || config_data.product.startsWith("TeleMega"); } AltosRecord sensor_mm(AltosConfigData config_data) throws InterruptedException, TimeoutException { diff --git a/altoslib/AltosLib.java b/altoslib/AltosLib.java index 0b5475f7..25d17e72 100644 --- a/altoslib/AltosLib.java +++ b/altoslib/AltosLib.java @@ -50,7 +50,7 @@ public class AltosLib { public static final int AO_LOG_SERIAL_NUMBER = 2002; public static final int AO_LOG_LOG_FORMAT = 2003; - /* Added for header fields in megametrum files */ + /* Added for header fields in telemega files */ public static final int AO_LOG_BARO_RESERVED = 3000; public static final int AO_LOG_BARO_SENS = 3001; public static final int AO_LOG_BARO_OFF = 3002; @@ -89,7 +89,7 @@ public class AltosLib { public final static int product_telelco = 0x0010; public final static int product_telescience = 0x0011; public final static int product_telepyro =0x0012; - public final static int product_megametrum = 0x0023; + public final static int product_telemega = 0x0023; public final static int product_megadongle = 0x0024; public final static int product_telegps = 0x0025; public final static int product_altusmetrum_min = 0x000a; @@ -215,7 +215,7 @@ public class AltosLib { public static final int AO_LOG_FORMAT_TINY = 2; public static final int AO_LOG_FORMAT_TELEMETRY = 3; public static final int AO_LOG_FORMAT_TELESCIENCE = 4; - public static final int AO_LOG_FORMAT_MEGAMETRUM = 5; + public static final int AO_LOG_FORMAT_TELEMEGA = 5; public static final int AO_LOG_FORMAT_NONE = 127; public static boolean isspace(int c) { diff --git a/altosui/AltosDataChooser.java b/altosui/AltosDataChooser.java index 7de18afb..f914f138 100644 --- a/altosui/AltosDataChooser.java +++ b/altosui/AltosDataChooser.java @@ -75,7 +75,7 @@ public class AltosDataChooser extends JFileChooser { "eeprom")); setFileFilter(new FileNameExtensionFilter("Telemetry file", "telem")); - setFileFilter(new FileNameExtensionFilter("MegaMetrum eeprom file", + setFileFilter(new FileNameExtensionFilter("TeleMega eeprom file", "mega")); setFileFilter(new FileNameExtensionFilter("Flight data file", "telem", "eeprom", "mega")); diff --git a/altosui/AltosEepromDownload.java b/altosui/AltosEepromDownload.java index 801d4ec0..a0523b58 100644 --- a/altosui/AltosEepromDownload.java +++ b/altosui/AltosEepromDownload.java @@ -366,7 +366,7 @@ public class AltosEepromDownload implements Runnable { extension = "science"; CaptureTeleScience(eechunk); break; - case AltosLib.AO_LOG_FORMAT_MEGAMETRUM: + case AltosLib.AO_LOG_FORMAT_TELEMEGA: extension = "mega"; CaptureMega(eechunk); } diff --git a/altosui/Makefile.am b/altosui/Makefile.am index 96cf77f2..4bfef47c 100644 --- a/altosui/Makefile.am +++ b/altosui/Makefile.am @@ -157,7 +157,7 @@ FIRMWARE=$(FIRMWARE_TM) $(FIRMWARE_TELEMINI) $(FIRMWARE_TD) ALTUSMETRUM_DOC=$(top_srcdir)/doc/altusmetrum.pdf ALTOS_DOC=$(top_srcdir)/doc/altos.pdf TELEMETRY_DOC=$(top_srcdir)/doc/telemetry.pdf -TEMPLATE_DOC=$(top_srcdir)/doc/telemetrum-outline.pdf $(top_srcdir)/doc/megametrum-outline.pdf +TEMPLATE_DOC=$(top_srcdir)/doc/telemetrum-outline.pdf $(top_srcdir)/doc/telemega-outline.pdf DOC=$(ALTUSMETRUM_DOC) $(ALTOS_DOC) $(TELEMETRY_DOC) $(TEMPLATE_DOC) diff --git a/altosui/altos-windows.nsi.in b/altosui/altos-windows.nsi.in index cde54b41..9886e4a2 100644 --- a/altosui/altos-windows.nsi.in +++ b/altosui/altos-windows.nsi.in @@ -131,7 +131,7 @@ Section "Documentation" File "../doc/altos.pdf" File "../doc/telemetry.pdf" File "../doc/telemetrum-outline.pdf" - File "../doc/megametrum-outline.pdf" + File "../doc/telemega-outline.pdf" SectionEnd Section "Uninstaller" diff --git a/altosuilib/AltosUSBDevice.java b/altosuilib/AltosUSBDevice.java index 5268927c..0f6cbd10 100644 --- a/altosuilib/AltosUSBDevice.java +++ b/altosuilib/AltosUSBDevice.java @@ -72,11 +72,11 @@ public class AltosUSBDevice extends altos_device implements AltosDevice { return matchProduct(AltosUILib.product_teledongle) || matchProduct(AltosUILib.product_teleterra) || matchProduct(AltosUILib.product_telebt) || - matchProduct(AltosUILib.product_megadongle); + matchProduct(AltosUILib.product_telemega); if (want_product == AltosUILib.product_altimeter) return matchProduct(AltosUILib.product_telemetrum) || - matchProduct(AltosUILib.product_megametrum) || + matchProduct(AltosUILib.product_telemega) || matchProduct(AltosUILib.product_telegps); int have_product = getProduct(); @@ -110,4 +110,4 @@ public class AltosUSBDevice extends altos_device implements AltosDevice { return device_list; } -} \ No newline at end of file +} diff --git a/ao-bringup/megametrum.cfg b/ao-bringup/megametrum.cfg deleted file mode 100644 index e95c6f2b..00000000 --- a/ao-bringup/megametrum.cfg +++ /dev/null @@ -1,4 +0,0 @@ -# openocd config for MegaMetrum using the Olimex ARM-USB-OCD dongle - -source /opt/stm32/share/openocd/scripts/interface/olimex-arm-usb-ocd.cfg -source /opt/stm32/share/openocd/scripts/target/stm32l.cfg diff --git a/ao-bringup/megametrum.gdb b/ao-bringup/megametrum.gdb deleted file mode 100644 index 964ae1f3..00000000 --- a/ao-bringup/megametrum.gdb +++ /dev/null @@ -1,2 +0,0 @@ -target remote localhost:3333 -monitor poll diff --git a/ao-bringup/telemega.cfg b/ao-bringup/telemega.cfg new file mode 100644 index 00000000..f6b96c13 --- /dev/null +++ b/ao-bringup/telemega.cfg @@ -0,0 +1,4 @@ +# openocd config for TeleMega using the Olimex ARM-USB-OCD dongle + +source /opt/stm32/share/openocd/scripts/interface/olimex-arm-usb-ocd.cfg +source /opt/stm32/share/openocd/scripts/target/stm32l.cfg diff --git a/ao-bringup/telemega.gdb b/ao-bringup/telemega.gdb new file mode 100644 index 00000000..964ae1f3 --- /dev/null +++ b/ao-bringup/telemega.gdb @@ -0,0 +1,2 @@ +target remote localhost:3333 +monitor poll diff --git a/debian/docs b/debian/docs index 3ac75ad4..dcdb7763 100644 --- a/debian/docs +++ b/debian/docs @@ -7,4 +7,4 @@ doc/telemetry.pdf doc/altos.html doc/altos.pdf doc/telemetrum-outline.pdf -doc/megametrum-outline.pdf +doc/telemega-outline.pdf diff --git a/doc/altos.xsl b/doc/altos.xsl index c301adde..5af94725 100644 --- a/doc/altos.xsl +++ b/doc/altos.xsl @@ -50,7 +50,7 @@ STM32L series from ST Microelectronics. This ARM Cortex-M3 based microcontroller offers low power consumption and a wide variety of built-in peripherals. Altus Metrum uses - this in the MegaMetrum, MegaDongle and TeleLCO projects. + this in the TeleMega, MegaDongle and TeleLCO projects. diff --git a/doc/megametrum-outline.pdf b/doc/megametrum-outline.pdf deleted file mode 100644 index f8fc26e2..00000000 Binary files a/doc/megametrum-outline.pdf and /dev/null differ diff --git a/doc/megametrum-outline.svg b/doc/megametrum-outline.svg deleted file mode 100644 index e8d74d38..00000000 --- a/doc/megametrum-outline.svg +++ /dev/null @@ -1,244 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - image/svg+xml - - - - - - - - - - - - - - - - - - - - - - - - - - - - - UP - - diff --git a/doc/release-notes-1.2.xsl b/doc/release-notes-1.2.xsl index 610fa1a2..b254c7b5 100644 --- a/doc/release-notes-1.2.xsl +++ b/doc/release-notes-1.2.xsl @@ -41,7 +41,7 @@ raised, breaking the Descent tab contents. - Add preliminary MegaMetrum support, including configuration, + Add preliminary TeleMega support, including configuration, data download and analysis. diff --git a/src/Makefile b/src/Makefile index d91a235a..e271ddf3 100644 --- a/src/Makefile +++ b/src/Makefile @@ -29,7 +29,7 @@ AVRDIRS=\ telescience-v0.1 telescience-pwm telepyro-v0.1 micropeak ARMDIRS=\ - megametrum-v0.1 megadongle-v0.1 stm-bringup stm-demo telelco-v0.1 \ + telemega-v0.1 megadongle-v0.1 stm-bringup stm-demo telelco-v0.1 \ telescience-v0.2 ifneq ($(shell which sdcc),) diff --git a/src/core/ao_fec_rx.c b/src/core/ao_fec_rx.c index 072a9e90..c4f5559a 100644 --- a/src/core/ao_fec_rx.c +++ b/src/core/ao_fec_rx.c @@ -18,7 +18,7 @@ #include #include -#ifdef MEGAMETRUM +#ifdef TELEMEGA #include #endif diff --git a/src/core/ao_log.h b/src/core/ao_log.h index cac78771..a68a40dd 100644 --- a/src/core/ao_log.h +++ b/src/core/ao_log.h @@ -43,7 +43,7 @@ extern __pdata enum ao_flight_state ao_log_state; #define AO_LOG_FORMAT_TINY 2 /* two byte state/baro records */ #define AO_LOG_FORMAT_TELEMETRY 3 /* 32 byte ao_telemetry records */ #define AO_LOG_FORMAT_TELESCIENCE 4 /* 32 byte typed telescience records */ -#define AO_LOG_FORMAT_MEGAMETRUM 5 /* 32 byte typed megametrum records */ +#define AO_LOG_FORMAT_TELEMEGA 5 /* 32 byte typed telemega records */ #define AO_LOG_FORMAT_NONE 127 /* No log at all */ extern __code uint8_t ao_log_format; diff --git a/src/core/ao_log_mega.c b/src/core/ao_log_mega.c index ba3f7bfc..abf953a6 100644 --- a/src/core/ao_log_mega.c +++ b/src/core/ao_log_mega.c @@ -23,7 +23,7 @@ static __xdata uint8_t ao_log_mutex; static __xdata struct ao_log_mega log; -__code uint8_t ao_log_format = AO_LOG_FORMAT_MEGAMETRUM; +__code uint8_t ao_log_format = AO_LOG_FORMAT_TELEMEGA; static uint8_t ao_log_csum(__xdata uint8_t *b) __reentrant diff --git a/src/core/ao_telemetry.c b/src/core/ao_telemetry.c index 3aa315c7..03aa48d8 100644 --- a/src/core/ao_telemetry.c +++ b/src/core/ao_telemetry.c @@ -29,7 +29,7 @@ static __pdata uint16_t ao_aprs_time; #include #endif -#if defined(MEGAMETRUM) +#if defined(TELEMEGA) #define AO_SEND_MEGA 1 #endif diff --git a/src/drivers/ao_companion.c b/src/drivers/ao_companion.c index 0ebe8429..0f405253 100644 --- a/src/drivers/ao_companion.c +++ b/src/drivers/ao_companion.c @@ -18,7 +18,7 @@ #include #include -#ifdef MEGAMETRUM +#ifdef TELEMEGA #define ao_spi_slow(b) #define ao_spi_fast(b) #endif diff --git a/src/megametrum-v0.1/.gitignore b/src/megametrum-v0.1/.gitignore deleted file mode 100644 index b04d3950..00000000 --- a/src/megametrum-v0.1/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -ao_product.h -megametrum-*.elf diff --git a/src/megametrum-v0.1/Makefile b/src/megametrum-v0.1/Makefile deleted file mode 100644 index a5fdcbb2..00000000 --- a/src/megametrum-v0.1/Makefile +++ /dev/null @@ -1,131 +0,0 @@ -# -# AltOS build -# -# - -include ../stm/Makefile.defs - -INC = \ - ao.h \ - ao_arch.h \ - ao_arch_funcs.h \ - ao_companion.h \ - ao_data.h \ - ao_sample.h \ - ao_pins.h \ - altitude-pa.h \ - ao_kalman.h \ - ao_product.h \ - ao_ms5607.h \ - ao_hmc5883.h \ - ao_mpu6000.h \ - ao_mma655x.h \ - ao_cc1120_CC1120.h \ - ao_profile.h \ - ao_task.h \ - ao_whiten.h \ - ao_sample_profile.h \ - ao_mpu.h \ - stm32l.h \ - Makefile - -# -# Common AltOS sources -# -# ao_hmc5883.c - -#PROFILE=ao_profile.c -#PROFILE_DEF=-DAO_PROFILE=1 - -#SAMPLE_PROFILE=ao_sample_profile.c \ -# ao_sample_profile_timer.c -#SAMPLE_PROFILE_DEF=-DHAS_SAMPLE_PROFILE=1 - -#STACK_GUARD=ao_mpu_stm.c -#STACK_GUARD_DEF=-DHAS_STACK_GUARD=1 - -ALTOS_SRC = \ - 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_serial_stm.c \ - ao_gps_skytraq.c \ - ao_gps_report_mega.c \ - ao_ignite.c \ - ao_freq.c \ - ao_dma_stm.c \ - ao_spi_stm.c \ - ao_cc1120.c \ - ao_fec_tx.c \ - ao_fec_rx.c \ - ao_data.c \ - ao_ms5607.c \ - ao_mma655x.c \ - ao_hmc5883.c \ - ao_adc_stm.c \ - ao_beep_stm.c \ - ao_storage.c \ - ao_m25.c \ - ao_usb_stm.c \ - ao_exti_stm.c \ - ao_report.c \ - ao_i2c_stm.c \ - ao_mpu6000.c \ - ao_convert_pa.c \ - ao_log.c \ - ao_log_mega.c \ - ao_sample.c \ - ao_kalman.c \ - ao_flight.c \ - ao_telemetry.c \ - ao_packet_slave.c \ - ao_packet.c \ - ao_companion.c \ - ao_pyro.c \ - ao_aprs.c \ - $(PROFILE) \ - $(SAMPLE_PROFILE) \ - $(STACK_GUARD) - -PRODUCT=MegaMetrum-v0.1 -PRODUCT_DEF=-DMEGAMETRUM -IDPRODUCT=0x0023 - -CFLAGS = $(PRODUCT_DEF) $(STM_CFLAGS) $(PROFILE_DEF) $(SAMPLE_PROFILE_DEF) $(STACK_GUARD_DEF) -Os -g - -PROGNAME=megametrum-v0.1 -PROG=$(PROGNAME)-$(VERSION).elf - -SRC=$(ALTOS_SRC) ao_megametrum.c -OBJ=$(SRC:.c=.o) - -all: $(PROG) - -$(PROG): Makefile $(OBJ) altos.ld - $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(OBJ) $(SAT_CLIB) -lgcc - -../altitude-pa.h: make-altitude-pa - nickle $< > $@ - -$(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 - rm -f ao_product.h - -install: - -uninstall: diff --git a/src/megametrum-v0.1/ao_megametrum.c b/src/megametrum-v0.1/ao_megametrum.c deleted file mode 100644 index fbdab64a..00000000 --- a/src/megametrum-v0.1/ao_megametrum.c +++ /dev/null @@ -1,100 +0,0 @@ -/* - * Copyright © 2011 Keith Packard - * - * 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 -#include -#include -#include -#include -#include -#include -#include -#include -#if HAS_SAMPLE_PROFILE -#include -#endif -#include -#if HAS_STACK_GUARD -#include -#endif - -int -main(void) -{ - ao_clock_init(); - -#if HAS_STACK_GUARD - ao_mpu_init(); -#endif - - ao_task_init(); - ao_serial_init(); - ao_led_init(LEDS_AVAILABLE); - ao_led_on(AO_LED_GREEN); - ao_timer_init(); - - ao_i2c_init(); - ao_spi_init(); - ao_dma_init(); - ao_exti_init(); - - ao_adc_init(); -#if HAS_BEEP - ao_beep_init(); -#endif - ao_cmd_init(); - -#if HAS_MS5607 - ao_ms5607_init(); -#endif -#if HAS_HMC5883 - ao_hmc5883_init(); -#endif -#if HAS_MPU6000 - ao_mpu6000_init(); -#endif -#if HAS_MMA655X - ao_mma655x_init(); -#endif - - ao_storage_init(); - - ao_flight_init(); - ao_log_init(); - ao_report_init(); - - ao_usb_init(); - ao_gps_init(); - ao_gps_report_mega_init(); - ao_telemetry_init(); - ao_radio_init(); - ao_packet_slave_init(FALSE); - ao_igniter_init(); - ao_companion_init(); - ao_pyro_init(); - - ao_config_init(); -#if AO_PROFILE - ao_profile_init(); -#endif -#if HAS_SAMPLE_PROFILE - ao_sample_profile_init(); -#endif - - ao_start_scheduler(); - return 0; -} diff --git a/src/megametrum-v0.1/ao_pins.h b/src/megametrum-v0.1/ao_pins.h deleted file mode 100644 index 4c645871..00000000 --- a/src/megametrum-v0.1/ao_pins.h +++ /dev/null @@ -1,359 +0,0 @@ -/* - * Copyright © 2012 Keith Packard - * - * 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_TASK_QUEUE 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) - -/* 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_SERIAL_1 1 -#define USE_SERIAL_1_STDIN 0 -#define SERIAL_1_PB6_PB7 0 -#define SERIAL_1_PA9_PA10 1 - -#define HAS_SERIAL_2 0 -#define USE_SERIAL_2_STDIN 0 -#define SERIAL_2_PA2_PA3 0 -#define SERIAL_2_PD5_PD6 0 - -#define HAS_SERIAL_3 1 -#define USE_SERIAL_3_STDIN 0 -#define SERIAL_3_PB10_PB11 0 -#define SERIAL_3_PC10_PC11 1 -#define SERIAL_3_PD8_PD9 0 - -#define ao_gps_getchar ao_serial3_getchar -#define ao_gps_putchar ao_serial3_putchar -#define ao_gps_set_speed ao_serial3_set_speed -#define ao_gps_fifo (ao_stm_usart3.rx_fifo) - -#define HAS_EEPROM 1 -#define USE_INTERNAL_FLASH 0 -#define HAS_USB 1 -#define HAS_BEEP 1 -#define HAS_RADIO 1 -#define HAS_TELEMETRY 1 -#define HAS_APRS 1 - -#define HAS_SPI_1 1 -#define SPI_1_PA5_PA6_PA7 1 /* Barometer */ -#define SPI_1_PB3_PB4_PB5 0 -#define SPI_1_PE13_PE14_PE15 1 /* Accelerometer */ -#define SPI_1_OSPEEDR STM_OSPEEDR_10MHz - -#define HAS_SPI_2 1 -#define SPI_2_PB13_PB14_PB15 1 /* Flash, Companion */ -#define SPI_2_PD1_PD3_PD4 0 -#define SPI_2_OSPEEDR STM_OSPEEDR_10MHz - -#define SPI_2_PORT (&stm_gpiob) -#define SPI_2_SCK_PIN 13 -#define SPI_2_MISO_PIN 14 -#define SPI_2_MOSI_PIN 15 - -#define HAS_I2C_1 1 -#define I2C_1_PB8_PB9 1 - -#define HAS_I2C_2 1 -#define I2C_2_PB10_PB11 1 - -#define PACKET_HAS_SLAVE 1 -#define PACKET_HAS_MASTER 0 - -#define LOW_LEVEL_DEBUG 0 - -#define LED_PORT_ENABLE STM_RCC_AHBENR_GPIOCEN -#define LED_PORT (&stm_gpioc) -#define LED_PIN_RED 8 -#define LED_PIN_GREEN 9 -#define AO_LED_RED (1 << LED_PIN_RED) -#define AO_LED_GREEN (1 << LED_PIN_GREEN) - -#define LEDS_AVAILABLE (AO_LED_RED | AO_LED_GREEN) - -#define HAS_GPS 1 -#define HAS_FLIGHT 1 -#define HAS_ADC 1 -#define HAS_LOG 1 - -/* - * Igniter - */ - -#define HAS_IGNITE 1 -#define HAS_IGNITE_REPORT 1 - -#define AO_SENSE_DROGUE(p) ((p)->adc.sense[0]) -#define AO_SENSE_MAIN(p) ((p)->adc.sense[1]) -#define AO_IGNITER_CLOSED 400 -#define AO_IGNITER_OPEN 60 - -#define AO_IGNITER_DROGUE_PORT (&stm_gpiod) -#define AO_IGNITER_DROGUE_PIN 6 - -#define AO_IGNITER_MAIN_PORT (&stm_gpiod) -#define AO_IGNITER_MAIN_PIN 7 - -#define AO_PYRO_PORT_0 (&stm_gpiob) -#define AO_PYRO_PIN_0 5 - -#define AO_PYRO_PORT_1 (&stm_gpioe) -#define AO_PYRO_PIN_1 4 - -#define AO_PYRO_PORT_2 (&stm_gpioe) -#define AO_PYRO_PIN_2 6 - -#define AO_PYRO_PORT_3 (&stm_gpioe) -#define AO_PYRO_PIN_3 5 - -/* Number of general purpose pyro channels available */ -#define AO_PYRO_NUM 4 - -#define AO_IGNITER_SET_DROGUE(v) stm_gpio_set(AO_IGNITER_DROGUE_PORT, AO_IGNITER_DROGUE_PIN, v) -#define AO_IGNITER_SET_MAIN(v) stm_gpio_set(AO_IGNITER_MAIN_PORT, AO_IGNITER_MAIN_PIN, v) - -/* - * ADC - */ -#define AO_DATA_RING 32 -#define AO_ADC_NUM_SENSE 6 - -struct ao_adc { - int16_t sense[AO_ADC_NUM_SENSE]; - int16_t v_batt; - int16_t v_pbatt; - int16_t accel_ref; - int16_t accel; - int16_t temp; -}; - -#define AO_ADC_SENSE_A 0 -#define AO_ADC_SENSE_A_PORT (&stm_gpioa) -#define AO_ADC_SENSE_A_PIN 0 - -#define AO_ADC_SENSE_B 1 -#define AO_ADC_SENSE_B_PORT (&stm_gpioa) -#define AO_ADC_SENSE_B_PIN 1 - -#define AO_ADC_SENSE_C 2 -#define AO_ADC_SENSE_C_PORT (&stm_gpioa) -#define AO_ADC_SENSE_C_PIN 2 - -#define AO_ADC_SENSE_D 3 -#define AO_ADC_SENSE_D_PORT (&stm_gpioa) -#define AO_ADC_SENSE_D_PIN 3 - -#define AO_ADC_SENSE_E 4 -#define AO_ADC_SENSE_E_PORT (&stm_gpioa) -#define AO_ADC_SENSE_E_PIN 4 - -#define AO_ADC_SENSE_F 22 -#define AO_ADC_SENSE_F_PORT (&stm_gpioe) -#define AO_ADC_SENSE_F_PIN 7 - -#define AO_ADC_V_BATT 8 -#define AO_ADC_V_BATT_PORT (&stm_gpiob) -#define AO_ADC_V_BATT_PIN 0 - -#define AO_ADC_V_PBATT 9 -#define AO_ADC_V_PBATT_PORT (&stm_gpiob) -#define AO_ADC_V_PBATT_PIN 1 - -#define AO_ADC_ACCEL_REF 10 -#define AO_ADC_ACCEL_REF_PORT (&stm_gpioc) -#define AO_ADC_ACCEL_REF_PIN 0 - -#define AO_ADC_ACCEL 11 -#define AO_ADC_ACCEL_PORT (&stm_gpioc) -#define AO_ADC_ACCEL_PIN 1 - -#define AO_ADC_TEMP 16 - -#define AO_ADC_RCC_AHBENR ((1 << STM_RCC_AHBENR_GPIOAEN) | \ - (1 << STM_RCC_AHBENR_GPIOEEN) | \ - (1 << STM_RCC_AHBENR_GPIOBEN) | \ - (1 << STM_RCC_AHBENR_GPIOCEN)) - -#define AO_NUM_ADC_PIN (AO_ADC_NUM_SENSE + 4) - -#define AO_ADC_PIN0_PORT AO_ADC_SENSE_A_PORT -#define AO_ADC_PIN0_PIN AO_ADC_SENSE_A_PIN -#define AO_ADC_PIN1_PORT AO_ADC_SENSE_B_PORT -#define AO_ADC_PIN1_PIN AO_ADC_SENSE_B_PIN -#define AO_ADC_PIN2_PORT AO_ADC_SENSE_C_PORT -#define AO_ADC_PIN2_PIN AO_ADC_SENSE_C_PIN -#define AO_ADC_PIN3_PORT AO_ADC_SENSE_D_PORT -#define AO_ADC_PIN3_PIN AO_ADC_SENSE_D_PIN -#define AO_ADC_PIN4_PORT AO_ADC_SENSE_E_PORT -#define AO_ADC_PIN4_PIN AO_ADC_SENSE_E_PIN -#define AO_ADC_PIN5_PORT AO_ADC_SENSE_F_PORT -#define AO_ADC_PIN5_PIN AO_ADC_SENSE_F_PIN -#define AO_ADC_PIN6_PORT AO_ADC_V_BATT_PORT -#define AO_ADC_PIN6_PIN AO_ADC_V_BATT_PIN -#define AO_ADC_PIN7_PORT AO_ADC_V_PBATT_PORT -#define AO_ADC_PIN7_PIN AO_ADC_V_PBATT_PIN -#define AO_ADC_PIN8_PORT AO_ADC_ACCEL_REF_PORT -#define AO_ADC_PIN8_PIN AO_ADC_ACCEL_REF_PIN -#define AO_ADC_PIN9_PORT AO_ADC_ACCEL_PORT -#define AO_ADC_PIN9_PIN AO_ADC_ACCEL_PIN - -#define AO_NUM_ADC (AO_ADC_NUM_SENSE + 5) - -#define AO_ADC_SQ1 AO_ADC_SENSE_A -#define AO_ADC_SQ2 AO_ADC_SENSE_B -#define AO_ADC_SQ3 AO_ADC_SENSE_C -#define AO_ADC_SQ4 AO_ADC_SENSE_D -#define AO_ADC_SQ5 AO_ADC_SENSE_E -#define AO_ADC_SQ6 AO_ADC_SENSE_F -#define AO_ADC_SQ7 AO_ADC_V_BATT -#define AO_ADC_SQ8 AO_ADC_V_PBATT -#define AO_ADC_SQ9 AO_ADC_ACCEL_REF -#define AO_ADC_SQ10 AO_ADC_ACCEL -#define AO_ADC_SQ11 AO_ADC_TEMP - -/* - * Pressure sensor settings - */ -#define HAS_MS5607 1 -#define HAS_MS5611 0 -#define AO_MS5607_PRIVATE_PINS 1 -#define AO_MS5607_CS_PORT (&stm_gpioc) -#define AO_MS5607_CS_PIN 4 -#define AO_MS5607_CS_MASK (1 << AO_MS5607_CS) -#define AO_MS5607_MISO_PORT (&stm_gpioa) -#define AO_MS5607_MISO_PIN 6 -#define AO_MS5607_MISO_MASK (1 << AO_MS5607_MISO) -#define AO_MS5607_SPI_INDEX AO_SPI_1_PA5_PA6_PA7 - -/* - * SPI Flash memory - */ - -#define M25_MAX_CHIPS 1 -#define AO_M25_SPI_CS_PORT (&stm_gpiod) -#define AO_M25_SPI_CS_MASK (1 << 3) -#define AO_M25_SPI_BUS AO_SPI_2_PB13_PB14_PB15 - -/* - * Radio (cc1120) - */ - -/* gets pretty close to 434.550 */ - -#define AO_RADIO_CAL_DEFAULT 0x6ca333 - -#define AO_FEC_DEBUG 0 -#define AO_CC1120_SPI_CS_PORT (&stm_gpioc) -#define AO_CC1120_SPI_CS_PIN 5 -#define AO_CC1120_SPI_BUS AO_SPI_2_PB13_PB14_PB15 -#define AO_CC1120_SPI stm_spi2 - -#define AO_CC1120_INT_PORT (&stm_gpioc) -#define AO_CC1120_INT_PIN 14 -#define AO_CC1120_MCU_WAKEUP_PORT (&stm_gpioc) -#define AO_CC1120_MCU_WAKEUP_PIN (0) - -#define AO_CC1120_INT_GPIO 2 -#define AO_CC1120_INT_GPIO_IOCFG CC1120_IOCFG2 - -#define AO_CC1120_MARC_GPIO 3 -#define AO_CC1120_MARC_GPIO_IOCFG CC1120_IOCFG3 - - -#define HAS_BOOT_RADIO 0 - -/* - * Mag sensor (hmc5883) - */ - -#define HAS_HMC5883 0 -#define AO_HMC5883_INT_PORT (&stm_gpioc) -#define AO_HMC5883_INT_PIN 12 -#define AO_HMC5883_I2C_INDEX STM_I2C_INDEX(1) - -/* - * mpu6000 - */ - -#define HAS_MPU6000 1 -#define AO_MPU6000_INT_PORT (&stm_gpioc) -#define AO_MPU6000_INT_PIN 13 -#define AO_MPU6000_I2C_INDEX STM_I2C_INDEX(1) - -#define HAS_HIGHG_ACCEL 0 - -/* - * mma655x - */ - -#define HAS_MMA655X 1 -#define AO_MMA655X_SPI_INDEX AO_SPI_1_PE13_PE14_PE15 -#define AO_MMA655X_CS_PORT (&stm_gpiod) -#define AO_MMA655X_CS_PIN 4 - -#define NUM_CMDS 16 - -/* - * Companion - */ - -#define AO_COMPANION_CS_PORT (&stm_gpiod) -#define AO_COMPANION_CS_PIN (0) -#define AO_COMPANION_SPI_BUS AO_SPI_2_PB13_PB14_PB15 - -/* - * Monitor - */ - -#define HAS_MONITOR 0 -#define LEGACY_MONITOR 0 -#define HAS_MONITOR_PUT 1 -#define AO_MONITOR_LED 0 -#define HAS_RSSI 0 - -/* - * Profiling Viterbi decoding - */ - -#ifndef AO_PROFILE -#define AO_PROFILE 0 -#endif - -#endif /* _AO_PINS_H_ */ diff --git a/src/megametrum-v0.1/stlink-pins b/src/megametrum-v0.1/stlink-pins deleted file mode 100644 index 390f8e5d..00000000 --- a/src/megametrum-v0.1/stlink-pins +++ /dev/null @@ -1,57 +0,0 @@ -ST discovery card pins - -1 AIN-1 -2 JTCK -3 GND -4 JTMS -5 NRST -6 SWO - -MegaMetrum v0.1 misc connector - -1 GND -2 reset_n -3 boot0 -4 tx1 -5 rx1 -6 +3.3V -7 GND -8 jtms -9 jtck -10 jtdi -11 jtdo -12 jntrst -13 sda2 -14 scl2 -15 pe1 -16 pe0 - -For debugging: - - ST MM v0.1 -JTCK 2 9 -GND 3 7 -JTMS 4 8 -NRST 5 2 - -Altus Metrum STM32L standard debug connector (4 pin MicoMaTch): - - TL ST -GND 1 3 -NRST 2 5 -SWDIO 3 4 -SWCLK 4 2 - -Altus Metrum standard 4-pin connector to MegaMetrum v0.1 misc connector: - - AMstd MM v0.1 -gnd 1 1 -nrst 2 2 -swdio 3 8 -swclk 4 9 - -MegaAccel: - -Jumpers -PC0 (pin15) (blue) PE0 (pin97) accel_ref (debug 16) -PC1 (pin16) (green) PE1 (pin98) accel (debug 15) diff --git a/src/stm/ao_i2c_stm.c b/src/stm/ao_i2c_stm.c index 779e2275..809b5c6f 100644 --- a/src/stm/ao_i2c_stm.c +++ b/src/stm/ao_i2c_stm.c @@ -36,7 +36,7 @@ static uint16_t ao_i2c_addr[STM_NUM_I2C]; uint8_t ao_i2c_mutex[STM_NUM_I2C]; # define I2C_HIGH_SLOW 5000 /* ns, 100kHz clock */ -#ifdef MEGAMETRUM +#ifdef TELEMEGA # define I2C_HIGH_FAST 2000 /* ns, 167kHz clock */ #else # define I2C_HIGH_FAST 1000 /* ns, 333kHz clock */ diff --git a/src/telelco-v0.1/Makefile b/src/telelco-v0.1/Makefile index d2702dd6..a4a83d02 100644 --- a/src/telelco-v0.1/Makefile +++ b/src/telelco-v0.1/Makefile @@ -61,7 +61,7 @@ ALTOS_SRC = \ ao_radio_cmac_cmd.c PRODUCT=TeleLCO-v0.1 -PRODUCT_DEF=-DMEGAMETRUM +PRODUCT_DEF=-DTELEMEGA IDPRODUCT=0x0023 CFLAGS = $(PRODUCT_DEF) $(STM_CFLAGS) $(PROFILE_DEF) -Os -g diff --git a/src/test/Makefile b/src/test/Makefile index 991bdbfc..a62b59c5 100644 --- a/src/test/Makefile +++ b/src/test/Makefile @@ -30,7 +30,7 @@ ao_flight_test_accel: ao_flight_test.c ao_host.h ao_flight.c ao_sample.c ao_kal cc $(CFLAGS) -o $@ -DFORCE_ACCEL=1 ao_flight_test.c ao_flight_test_mm: ao_flight_test.c ao_host.h ao_flight.c ao_sample.c ao_kalman.c $(INCS) - cc -DMEGAMETRUM=1 $(CFLAGS) -o $@ $< -lm + cc -DTELEMEGA=1 $(CFLAGS) -o $@ $< -lm ao_gps_test: ao_gps_test.c ao_gps_sirf.c ao_gps_print.c ao_host.h cc $(CFLAGS) -o $@ $< diff --git a/src/test/ao_flight_test.c b/src/test/ao_flight_test.c index cdd1f236..99bed7ee 100644 --- a/src/test/ao_flight_test.c +++ b/src/test/ao_flight_test.c @@ -35,7 +35,7 @@ #define AO_MS_TO_SPEED(ms) ((int16_t) ((ms) * 16)) #define AO_MSS_TO_ACCEL(mss) ((int16_t) ((mss) * 16)) -#if MEGAMETRUM +#if TELEMEGA #define AO_ADC_NUM_SENSE 6 #define HAS_MS5607 1 #define HAS_MPU6000 1 @@ -195,7 +195,7 @@ struct ao_cmds { #define ao_xmemcmp(d,s,c) memcmp(d,s,c) #define AO_NEED_ALTITUDE_TO_PRES 1 -#if MEGAMETRUM +#if TELEMEGA #include "ao_convert_pa.c" #include struct ao_ms5607_prom ms5607_prom; @@ -333,7 +333,7 @@ ao_insert(void) #else double accel = 0.0; #endif -#if MEGAMETRUM +#if TELEMEGA double height; ao_ms5607_convert(&ao_data_static.ms5607_raw, &ao_data_static.ms5607_cooked); @@ -373,7 +373,7 @@ ao_insert(void) if (!ao_summary) { printf("%7.2f height %8.2f accel %8.3f " -#if MEGAMETRUM +#if TELEMEGA "roll %8.3f angle %8.3f qangle %8.3f " "accel_x %8.3f accel_y %8.3f accel_z %8.3f gyro_x %8.3f gyro_y %8.3f gyro_z %8.3f " #endif @@ -381,7 +381,7 @@ ao_insert(void) time, height, accel, -#if MEGAMETRUM +#if TELEMEGA ao_mpu6000_gyro(ao_sample_roll_angle) / 100.0, ao_mpu6000_gyro(ao_sample_angle) / 100.0, ao_sample_qangle, @@ -555,7 +555,7 @@ int32(uint8_t *bytes, int off) static int log_format; -#if MEGAMETRUM +#if TELEMEGA static double ao_vec_norm(double x, double y, double z) @@ -774,7 +774,7 @@ ao_sleep(void *wchan) for (;;) { if (ao_records_read > 2 && ao_flight_state == ao_flight_startup) { -#if MEGAMETRUM +#if TELEMEGA ao_data_static.mpu6000 = ao_ground_mpu6000; #else ao_data_static.adc.accel = ao_flight_ground_accel; @@ -800,8 +800,8 @@ ao_sleep(void *wchan) if (words[nword] == NULL) break; } -#if MEGAMETRUM - if (log_format == AO_LOG_FORMAT_MEGAMETRUM && nword == 30 && strlen(words[0]) == 1) { +#if TELEMEGA + if (log_format == AO_LOG_FORMAT_TELEMEGA && nword == 30 && strlen(words[0]) == 1) { int i; struct ao_ms5607_value value; @@ -885,7 +885,7 @@ ao_sleep(void *wchan) continue; } #else - if (nword == 4 && log_format != AO_LOG_FORMAT_MEGAMETRUM) { + if (nword == 4 && log_format != AO_LOG_FORMAT_TELEMEGA) { type = words[0][0]; tick = strtoul(words[1], NULL, 16); a = strtoul(words[2], NULL, 16); @@ -1002,7 +1002,7 @@ ao_sleep(void *wchan) if (type != 'F' && !ao_flight_started) continue; -#if MEGAMETRUM +#if TELEMEGA (void) a; (void) b; #else diff --git a/telemetrum.inf b/telemetrum.inf index 91416bca..386dd286 100755 --- a/telemetrum.inf +++ b/telemetrum.inf @@ -30,7 +30,7 @@ DefaultDestDir = 12 %TeleScience% = AltusMetrum.Install, USB\VID_FFFE&PID_0011, AltusMetrumSerial %TelePyro% = AltusMetrum.Install, USB\VID_FFFE&PID_0012, AltusMetrumSerial %TeleShield% = AltusMetrum.Install, USB\VID_FFFE&PID_0013, AltusMetrumSerial -%MegaMetrum% = AltusMetrum.Install, USB\VID_FFFE&PID_0023, AltusMetrumSerial +%TeleMega% = AltusMetrum.Install, USB\VID_FFFE&PID_0023, AltusMetrumSerial %MegaDongle = AltusMetrum.Install, USB\VID_FFFE&PID_0024, AltusMetrumSerial %TeleGPS% = AltusMetrum.Install, USB\VID_FFFE&PID_0025, AltusMetrumSerial %AltusMetrum26% = AltusMetrum.Install, USB\VID_FFFE&PID_0026, AltusMetrumSerial @@ -52,7 +52,7 @@ DefaultDestDir = 12 %TeleScience% = AltusMetrum.Install, USB\VID_FFFE&PID_0011, AltusMetrumSerial %TelePyro% = AltusMetrum.Install, USB\VID_FFFE&PID_0012, AltusMetrumSerial %TeleShield% = AltusMetrum.Install, USB\VID_FFFE&PID_0013, AltusMetrumSerial -%MegaMetrum% = AltusMetrum.Install, USB\VID_FFFE&PID_0023, AltusMetrumSerial +%TeleMega% = AltusMetrum.Install, USB\VID_FFFE&PID_0023, AltusMetrumSerial %MegaDongle = AltusMetrum.Install, USB\VID_FFFE&PID_0024, AltusMetrumSerial %TeleGPS% = AltusMetrum.Install, USB\VID_FFFE&PID_0025, AltusMetrumSerial %AltusMetrum26% = AltusMetrum.Install, USB\VID_FFFE&PID_0026, AltusMetrumSerial @@ -74,7 +74,7 @@ DefaultDestDir = 12 %TeleScience% = AltusMetrum.Install, USB\VID_FFFE&PID_0011, AltusMetrumSerial %TelePyro% = AltusMetrum.Install, USB\VID_FFFE&PID_0012, AltusMetrumSerial %TeleShield% = AltusMetrum.Install, USB\VID_FFFE&PID_0013, AltusMetrumSerial -%MegaMetrum% = AltusMetrum.Install, USB\VID_FFFE&PID_0023, AltusMetrumSerial +%TeleMega% = AltusMetrum.Install, USB\VID_FFFE&PID_0023, AltusMetrumSerial %MegaDongle = AltusMetrum.Install, USB\VID_FFFE&PID_0024, AltusMetrumSerial %TeleGPS% = AltusMetrum.Install, USB\VID_FFFE&PID_0025, AltusMetrumSerial %AltusMetrum26% = AltusMetrum.Install, USB\VID_FFFE&PID_0026, AltusMetrumSerial @@ -96,7 +96,7 @@ DefaultDestDir = 12 %TeleScience% = AltusMetrum.Install, USB\VID_FFFE&PID_0011, AltusMetrumSerial %TelePyro% = AltusMetrum.Install, USB\VID_FFFE&PID_0012, AltusMetrumSerial %TeleShield% = AltusMetrum.Install, USB\VID_FFFE&PID_0013, AltusMetrumSerial -%MegaMetrum% = AltusMetrum.Install, USB\VID_FFFE&PID_0023, AltusMetrumSerial +%TeleMega% = AltusMetrum.Install, USB\VID_FFFE&PID_0023, AltusMetrumSerial %MegaDongle = AltusMetrum.Install, USB\VID_FFFE&PID_0024, AltusMetrumSerial %TeleGPS% = AltusMetrum.Install, USB\VID_FFFE&PID_0025, AltusMetrumSerial %AltusMetrum26% = AltusMetrum.Install, USB\VID_FFFE&PID_0026, AltusMetrumSerial -- cgit v1.2.3 From 3cbec0292d5167bce5c23eeea95f7a2d13bccc79 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 24 Mar 2013 15:20:09 -0700 Subject: altos/stm: Always declare all romconfig variables I haven't figured out how to assign addresses for specific initialized variables, so we'll just have to always declare all of them and make sure that we add new ones at the end. Signed-off-by: Keith Packard --- src/stm/ao_romconfig.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'src/stm') diff --git a/src/stm/ao_romconfig.c b/src/stm/ao_romconfig.c index cbb922ec..5da15072 100644 --- a/src/stm/ao_romconfig.c +++ b/src/stm/ao_romconfig.c @@ -20,6 +20,8 @@ AO_ROMCONFIG_SYMBOL (0) uint16_t ao_romconfig_version = AO_ROMCONFIG_VERSION; AO_ROMCONFIG_SYMBOL (0) uint16_t ao_romconfig_check = ~AO_ROMCONFIG_VERSION; AO_ROMCONFIG_SYMBOL (0) uint16_t ao_serial_number = 0; -#ifdef AO_RADIO_CAL_DEFAULT -AO_ROMCONFIG_SYMBOL (0) uint32_t ao_radio_cal = AO_RADIO_CAL_DEFAULT; +#ifndef AO_RADIO_CAL_DEFAULT +#define AO_RADIO_CAL_DEFAULT 0x01020304 #endif +AO_ROMCONFIG_SYMBOL (0) uint32_t ao_radio_cal = AO_RADIO_CAL_DEFAULT; + -- cgit v1.2.3 From 168188f6650dc9a777d57f9c7a8ff1be957bc892 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 22 Apr 2013 20:23:48 -0500 Subject: altos/stm: Remove USB EP0 task Handl EP0 actions from interrupt handler. This allows USB to be used in a taskless environment, like the STM flash loader Signed-off-by: Keith Packard --- src/stm/ao_usb_stm.c | 223 ++++++++++++++++++++++++--------------------------- 1 file changed, 104 insertions(+), 119 deletions(-) (limited to 'src/stm') diff --git a/src/stm/ao_usb_stm.c b/src/stm/ao_usb_stm.c index e29abc87..e484cd22 100644 --- a/src/stm/ao_usb_stm.c +++ b/src/stm/ao_usb_stm.c @@ -35,8 +35,6 @@ #define debug_data(format, args...) #endif -struct ao_task ao_usb_task; - struct ao_usb_setup { uint8_t dir_type_recip; uint8_t request; @@ -398,81 +396,6 @@ static uint16_t in_count; static uint16_t out_count; static uint16_t reset_count; -void -stm_usb_lp_isr(void) -{ - uint32_t istr = stm_usb.istr; - - if (istr & (1 << STM_USB_ISTR_CTR)) { - uint8_t ep = istr & STM_USB_ISTR_EP_ID_MASK; - uint32_t epr, epr_write; - - /* Preserve the SW write bits, don't mess with most HW writable bits, - * clear the CTR_RX and CTR_TX bits - */ - epr = stm_usb.epr[ep]; - epr_write = epr; - epr_write &= STM_USB_EPR_PRESERVE_MASK; - epr_write |= STM_USB_EPR_INVARIANT; - epr_write &= ~(1 << STM_USB_EPR_CTR_RX); - epr_write &= ~(1 << STM_USB_EPR_CTR_TX); - stm_usb.epr[ep] = epr_write; - - switch (ep) { - case 0: - ++control_count; - if (ao_usb_epr_ctr_rx(epr)) { - if (ao_usb_epr_setup(epr)) - ao_usb_ep0_receive |= AO_USB_EP0_GOT_SETUP; - else - ao_usb_ep0_receive |= AO_USB_EP0_GOT_RX_DATA; - } - if (ao_usb_epr_ctr_tx(epr)) - ao_usb_ep0_receive |= AO_USB_EP0_GOT_TX_ACK; - ao_wakeup(&ao_usb_ep0_receive); - break; - case AO_USB_OUT_EPR: - ++out_count; - if (ao_usb_epr_ctr_rx(epr)) { - _rx_dbg1("RX ISR", epr); - ao_usb_out_avail = 1; - _rx_dbg0("out avail set"); - ao_wakeup(&ao_stdin_ready); - _rx_dbg0("stdin awoken"); - } - break; - case AO_USB_IN_EPR: - ++in_count; - _tx_dbg1("TX ISR", epr); - if (ao_usb_epr_ctr_tx(epr)) { - ao_usb_in_pending = 0; - ao_wakeup(&ao_usb_in_pending); - } - break; - case AO_USB_INT_EPR: - ++int_count; - if (ao_usb_epr_ctr_tx(epr)) - _ao_usb_set_stat_tx(AO_USB_INT_EPR, STM_USB_EPR_STAT_TX_NAK); - break; - } - return; - } - - if (istr & (1 << STM_USB_ISTR_RESET)) { - ++reset_count; - stm_usb.istr &= ~(1 << STM_USB_ISTR_RESET); - ao_usb_ep0_receive |= AO_USB_EP0_GOT_RESET; - ao_wakeup(&ao_usb_ep0_receive); - } -} - -void -stm_usb_fs_wkup(void) -{ - /* USB wakeup, just clear the bit for now */ - stm_usb.istr &= ~(1 << STM_USB_ISTR_WKUP); -} - /* The USB memory holds 16 bit values on 32 bit boundaries * and must be accessed only in 32 bit units. Sigh. */ @@ -772,55 +695,117 @@ ao_usb_ep0_setup(void) ao_usb_ep0_in_start(ao_usb_setup.length); } -/* End point 0 receives all of the control messages. */ static void -ao_usb_ep0(void) +ao_usb_ep0_handle(uint8_t receive) { - uint8_t intx, udint; - - debug ("usb task started\n"); - ao_usb_ep0_state = AO_USB_EP0_IDLE; - for (;;) { - uint8_t receive; - ao_arch_critical( - while (!(receive = ao_usb_ep0_receive)) - ao_sleep(&ao_usb_ep0_receive); - ao_usb_ep0_receive = 0; - ); - - if (receive & AO_USB_EP0_GOT_RESET) { - debug ("\treset\n"); - ao_usb_set_ep0(); - continue; - } - if (receive & AO_USB_EP0_GOT_SETUP) { - debug ("\tsetup\n"); - ao_usb_ep0_setup(); - } - if (receive & AO_USB_EP0_GOT_RX_DATA) { - debug ("\tgot rx data\n"); - if (ao_usb_ep0_state == AO_USB_EP0_DATA_OUT) { - ao_usb_ep0_fill(); - if (ao_usb_ep0_out_len == 0) { - ao_usb_ep0_state = AO_USB_EP0_DATA_IN; - ao_usb_ep0_in_start(0); - } + 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(); + } + if (receive & AO_USB_EP0_GOT_RX_DATA) { + debug ("\tgot rx data\n"); + if (ao_usb_ep0_state == AO_USB_EP0_DATA_OUT) { + ao_usb_ep0_fill(); + if (ao_usb_ep0_out_len == 0) { + ao_usb_ep0_state = AO_USB_EP0_DATA_IN; + ao_usb_ep0_in_start(0); } } - if (receive & AO_USB_EP0_GOT_TX_ACK) { - debug ("\tgot tx ack\n"); - - /* Wait until the IN packet is received from addr 0 - * before assigning our local address - */ - if (ao_usb_address_pending) - ao_usb_set_address(ao_usb_address); - if (ao_usb_ep0_state == AO_USB_EP0_DATA_IN) - ao_usb_ep0_flush(); + } + if (receive & AO_USB_EP0_GOT_TX_ACK) { + debug ("\tgot tx ack\n"); + + /* Wait until the IN packet is received from addr 0 + * before assigning our local address + */ + if (ao_usb_address_pending) + ao_usb_set_address(ao_usb_address); + if (ao_usb_ep0_state == AO_USB_EP0_DATA_IN) + ao_usb_ep0_flush(); + } +} + +void +stm_usb_lp_isr(void) +{ + uint32_t istr = stm_usb.istr; + + if (istr & (1 << STM_USB_ISTR_CTR)) { + uint8_t ep = istr & STM_USB_ISTR_EP_ID_MASK; + uint32_t epr, epr_write; + + /* Preserve the SW write bits, don't mess with most HW writable bits, + * clear the CTR_RX and CTR_TX bits + */ + epr = stm_usb.epr[ep]; + epr_write = epr; + epr_write &= STM_USB_EPR_PRESERVE_MASK; + epr_write |= STM_USB_EPR_INVARIANT; + epr_write &= ~(1 << STM_USB_EPR_CTR_RX); + epr_write &= ~(1 << STM_USB_EPR_CTR_TX); + stm_usb.epr[ep] = epr_write; + + switch (ep) { + case 0: + ++control_count; + if (ao_usb_epr_ctr_rx(epr)) { + if (ao_usb_epr_setup(epr)) + ao_usb_ep0_receive |= AO_USB_EP0_GOT_SETUP; + else + ao_usb_ep0_receive |= AO_USB_EP0_GOT_RX_DATA; + } + if (ao_usb_epr_ctr_tx(epr)) + ao_usb_ep0_receive |= AO_USB_EP0_GOT_TX_ACK; + ao_usb_ep0_handle(ao_usb_ep0_receive); + break; + case AO_USB_OUT_EPR: + ++out_count; + if (ao_usb_epr_ctr_rx(epr)) { + _rx_dbg1("RX ISR", epr); + ao_usb_out_avail = 1; + _rx_dbg0("out avail set"); + ao_wakeup(&ao_stdin_ready); + _rx_dbg0("stdin awoken"); + } + break; + case AO_USB_IN_EPR: + ++in_count; + _tx_dbg1("TX ISR", epr); + if (ao_usb_epr_ctr_tx(epr)) { + ao_usb_in_pending = 0; + ao_wakeup(&ao_usb_in_pending); + } + break; + case AO_USB_INT_EPR: + ++int_count; + if (ao_usb_epr_ctr_tx(epr)) + _ao_usb_set_stat_tx(AO_USB_INT_EPR, STM_USB_EPR_STAT_TX_NAK); + break; } + return; + } + + if (istr & (1 << STM_USB_ISTR_RESET)) { + ++reset_count; + stm_usb.istr &= ~(1 << STM_USB_ISTR_RESET); + ao_usb_ep0_receive |= AO_USB_EP0_GOT_RESET; + ao_usb_ep0_handle(ao_usb_ep0_receive); } } +void +stm_usb_fs_wkup(void) +{ + /* USB wakeup, just clear the bit for now */ + stm_usb.istr &= ~(1 << STM_USB_ISTR_WKUP); +} + /* Queue the current IN buffer for transmission */ static void _ao_usb_in_send(void) @@ -1071,7 +1056,7 @@ ao_usb_init(void) ao_usb_enable(); debug ("ao_usb_init\n"); - ao_add_task(&ao_usb_task, ao_usb_ep0, "usb"); + ao_usb_ep0_state = AO_USB_EP0_IDLE; #if USB_ECHO ao_add_task(&ao_usb_echo_task, ao_usb_echo, "usb echo"); #endif -- cgit v1.2.3 From 38d4110e59a44687d8a4743b8cd04cbf2761c9d8 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 28 Apr 2013 23:08:03 -0700 Subject: altos: Allow LCD segments to not be multiplexed across digits This allows each LCD segment to be individually configured as to which COM and which SEG drives it, permitting maximum flexibility in wiring. Signed-off-by: Keith Packard --- src/drivers/ao_seven_segment.c | 264 +++++++++++++++++++++-------------------- src/stm/ao_lcd_stm.c | 51 ++++++-- 2 files changed, 175 insertions(+), 140 deletions(-) (limited to 'src/stm') diff --git a/src/drivers/ao_seven_segment.c b/src/drivers/ao_seven_segment.c index b3b5f878..961fbb84 100644 --- a/src/drivers/ao_seven_segment.c +++ b/src/drivers/ao_seven_segment.c @@ -34,134 +34,138 @@ * */ +#ifndef SEVEN_SEGMENT_DEBUG +#define SEVEN_SEGMENT_DEBUG 0 +#endif + static const uint8_t ao_segments[] = { - (1 << AO_SEGMENT_0) | - (1 << AO_SEGMENT_1) | - (1 << AO_SEGMENT_2) | - (0 << AO_SEGMENT_3) | - (1 << AO_SEGMENT_4) | - (1 << AO_SEGMENT_5) | - (1 << AO_SEGMENT_6), /* 0 */ - - (0 << AO_SEGMENT_0) | - (0 << AO_SEGMENT_1) | - (1 << AO_SEGMENT_2) | - (0 << AO_SEGMENT_3) | - (0 << AO_SEGMENT_4) | - (1 << AO_SEGMENT_5) | - (0 << AO_SEGMENT_6), /* 1 */ - - (1 << AO_SEGMENT_0) | - (0 << AO_SEGMENT_1) | - (1 << AO_SEGMENT_2) | - (1 << AO_SEGMENT_3) | - (1 << AO_SEGMENT_4) | - (0 << AO_SEGMENT_5) | - (1 << AO_SEGMENT_6), /* 2 */ - - (1 << AO_SEGMENT_0) | - (0 << AO_SEGMENT_1) | - (1 << AO_SEGMENT_2) | - (1 << AO_SEGMENT_3) | - (0 << AO_SEGMENT_4) | - (1 << AO_SEGMENT_5) | - (1 << AO_SEGMENT_6), /* 3 */ - - (0 << AO_SEGMENT_0) | - (1 << AO_SEGMENT_1) | - (1 << AO_SEGMENT_2) | - (1 << AO_SEGMENT_3) | - (0 << AO_SEGMENT_4) | - (1 << AO_SEGMENT_5) | - (0 << AO_SEGMENT_6), /* 4 */ - - (1 << AO_SEGMENT_0) | - (1 << AO_SEGMENT_1) | - (0 << AO_SEGMENT_2) | - (1 << AO_SEGMENT_3) | - (0 << AO_SEGMENT_4) | - (1 << AO_SEGMENT_5) | - (1 << AO_SEGMENT_6), /* 5 */ - - (1 << AO_SEGMENT_0) | - (1 << AO_SEGMENT_1) | - (0 << AO_SEGMENT_2) | - (1 << AO_SEGMENT_3) | - (1 << AO_SEGMENT_4) | - (1 << AO_SEGMENT_5) | - (1 << AO_SEGMENT_6), /* 6 */ - - (1 << AO_SEGMENT_0) | - (0 << AO_SEGMENT_1) | - (1 << AO_SEGMENT_2) | - (0 << AO_SEGMENT_3) | - (0 << AO_SEGMENT_4) | - (1 << AO_SEGMENT_5) | - (0 << AO_SEGMENT_6), /* 7 */ - - (1 << AO_SEGMENT_0) | - (1 << AO_SEGMENT_1) | - (1 << AO_SEGMENT_2) | - (1 << AO_SEGMENT_3) | - (1 << AO_SEGMENT_4) | - (1 << AO_SEGMENT_5) | - (1 << AO_SEGMENT_6), /* 8 */ - - (1 << AO_SEGMENT_0) | - (1 << AO_SEGMENT_1) | - (1 << AO_SEGMENT_2) | - (1 << AO_SEGMENT_3) | - (0 << AO_SEGMENT_4) | - (1 << AO_SEGMENT_5) | - (1 << AO_SEGMENT_6), /* 9 */ - - (1 << AO_SEGMENT_0) | - (1 << AO_SEGMENT_1) | - (1 << AO_SEGMENT_2) | - (1 << AO_SEGMENT_3) | - (1 << AO_SEGMENT_4) | - (1 << AO_SEGMENT_5) | - (0 << AO_SEGMENT_6), /* A */ - - (0 << AO_SEGMENT_0) | - (1 << AO_SEGMENT_1) | - (0 << AO_SEGMENT_2) | - (1 << AO_SEGMENT_3) | - (1 << AO_SEGMENT_4) | - (1 << AO_SEGMENT_5) | - (1 << AO_SEGMENT_6), /* b */ - - (1 << AO_SEGMENT_0) | - (1 << AO_SEGMENT_1) | - (0 << AO_SEGMENT_2) | - (0 << AO_SEGMENT_3) | - (1 << AO_SEGMENT_4) | - (0 << AO_SEGMENT_5) | - (1 << AO_SEGMENT_6), /* c */ - - (0 << AO_SEGMENT_0) | - (0 << AO_SEGMENT_1) | - (1 << AO_SEGMENT_2) | - (1 << AO_SEGMENT_3) | - (1 << AO_SEGMENT_4) | - (1 << AO_SEGMENT_5) | - (1 << AO_SEGMENT_6), /* d */ - - (1 << AO_SEGMENT_0) | - (1 << AO_SEGMENT_1) | - (0 << AO_SEGMENT_2) | - (1 << AO_SEGMENT_3) | - (1 << AO_SEGMENT_4) | - (0 << AO_SEGMENT_5) | - (1 << AO_SEGMENT_6), /* E */ - - (1 << AO_SEGMENT_0) | - (1 << AO_SEGMENT_1) | - (0 << AO_SEGMENT_2) | - (1 << AO_SEGMENT_3) | - (1 << AO_SEGMENT_4) | - (0 << AO_SEGMENT_5) | - (0 << AO_SEGMENT_6), /* F */ + (1 << 0) | + (1 << 1) | + (1 << 2) | + (0 << 3) | + (1 << 4) | + (1 << 5) | + (1 << 6), /* 0 */ + + (0 << 0) | + (0 << 1) | + (1 << 2) | + (0 << 3) | + (0 << 4) | + (1 << 5) | + (0 << 6), /* 1 */ + + (1 << 0) | + (0 << 1) | + (1 << 2) | + (1 << 3) | + (1 << 4) | + (0 << 5) | + (1 << 6), /* 2 */ + + (1 << 0) | + (0 << 1) | + (1 << 2) | + (1 << 3) | + (0 << 4) | + (1 << 5) | + (1 << 6), /* 3 */ + + (0 << 0) | + (1 << 1) | + (1 << 2) | + (1 << 3) | + (0 << 4) | + (1 << 5) | + (0 << 6), /* 4 */ + + (1 << 0) | + (1 << 1) | + (0 << 2) | + (1 << 3) | + (0 << 4) | + (1 << 5) | + (1 << 6), /* 5 */ + + (1 << 0) | + (1 << 1) | + (0 << 2) | + (1 << 3) | + (1 << 4) | + (1 << 5) | + (1 << 6), /* 6 */ + + (1 << 0) | + (0 << 1) | + (1 << 2) | + (0 << 3) | + (0 << 4) | + (1 << 5) | + (0 << 6), /* 7 */ + + (1 << 0) | + (1 << 1) | + (1 << 2) | + (1 << 3) | + (1 << 4) | + (1 << 5) | + (1 << 6), /* 8 */ + + (1 << 0) | + (1 << 1) | + (1 << 2) | + (1 << 3) | + (0 << 4) | + (1 << 5) | + (1 << 6), /* 9 */ + + (1 << 0) | + (1 << 1) | + (1 << 2) | + (1 << 3) | + (1 << 4) | + (1 << 5) | + (0 << 6), /* A */ + + (0 << 0) | + (1 << 1) | + (0 << 2) | + (1 << 3) | + (1 << 4) | + (1 << 5) | + (1 << 6), /* b */ + + (1 << 0) | + (1 << 1) | + (0 << 2) | + (0 << 3) | + (1 << 4) | + (0 << 5) | + (1 << 6), /* c */ + + (0 << 0) | + (0 << 1) | + (1 << 2) | + (1 << 3) | + (1 << 4) | + (1 << 5) | + (1 << 6), /* d */ + + (1 << 0) | + (1 << 1) | + (0 << 2) | + (1 << 3) | + (1 << 4) | + (0 << 5) | + (1 << 6), /* E */ + + (1 << 0) | + (1 << 1) | + (0 << 2) | + (1 << 3) | + (1 << 4) | + (0 << 5) | + (0 << 6), /* F */ }; void @@ -177,7 +181,7 @@ ao_seven_segment_set(uint8_t digit, uint8_t value) /* Check for decimal point */ if (value & 0x10) - segments |= (1 << AO_SEGMENT_7); + segments |= (1 << 7); } for (s = 0; s <= 7; s++) @@ -192,7 +196,7 @@ ao_seven_segment_clear(void) } -#if 0 +#if SEVEN_SEGMENT_DEBUG static void ao_seven_segment_show(void) { @@ -214,7 +218,7 @@ static const struct ao_cmds ao_seven_segment_cmds[] = { void ao_seven_segment_init(void) { -#if 0 +#if SEVEN_SEGMENT_DEBUG ao_cmd_register(ao_seven_segment_cmds); #endif } diff --git a/src/stm/ao_lcd_stm.c b/src/stm/ao_lcd_stm.c index 4f2a2242..47ea374e 100644 --- a/src/stm/ao_lcd_stm.c +++ b/src/stm/ao_lcd_stm.c @@ -18,6 +18,10 @@ #include #include +#ifndef LCD_DEBUG +#define LCD_DEBUG 0 +#endif + struct ao_lcd_segment { uint8_t reg; uint8_t bit; @@ -271,24 +275,51 @@ ao_lcd_clear(void) ao_lcd_flush(); } +#ifdef AO_SEGMENT_MAP +#if AO_LCD_PER_DIGIT +static const struct ao_lcd_map { + uint8_t com, seg; +} ao_lcd_map[AO_LCD_DIGITS * AO_LCD_SEGMENTS] = AO_SEGMENT_MAP; +#else +static const uint8_t ao_lcd_map[] = AO_SEGMENT_MAP; +#endif +#endif + void ao_lcd_set(uint8_t digit, uint8_t segment, uint8_t value) { uint8_t n; + uint8_t com, seg; - if (digit >= NCOM) - digit = NCOM-1; - if (segment >= NSEG) - segment = NSEG-1; +#ifdef AO_SEGMENT_MAP +#if AO_LCD_PER_DIGIT + n = digit * AO_LCD_SEGMENTS + segment; + com = ao_lcd_map[n].com; + seg = ao_lcd_map[n].seg; +#else + com = digit; + seg = ao_lcd_map[segment]; +#endif +#else + com = digit; + seg = segment; +#endif + if (com >= NCOM) + com = NCOM-1; + if (seg >= NSEG) + seg = NSEG-1; - n = (segment >> 5) & 1; +#if LCD_DEBUG + printf ("digit %d segment %d -> com %d seg %d\n", digit, segment, com, seg); +#endif + n = (seg >> 5) & 1; if (value) - stm_lcd.ram[digit * 2 + n] |= (1 << (segment & 0x1f)); + stm_lcd.ram[com * 2 + n] |= (1 << (seg & 0x1f)); else - stm_lcd.ram[digit * 2 + n] &= ~(1 << (segment & 0x1f)); + stm_lcd.ram[com * 2 + n] &= ~(1 << (seg & 0x1f)); } -#if 0 +#if LCD_DEBUG static void ao_lcd_stm_seg_set(void) { @@ -307,7 +338,7 @@ ao_lcd_stm_seg_set(void) static const struct ao_cmds ao_lcd_stm_cmds[] = { { ao_lcd_stm_seg_set, "s \0Set LCD segment" }, - { ao_lcd_clear, "C\0Clear LCD" }, + { ao_lcd_clear, "x\0Clear LCD" }, { 0, NULL }, }; #endif @@ -411,7 +442,7 @@ ao_lcd_stm_init(void) stm_nvic_set_priority(STM_ISR_LCD_POS, AO_STM_NVIC_LOW_PRIORITY); /* All done */ -#if 0 +#if LCD_DEBUG ao_cmd_register(ao_lcd_stm_cmds); #endif } -- cgit v1.2.3 From 1e9b405e939136d25d937334d1f14f06c7d6127b Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 30 Apr 2013 19:04:26 -0700 Subject: altos: Use separate exception stack on STM32L This reserves 512 bytes of memory for a stack, then makes sure that exceptions continue to use that stack while processes use the per-task stack. Signed-off-by: Keith Packard --- src/core/ao_task.c | 3 +++ src/stm/altos.ld | 6 ++++-- src/stm/ao_arch_funcs.h | 13 +++++++++++++ 3 files changed, 20 insertions(+), 2 deletions(-) (limited to 'src/stm') diff --git a/src/core/ao_task.c b/src/core/ao_task.c index 9cb074b5..c24c9929 100644 --- a/src/core/ao_task.c +++ b/src/core/ao_task.c @@ -536,5 +536,8 @@ ao_start_scheduler(void) ao_cur_task_index = AO_NO_TASK_INDEX; #endif ao_cur_task = NULL; +#if HAS_ARCH_START_SCHEDULER + ao_arch_start_scheduler(); +#endif ao_yield(); } diff --git a/src/stm/altos.ld b/src/stm/altos.ld index f78a45d6..d218e992 100644 --- a/src/stm/altos.ld +++ b/src/stm/altos.ld @@ -17,7 +17,8 @@ MEMORY { rom (rx) : ORIGIN = 0x08000000, LENGTH = 128K - ram (!w) : ORIGIN = 0x20000000, LENGTH = 16K + ram (!w) : ORIGIN = 0x20000000, LENGTH = 15872 + stack (!w) : ORIGIN = 0x20003e00, LENGTH = 512 } INCLUDE registers.ld @@ -63,8 +64,9 @@ SECTIONS { __bss_end__ = .; } >ram - PROVIDE(__stack__ = ORIGIN(ram) + LENGTH(ram)); PROVIDE(end = .); + + PROVIDE(__stack__ = ORIGIN(stack) + LENGTH(stack)); } ENTRY(start); diff --git a/src/stm/ao_arch_funcs.h b/src/stm/ao_arch_funcs.h index d1779307..f3d68202 100644 --- a/src/stm/ao_arch_funcs.h +++ b/src/stm/ao_arch_funcs.h @@ -317,6 +317,19 @@ static inline void ao_arch_restore_stack(void) { asm("bx lr"); } +#define HAS_ARCH_START_SCHEDULER 1 + +static inline void ao_arch_start_scheduler(void) { + uint32_t sp; + uint32_t control; + + asm("mrs %0,msp" : "=&r" (sp)); + asm("msr psp,%0" : : "r" (sp)); + asm("mrs %0,control" : "=&r" (control)); + control |= (1 << 1); + asm("msr control,%0" : : "r" (control)); +} + #define ao_arch_isr_stack() #define ao_arch_wait_interrupt() do { \ -- cgit v1.2.3 From 091582c446319fe4a79154153ece5372b2faec83 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 1 May 2013 08:58:17 -0700 Subject: altos: Use SYSTICK on STM32L It's probably more power efficient than using one of the timers, and it's certainly easier to configure. Signed-off-by: Keith Packard --- src/stm/ao_arch.h | 1 + src/stm/ao_timer.c | 40 +++++++++------------------------------- src/stm/registers.ld | 2 ++ src/stm/stm32l.h | 18 ++++++++++++++++++ 4 files changed, 30 insertions(+), 31 deletions(-) (limited to 'src/stm') diff --git a/src/stm/ao_arch.h b/src/stm/ao_arch.h index 007f7e2e..27a942f2 100644 --- a/src/stm/ao_arch.h +++ b/src/stm/ao_arch.h @@ -99,6 +99,7 @@ extern const uint32_t ao_radio_cal; #define AO_HCLK (AO_SYSCLK / AO_AHB_PRESCALER) #define AO_PCLK1 (AO_HCLK / AO_APB1_PRESCALER) #define AO_PCLK2 (AO_HCLK / AO_APB2_PRESCALER) +#define AO_SYSTICK (AO_HCLK / 8) #if AO_APB1_PRESCALER == 1 #define AO_TIM23467_CLK AO_PCLK1 diff --git a/src/stm/ao_timer.c b/src/stm/ao_timer.c index 8b7c2327..5976eb3f 100644 --- a/src/stm/ao_timer.c +++ b/src/stm/ao_timer.c @@ -31,14 +31,9 @@ volatile __data uint8_t ao_data_interval = 1; volatile __data uint8_t ao_data_count; #endif -void -ao_debug_out(char c); - - -void stm_tim6_isr(void) +void stm_systick_isr(void) { - if (stm_tim6.sr & (1 << STM_TIM67_SR_UIF)) { - stm_tim6.sr = 0; + if (stm_systick.csr & (1 << STM_SYSTICK_CSR_COUNTFLAG)) { ++ao_tick_count; #if HAS_TASK_QUEUE if (ao_task_alarm_tick && (int16_t) (ao_tick_count - ao_task_alarm_tick) >= 0) @@ -81,33 +76,16 @@ ao_timer_set_adc_interval(uint8_t interval) #define TIMER_10kHz ((AO_PCLK1 * TIMER_23467_SCALER) / 10000) +#define SYSTICK_RELOAD (AO_SYSTICK / 100 - 1) + void ao_timer_init(void) { - stm_nvic_set_enable(STM_ISR_TIM6_POS); - stm_nvic_set_priority(STM_ISR_TIM6_POS, AO_STM_NVIC_CLOCK_PRIORITY); - - /* Turn on timer 6 */ - stm_rcc.apb1enr |= (1 << STM_RCC_APB1ENR_TIM6EN); - - stm_tim6.psc = TIMER_10kHz; - stm_tim6.arr = 99; - stm_tim6.cnt = 0; - - /* Enable update interrupt */ - stm_tim6.dier = (1 << STM_TIM67_DIER_UIE); - - /* Poke timer to reload values */ - stm_tim6.egr |= (1 << STM_TIM67_EGR_UG); - - stm_tim6.cr2 = (STM_TIM67_CR2_MMS_RESET << STM_TIM67_CR2_MMS); - - /* And turn it on */ - stm_tim6.cr1 = ((0 << STM_TIM67_CR1_ARPE) | - (0 << STM_TIM67_CR1_OPM) | - (1 << STM_TIM67_CR1_URS) | - (0 << STM_TIM67_CR1_UDIS) | - (1 << STM_TIM67_CR1_CEN)); + stm_systick.rvr = SYSTICK_RELOAD; + stm_systick.cvr = 0; + stm_systick.csr = ((1 << STM_SYSTICK_CSR_ENABLE) | + (1 << STM_SYSTICK_CSR_TICKINT) | + (STM_SYSTICK_CSR_CLKSOURCE_HCLK_8 << STM_SYSTICK_CSR_CLKSOURCE)); } void diff --git a/src/stm/registers.ld b/src/stm/registers.ld index 95a86e35..8318c75a 100644 --- a/src/stm/registers.ld +++ b/src/stm/registers.ld @@ -44,6 +44,8 @@ stm_tim4 = 0x40000800; stm_tim3 = 0x40000400; stm_tim2 = 0x40000000; +stm_systick = 0xe000e010; + stm_nvic = 0xe000e100; stm_scb = 0xe000ed00; diff --git a/src/stm/stm32l.h b/src/stm/stm32l.h index 1d636037..5c0748a6 100644 --- a/src/stm/stm32l.h +++ b/src/stm/stm32l.h @@ -811,6 +811,24 @@ extern struct stm_lcd stm_lcd; #define STM_LCD_CLR_UDDC (3) #define STM_LCD_CLR_SOFC (1) +/* The SYSTICK starts at 0xe000e010 */ + +struct stm_systick { + vuint32_t csr; + vuint32_t rvr; + vuint32_t cvr; + vuint32_t calib; +}; + +extern struct stm_systick stm_systick; + +#define STM_SYSTICK_CSR_ENABLE 0 +#define STM_SYSTICK_CSR_TICKINT 1 +#define STM_SYSTICK_CSR_CLKSOURCE 2 +#define STM_SYSTICK_CSR_CLKSOURCE_HCLK_8 0 +#define STM_SYSTICK_CSR_CLKSOURCE_HCLK 1 +#define STM_SYSTICK_CSR_COUNTFLAG 16 + /* The NVIC starts at 0xe000e100, so add that to the offsets to find the absolute address */ struct stm_nvic { -- cgit v1.2.3 From a6887032b4d217bca5236ea15389218f10d69545 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 24 Feb 2013 00:18:14 -0800 Subject: Add STM self-flashing loader This allows the real application to get loaded at 0x2000 and jumps to that at startup time if the boot pin is set appropriately Signed-off-by: Keith Packard --- src/stm-flash/Makefile | 60 +++++++++++++++++++++++++++++++++++++ src/stm-flash/ao_pins.h | 71 ++++++++++++++++++++++++++++++++++++++++++++ src/stm-flash/ao_stm_flash.c | 28 +++++++++++++++++ src/stm/ao_arch_funcs.h | 23 ++++++++++++-- src/stm/ao_interrupt.c | 40 +++++++++++++++++++++++++ 5 files changed, 219 insertions(+), 3 deletions(-) create mode 100644 src/stm-flash/Makefile create mode 100644 src/stm-flash/ao_pins.h (limited to 'src/stm') diff --git a/src/stm-flash/Makefile b/src/stm-flash/Makefile new file mode 100644 index 00000000..fbc6603d --- /dev/null +++ b/src/stm-flash/Makefile @@ -0,0 +1,60 @@ +# +# AltOS build +# +# + +include ../stm/Makefile.defs + +INC = \ + ao.h \ + ao_arch.h \ + ao_arch_funcs.h \ + ao_pins.h \ + ao_product.h + +# +# Common AltOS sources +# +ALTOS_SRC = \ + ao_interrupt.c \ + ao_product.c \ + ao_romconfig.c \ + ao_task.c \ + ao_timer.c \ + ao_mutex.c \ + ao_usb_stm.c \ + ao_stdio.c \ + ao_cmd.c + +PRODUCT=StmFlash-v0.0 +PRODUCT_DEF=-DSTM_FLASH +IDPRODUCT=0x000a + +CFLAGS = $(PRODUCT_DEF) $(STM_CFLAGS) -g -Os + +PROG=stm-flash + +SRC=$(ALTOS_SRC) ao_stm_flash.c +OBJ=$(SRC:.c=.o) + +all: $(PROG) + +LDFLAGS=-L../stm -Wl,-Taltos-loader.ld + +$(PROG): Makefile $(OBJ) + $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(OBJ) $(SAT_CLIB) -lgcc + +ao_product.h: ao-make-product.5c ../Version + $(call quiet,NICKLE,$<) $< -m altusmetrum.org -i $(IDPRODUCT) -p $(PRODUCT) -v $(VERSION) > $@ + +$(OBJ): $(INC) + +distclean: clean + +clean: + rm -f *.o $(PROG) + rm -f ao_product.h + +install: + +uninstall: diff --git a/src/stm-flash/ao_pins.h b/src/stm-flash/ao_pins.h new file mode 100644 index 00000000..b232f373 --- /dev/null +++ b/src/stm-flash/ao_pins.h @@ -0,0 +1,71 @@ +/* + * Copyright © 2013 Keith Packard + * + * 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_TASK_QUEUE 0 + +#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) + +/* SYSCLK = 32MHz */ +#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 HCLK/1 */ +#define AO_APB1_PRESCALER 1 +#define AO_RCC_CFGR_PPRE1_DIV STM_RCC_CFGR_PPRE2_DIV_1 + +/* Run APB2 at HCLK/1 */ +#define AO_APB2_PRESCALER 1 +#define AO_RCC_CFGR_PPRE2_DIV STM_RCC_CFGR_PPRE2_DIV_1 + +#define HAS_USB 1 +#define USE_USB_STDIN 1 +#define HAS_BEEP 0 + +#define PACKET_HAS_SLAVE 0 + +#define LED_PORT_ENABLE STM_RCC_AHBENR_GPIOCEN +#define LED_PORT (&stm_gpioc) +#define LED_PIN_RED 8 +#define LED_PIN_GREEN 9 +#define AO_LED_RED (1 << LED_PIN_RED) +#define AO_LED_GREEN (1 << LED_PIN_GREEN) + +#define LEDS_AVAILABLE (AO_LED_RED | AO_LED_GREEN) + +#define AO_TICK_TYPE uint32_t +#define AO_TICK_SIGNED int32_t + +#define HAS_TASK_INFO 0 + +#define AO_BOOT_APPLICATION_GPIO stm_gpiob +#define AO_BOOT_APPLICATION_PIN 5 +#define AO_BOOT_APPLICATION_VALUE 0 +#define AO_BOOT_APPLICATION_MODE AO_EXTI_MODE_PULL_UP +#define AO_BOOT_APPLICATION_BASE 0x2000 + +#endif /* _AO_PINS_H_ */ diff --git a/src/stm-flash/ao_stm_flash.c b/src/stm-flash/ao_stm_flash.c index df466d85..81ae86df 100644 --- a/src/stm-flash/ao_stm_flash.c +++ b/src/stm-flash/ao_stm_flash.c @@ -17,6 +17,7 @@ #include "ao.h" #include +<<<<<<< HEAD #include #include @@ -117,21 +118,48 @@ __code struct ao_cmds ao_flash_cmds[] = { { ao_block_read, "R \0Read block. Returns 256 bytes" }, { 0, NULL }, }; +======= + +void +ao_panic(uint8_t c) +{ +} + +void +ao_test(void) +{ + char c; + + for (;;) { + c = ao_usb_getchar(); + ao_usb_putchar(c); + ao_usb_flush(); + } +} + +struct ao_task ao_test_task; +>>>>>>> 5187bb4... Add STM self-flashing loader int main(void) { ao_clock_init(); +<<<<<<< HEAD ao_task_init(); +======= +>>>>>>> 5187bb4... Add STM self-flashing loader ao_timer_init(); // ao_dma_init(); ao_cmd_init(); // ao_exti_init(); ao_usb_init(); +<<<<<<< HEAD ao_cmd_register(&ao_flash_cmds[0]); +======= +>>>>>>> 5187bb4... Add STM self-flashing loader ao_start_scheduler(); return 0; } diff --git a/src/stm/ao_arch_funcs.h b/src/stm/ao_arch_funcs.h index f3d68202..2c0f173c 100644 --- a/src/stm/ao_arch_funcs.h +++ b/src/stm/ao_arch_funcs.h @@ -113,6 +113,19 @@ ao_spi_init(void); stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_GPIOEEN); \ } while (0) +#define ao_disable_port(port) do { \ + if ((port) == &stm_gpioa) \ + stm_rcc.ahbenr &= ~(1 << STM_RCC_AHBENR_GPIOAEN); \ + else if ((port) == &stm_gpiob) \ + stm_rcc.ahbenr &= ~(1 << STM_RCC_AHBENR_GPIOBEN); \ + else if ((port) == &stm_gpioc) \ + stm_rcc.ahbenr &= ~(1 << STM_RCC_AHBENR_GPIOCEN); \ + else if ((port) == &stm_gpiod) \ + stm_rcc.ahbenr &= ~(1 << STM_RCC_AHBENR_GPIODEN); \ + else if ((port) == &stm_gpioe) \ + stm_rcc.ahbenr &= ~(1 << STM_RCC_AHBENR_GPIOEEN); \ + } while (0) + #define ao_gpio_set(port, bit, pin, v) stm_gpio_set(port, bit, v) @@ -124,9 +137,7 @@ ao_spi_init(void); stm_moder_set(port, bit, STM_MODER_OUTPUT);\ } while (0) -#define ao_enable_input(port,bit,mode) do { \ - ao_enable_port(port); \ - stm_moder_set(port, bit, STM_MODER_INPUT); \ +#define ao_gpio_set_mode(port,bit,mode) do { \ if (mode == AO_EXTI_MODE_PULL_UP) \ stm_pupdr_set(port, bit, STM_PUPDR_PULL_UP); \ else if (mode == AO_EXTI_MODE_PULL_DOWN) \ @@ -134,6 +145,12 @@ ao_spi_init(void); else \ stm_pupdr_set(port, bit, STM_PUPDR_NONE); \ } while (0) + +#define ao_enable_input(port,bit,mode) do { \ + ao_enable_port(port); \ + stm_moder_set(port, bit, STM_MODER_INPUT); \ + ao_gpio_set_mode(port, bit, mode); \ + } while (0) #define ao_enable_cs(port,bit) do { \ stm_gpio_set((port), bit, 1); \ diff --git a/src/stm/ao_interrupt.c b/src/stm/ao_interrupt.c index a423d8b1..12763a30 100644 --- a/src/stm/ao_interrupt.c +++ b/src/stm/ao_interrupt.c @@ -36,7 +36,47 @@ void stm_ignore_isr(void) { } +const void *stm_interrupt_vector[]; + +#define BOOT_FETCH(o) (*((uint32_t *) (AO_BOOT_APPLICATION_BASE + (o)))) + +#ifdef AO_BOOT_APPLICATION_PIN +#include +#endif + void start(void) { +#ifdef AO_BOOT_APPLICATION_PIN + uint16_t v; + + /* Enable power interface clock */ + stm_rcc.apb1enr |= (1 << STM_RCC_APB1ENR_PWREN); + + /* Enable the input pin */ + ao_enable_input(&AO_BOOT_APPLICATION_GPIO, AO_BOOT_APPLICATION_PIN, + AO_BOOT_APPLICATION_MODE); + + /* Read the value */ + v = stm_gpio_get(&AO_BOOT_APPLICATION_GPIO, AO_BOOT_APPLICATION_PIN); + + /* Reset the chip to turn off the port and the power interface clock */ + ao_gpio_set_mode(&AO_BOOT_APPLICATION_GPIO, AO_BOOT_APPLICATION_PIN, 0); + ao_disable_port(&AO_BOOT_APPLICATION_GPIO); + stm_rcc.apb1enr &= ~(1 << STM_RCC_APB1ENR_PWREN); + if (v == AO_BOOT_APPLICATION_VALUE) + { + uint32_t sp; + uint32_t pc; + + sp = BOOT_FETCH(0); + pc = BOOT_FETCH(4); + asm ("mov sp, %0" : : "r" (sp)); + asm ("mov lr, %0" : : "r" (pc)); + asm ("bx lr"); + } +#endif + + /* Set interrupt vector table offset */ + stm_nvic.vto = (uint32_t) &stm_interrupt_vector; memcpy(&__data_start__, &__text_end__, &__data_end__ - &__data_start__); memset(&__bss_start__, '\0', &__bss_end__ - &__bss_start__); main(); -- cgit v1.2.3 From c9c35b100c3fcae661501d2bf89eedc7fceb2e1c Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 10 Mar 2013 21:02:59 -0700 Subject: altos: Make stm-flash capable of switching to application This shrinks the base OS load down a bit as well so that stm-flash fits comfortably in the first 8kB of memory. Signed-off-by: Keith Packard --- src/core/ao_cmd.c | 11 +++++++ src/core/ao_task.c | 2 ++ src/core/ao_task.h | 4 +++ src/stm-demo/Makefile | 2 +- src/stm-flash/ao_pins.h | 13 +++++--- src/stm-flash/ao_stm_flash.c | 28 +---------------- src/stm/altos-application.ld | 72 ++++++++++++++++++++++++++++++++++++++++++++ src/stm/altos-loader.ld | 72 ++++++++++++++++++++++++++++++++++++++++++++ src/stm/ao_boot.h | 24 +++++++++++++++ src/stm/ao_interrupt.c | 44 +++++++++++++++++++++------ 10 files changed, 229 insertions(+), 43 deletions(-) create mode 100644 src/stm/altos-application.ld create mode 100644 src/stm/altos-loader.ld create mode 100644 src/stm/ao_boot.h (limited to 'src/stm') diff --git a/src/core/ao_cmd.c b/src/core/ao_cmd.c index 6eed08d9..7da2384f 100644 --- a/src/core/ao_cmd.c +++ b/src/core/ao_cmd.c @@ -16,6 +16,7 @@ */ #include "ao.h" +#include "ao_task.h" __pdata uint16_t ao_cmd_lex_i; __pdata uint32_t ao_cmd_lex_u32; @@ -262,6 +263,11 @@ ao_reboot(void) ao_panic(AO_PANIC_REBOOT); } +#ifndef HAS_VERSION +#define HAS_VERSION 1 +#endif + +#if HAS_VERSION static void version(void) { @@ -289,6 +295,7 @@ version(void) #endif printf("software-version %s\n", ao_version); } +#endif #ifndef NUM_CMDS #define NUM_CMDS 11 @@ -382,10 +389,14 @@ __xdata struct ao_task ao_cmd_task; __code struct ao_cmds ao_base_cmds[] = { { help, "?\0Help" }, +#if HAS_TASK_INFO { ao_task_info, "T\0Tasks" }, +#endif { echo, "E <0 off, 1 on>\0Echo" }, { ao_reboot, "r eboot\0Reboot" }, +#if HAS_VERSION { version, "v\0Version" }, +#endif { 0, NULL }, }; diff --git a/src/core/ao_task.c b/src/core/ao_task.c index c24c9929..0aad6508 100644 --- a/src/core/ao_task.c +++ b/src/core/ao_task.c @@ -512,6 +512,7 @@ ao_exit(void) /* we'll never get back here */ } +#if HAS_TASK_INFO void ao_task_info(void) { @@ -528,6 +529,7 @@ ao_task_info(void) ao_task_validate(); #endif } +#endif void ao_start_scheduler(void) diff --git a/src/core/ao_task.h b/src/core/ao_task.h index 50bfb220..1a4b5b6b 100644 --- a/src/core/ao_task.h +++ b/src/core/ao_task.h @@ -21,6 +21,10 @@ #include #endif +#ifndef HAS_TASK_INFO +#define HAS_TASK_INFO 1 +#endif + /* An AltOS task */ struct ao_task { __xdata void *wchan; /* current wait channel (NULL if running) */ diff --git a/src/stm-demo/Makefile b/src/stm-demo/Makefile index 3b1b671b..ab12f47b 100644 --- a/src/stm-demo/Makefile +++ b/src/stm-demo/Makefile @@ -53,7 +53,7 @@ OBJ=$(SRC:.c=.o) all: $(PROG) -LDFLAGS=-L../stm -Wl,-Taltos.ld +LDFLAGS=-L../stm -Wl,-Taltos-application.ld $(PROG): Makefile $(OBJ) $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(OBJ) $(SAT_CLIB) -lgcc diff --git a/src/stm-flash/ao_pins.h b/src/stm-flash/ao_pins.h index b232f373..ca53d844 100644 --- a/src/stm-flash/ao_pins.h +++ b/src/stm-flash/ao_pins.h @@ -20,7 +20,9 @@ #define HAS_TASK_QUEUE 0 -#define AO_HSE 8000000 +/* Bridge SB17 on the board and use the MCO from the other chip */ +#define AO_HSE 8000000 +#define AO_HSE_BYPASS 1 /* PLLVCO = 96MHz (so that USB will work) */ #define AO_PLLMUL 12 @@ -61,11 +63,12 @@ #define AO_TICK_SIGNED int32_t #define HAS_TASK_INFO 0 +#define HAS_VERSION 0 -#define AO_BOOT_APPLICATION_GPIO stm_gpiob -#define AO_BOOT_APPLICATION_PIN 5 -#define AO_BOOT_APPLICATION_VALUE 0 -#define AO_BOOT_APPLICATION_MODE AO_EXTI_MODE_PULL_UP +#define AO_BOOT_APPLICATION_GPIO stm_gpioa +#define AO_BOOT_APPLICATION_PIN 0 +#define AO_BOOT_APPLICATION_VALUE 1 +#define AO_BOOT_APPLICATION_MODE 0 #define AO_BOOT_APPLICATION_BASE 0x2000 #endif /* _AO_PINS_H_ */ diff --git a/src/stm-flash/ao_stm_flash.c b/src/stm-flash/ao_stm_flash.c index 81ae86df..e2d7ec65 100644 --- a/src/stm-flash/ao_stm_flash.c +++ b/src/stm-flash/ao_stm_flash.c @@ -17,7 +17,6 @@ #include "ao.h" #include -<<<<<<< HEAD #include #include @@ -118,48 +117,23 @@ __code struct ao_cmds ao_flash_cmds[] = { { ao_block_read, "R \0Read block. Returns 256 bytes" }, { 0, NULL }, }; -======= -void -ao_panic(uint8_t c) -{ -} - -void -ao_test(void) -{ - char c; - - for (;;) { - c = ao_usb_getchar(); - ao_usb_putchar(c); - ao_usb_flush(); - } -} - -struct ao_task ao_test_task; ->>>>>>> 5187bb4... Add STM self-flashing loader int main(void) { ao_clock_init(); -<<<<<<< HEAD ao_task_init(); -======= ->>>>>>> 5187bb4... Add STM self-flashing loader ao_timer_init(); // ao_dma_init(); ao_cmd_init(); // ao_exti_init(); ao_usb_init(); -<<<<<<< HEAD ao_cmd_register(&ao_flash_cmds[0]); -======= ->>>>>>> 5187bb4... Add STM self-flashing loader + ao_cmd_register(&ao_flash_cmds[0]); ao_start_scheduler(); return 0; } diff --git a/src/stm/altos-application.ld b/src/stm/altos-application.ld new file mode 100644 index 00000000..63a3be00 --- /dev/null +++ b/src/stm/altos-application.ld @@ -0,0 +1,72 @@ +/* + * Copyright © 2012 Keith Packard + * + * 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. + */ + +MEMORY { + rom (rx) : ORIGIN = 0x08002000, LENGTH = 120K + ram (!w) : ORIGIN = 0x20000000, LENGTH = 16K +} + +INCLUDE registers.ld + +EXTERN (stm_interrupt_vector) + +SECTIONS { + /* + * Rom contents + */ + + .text ORIGIN(rom) : { + __text_start__ = .; + *(.interrupt) /* Interrupt vectors */ + + . = ORIGIN(rom) + 0x100; + + ao_romconfig.o(.romconfig*) + ao_product.o(.romconfig*) + + *(.text*) /* Executable code */ + *(.rodata*) /* Constants */ + + } > rom + + .ARM.exidx : { + *(.ARM.exidx* .gnu.linkonce.armexidx.*) + __text_end__ = .; + } > rom + + /* Data -- relocated to RAM, but written to ROM + */ + .data ORIGIN(ram) : AT (ADDR(.ARM.exidx) + SIZEOF (.ARM.exidx)) { + __data_start__ = .; + *(.data) /* initialized data */ + __data_end__ = .; + __bss_start__ = .; + } >ram + + .bss : { + *(.bss) + *(COMMON) + __bss_end__ = .; + } >ram + + PROVIDE(__stack__ = ORIGIN(ram) + LENGTH(ram)); + PROVIDE(end = .); +} + +ENTRY(start); + + diff --git a/src/stm/altos-loader.ld b/src/stm/altos-loader.ld new file mode 100644 index 00000000..2d71b4ee --- /dev/null +++ b/src/stm/altos-loader.ld @@ -0,0 +1,72 @@ +/* + * Copyright © 2012 Keith Packard + * + * 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. + */ + +MEMORY { + rom (rx) : ORIGIN = 0x08000000, LENGTH = 8K + ram (!w) : ORIGIN = 0x20000000, LENGTH = 16K +} + +INCLUDE registers.ld + +EXTERN (stm_interrupt_vector) + +SECTIONS { + /* + * Rom contents + */ + + .text ORIGIN(rom) : { + __text_start__ = .; + *(.interrupt) /* Interrupt vectors */ + + . = ORIGIN(rom) + 0x100; + + ao_romconfig.o(.romconfig*) + ao_product.o(.romconfig*) + + *(.text*) /* Executable code */ + *(.rodata*) /* Constants */ + + } > rom + + .ARM.exidx : { + *(.ARM.exidx* .gnu.linkonce.armexidx.*) + __text_end__ = .; + } > rom + + /* Data -- relocated to RAM, but written to ROM + */ + .data ORIGIN(ram) : AT (ADDR(.ARM.exidx) + SIZEOF (.ARM.exidx)) { + __data_start__ = .; + *(.data) /* initialized data */ + __data_end__ = .; + __bss_start__ = .; + } >ram + + .bss : { + *(.bss) + *(COMMON) + __bss_end__ = .; + } >ram + + PROVIDE(__stack__ = ORIGIN(ram) + LENGTH(ram)); + PROVIDE(end = .); +} + +ENTRY(start); + + diff --git a/src/stm/ao_boot.h b/src/stm/ao_boot.h new file mode 100644 index 00000000..863d8e05 --- /dev/null +++ b/src/stm/ao_boot.h @@ -0,0 +1,24 @@ +/* + * Copyright © 2013 Keith Packard + * + * 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_BOOT_H_ +#define _AO_BOOT_H_ + +void +ao_reboot_application(void); + +#endif /* _AO_BOOT_H_ */ diff --git a/src/stm/ao_interrupt.c b/src/stm/ao_interrupt.c index 12763a30..9e756219 100644 --- a/src/stm/ao_interrupt.c +++ b/src/stm/ao_interrupt.c @@ -42,12 +42,45 @@ const void *stm_interrupt_vector[]; #ifdef AO_BOOT_APPLICATION_PIN #include + +#define AO_BOOT_APPLICATION 0x5a5aa5a5 +#define AO_BOOT_APPLICATION_CHECK 0xc3c33c3c + +static uint32_t ao_boot_application; +static uint32_t ao_boot_application_check; + +static void +ao_boot_chain(void) { + uint32_t sp; + uint32_t pc; + + sp = BOOT_FETCH(0); + pc = BOOT_FETCH(4); + asm ("mov sp, %0" : : "r" (sp)); + asm ("mov lr, %0" : : "r" (pc)); + asm ("bx lr"); +} + +void +ao_reboot_application(void) +{ + ao_boot_application = AO_BOOT_APPLICATION; + ao_boot_application_check = AO_BOOT_APPLICATION_CHECK; + ao_arch_reboot(); +} + #endif void start(void) { #ifdef AO_BOOT_APPLICATION_PIN uint16_t v; + if (ao_boot_application == AO_BOOT_APPLICATION && + ao_boot_application_check == AO_BOOT_APPLICATION_CHECK) { + ao_boot_application = 0; + ao_boot_application_check = 0; + ao_boot_chain(); + } /* Enable power interface clock */ stm_rcc.apb1enr |= (1 << STM_RCC_APB1ENR_PWREN); @@ -63,16 +96,7 @@ void start(void) { ao_disable_port(&AO_BOOT_APPLICATION_GPIO); stm_rcc.apb1enr &= ~(1 << STM_RCC_APB1ENR_PWREN); if (v == AO_BOOT_APPLICATION_VALUE) - { - uint32_t sp; - uint32_t pc; - - sp = BOOT_FETCH(0); - pc = BOOT_FETCH(4); - asm ("mov sp, %0" : : "r" (sp)); - asm ("mov lr, %0" : : "r" (pc)); - asm ("bx lr"); - } + ao_boot_chain(); #endif /* Set interrupt vector table offset */ -- cgit v1.2.3 From 56a7cbbf51f5c9ebbfe17d1cc30ed807572af3cc Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 11 Mar 2013 00:01:52 -0700 Subject: altos: Add program flash function And get it loaded to RAM so it can execute correctly. Nothing calls it yet... Signed-off-by: Keith Packard --- src/stm-flash/Makefile | 1 + src/stm/altos-loader.ld | 31 +++++++++------ src/stm/ao_flash_stm.c | 103 ++++++++++++++++++++++++++++++++++++++++++++++++ src/stm/ao_flash_stm.h | 24 +++++++++++ src/stm/stm32l.h | 3 ++ 5 files changed, 151 insertions(+), 11 deletions(-) create mode 100644 src/stm/ao_flash_stm.c create mode 100644 src/stm/ao_flash_stm.h (limited to 'src/stm') diff --git a/src/stm-flash/Makefile b/src/stm-flash/Makefile index fbc6603d..3c7b4966 100644 --- a/src/stm-flash/Makefile +++ b/src/stm-flash/Makefile @@ -24,6 +24,7 @@ ALTOS_SRC = \ ao_mutex.c \ ao_usb_stm.c \ ao_stdio.c \ + ao_flash_stm.c \ ao_cmd.c PRODUCT=StmFlash-v0.0 diff --git a/src/stm/altos-loader.ld b/src/stm/altos-loader.ld index 2d71b4ee..50a425c7 100644 --- a/src/stm/altos-loader.ld +++ b/src/stm/altos-loader.ld @@ -16,8 +16,8 @@ */ MEMORY { - rom (rx) : ORIGIN = 0x08000000, LENGTH = 8K - ram (!w) : ORIGIN = 0x20000000, LENGTH = 16K + rom : ORIGIN = 0x08000000, LENGTH = 8K + ram : ORIGIN = 0x20000000, LENGTH = 16K } INCLUDE registers.ld @@ -29,7 +29,7 @@ SECTIONS { * Rom contents */ - .text ORIGIN(rom) : { + .text : { __text_start__ = .; *(.interrupt) /* Interrupt vectors */ @@ -38,26 +38,35 @@ SECTIONS { ao_romconfig.o(.romconfig*) ao_product.o(.romconfig*) - *(.text*) /* Executable code */ - *(.rodata*) /* Constants */ + *(.text) /* Executable code */ + *(.rodata) /* Constants */ } > rom .ARM.exidx : { *(.ARM.exidx* .gnu.linkonce.armexidx.*) - __text_end__ = .; } > rom + __text_end__ = .; + + /* Functions placed in RAM (required for flashing) */ + .textram : { + __text_ram_start = .; + __data_start__ = .; + *(.text.ram) + . = ALIGN(4); + } >ram AT>rom + __text_ram_end = .; /* Data -- relocated to RAM, but written to ROM */ - .data ORIGIN(ram) : AT (ADDR(.ARM.exidx) + SIZEOF (.ARM.exidx)) { - __data_start__ = .; + .data : { *(.data) /* initialized data */ - __data_end__ = .; - __bss_start__ = .; - } >ram + . = ALIGN (4); + } >ram AT>rom + __data_end__ = .; .bss : { + __bss_start__ = .; *(.bss) *(COMMON) __bss_end__ = .; diff --git a/src/stm/ao_flash_stm.c b/src/stm/ao_flash_stm.c new file mode 100644 index 00000000..b3ef6a62 --- /dev/null +++ b/src/stm/ao_flash_stm.c @@ -0,0 +1,103 @@ +/* + * Copyright © 2013 Keith Packard + * + * 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 +#include + +static uint8_t +ao_flash_pecr_is_locked(void) +{ + return (stm_flash.pecr & (1 << STM_FLASH_PECR_PELOCK)) != 0; +} + +static uint8_t +ao_flash_pgr_is_locked(void) +{ + return (stm_flash.pecr & (1 << STM_FLASH_PECR_PRGLOCK)) != 0; +} + +static void +ao_flash_pecr_unlock(void) +{ + if (!ao_flash_pecr_is_locked()) + return; + + /* Unlock Data EEPROM and FLASH_PECR register */ + stm_flash.pekeyr = STM_FLASH_PEKEYR_PEKEY1; + stm_flash.pekeyr = STM_FLASH_PEKEYR_PEKEY2; +} + +static void +ao_flash_pgr_unlock(void) +{ + if (!ao_flash_pgr_is_locked()) + return; + + /* Unlock program memory */ + stm_flash.prgkeyr = STM_FLASH_PRGKEYR_PRGKEY1; + stm_flash.prgkeyr = STM_FLASH_PRGKEYR_PRGKEY2; +} + +static void +ao_flash_wait_bsy(void) +{ + while (stm_flash.sr & (1 << STM_FLASH_SR_BSY)) + ; +} + +static void +ao_flash_erase_page(uint32_t *page) +{ + ao_flash_pecr_unlock(); + ao_flash_pgr_unlock(); + + stm_flash.pecr |= (1 << STM_FLASH_PECR_ERASE); + stm_flash.pecr |= (1 << STM_FLASH_PECR_PROG); + + ao_flash_wait_bsy(); + + *page = 0x00000000; +} + +static void __attribute__ ((section(".text.ram"), noinline)) + _ao_flash_half_page(uint32_t *dst, uint32_t *src) +{ + uint8_t i; + + stm_flash.pecr |= (1 << STM_FLASH_PECR_FPRG); + stm_flash.pecr |= (1 << STM_FLASH_PECR_PROG); + while (stm_flash.sr & (1 << STM_FLASH_SR_BSY)) + ; + + for (i = 0; i < 32; i++) + *dst++ = *src++; +} + +void +ao_flash_page(uint32_t *page, uint32_t *src) +{ + uint8_t h; + + ao_flash_erase_page(page); + for (h = 0; h < 2; h++) { + ao_flash_pecr_unlock(); + ao_flash_pgr_unlock(); + _ao_flash_half_page(page, src); + page += 32; + src += 32; + } +} diff --git a/src/stm/ao_flash_stm.h b/src/stm/ao_flash_stm.h new file mode 100644 index 00000000..b4067d8d --- /dev/null +++ b/src/stm/ao_flash_stm.h @@ -0,0 +1,24 @@ +/* + * Copyright © 2013 Keith Packard + * + * 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_FLASH_STM_H_ +#define _AO_FLASH_STM_H_ + +void +ao_flash_page(uint32_t *page, uint32_t *src); + +#endif /* _AO_FLASH_STM_H_ */ diff --git a/src/stm/stm32l.h b/src/stm/stm32l.h index 5c0748a6..63bde0f8 100644 --- a/src/stm/stm32l.h +++ b/src/stm/stm32l.h @@ -435,6 +435,9 @@ extern struct stm_flash stm_flash; #define STM_FLASH_PEKEYR_PEKEY1 0x89ABCDEF #define STM_FLASH_PEKEYR_PEKEY2 0x02030405 +#define STM_FLASH_PRGKEYR_PRGKEY1 0x8C9DAEBF +#define STM_FLASH_PRGKEYR_PRGKEY2 0x13141516 + struct stm_rcc { vuint32_t cr; vuint32_t icscr; -- cgit v1.2.3 From b1a43ce313c85cb7f8f16f7f0647d9d4320ba692 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 11 Mar 2013 13:21:04 -0700 Subject: altos: Clean up boot loader support Split out code into separate files. Add support for getting back to boot loader from application. Signed-off-by: Keith Packard --- src/stm-demo/Makefile | 1 + src/stm-demo/ao_demo.c | 9 +++++ src/stm-demo/ao_pins.h | 2 ++ src/stm-flash/Makefile | 2 ++ src/stm-flash/ao_pins.h | 5 ++- src/stm-flash/ao_stm_flash.c | 84 +------------------------------------------- src/stm/altos-application.ld | 17 +++++++-- src/stm/altos-loader.ld | 13 ++++++- src/stm/ao_boot.h | 11 +++++- src/stm/ao_boot_chain.c | 62 ++++++++++++++++++++++++++++++++ src/stm/ao_boot_pin.c | 43 +++++++++++++++++++++++ src/stm/ao_interrupt.c | 64 ++++----------------------------- 12 files changed, 166 insertions(+), 147 deletions(-) create mode 100644 src/stm/ao_boot_chain.c create mode 100644 src/stm/ao_boot_pin.c (limited to 'src/stm') diff --git a/src/stm-demo/Makefile b/src/stm-demo/Makefile index ab12f47b..e6cd55e4 100644 --- a/src/stm-demo/Makefile +++ b/src/stm-demo/Makefile @@ -17,6 +17,7 @@ INC = \ # ALTOS_SRC = \ ao_interrupt.c \ + ao_boot_chain.c \ ao_product.c \ ao_romconfig.c \ ao_cmd.c \ diff --git a/src/stm-demo/ao_demo.c b/src/stm-demo/ao_demo.c index 9ee0be03..ec572fdc 100644 --- a/src/stm-demo/ao_demo.c +++ b/src/stm-demo/ao_demo.c @@ -20,6 +20,7 @@ #include #include #include +#include struct ao_task demo_task; @@ -168,6 +169,13 @@ ao_event(void) } +static void +ao_boot_loader(void) +{ + flush(); + ao_boot_reboot((uint32_t *) 0); +} + __code struct ao_cmds ao_demo_cmds[] = { { ao_dma_test, "D\0DMA test" }, { ao_spi_write, "W\0SPI write" }, @@ -175,6 +183,7 @@ __code struct ao_cmds ao_demo_cmds[] = { { ao_i2c_write, "i\0I2C write" }, { ao_temp, "t\0Show temp" }, { ao_event, "e\0Monitor event queue" }, + { ao_boot_loader, "L\0Reboot to boot loader" }, { 0, NULL } }; diff --git a/src/stm-demo/ao_pins.h b/src/stm-demo/ao_pins.h index 07b4a19d..40e48a36 100644 --- a/src/stm-demo/ao_pins.h +++ b/src/stm-demo/ao_pins.h @@ -68,6 +68,8 @@ #define HAS_BEEP 0 #define PACKET_HAS_SLAVE 0 +#define AO_BOOT_CHAIN 1 + #define LOW_LEVEL_DEBUG 1 #define LED_PORT_ENABLE STM_RCC_AHBENR_GPIOBEN diff --git a/src/stm-flash/Makefile b/src/stm-flash/Makefile index 3c7b4966..e4a2f321 100644 --- a/src/stm-flash/Makefile +++ b/src/stm-flash/Makefile @@ -17,6 +17,8 @@ INC = \ # ALTOS_SRC = \ ao_interrupt.c \ + ao_boot_chain.c \ + ao_boot_pin.c \ ao_product.c \ ao_romconfig.c \ ao_task.c \ diff --git a/src/stm-flash/ao_pins.h b/src/stm-flash/ao_pins.h index ca53d844..382ef353 100644 --- a/src/stm-flash/ao_pins.h +++ b/src/stm-flash/ao_pins.h @@ -65,10 +65,13 @@ #define HAS_TASK_INFO 0 #define HAS_VERSION 0 +#define AO_BOOT_CHAIN 1 +#define AO_BOOT_PIN 1 + #define AO_BOOT_APPLICATION_GPIO stm_gpioa #define AO_BOOT_APPLICATION_PIN 0 #define AO_BOOT_APPLICATION_VALUE 1 #define AO_BOOT_APPLICATION_MODE 0 -#define AO_BOOT_APPLICATION_BASE 0x2000 +#define AO_BOOT_APPLICATION_BASE ((uint32_t *) 0x2000) #endif /* _AO_PINS_H_ */ diff --git a/src/stm-flash/ao_stm_flash.c b/src/stm-flash/ao_stm_flash.c index e2d7ec65..2988a937 100644 --- a/src/stm-flash/ao_stm_flash.c +++ b/src/stm-flash/ao_stm_flash.c @@ -32,89 +32,8 @@ ao_application(void) ao_boot_reboot(AO_BOOT_APPLICATION_BASE); } -static uint32_t -ao_cmd_hex32(void) -{ - __pdata uint8_t r = ao_cmd_lex_error; - int8_t n; - uint32_t v = 0; - - ao_cmd_white(); - for(;;) { - n = ao_cmd_hexchar(ao_cmd_lex_c); - if (n < 0) - break; - v = (v << 4) | n; - r = ao_cmd_success; - ao_cmd_lex(); - } - if (r != ao_cmd_success) - ao_cmd_status = r; - return v; -} - -void -ao_block_erase(void) -{ - uint32_t addr = ao_cmd_hex32(); - uint32_t *p = (uint32_t *) addr; - - ao_flash_erase_page(p); -} - -void -ao_block_write(void) -{ - uint32_t addr = ao_cmd_hex32(); - uint32_t *p = (uint32_t *) addr; - union { - uint8_t data8[256]; - uint32_t data32[64]; - } u; - uint16_t i; - - if (addr < 0x08002000 || 0x08200000 <= addr) { - puts("Invalid address"); - return; - } - for (i = 0; i < 256; i++) - u.data8[i] = i; - ao_flash_page(p, u.data32); -} - -static void -puthex(uint8_t c) -{ - c &= 0xf; - if (c < 10) - c += '0'; - else - c += 'a' - 10; - putchar (c); -} - -void -ao_block_read(void) -{ - uint32_t addr = ao_cmd_hex32(); - uint8_t *p = (uint8_t *) addr; - uint16_t i; - uint8_t c; - - for (i = 0; i < 256; i++) { - c = *p++; - puthex(c); - puthex(c>>4); - if ((i & 0xf) == 0xf) - putchar('\n'); - } -} - __code struct ao_cmds ao_flash_cmds[] = { - { ao_application, "a\0Switch to application" }, - { ao_block_erase, "e \0Erase block." }, - { ao_block_write, "W \0Write block. 256 binary bytes follow newline" }, - { ao_block_read, "R \0Read block. Returns 256 bytes" }, + { ao_application, "A\0Switch to application" }, { 0, NULL }, }; @@ -132,7 +51,6 @@ main(void) // ao_exti_init(); ao_usb_init(); - ao_cmd_register(&ao_flash_cmds[0]); ao_cmd_register(&ao_flash_cmds[0]); ao_start_scheduler(); return 0; diff --git a/src/stm/altos-application.ld b/src/stm/altos-application.ld index 63a3be00..5110da84 100644 --- a/src/stm/altos-application.ld +++ b/src/stm/altos-application.ld @@ -48,16 +48,27 @@ SECTIONS { __text_end__ = .; } > rom + /* Boot data which must live at the start of ram so that + * the application and bootloader share the same addresses. + * This must be all uninitialized data + */ + .boot : { + __boot_start__ = .; + *(.boot) + . = ALIGN(4); + __boot_end__ = .; + } >ram + /* Data -- relocated to RAM, but written to ROM */ - .data ORIGIN(ram) : AT (ADDR(.ARM.exidx) + SIZEOF (.ARM.exidx)) { + .data : { __data_start__ = .; *(.data) /* initialized data */ __data_end__ = .; - __bss_start__ = .; - } >ram + } >ram AT>rom .bss : { + __bss_start__ = .; *(.bss) *(COMMON) __bss_end__ = .; diff --git a/src/stm/altos-loader.ld b/src/stm/altos-loader.ld index 50a425c7..2e36dce9 100644 --- a/src/stm/altos-loader.ld +++ b/src/stm/altos-loader.ld @@ -48,9 +48,20 @@ SECTIONS { } > rom __text_end__ = .; + /* Boot data which must live at the start of ram so that + * the application and bootloader share the same addresses. + * This must be all uninitialized data + */ + .boot : { + __boot_start__ = .; + *(.boot) + . = ALIGN(4); + __boot_end__ = .; + } >ram + /* Functions placed in RAM (required for flashing) */ .textram : { - __text_ram_start = .; + __text_ram_start__ = .; __data_start__ = .; *(.text.ram) . = ALIGN(4); diff --git a/src/stm/ao_boot.h b/src/stm/ao_boot.h index 863d8e05..3e8c50ba 100644 --- a/src/stm/ao_boot.h +++ b/src/stm/ao_boot.h @@ -19,6 +19,15 @@ #define _AO_BOOT_H_ void -ao_reboot_application(void); +ao_boot_chain(uint32_t *base); + +void +ao_boot_check_pin(void); + +void +ao_boot_check_chain(void); + +void +ao_boot_reboot(uint32_t *base); #endif /* _AO_BOOT_H_ */ diff --git a/src/stm/ao_boot_chain.c b/src/stm/ao_boot_chain.c new file mode 100644 index 00000000..9c63272b --- /dev/null +++ b/src/stm/ao_boot_chain.c @@ -0,0 +1,62 @@ +/* + * Copyright © 2013 Keith Packard + * + * 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 +#include + +void +ao_boot_chain(uint32_t *base) +{ + uint32_t sp; + uint32_t pc; + + sp = base[0]; + pc = base[1]; + asm ("mov sp, %0" : : "r" (sp)); + asm ("mov lr, %0" : : "r" (pc)); + asm ("bx lr"); +} + +#define AO_BOOT_SIGNAL 0x5a5aa5a5 +#define AO_BOOT_CHECK 0xc3c33c3c + +struct ao_boot { + uint32_t *base; + uint32_t signal; + uint32_t check; +}; + +static struct ao_boot __attribute__ ((section(".boot"))) ao_boot; + +void +ao_boot_check_chain(void) +{ + if (ao_boot.signal == AO_BOOT_SIGNAL && ao_boot.check == AO_BOOT_CHECK) { + ao_boot.signal = 0; + ao_boot.check = 0; + ao_boot_chain(ao_boot.base); + } +} + +void +ao_boot_reboot(uint32_t *base) +{ + ao_boot.base = base; + ao_boot.signal = AO_BOOT_SIGNAL; + ao_boot.check = AO_BOOT_CHECK; + ao_arch_reboot(); +} diff --git a/src/stm/ao_boot_pin.c b/src/stm/ao_boot_pin.c new file mode 100644 index 00000000..03b0214f --- /dev/null +++ b/src/stm/ao_boot_pin.c @@ -0,0 +1,43 @@ +/* + * Copyright © 2013 Keith Packard + * + * 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 +#include +#include + +void +ao_boot_check_pin(void) +{ + uint16_t v; + + /* Enable power interface clock */ + stm_rcc.apb1enr |= (1 << STM_RCC_APB1ENR_PWREN); + + /* Enable the input pin */ + ao_enable_input(&AO_BOOT_APPLICATION_GPIO, AO_BOOT_APPLICATION_PIN, + AO_BOOT_APPLICATION_MODE); + + /* Read the value */ + v = stm_gpio_get(&AO_BOOT_APPLICATION_GPIO, AO_BOOT_APPLICATION_PIN); + + /* Reset the chip to turn off the port and the power interface clock */ + ao_gpio_set_mode(&AO_BOOT_APPLICATION_GPIO, AO_BOOT_APPLICATION_PIN, 0); + ao_disable_port(&AO_BOOT_APPLICATION_GPIO); + stm_rcc.apb1enr &= ~(1 << STM_RCC_APB1ENR_PWREN); + if (v == AO_BOOT_APPLICATION_VALUE) + ao_boot_chain(AO_BOOT_APPLICATION_BASE); +} diff --git a/src/stm/ao_interrupt.c b/src/stm/ao_interrupt.c index 9e756219..49156285 100644 --- a/src/stm/ao_interrupt.c +++ b/src/stm/ao_interrupt.c @@ -18,6 +18,7 @@ #include #include "stm32l.h" #include +#include extern void main(void); extern char __stack__; @@ -38,67 +39,14 @@ void stm_ignore_isr(void) const void *stm_interrupt_vector[]; -#define BOOT_FETCH(o) (*((uint32_t *) (AO_BOOT_APPLICATION_BASE + (o)))) - -#ifdef AO_BOOT_APPLICATION_PIN -#include - -#define AO_BOOT_APPLICATION 0x5a5aa5a5 -#define AO_BOOT_APPLICATION_CHECK 0xc3c33c3c - -static uint32_t ao_boot_application; -static uint32_t ao_boot_application_check; - -static void -ao_boot_chain(void) { - uint32_t sp; - uint32_t pc; - - sp = BOOT_FETCH(0); - pc = BOOT_FETCH(4); - asm ("mov sp, %0" : : "r" (sp)); - asm ("mov lr, %0" : : "r" (pc)); - asm ("bx lr"); -} - -void -ao_reboot_application(void) +void start(void) { - ao_boot_application = AO_BOOT_APPLICATION; - ao_boot_application_check = AO_BOOT_APPLICATION_CHECK; - ao_arch_reboot(); -} - +#ifdef AO_BOOT_CHAIN + ao_boot_check_chain(); #endif - -void start(void) { -#ifdef AO_BOOT_APPLICATION_PIN - uint16_t v; - - if (ao_boot_application == AO_BOOT_APPLICATION && - ao_boot_application_check == AO_BOOT_APPLICATION_CHECK) { - ao_boot_application = 0; - ao_boot_application_check = 0; - ao_boot_chain(); - } - /* Enable power interface clock */ - stm_rcc.apb1enr |= (1 << STM_RCC_APB1ENR_PWREN); - - /* Enable the input pin */ - ao_enable_input(&AO_BOOT_APPLICATION_GPIO, AO_BOOT_APPLICATION_PIN, - AO_BOOT_APPLICATION_MODE); - - /* Read the value */ - v = stm_gpio_get(&AO_BOOT_APPLICATION_GPIO, AO_BOOT_APPLICATION_PIN); - - /* Reset the chip to turn off the port and the power interface clock */ - ao_gpio_set_mode(&AO_BOOT_APPLICATION_GPIO, AO_BOOT_APPLICATION_PIN, 0); - ao_disable_port(&AO_BOOT_APPLICATION_GPIO); - stm_rcc.apb1enr &= ~(1 << STM_RCC_APB1ENR_PWREN); - if (v == AO_BOOT_APPLICATION_VALUE) - ao_boot_chain(); +#ifdef AO_BOOT_PIN + ao_boot_check_pin(); #endif - /* Set interrupt vector table offset */ stm_nvic.vto = (uint32_t) &stm_interrupt_vector; memcpy(&__data_start__, &__text_end__, &__data_end__ - &__data_start__); -- cgit v1.2.3 From db7f17980c303e442f88c8a4168351dbc2c0b1a0 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 23 Mar 2013 02:17:04 -0700 Subject: altos: Mark .boot section as (NOLOAD) For some reason, the silly linker marks things in section .boot as data rather than bss, so they'd end up initialized by default. Force them to be NOLOAD so they preserve values across reboot so that boot chaining works properly. Signed-off-by: Keith Packard --- src/stm/altos-application.ld | 6 ++++-- src/stm/altos-loader.ld | 2 +- 2 files changed, 5 insertions(+), 3 deletions(-) (limited to 'src/stm') diff --git a/src/stm/altos-application.ld b/src/stm/altos-application.ld index 5110da84..5bdfcd05 100644 --- a/src/stm/altos-application.ld +++ b/src/stm/altos-application.ld @@ -45,14 +45,14 @@ SECTIONS { .ARM.exidx : { *(.ARM.exidx* .gnu.linkonce.armexidx.*) - __text_end__ = .; } > rom + __text_end__ = .; /* Boot data which must live at the start of ram so that * the application and bootloader share the same addresses. * This must be all uninitialized data */ - .boot : { + .boot (NOLOAD) : { __boot_start__ = .; *(.boot) . = ALIGN(4); @@ -64,6 +64,7 @@ SECTIONS { .data : { __data_start__ = .; *(.data) /* initialized data */ + . = ALIGN(4); __data_end__ = .; } >ram AT>rom @@ -71,6 +72,7 @@ SECTIONS { __bss_start__ = .; *(.bss) *(COMMON) + . = ALIGN(4); __bss_end__ = .; } >ram diff --git a/src/stm/altos-loader.ld b/src/stm/altos-loader.ld index 2e36dce9..7184b96c 100644 --- a/src/stm/altos-loader.ld +++ b/src/stm/altos-loader.ld @@ -52,7 +52,7 @@ SECTIONS { * the application and bootloader share the same addresses. * This must be all uninitialized data */ - .boot : { + .boot (NOLOAD) : { __boot_start__ = .; *(.boot) . = ALIGN(4); -- cgit v1.2.3 From 35ef1f17e3efaa6d586ab7bb301f8133d52023b6 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 23 Mar 2013 02:18:55 -0700 Subject: altos: Validate boot chain start address If the first block of boot memory has been smashed, and the start address is bogus, don't bother trying to jump to the application. This makes the system more resiliant to flash failures, presuming the loader erases the first block, programs the other blocks and then finally comes back to program the first block. Signed-off-by: Keith Packard --- src/stm/ao_boot_chain.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'src/stm') diff --git a/src/stm/ao_boot_chain.c b/src/stm/ao_boot_chain.c index 9c63272b..668f6e6d 100644 --- a/src/stm/ao_boot_chain.c +++ b/src/stm/ao_boot_chain.c @@ -26,9 +26,11 @@ ao_boot_chain(uint32_t *base) sp = base[0]; pc = base[1]; - asm ("mov sp, %0" : : "r" (sp)); - asm ("mov lr, %0" : : "r" (pc)); - asm ("bx lr"); + if (0x08000100 <= pc && pc <= 0x08200000) { + asm ("mov sp, %0" : : "r" (sp)); + asm ("mov lr, %0" : : "r" (pc)); + asm ("bx lr"); + } } #define AO_BOOT_SIGNAL 0x5a5aa5a5 -- cgit v1.2.3 From ac6b4fca0970faa0a537a813242585693b839469 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 23 Mar 2013 02:21:27 -0700 Subject: altos: Fix STM flash programming Wait for flash to go non-busy after writing or erasing a page and before jumping back out of the RAM code. Export a separate 'erase' operation for testing. Re-lock flash after every operation. Signed-off-by: Keith Packard --- src/stm/ao_flash_stm.c | 46 +++++++++++++++++++++++++++++++++++----------- src/stm/ao_flash_stm.h | 3 +++ 2 files changed, 38 insertions(+), 11 deletions(-) (limited to 'src/stm') diff --git a/src/stm/ao_flash_stm.c b/src/stm/ao_flash_stm.c index b3ef6a62..b4d47024 100644 --- a/src/stm/ao_flash_stm.c +++ b/src/stm/ao_flash_stm.c @@ -39,6 +39,8 @@ ao_flash_pecr_unlock(void) /* Unlock Data EEPROM and FLASH_PECR register */ stm_flash.pekeyr = STM_FLASH_PEKEYR_PEKEY1; stm_flash.pekeyr = STM_FLASH_PEKEYR_PEKEY2; + if (ao_flash_pecr_is_locked()) + ao_panic(AO_PANIC_FLASH); } static void @@ -50,6 +52,14 @@ ao_flash_pgr_unlock(void) /* Unlock program memory */ stm_flash.prgkeyr = STM_FLASH_PRGKEYR_PRGKEY1; stm_flash.prgkeyr = STM_FLASH_PRGKEYR_PRGKEY2; + if (ao_flash_pgr_is_locked()) + ao_panic(AO_PANIC_FLASH); +} + +static void +ao_flash_lock(void) +{ + stm_flash.pecr |= (1 << STM_FLASH_PECR_OPTLOCK) | (1 << STM_FLASH_PECR_PRGLOCK) | (1 << STM_FLASH_PECR_PELOCK); } static void @@ -59,32 +69,45 @@ ao_flash_wait_bsy(void) ; } -static void +static void __attribute__ ((section(".text.ram"),noinline)) +_ao_flash_erase_page(uint32_t *page) +{ + stm_flash.pecr |= (1 << STM_FLASH_PECR_ERASE) | (1 << STM_FLASH_PECR_PROG); + + *page = 0x00000000; + + while (stm_flash.sr & (1 << STM_FLASH_SR_BSY)) + ; +} + +void ao_flash_erase_page(uint32_t *page) { ao_flash_pecr_unlock(); ao_flash_pgr_unlock(); - stm_flash.pecr |= (1 << STM_FLASH_PECR_ERASE); - stm_flash.pecr |= (1 << STM_FLASH_PECR_PROG); - - ao_flash_wait_bsy(); + _ao_flash_erase_page(page); - *page = 0x00000000; + ao_flash_lock(); } static void __attribute__ ((section(".text.ram"), noinline)) - _ao_flash_half_page(uint32_t *dst, uint32_t *src) +_ao_flash_half_page(uint32_t *dst, uint32_t *src) { uint8_t i; stm_flash.pecr |= (1 << STM_FLASH_PECR_FPRG); stm_flash.pecr |= (1 << STM_FLASH_PECR_PROG); + while (stm_flash.sr & (1 << STM_FLASH_SR_BSY)) ; - - for (i = 0; i < 32; i++) + + for (i = 0; i < 32; i++) { *dst++ = *src++; + } + + while (stm_flash.sr & (1 << STM_FLASH_SR_BSY)) + ; } void @@ -93,11 +116,12 @@ ao_flash_page(uint32_t *page, uint32_t *src) uint8_t h; ao_flash_erase_page(page); + ao_flash_pecr_unlock(); + ao_flash_pgr_unlock(); for (h = 0; h < 2; h++) { - ao_flash_pecr_unlock(); - ao_flash_pgr_unlock(); _ao_flash_half_page(page, src); page += 32; src += 32; } + ao_flash_lock(); } diff --git a/src/stm/ao_flash_stm.h b/src/stm/ao_flash_stm.h index b4067d8d..09ca5ac1 100644 --- a/src/stm/ao_flash_stm.h +++ b/src/stm/ao_flash_stm.h @@ -18,6 +18,9 @@ #ifndef _AO_FLASH_STM_H_ #define _AO_FLASH_STM_H_ +void +ao_flash_erase_page(uint32_t *page); + void ao_flash_page(uint32_t *page, uint32_t *src); -- cgit v1.2.3 From ab1cbc0f51ddf897a3a7a768862d9dfe26a6c14d Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 24 Mar 2013 15:26:26 -0700 Subject: altos/stm: Add .elf to .ihx rule Uses objcopy -O ihex to extract the initialized bits from an elf file Signed-off-by: Keith Packard --- src/stm/Makefile.defs | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'src/stm') diff --git a/src/stm/Makefile.defs b/src/stm/Makefile.defs index 1480f0b3..c8bb7d70 100644 --- a/src/stm/Makefile.defs +++ b/src/stm/Makefile.defs @@ -7,6 +7,11 @@ vpath load_csv.5c ../kalman vpath matrix.5c ../kalman vpath ao-make-product.5c ../util +.SUFFIXES: .elf .ihx + +.elf.ihx: + objcopy -O ihex $*.elf $@ + CC=arm-none-eabi-gcc SAT=/opt/cortex SAT_CLIB=$(SAT)/lib/pdclib-cortex-m3.a -- cgit v1.2.3 From 7d98fc5d3f106f3063608a2e5c69d9359061437a Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 24 Mar 2013 15:27:42 -0700 Subject: altos/stm: Add comments to the .ld files explaining how the romconfig stuff works Would be nice to be able to explicitly define addresses for the romconfig variables, but I can't figure out how to make that work. Instead, just explicitly load the files in teh right order to make things land in the right places. Signed-off-by: Keith Packard --- src/stm/altos-application.ld | 12 +++++++++++- src/stm/altos-loader.ld | 11 ++++++++++- 2 files changed, 21 insertions(+), 2 deletions(-) (limited to 'src/stm') diff --git a/src/stm/altos-application.ld b/src/stm/altos-application.ld index 5bdfcd05..c94c06b8 100644 --- a/src/stm/altos-application.ld +++ b/src/stm/altos-application.ld @@ -35,9 +35,19 @@ SECTIONS { . = ORIGIN(rom) + 0x100; + + /* Ick. What I want is to specify the + * addresses of some global constants so + * that I can find them across versions + * of the application. I can't figure out + * how to make gnu ld do that, so instead + * we just load the two files that include + * these defines in the right order here and + * expect things to 'just work'. Don't change + * the contents of those files, ok? + */ ao_romconfig.o(.romconfig*) ao_product.o(.romconfig*) - *(.text*) /* Executable code */ *(.rodata*) /* Constants */ diff --git a/src/stm/altos-loader.ld b/src/stm/altos-loader.ld index 7184b96c..14b45351 100644 --- a/src/stm/altos-loader.ld +++ b/src/stm/altos-loader.ld @@ -35,9 +35,18 @@ SECTIONS { . = ORIGIN(rom) + 0x100; + /* Ick. What I want is to specify the + * addresses of some global constants so + * that I can find them across versions + * of the application. I can't figure out + * how to make gnu ld do that, so instead + * we just load the two files that include + * these defines in the right order here and + * expect things to 'just work'. Don't change + * the contents of those files, ok? + */ ao_romconfig.o(.romconfig*) ao_product.o(.romconfig*) - *(.text) /* Executable code */ *(.rodata) /* Constants */ -- cgit v1.2.3 From a453e2245996854e722346789f972fd088e33ba8 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 22 Apr 2013 20:29:56 -0500 Subject: altos/stm: Don't define task macros when not tasking The necessary data structures aren't defined in this case. Signed-off-by: Keith Packard --- src/stm/ao_arch_funcs.h | 3 +++ 1 file changed, 3 insertions(+) (limited to 'src/stm') diff --git a/src/stm/ao_arch_funcs.h b/src/stm/ao_arch_funcs.h index 2c0f173c..1e78cabc 100644 --- a/src/stm/ao_arch_funcs.h +++ b/src/stm/ao_arch_funcs.h @@ -267,6 +267,7 @@ ao_arch_memory_barrier() { asm volatile("" ::: "memory"); } +#if HAS_TASK static inline void ao_arch_init_stack(struct ao_task *task, void *start) { @@ -349,6 +350,8 @@ static inline void ao_arch_start_scheduler(void) { #define ao_arch_isr_stack() +#endif + #define ao_arch_wait_interrupt() do { \ asm(".global ao_idle_loc\n\twfi\nao_idle_loc:"); \ ao_arch_release_interrupts(); \ -- cgit v1.2.3 From 02681adbc5919bd3713788da352aa36ace619ef4 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 22 Apr 2013 20:30:31 -0500 Subject: altos/stm: Allow core timer to be excluded from build This removes all of the support for the base 100Hz timer from the system, saving space when not needed Signed-off-by: Keith Packard --- src/stm/ao_timer.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'src/stm') diff --git a/src/stm/ao_timer.c b/src/stm/ao_timer.c index 5976eb3f..daf2f400 100644 --- a/src/stm/ao_timer.c +++ b/src/stm/ao_timer.c @@ -18,6 +18,11 @@ #include "ao.h" #include +#ifndef HAS_TICK +#define HAS_TICK 1 +#endif + +#if HAS_TICK volatile AO_TICK_TYPE ao_tick_count; AO_TICK_TYPE @@ -88,6 +93,8 @@ ao_timer_init(void) (STM_SYSTICK_CSR_CLKSOURCE_HCLK_8 << STM_SYSTICK_CSR_CLKSOURCE)); } +#endif + void ao_clock_init(void) { -- cgit v1.2.3 From 6cd015b8b6b02bd8e0ce28f248426ae75c242b53 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 22 Apr 2013 20:32:18 -0500 Subject: altos/stm: Shrink stm flash loader to < 4kB Saves 4kB of flash space for applications. Signed-off-by: Keith Packard --- src/stm-flash/Makefile | 7 +--- src/stm-flash/ao_pins.h | 3 ++ src/stm-flash/ao_stm_flash.c | 96 ++++++++++++++++++-------------------------- src/stm/altos-loader.ld | 16 +------- 4 files changed, 46 insertions(+), 76 deletions(-) (limited to 'src/stm') diff --git a/src/stm-flash/Makefile b/src/stm-flash/Makefile index 46bc61af..a4dd5ab8 100644 --- a/src/stm-flash/Makefile +++ b/src/stm-flash/Makefile @@ -20,14 +20,11 @@ ALTOS_SRC = \ ao_boot_chain.c \ ao_boot_pin.c \ ao_product.c \ - ao_romconfig.c \ - ao_task.c \ + ao_notask.c \ ao_timer.c \ - ao_mutex.c \ ao_usb_stm.c \ ao_stdio.c \ - ao_flash_stm.c \ - ao_cmd.c + ao_flash_stm.c PRODUCT=StmFlash-v0.0 PRODUCT_DEF=-DSTM_FLASH diff --git a/src/stm-flash/ao_pins.h b/src/stm-flash/ao_pins.h index 048fc828..6779fc42 100644 --- a/src/stm-flash/ao_pins.h +++ b/src/stm-flash/ao_pins.h @@ -47,6 +47,9 @@ #define HAS_USB 1 #define USE_USB_STDIN 1 #define HAS_BEEP 0 +#define HAS_TASK 0 +#define HAS_ECHO 0 +#define HAS_TICK 0 #define PACKET_HAS_SLAVE 0 diff --git a/src/stm-flash/ao_stm_flash.c b/src/stm-flash/ao_stm_flash.c index 344bceb9..f0abe7fb 100644 --- a/src/stm-flash/ao_stm_flash.c +++ b/src/stm-flash/ao_stm_flash.c @@ -26,6 +26,14 @@ ao_panic(uint8_t reason) for (;;); } +void +ao_put_string(__code char *s) +{ + char c; + while ((c = *s++)) + putchar(c); +} + void ao_application(void) { @@ -33,30 +41,35 @@ ao_application(void) } static uint32_t -ao_cmd_hex32(void) +ao_get_hex32(void) { - __pdata uint8_t r = ao_cmd_lex_error; int8_t n; uint32_t v = 0; - ao_cmd_white(); + for (;;) { + n = getchar(); + if (n != ' ') + break; + } for(;;) { - n = ao_cmd_hexchar(ao_cmd_lex_c); - if (n < 0) + if ('0' <= n && n <= '9') + n = n - '0'; + else if ('a' <= n && n <= 'f') + n = n - ('a' - 10); + else if ('A' <= n && n <= 'F') + n = n - ('A' - 10); + else break; v = (v << 4) | n; - r = ao_cmd_success; - ao_cmd_lex(); + n = getchar(); } - if (r != ao_cmd_success) - ao_cmd_status = r; return v; } void ao_block_erase(void) { - uint32_t addr = ao_cmd_hex32(); + uint32_t addr = ao_get_hex32(); uint32_t *p = (uint32_t *) addr; ao_flash_erase_page(p); @@ -65,7 +78,7 @@ ao_block_erase(void) void ao_block_write(void) { - uint32_t addr = ao_cmd_hex32(); + uint32_t addr = ao_get_hex32(); uint32_t *p = (uint32_t *) addr; union { uint8_t data8[256]; @@ -82,45 +95,17 @@ ao_block_write(void) ao_flash_page(p, u.data32); } -static void -puthex(uint8_t c) -{ - c &= 0xf; - if (c < 10) - c += '0'; - else - c += 'a' - 10; - putchar (c); -} - void ao_block_read(void) { - uint32_t addr = ao_cmd_hex32(); + uint32_t addr = ao_get_hex32(); uint8_t *p = (uint8_t *) addr; uint16_t i; uint8_t c; for (i = 0; i < 256; i++) { c = *p++; - (*ao_stdios[ao_cur_stdio].putchar)(c); - } -} - -void -ao_block_read_hex(void) -{ - uint32_t addr = ao_cmd_hex32(); - uint8_t *p = (uint8_t *) addr; - uint16_t i; - uint8_t c; - - for (i = 0; i < 256; i++) { - c = *p++; - puthex(c>>4); - puthex(c); - if ((i & 0xf) == 0xf) - putchar('\n'); + putchar(c); } } @@ -133,15 +118,18 @@ ao_show_version(void) ao_put_string("software-version "); puts(ao_version); } -__code struct ao_cmds ao_flash_cmds[] = { - { ao_show_version, "v\0Version" }, - { ao_application, "a\0Switch to application" }, - { ao_block_erase, "X \0Erase block." }, - { ao_block_write, "W \0Write block. 256 binary bytes follow newline" }, - { ao_block_read, "R \0Read block. Returns 256 binary bytes" }, - { ao_block_read_hex, "H \0Hex read block. Returns 256 bytes in hex" }, - { 0, NULL }, -}; +static void +ao_flash_task(void) { + for (;;) { + switch (getchar()) { + case 'v': ao_show_version(); break; + case 'a': ao_application(); break; + case 'X': ao_block_erase(); break; + case 'W': ao_block_write(); break; + case 'R': ao_block_read(); break; + } + } +} int @@ -149,15 +137,11 @@ main(void) { ao_clock_init(); - ao_task_init(); - - ao_timer_init(); +// ao_timer_init(); // ao_dma_init(); - ao_cmd_init(); // ao_exti_init(); ao_usb_init(); - ao_cmd_register(&ao_flash_cmds[0]); - ao_start_scheduler(); + ao_flash_task(); return 0; } diff --git a/src/stm/altos-loader.ld b/src/stm/altos-loader.ld index 14b45351..78649be2 100644 --- a/src/stm/altos-loader.ld +++ b/src/stm/altos-loader.ld @@ -32,21 +32,7 @@ SECTIONS { .text : { __text_start__ = .; *(.interrupt) /* Interrupt vectors */ - - . = ORIGIN(rom) + 0x100; - - /* Ick. What I want is to specify the - * addresses of some global constants so - * that I can find them across versions - * of the application. I can't figure out - * how to make gnu ld do that, so instead - * we just load the two files that include - * these defines in the right order here and - * expect things to 'just work'. Don't change - * the contents of those files, ok? - */ - ao_romconfig.o(.romconfig*) - ao_product.o(.romconfig*) + *(.romconfig) *(.text) /* Executable code */ *(.rodata) /* Constants */ -- cgit v1.2.3 From 8ded61d59888c79ef1f94e664b5fb770841a801a Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 22 Apr 2013 20:33:33 -0500 Subject: altos/stm: Provide another 4kB of flash space for apps With the flash loader now < 4kB, we can use the spare 4kB for applications Signed-off-by: Keith Packard --- src/stm-flash/ao_pins.h | 2 +- src/stm/altos-application.ld | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'src/stm') diff --git a/src/stm-flash/ao_pins.h b/src/stm-flash/ao_pins.h index 6779fc42..1c00675b 100644 --- a/src/stm-flash/ao_pins.h +++ b/src/stm-flash/ao_pins.h @@ -75,6 +75,6 @@ #define AO_BOOT_APPLICATION_PIN 0 #define AO_BOOT_APPLICATION_VALUE 1 #define AO_BOOT_APPLICATION_MODE 0 -#define AO_BOOT_APPLICATION_BASE ((uint32_t *) 0x2000) +#define AO_BOOT_APPLICATION_BASE ((uint32_t *) 0x1000) #endif /* _AO_PINS_H_ */ diff --git a/src/stm/altos-application.ld b/src/stm/altos-application.ld index c94c06b8..6affc376 100644 --- a/src/stm/altos-application.ld +++ b/src/stm/altos-application.ld @@ -16,7 +16,7 @@ */ MEMORY { - rom (rx) : ORIGIN = 0x08002000, LENGTH = 120K + rom (rx) : ORIGIN = 0x08001000, LENGTH = 124K ram (!w) : ORIGIN = 0x20000000, LENGTH = 16K } -- cgit v1.2.3 From dfc268e0021e1cd3045f73339a749d292a6a6300 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 22 Apr 2013 20:35:57 -0500 Subject: altos: Use flash loader on all STM products Includes the boot chain stuff Signed-off-by: Keith Packard --- src/core/ao_cmd.c | 15 +++++++ src/megadongle-v0.1/Makefile | 1 + src/stm-demo/Makefile | 2 +- src/stm-demo/ao_demo.c | 8 ---- src/stm-flash/ao_pins.h | 1 - src/stm/altos-application.ld | 95 ------------------------------------------- src/stm/altos.ld | 35 +++++++++++++--- src/stm/ao_arch.h | 5 +++ src/stm/ao_boot.h | 5 +++ src/telegps-v0.1/Makefile | 1 + src/telelco-v0.1/Makefile | 1 + src/telemega-v0.1/Makefile | 1 + src/telescience-v0.2/Makefile | 1 + 13 files changed, 60 insertions(+), 111 deletions(-) delete mode 100644 src/stm/altos-application.ld (limited to 'src/stm') diff --git a/src/core/ao_cmd.c b/src/core/ao_cmd.c index 7da2384f..188b8bb4 100644 --- a/src/core/ao_cmd.c +++ b/src/core/ao_cmd.c @@ -385,6 +385,18 @@ ao_cmd(void) } } +#if HAS_BOOT_LOADER + +#include + +static void +ao_loader(void) +{ + flush(); + ao_boot_loader(); +} +#endif + __xdata struct ao_task ao_cmd_task; __code struct ao_cmds ao_base_cmds[] = { @@ -396,6 +408,9 @@ __code struct ao_cmds ao_base_cmds[] = { { ao_reboot, "r eboot\0Reboot" }, #if HAS_VERSION { version, "v\0Version" }, +#endif +#if HAS_BOOT_LOADER + { ao_loader, "X\0Switch to boot loader" }, #endif { 0, NULL }, }; diff --git a/src/megadongle-v0.1/Makefile b/src/megadongle-v0.1/Makefile index fe392ce1..7f12963f 100644 --- a/src/megadongle-v0.1/Makefile +++ b/src/megadongle-v0.1/Makefile @@ -28,6 +28,7 @@ INC = \ #STACK_GUARD_DEF=-DHAS_STACK_GUARD=1 ALTOS_SRC = \ + ao_boot_chain.c \ ao_interrupt.c \ ao_product.c \ ao_romconfig.c \ diff --git a/src/stm-demo/Makefile b/src/stm-demo/Makefile index e84a7675..d1f825db 100644 --- a/src/stm-demo/Makefile +++ b/src/stm-demo/Makefile @@ -56,7 +56,7 @@ OBJ=$(SRC:.c=.o) all: $(ELF) $(IHX) -LDFLAGS=-L../stm -Wl,-Taltos-application.ld +LDFLAGS=-L../stm -Wl,-Taltos.ld $(ELF): Makefile $(OBJ) $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $@ $(OBJ) $(SAT_CLIB) -lgcc diff --git a/src/stm-demo/ao_demo.c b/src/stm-demo/ao_demo.c index ec572fdc..5677cdf4 100644 --- a/src/stm-demo/ao_demo.c +++ b/src/stm-demo/ao_demo.c @@ -169,13 +169,6 @@ ao_event(void) } -static void -ao_boot_loader(void) -{ - flush(); - ao_boot_reboot((uint32_t *) 0); -} - __code struct ao_cmds ao_demo_cmds[] = { { ao_dma_test, "D\0DMA test" }, { ao_spi_write, "W\0SPI write" }, @@ -183,7 +176,6 @@ __code struct ao_cmds ao_demo_cmds[] = { { ao_i2c_write, "i\0I2C write" }, { ao_temp, "t\0Show temp" }, { ao_event, "e\0Monitor event queue" }, - { ao_boot_loader, "L\0Reboot to boot loader" }, { 0, NULL } }; diff --git a/src/stm-flash/ao_pins.h b/src/stm-flash/ao_pins.h index 1c00675b..8fb56f7b 100644 --- a/src/stm-flash/ao_pins.h +++ b/src/stm-flash/ao_pins.h @@ -75,6 +75,5 @@ #define AO_BOOT_APPLICATION_PIN 0 #define AO_BOOT_APPLICATION_VALUE 1 #define AO_BOOT_APPLICATION_MODE 0 -#define AO_BOOT_APPLICATION_BASE ((uint32_t *) 0x1000) #endif /* _AO_PINS_H_ */ diff --git a/src/stm/altos-application.ld b/src/stm/altos-application.ld deleted file mode 100644 index 6affc376..00000000 --- a/src/stm/altos-application.ld +++ /dev/null @@ -1,95 +0,0 @@ -/* - * Copyright © 2012 Keith Packard - * - * 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. - */ - -MEMORY { - rom (rx) : ORIGIN = 0x08001000, LENGTH = 124K - ram (!w) : ORIGIN = 0x20000000, LENGTH = 16K -} - -INCLUDE registers.ld - -EXTERN (stm_interrupt_vector) - -SECTIONS { - /* - * Rom contents - */ - - .text ORIGIN(rom) : { - __text_start__ = .; - *(.interrupt) /* Interrupt vectors */ - - . = ORIGIN(rom) + 0x100; - - - /* Ick. What I want is to specify the - * addresses of some global constants so - * that I can find them across versions - * of the application. I can't figure out - * how to make gnu ld do that, so instead - * we just load the two files that include - * these defines in the right order here and - * expect things to 'just work'. Don't change - * the contents of those files, ok? - */ - ao_romconfig.o(.romconfig*) - ao_product.o(.romconfig*) - *(.text*) /* Executable code */ - *(.rodata*) /* Constants */ - - } > rom - - .ARM.exidx : { - *(.ARM.exidx* .gnu.linkonce.armexidx.*) - } > rom - __text_end__ = .; - - /* Boot data which must live at the start of ram so that - * the application and bootloader share the same addresses. - * This must be all uninitialized data - */ - .boot (NOLOAD) : { - __boot_start__ = .; - *(.boot) - . = ALIGN(4); - __boot_end__ = .; - } >ram - - /* Data -- relocated to RAM, but written to ROM - */ - .data : { - __data_start__ = .; - *(.data) /* initialized data */ - . = ALIGN(4); - __data_end__ = .; - } >ram AT>rom - - .bss : { - __bss_start__ = .; - *(.bss) - *(COMMON) - . = ALIGN(4); - __bss_end__ = .; - } >ram - - PROVIDE(__stack__ = ORIGIN(ram) + LENGTH(ram)); - PROVIDE(end = .); -} - -ENTRY(start); - - diff --git a/src/stm/altos.ld b/src/stm/altos.ld index d218e992..3106cc3b 100644 --- a/src/stm/altos.ld +++ b/src/stm/altos.ld @@ -16,7 +16,7 @@ */ MEMORY { - rom (rx) : ORIGIN = 0x08000000, LENGTH = 128K + rom (rx) : ORIGIN = 0x08001000, LENGTH = 124K ram (!w) : ORIGIN = 0x20000000, LENGTH = 15872 stack (!w) : ORIGIN = 0x20003e00, LENGTH = 512 } @@ -36,9 +36,19 @@ SECTIONS { . = ORIGIN(rom) + 0x100; + + /* Ick. What I want is to specify the + * addresses of some global constants so + * that I can find them across versions + * of the application. I can't figure out + * how to make gnu ld do that, so instead + * we just load the two files that include + * these defines in the right order here and + * expect things to 'just work'. Don't change + * the contents of those files, ok? + */ ao_romconfig.o(.romconfig*) ao_product.o(.romconfig*) - *(.text*) /* Executable code */ *(.rodata*) /* Constants */ @@ -46,21 +56,34 @@ SECTIONS { .ARM.exidx : { *(.ARM.exidx* .gnu.linkonce.armexidx.*) - __text_end__ = .; } > rom + __text_end__ = .; + + /* Boot data which must live at the start of ram so that + * the application and bootloader share the same addresses. + * This must be all uninitialized data + */ + .boot (NOLOAD) : { + __boot_start__ = .; + *(.boot) + . = ALIGN(4); + __boot_end__ = .; + } >ram /* Data -- relocated to RAM, but written to ROM */ - .data ORIGIN(ram) : AT (ADDR(.ARM.exidx) + SIZEOF (.ARM.exidx)) { + .data : { __data_start__ = .; *(.data) /* initialized data */ + . = ALIGN(4); __data_end__ = .; - __bss_start__ = .; - } >ram + } >ram AT>rom .bss : { + __bss_start__ = .; *(.bss) *(COMMON) + . = ALIGN(4); __bss_end__ = .; } >ram diff --git a/src/stm/ao_arch.h b/src/stm/ao_arch.h index 27a942f2..cc83eac2 100644 --- a/src/stm/ao_arch.h +++ b/src/stm/ao_arch.h @@ -129,5 +129,10 @@ extern const uint32_t ao_radio_cal; void ao_adc_init(); +#define AO_BOOT_APPLICATION_BASE ((uint32_t *) 0x1000) +#define AO_BOOT_LOADER_BASE ((uint32_t *) 0x0) +#define HAS_BOOT_LOADER 1 + #endif /* _AO_ARCH_H_ */ + diff --git a/src/stm/ao_boot.h b/src/stm/ao_boot.h index 3e8c50ba..862e8755 100644 --- a/src/stm/ao_boot.h +++ b/src/stm/ao_boot.h @@ -30,4 +30,9 @@ ao_boot_check_chain(void); void ao_boot_reboot(uint32_t *base); +static inline void +ao_boot_loader(void) { + ao_boot_reboot(AO_BOOT_LOADER_BASE); +} + #endif /* _AO_BOOT_H_ */ diff --git a/src/telegps-v0.1/Makefile b/src/telegps-v0.1/Makefile index aae37660..2c41235b 100644 --- a/src/telegps-v0.1/Makefile +++ b/src/telegps-v0.1/Makefile @@ -33,6 +33,7 @@ INC = \ #STACK_GUARD_DEF=-DHAS_STACK_GUARD=1 ALTOS_SRC = \ + ao_boot_chain.c \ ao_interrupt.c \ ao_product.c \ ao_romconfig.c \ diff --git a/src/telelco-v0.1/Makefile b/src/telelco-v0.1/Makefile index a4a83d02..24083308 100644 --- a/src/telelco-v0.1/Makefile +++ b/src/telelco-v0.1/Makefile @@ -30,6 +30,7 @@ INC = \ #PROFILE_DEF=-DAO_PROFILE=1 ALTOS_SRC = \ + ao_boot_chain.c \ ao_interrupt.c \ ao_product.c \ ao_romconfig.c \ diff --git a/src/telemega-v0.1/Makefile b/src/telemega-v0.1/Makefile index 16393ea0..a72d08f2 100644 --- a/src/telemega-v0.1/Makefile +++ b/src/telemega-v0.1/Makefile @@ -45,6 +45,7 @@ INC = \ #STACK_GUARD_DEF=-DHAS_STACK_GUARD=1 ALTOS_SRC = \ + ao_boot_chain.c \ ao_interrupt.c \ ao_product.c \ ao_romconfig.c \ diff --git a/src/telescience-v0.2/Makefile b/src/telescience-v0.2/Makefile index fbeeb75c..f16ef268 100644 --- a/src/telescience-v0.2/Makefile +++ b/src/telescience-v0.2/Makefile @@ -28,6 +28,7 @@ INC = \ #STACK_GUARD_DEF=-DHAS_STACK_GUARD=1 ALTOS_SRC = \ + ao_boot_chain.c \ ao_interrupt.c \ ao_product.c \ ao_romconfig.c \ -- cgit v1.2.3 From afad5ae893a48785f3b50ff4125dc78648343a2d Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 22 Apr 2013 20:08:35 -0600 Subject: altos/stm-flash: Check target flash address against AO_BOOT_APPLICATION_BASE Allows that value to change Signed-off-by: Keith Packard --- src/stm-flash/ao_stm_flash.c | 2 +- src/stm/ao_arch.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'src/stm') diff --git a/src/stm-flash/ao_stm_flash.c b/src/stm-flash/ao_stm_flash.c index f0abe7fb..df06bb09 100644 --- a/src/stm-flash/ao_stm_flash.c +++ b/src/stm-flash/ao_stm_flash.c @@ -86,7 +86,7 @@ ao_block_write(void) } u; uint16_t i; - if (addr < 0x08002000 || 0x08200000 <= addr) { + if (addr < (uint32_t) AO_BOOT_APPLICATION_BASE) { ao_put_string("Invalid address\n"); return; } diff --git a/src/stm/ao_arch.h b/src/stm/ao_arch.h index cc83eac2..757b5251 100644 --- a/src/stm/ao_arch.h +++ b/src/stm/ao_arch.h @@ -129,7 +129,7 @@ extern const uint32_t ao_radio_cal; void ao_adc_init(); -#define AO_BOOT_APPLICATION_BASE ((uint32_t *) 0x1000) +#define AO_BOOT_APPLICATION_BASE ((uint32_t *) 0x08001000) #define AO_BOOT_LOADER_BASE ((uint32_t *) 0x0) #define HAS_BOOT_LOADER 1 -- cgit v1.2.3 From e2412e867138635d79ea0fa8d43efc0a6aa19784 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 27 Apr 2013 00:19:13 -0700 Subject: altos: Allow STM usb driver to be used without stdio This lets the self flashing loader be linked without any of the stdio code, which saves a bunch of memory. Signed-off-by: Keith Packard --- src/stm/ao_usb_stm.c | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) (limited to 'src/stm') diff --git a/src/stm/ao_usb_stm.c b/src/stm/ao_usb_stm.c index e484cd22..11dde92e 100644 --- a/src/stm/ao_usb_stm.c +++ b/src/stm/ao_usb_stm.c @@ -23,6 +23,16 @@ #define USB_DEBUG_DATA 0 #define USB_ECHO 0 +#ifndef USE_USB_STDIO +#define USE_USB_STDIO 1 +#endif + +#if USE_USB_STDIO +#define AO_USB_OUT_SLEEP_ADDR (&ao_stdin_ready) +#else +#define AO_USB_OUT_SLEEP_ADDR (&ao_usb_out_avail) +#endif + #if USB_DEBUG #define debug(format, args...) printf(format, ## args); #else @@ -770,7 +780,7 @@ stm_usb_lp_isr(void) _rx_dbg1("RX ISR", epr); ao_usb_out_avail = 1; _rx_dbg0("out avail set"); - ao_wakeup(&ao_stdin_ready); + ao_wakeup(AO_USB_OUT_SLEEP_ADDR); _rx_dbg0("stdin awoken"); } break; @@ -936,7 +946,7 @@ ao_usb_getchar(void) ao_arch_block_interrupts(); while ((c = _ao_usb_pollchar()) == AO_READ_AGAIN) - ao_sleep(&ao_stdin_ready); + ao_sleep(AO_USB_OUT_SLEEP_ADDR); ao_arch_release_interrupts(); return c; } @@ -1064,8 +1074,10 @@ ao_usb_init(void) ao_cmd_register(&ao_usb_cmds[0]); #endif #if !USB_ECHO +#if USE_USB_STDIO ao_add_stdio(_ao_usb_pollchar, ao_usb_putchar, ao_usb_flush); #endif +#endif } #if TX_DBG || RX_DBG -- cgit v1.2.3 From 0b1797312b34ba2b8121f82605f8d2c419167737 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 27 Apr 2013 00:20:47 -0700 Subject: altos: Run self loader when application sets boot addr to 0 This causes the flash loader startup code to fall into the loader when the application sets the boot address to zero. Signed-off-by: Keith Packard --- src/stm/ao_boot.h | 3 ++- src/stm/ao_boot_chain.c | 7 +++++-- src/stm/ao_interrupt.c | 7 ++++--- 3 files changed, 11 insertions(+), 6 deletions(-) (limited to 'src/stm') diff --git a/src/stm/ao_boot.h b/src/stm/ao_boot.h index 862e8755..e0ed4de7 100644 --- a/src/stm/ao_boot.h +++ b/src/stm/ao_boot.h @@ -24,7 +24,8 @@ ao_boot_chain(uint32_t *base); void ao_boot_check_pin(void); -void +/* Return true to switch to application (if present) */ +int ao_boot_check_chain(void); void diff --git a/src/stm/ao_boot_chain.c b/src/stm/ao_boot_chain.c index 668f6e6d..6a3864a7 100644 --- a/src/stm/ao_boot_chain.c +++ b/src/stm/ao_boot_chain.c @@ -26,7 +26,7 @@ ao_boot_chain(uint32_t *base) sp = base[0]; pc = base[1]; - if (0x08000100 <= pc && pc <= 0x08200000) { + if (0x08000100 <= pc && pc <= 0x08200000 && (pc & 1) == 1) { asm ("mov sp, %0" : : "r" (sp)); asm ("mov lr, %0" : : "r" (pc)); asm ("bx lr"); @@ -44,14 +44,17 @@ struct ao_boot { static struct ao_boot __attribute__ ((section(".boot"))) ao_boot; -void +int ao_boot_check_chain(void) { if (ao_boot.signal == AO_BOOT_SIGNAL && ao_boot.check == AO_BOOT_CHECK) { ao_boot.signal = 0; ao_boot.check = 0; + if (ao_boot.base == 0) + return 0; ao_boot_chain(ao_boot.base); } + return 1; } void diff --git a/src/stm/ao_interrupt.c b/src/stm/ao_interrupt.c index 49156285..969e6a0f 100644 --- a/src/stm/ao_interrupt.c +++ b/src/stm/ao_interrupt.c @@ -42,10 +42,11 @@ const void *stm_interrupt_vector[]; void start(void) { #ifdef AO_BOOT_CHAIN - ao_boot_check_chain(); -#endif + if (ao_boot_check_chain()) { #ifdef AO_BOOT_PIN - ao_boot_check_pin(); + ao_boot_check_pin(); +#endif + } #endif /* Set interrupt vector table offset */ stm_nvic.vto = (uint32_t) &stm_interrupt_vector; -- cgit v1.2.3 From a2e0676f476b0e2bdd5102315ebd5904b57f384a Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 27 Apr 2013 00:24:08 -0700 Subject: altos: Get rodata into flash, make sure sections are aligned .rodata* needs to be in flash; otherwise strings get left in ram. Failing to align sections makes the initialized data get dumped into the wrong place in memory. Signed-off-by: Keith Packard --- src/stm/altos-loader.ld | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) (limited to 'src/stm') diff --git a/src/stm/altos-loader.ld b/src/stm/altos-loader.ld index 78649be2..5e10e5ba 100644 --- a/src/stm/altos-loader.ld +++ b/src/stm/altos-loader.ld @@ -16,7 +16,7 @@ */ MEMORY { - rom : ORIGIN = 0x08000000, LENGTH = 8K + rom : ORIGIN = 0x08000000, LENGTH = 4K ram : ORIGIN = 0x20000000, LENGTH = 16K } @@ -32,14 +32,17 @@ SECTIONS { .text : { __text_start__ = .; *(.interrupt) /* Interrupt vectors */ - *(.romconfig) + *(.romconfig*) *(.text) /* Executable code */ - *(.rodata) /* Constants */ - + . = ALIGN(4); + *(.rodata*) /* Constants */ + . = ALIGN(4); } > rom .ARM.exidx : { + . = ALIGN(4); *(.ARM.exidx* .gnu.linkonce.armexidx.*) + . = ALIGN(4); } > rom __text_end__ = .; @@ -56,20 +59,19 @@ SECTIONS { /* Functions placed in RAM (required for flashing) */ .textram : { - __text_ram_start__ = .; __data_start__ = .; + __text_ram_start__ = .; *(.text.ram) - . = ALIGN(4); + __text_ram_end = .; } >ram AT>rom - __text_ram_end = .; /* Data -- relocated to RAM, but written to ROM */ .data : { *(.data) /* initialized data */ - . = ALIGN (4); + __data_end__ = .; } >ram AT>rom - __data_end__ = .; + .bss : { __bss_start__ = .; -- cgit v1.2.3 From 4a90eec4b8ee4a35711aa74c13b3f30d12c0fe08 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 27 Apr 2013 15:33:04 -0700 Subject: altos/stm: Create per-product flash loaders Split the flash loader prototype into pieces so that each product can build a custom flash loader with very little code. Signed-off-by: Keith Packard --- src/Makefile | 7 +- src/megadongle-v0.1/flash-loader/Makefile | 7 ++ src/megadongle-v0.1/flash-loader/ao_pins.h | 34 +++++++ src/product/ao_flash_pins.h | 40 ++++++++ src/product/ao_flash_task.c | 137 ++++++++++++++++++++++++++ src/product/ao_flash_task.h | 24 +++++ src/stm-flash/ao_stm_flash.c | 152 ----------------------------- src/stm/Makefile-flash.defs | 92 +++++++++++++++++ src/stm/altos-loader.ld | 31 +++--- src/stm/ao_arch.h | 4 + src/stm/ao_flash.h | 27 +++++ src/stm/ao_flash_loader_stm.c | 32 ++++++ src/stm/ao_flash_stm.c | 2 +- src/stm/ao_flash_stm.h | 27 ----- src/stm/ao_flash_stm_pins.h | 43 ++++++++ src/telegps-v0.1/flash-loader/Makefile | 8 ++ src/telegps-v0.1/flash-loader/ao_pins.h | 34 +++++++ src/telemega-v0.1/flash-loader/Makefile | 7 ++ src/telemega-v0.1/flash-loader/ao_pins.h | 34 +++++++ src/telemega-v0.3/flash-loader/Makefile | 8 ++ src/telemega-v0.3/flash-loader/ao_pins.h | 34 +++++++ 21 files changed, 590 insertions(+), 194 deletions(-) create mode 100644 src/megadongle-v0.1/flash-loader/Makefile create mode 100644 src/megadongle-v0.1/flash-loader/ao_pins.h create mode 100644 src/product/ao_flash_pins.h create mode 100644 src/product/ao_flash_task.c create mode 100644 src/product/ao_flash_task.h delete mode 100644 src/stm-flash/ao_stm_flash.c create mode 100644 src/stm/Makefile-flash.defs create mode 100644 src/stm/ao_flash.h create mode 100644 src/stm/ao_flash_loader_stm.c delete mode 100644 src/stm/ao_flash_stm.h create mode 100644 src/stm/ao_flash_stm_pins.h create mode 100644 src/telegps-v0.1/flash-loader/Makefile create mode 100644 src/telegps-v0.1/flash-loader/ao_pins.h create mode 100644 src/telemega-v0.1/flash-loader/Makefile create mode 100644 src/telemega-v0.1/flash-loader/ao_pins.h create mode 100644 src/telemega-v0.3/flash-loader/Makefile create mode 100644 src/telemega-v0.3/flash-loader/ao_pins.h (limited to 'src/stm') diff --git a/src/Makefile b/src/Makefile index 90a74166..5ae61a00 100644 --- a/src/Makefile +++ b/src/Makefile @@ -29,7 +29,12 @@ AVRDIRS=\ telescience-v0.1 telescience-pwm telepyro-v0.1 micropeak ARMDIRS=\ - telemega-v0.1 telemega-v0.3 megadongle-v0.1 stm-bringup stm-demo telelco-v0.1 \ + telemega-v0.1 telemega-v0.1/flash-loader \ + telemega-v0.3 telemega-v0.3/flash-loader \ + megadongle-v0.1 megadongle-v0.1/flash-loader \ + telegps-v0.1 telegps-v0.1/flash-loader \ + stm-bringup stm-demo telelco-v0.1 \ + telelco-v0.2 telelco-v0.2/flash-loader \ telescience-v0.2 ifneq ($(shell which sdcc),) diff --git a/src/megadongle-v0.1/flash-loader/Makefile b/src/megadongle-v0.1/flash-loader/Makefile new file mode 100644 index 00000000..adea5786 --- /dev/null +++ b/src/megadongle-v0.1/flash-loader/Makefile @@ -0,0 +1,7 @@ +# +# AltOS flash loader build +# + +TOPDIR=../.. +HARDWARE=megadongle-v0.1 +include $(TOPDIR)/stm/Makefile-flash.defs diff --git a/src/megadongle-v0.1/flash-loader/ao_pins.h b/src/megadongle-v0.1/flash-loader/ao_pins.h new file mode 100644 index 00000000..1af92f13 --- /dev/null +++ b/src/megadongle-v0.1/flash-loader/ao_pins.h @@ -0,0 +1,34 @@ +/* + * Copyright © 2013 Keith Packard + * + * 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 + +/* Companion port cs_companion0 PD0 */ + +#define AO_BOOT_PIN 1 +#define AO_BOOT_APPLICATION_GPIO stm_gpiod +#define AO_BOOT_APPLICATION_PIN 0 +#define AO_BOOT_APPLICATION_VALUE 1 +#define AO_BOOT_APPLICATION_MODE AO_EXTI_MODE_PULL_UP + +#endif /* _AO_PINS_H_ */ diff --git a/src/product/ao_flash_pins.h b/src/product/ao_flash_pins.h new file mode 100644 index 00000000..b774df6d --- /dev/null +++ b/src/product/ao_flash_pins.h @@ -0,0 +1,40 @@ +/* + * Copyright © 2013 Keith Packard + * + * 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_FLASH_PINS_H_ +#define _AO_FLASH_PINS_H_ + +/* Common definitions for the USB flash loader */ + +#define HAS_TASK_QUEUE 0 + +#define HAS_USB 1 +#define USE_USB_STDIO 0 +#define HAS_BEEP 0 +#define HAS_TASK 0 +#define HAS_ECHO 0 +#define HAS_TICK 0 + +#define PACKET_HAS_SLAVE 0 + +#define HAS_TASK_INFO 0 +#define HAS_VERSION 0 + +#define AO_BOOT_CHAIN 1 +#define AO_BOOT_PIN 1 + +#endif /* _AO_FLASH_PINS_H_ */ diff --git a/src/product/ao_flash_task.c b/src/product/ao_flash_task.c new file mode 100644 index 00000000..fdc4d0aa --- /dev/null +++ b/src/product/ao_flash_task.c @@ -0,0 +1,137 @@ +/* + * Copyright © 2013 Keith Packard + * + * 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 +#include +#include +#include + +void +ao_panic(uint8_t reason) +{ +} + +void +ao_put_string(__code char *s) +{ + char c; + while ((c = *s++)) { + if (c == '\n') + ao_usb_putchar('\r'); + ao_usb_putchar(c); + } +} + +static void +ao_application(void) +{ + ao_boot_reboot(AO_BOOT_APPLICATION_BASE); +} + +static uint32_t +ao_get_hex32(void) +{ + int8_t n; + uint32_t v = 0; + + for (;;) { + n = ao_usb_getchar(); + if (n != ' ') + break; + } + for(;;) { + if ('0' <= n && n <= '9') + n = n - '0'; + else if ('a' <= n && n <= 'f') + n = n - ('a' - 10); + else if ('A' <= n && n <= 'F') + n = n - ('A' - 10); + else + break; + v = (v << 4) | n; + n = ao_usb_getchar(); + } + return v; +} + +static void +ao_block_erase(void) +{ + uint32_t addr = ao_get_hex32(); + uint32_t *p = (uint32_t *) addr; + + ao_flash_erase_page(p); +} + +static void +ao_block_write(void) +{ + uint32_t addr = ao_get_hex32(); + uint32_t *p = (uint32_t *) addr; + union { + uint8_t data8[256]; + uint32_t data32[64]; + } u; + uint16_t i; + + if (addr < (uint32_t) AO_BOOT_APPLICATION_BASE) { + ao_put_string("Invalid address\n"); + return; + } + for (i = 0; i < 256; i++) + u.data8[i] = ao_usb_getchar(); + ao_flash_page(p, u.data32); +} + +static void +ao_block_read(void) +{ + uint32_t addr = ao_get_hex32(); + uint8_t *p = (uint8_t *) addr; + uint16_t i; + uint8_t c; + + for (i = 0; i < 256; i++) { + c = *p++; + ao_usb_putchar(c); + } +} + +static void +ao_show_version(void) +{ + ao_put_string("altos-loader"); + ao_put_string("\nmanufacturer "); ao_put_string(ao_manufacturer); + ao_put_string("\nproduct "); ao_put_string(ao_product); + ao_put_string("\nsoftware-version "); ao_put_string(ao_version); + ao_put_string("\n"); +} + +void +ao_flash_task(void) { + for (;;) { + ao_usb_flush(); + switch (ao_usb_getchar()) { + case 'v': ao_show_version(); break; + case 'a': ao_application(); break; + case 'X': ao_block_erase(); break; + case 'W': ao_block_write(); break; + case 'R': ao_block_read(); break; + } + } +} diff --git a/src/product/ao_flash_task.h b/src/product/ao_flash_task.h new file mode 100644 index 00000000..0a2fbb35 --- /dev/null +++ b/src/product/ao_flash_task.h @@ -0,0 +1,24 @@ +/* + * Copyright © 2013 Keith Packard + * + * 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_FLASH_TASK_H_ +#define _AO_FLASH_TASK_H_ + +void +ao_flash_task(void); + +#endif /* _AO_FLASH_TASK_H_ */ diff --git a/src/stm-flash/ao_stm_flash.c b/src/stm-flash/ao_stm_flash.c deleted file mode 100644 index f8580735..00000000 --- a/src/stm-flash/ao_stm_flash.c +++ /dev/null @@ -1,152 +0,0 @@ -/* - * Copyright © 2011 Keith Packard - * - * 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 -#include -#include - -void -ao_panic(uint8_t reason) -{ - for (;;); -} - -void -ao_put_string(__code char *s) -{ - char c; - while ((c = *s++)) { - if (c == '\n') - ao_usb_putchar('\r'); - ao_usb_putchar(c); - } -} - -void -ao_application(void) -{ - ao_boot_reboot(AO_BOOT_APPLICATION_BASE); -} - -static uint32_t -ao_get_hex32(void) -{ - int8_t n; - uint32_t v = 0; - - for (;;) { - n = ao_usb_getchar(); - if (n != ' ') - break; - } - for(;;) { - if ('0' <= n && n <= '9') - n = n - '0'; - else if ('a' <= n && n <= 'f') - n = n - ('a' - 10); - else if ('A' <= n && n <= 'F') - n = n - ('A' - 10); - else - break; - v = (v << 4) | n; - n = ao_usb_getchar(); - } - return v; -} - -void -ao_block_erase(void) -{ - uint32_t addr = ao_get_hex32(); - uint32_t *p = (uint32_t *) addr; - - ao_flash_erase_page(p); -} - -void -ao_block_write(void) -{ - uint32_t addr = ao_get_hex32(); - uint32_t *p = (uint32_t *) addr; - union { - uint8_t data8[256]; - uint32_t data32[64]; - } u; - uint16_t i; - - if (addr < (uint32_t) AO_BOOT_APPLICATION_BASE) { - ao_put_string("Invalid address\n"); - return; - } - for (i = 0; i < 256; i++) - u.data8[i] = ao_usb_getchar(); - ao_flash_page(p, u.data32); -} - -void -ao_block_read(void) -{ - uint32_t addr = ao_get_hex32(); - uint8_t *p = (uint8_t *) addr; - uint16_t i; - uint8_t c; - - for (i = 0; i < 256; i++) { - c = *p++; - ao_usb_putchar(c); - } -} - -static void -ao_show_version(void) -{ - ao_put_string("altos-loader"); - ao_put_string("\nmanufacturer "); ao_put_string(ao_manufacturer); - ao_put_string("\nproduct "); ao_put_string(ao_product); - ao_put_string("\nsoftware-version "); ao_put_string(ao_version); - ao_put_string("\n"); -} - -static void -ao_flash_task(void) { - for (;;) { - ao_usb_flush(); - switch (ao_usb_getchar()) { - case 'v': ao_show_version(); break; - case 'a': ao_application(); break; - case 'X': ao_block_erase(); break; - case 'W': ao_block_write(); break; - case 'R': ao_block_read(); break; - } - } -} - - -int -main(void) -{ - ao_clock_init(); - -// ao_timer_init(); -// ao_dma_init(); -// ao_exti_init(); - ao_usb_init(); - - ao_flash_task(); - return 0; -} diff --git a/src/stm/Makefile-flash.defs b/src/stm/Makefile-flash.defs new file mode 100644 index 00000000..016bb7e7 --- /dev/null +++ b/src/stm/Makefile-flash.defs @@ -0,0 +1,92 @@ +vpath % $(TOPDIR)/stm:$(TOPDIR)/product:$(TOPDIR)/drivers:$(TOPDIR)/core:$(TOPDIR)/util:$(TOPDIR) +vpath ao-make-product.5c $(TOPDIR)/util + +.SUFFIXES: .elf .ihx + +.elf.ihx: + objcopy -O ihex $*.elf $@ + +CC=arm-none-eabi-gcc +SAT=/opt/cortex +SAT_CLIB=$(SAT)/lib/pdclib-cortex-m3.a +SAT_CFLAGS=-I$(SAT)/include + +ifndef VERSION +include $(TOPDIR)/Version +endif + +AO_CFLAGS=-I. -I$(TOPDIR)/stm -I$(TOPDIR)/core -I$(TOPDIR)/drivers -I$(TOPDIR)/product -I$(TOPDIR) +STM_CFLAGS=-std=gnu99 -mlittle-endian -mcpu=cortex-m3 -mthumb -ffreestanding -nostdlib $(AO_CFLAGS) $(SAT_CFLAGS) + +LDFLAGS=-L$(TOPDIR)/stm -Wl,-Taltos-loader.ld + +NICKLE=nickle + +V=0 +# The user has explicitly enabled quiet compilation. +ifeq ($(V),0) +quiet = @printf " $1 $2 $@\n"; $($1) +endif +# Otherwise, print the full command line. +quiet ?= $($1) + +.c.o: + $(call quiet,CC) -c $(CFLAGS) -o $@ $< + +INC = \ + ao.h \ + ao_arch.h \ + ao_arch_funcs.h \ + ao_flash_pins.h \ + ao_flash_stm_pins.h \ + ao_flash_task.h \ + ao_pins.h \ + ao_product.h \ + Makefile + +# +# Common AltOS sources +# +SRC = \ + ao_interrupt.c \ + ao_romconfig.c \ + ao_boot_chain.c \ + ao_boot_pin.c \ + ao_product.c \ + ao_notask.c \ + ao_timer.c \ + ao_usb_stm.c \ + ao_flash_stm.c \ + ao_flash_task.c \ + ao_flash_loader_stm.c + +OBJ=$(SRC:.c=.o) + +PRODUCT=AltosFlash-$(VERSION) +PRODUCT_DEF=-DALTOS_FLASH +IDPRODUCT=0x000a + +CFLAGS = $(PRODUCT_DEF) $(STM_CFLAGS) -g -Os + +PROGNAME=altos-flash +PROG=$(HARDWARE)-$(PROGNAME)-$(VERSION).elf + +$(PROG): Makefile $(OBJ) altos-loader.ld + $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(OBJ) $(SAT_CLIB) -lgcc + +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: + rm -f *.o $(PROG) + rm -f ao_product.h + +install: + +uninstall: diff --git a/src/stm/altos-loader.ld b/src/stm/altos-loader.ld index 5e10e5ba..2be964f2 100644 --- a/src/stm/altos-loader.ld +++ b/src/stm/altos-loader.ld @@ -32,19 +32,16 @@ SECTIONS { .text : { __text_start__ = .; *(.interrupt) /* Interrupt vectors */ - *(.romconfig*) - *(.text) /* Executable code */ - . = ALIGN(4); - *(.rodata*) /* Constants */ - . = ALIGN(4); - } > rom - .ARM.exidx : { - . = ALIGN(4); + . = ORIGIN(rom) + 0x100; + + ao_romconfig.o(.romconfig*) + ao_product.o(.romconfig*) + *(.text) /* Executable code */ *(.ARM.exidx* .gnu.linkonce.armexidx.*) - . = ALIGN(4); + *(.rodata*) /* Constants */ + __text_end__ = .; } > rom - __text_end__ = .; /* Boot data which must live at the start of ram so that * the application and bootloader share the same addresses. @@ -53,12 +50,20 @@ SECTIONS { .boot (NOLOAD) : { __boot_start__ = .; *(.boot) - . = ALIGN(4); __boot_end__ = .; } >ram - /* Functions placed in RAM (required for flashing) */ - .textram : { + /* Functions placed in RAM (required for flashing) + * + * Align to 8 bytes as that's what the ARM likes text + * segment alignments to be, and if we don't, then + * we end up with a mismatch between the location in + * ROM and the desired location in RAM. I don't + * entirely understand this, but at least this appears + * to work... + */ + + .textram BLOCK(8): { __data_start__ = .; __text_ram_start__ = .; *(.text.ram) diff --git a/src/stm/ao_arch.h b/src/stm/ao_arch.h index 757b5251..adc288c3 100644 --- a/src/stm/ao_arch.h +++ b/src/stm/ao_arch.h @@ -88,6 +88,10 @@ extern const uint32_t ao_radio_cal; * For now, we're running at a weird frequency */ +#ifndef AO_HSE +#error High speed frequency undefined +#endif + #if AO_HSE #define AO_PLLSRC AO_HSE #else diff --git a/src/stm/ao_flash.h b/src/stm/ao_flash.h new file mode 100644 index 00000000..09ca5ac1 --- /dev/null +++ b/src/stm/ao_flash.h @@ -0,0 +1,27 @@ +/* + * Copyright © 2013 Keith Packard + * + * 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_FLASH_STM_H_ +#define _AO_FLASH_STM_H_ + +void +ao_flash_erase_page(uint32_t *page); + +void +ao_flash_page(uint32_t *page, uint32_t *src); + +#endif /* _AO_FLASH_STM_H_ */ diff --git a/src/stm/ao_flash_loader_stm.c b/src/stm/ao_flash_loader_stm.c new file mode 100644 index 00000000..2ab548cf --- /dev/null +++ b/src/stm/ao_flash_loader_stm.c @@ -0,0 +1,32 @@ +/* + * Copyright © 2013 Keith Packard + * + * 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 +#include +#include + +int +main(void) +{ + ao_clock_init(); + + ao_usb_init(); + + ao_flash_task(); + return 0; +} diff --git a/src/stm/ao_flash_stm.c b/src/stm/ao_flash_stm.c index b4d47024..d7a85582 100644 --- a/src/stm/ao_flash_stm.c +++ b/src/stm/ao_flash_stm.c @@ -16,7 +16,7 @@ */ #include -#include +#include static uint8_t ao_flash_pecr_is_locked(void) diff --git a/src/stm/ao_flash_stm.h b/src/stm/ao_flash_stm.h deleted file mode 100644 index 09ca5ac1..00000000 --- a/src/stm/ao_flash_stm.h +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright © 2013 Keith Packard - * - * 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_FLASH_STM_H_ -#define _AO_FLASH_STM_H_ - -void -ao_flash_erase_page(uint32_t *page); - -void -ao_flash_page(uint32_t *page, uint32_t *src); - -#endif /* _AO_FLASH_STM_H_ */ diff --git a/src/stm/ao_flash_stm_pins.h b/src/stm/ao_flash_stm_pins.h new file mode 100644 index 00000000..d157a226 --- /dev/null +++ b/src/stm/ao_flash_stm_pins.h @@ -0,0 +1,43 @@ +/* + * Copyright © 2013 Keith Packard + * + * 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_FLASH_STM_PINS_H_ +#define _AO_FLASH_STM_PINS_H_ + +#include + +/* PLLVCO = 96MHz (so that USB will work) */ +#define AO_PLLMUL 12 +#define AO_RCC_CFGR_PLLMUL (STM_RCC_CFGR_PLLMUL_12) + +/* SYSCLK = 32MHz */ +#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 HCLK/1 */ +#define AO_APB1_PRESCALER 1 +#define AO_RCC_CFGR_PPRE1_DIV STM_RCC_CFGR_PPRE2_DIV_1 + +/* Run APB2 at HCLK/1 */ +#define AO_APB2_PRESCALER 1 +#define AO_RCC_CFGR_PPRE2_DIV STM_RCC_CFGR_PPRE2_DIV_1 + +#endif /* _AO_FLASH_STM_PINS_H_ */ diff --git a/src/telegps-v0.1/flash-loader/Makefile b/src/telegps-v0.1/flash-loader/Makefile new file mode 100644 index 00000000..efc98d14 --- /dev/null +++ b/src/telegps-v0.1/flash-loader/Makefile @@ -0,0 +1,8 @@ +# +# AltOS flash loader build +# +# + +TOPDIR=../.. +HARDWARE=telegps-v0.1 +include $(TOPDIR)/stm/Makefile-flash.defs diff --git a/src/telegps-v0.1/flash-loader/ao_pins.h b/src/telegps-v0.1/flash-loader/ao_pins.h new file mode 100644 index 00000000..564e84de --- /dev/null +++ b/src/telegps-v0.1/flash-loader/ao_pins.h @@ -0,0 +1,34 @@ +/* + * Copyright © 2013 Keith Packard + * + * 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 + +/* Telemetry TX pin PB6 */ + +#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/telemega-v0.1/flash-loader/Makefile b/src/telemega-v0.1/flash-loader/Makefile new file mode 100644 index 00000000..7aa8549f --- /dev/null +++ b/src/telemega-v0.1/flash-loader/Makefile @@ -0,0 +1,7 @@ +# +# AltOS flash loader build +# + +TOPDIR=../.. +HARDWARE=telemega-v0.1 +include $(TOPDIR)/stm/Makefile-flash.defs diff --git a/src/telemega-v0.1/flash-loader/ao_pins.h b/src/telemega-v0.1/flash-loader/ao_pins.h new file mode 100644 index 00000000..1af92f13 --- /dev/null +++ b/src/telemega-v0.1/flash-loader/ao_pins.h @@ -0,0 +1,34 @@ +/* + * Copyright © 2013 Keith Packard + * + * 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 + +/* Companion port cs_companion0 PD0 */ + +#define AO_BOOT_PIN 1 +#define AO_BOOT_APPLICATION_GPIO stm_gpiod +#define AO_BOOT_APPLICATION_PIN 0 +#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.3/flash-loader/Makefile b/src/telemega-v0.3/flash-loader/Makefile new file mode 100644 index 00000000..8fda18cd --- /dev/null +++ b/src/telemega-v0.3/flash-loader/Makefile @@ -0,0 +1,8 @@ +# +# AltOS flash loader build +# +# + +TOPDIR=../.. +HARDWARE=telemega-v0.3 +include $(TOPDIR)/stm/Makefile-flash.defs diff --git a/src/telemega-v0.3/flash-loader/ao_pins.h b/src/telemega-v0.3/flash-loader/ao_pins.h new file mode 100644 index 00000000..1af92f13 --- /dev/null +++ b/src/telemega-v0.3/flash-loader/ao_pins.h @@ -0,0 +1,34 @@ +/* + * Copyright © 2013 Keith Packard + * + * 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 + +/* Companion port cs_companion0 PD0 */ + +#define AO_BOOT_PIN 1 +#define AO_BOOT_APPLICATION_GPIO stm_gpiod +#define AO_BOOT_APPLICATION_PIN 0 +#define AO_BOOT_APPLICATION_VALUE 1 +#define AO_BOOT_APPLICATION_MODE AO_EXTI_MODE_PULL_UP + +#endif /* _AO_PINS_H_ */ -- cgit v1.2.3 From ecb128579e7576fc27c8ca93708f316b9ac91630 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 28 Apr 2013 23:06:24 -0700 Subject: altos: Wait after configuring boot pin before testing it Clearly the pin isn't quite ready just after it's been configured, so hang around for a while (100 nops) to let things setting down before testing the value of the pin. Makes booting a lot more reliable. Signed-off-by: Keith Packard --- src/stm/ao_boot_pin.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'src/stm') diff --git a/src/stm/ao_boot_pin.c b/src/stm/ao_boot_pin.c index 03b0214f..1000a65a 100644 --- a/src/stm/ao_boot_pin.c +++ b/src/stm/ao_boot_pin.c @@ -31,6 +31,9 @@ ao_boot_check_pin(void) ao_enable_input(&AO_BOOT_APPLICATION_GPIO, AO_BOOT_APPLICATION_PIN, AO_BOOT_APPLICATION_MODE); + for (v = 0; v < 100; v++) + ao_arch_nop(); + /* Read the value */ v = stm_gpio_get(&AO_BOOT_APPLICATION_GPIO, AO_BOOT_APPLICATION_PIN); -- cgit v1.2.3