From 02fd767ab60a9957faa2bff29c62ed954abc34e7 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 19 Jan 2016 18:30:57 -0800 Subject: src/chaoskey-v0.1: Add HV enable support Turn on the HV supply when the OS starts. Signed-off-by: Keith Packard --- src/chaoskey-v0.1/ao_chaoskey.c | 8 ++++++++ src/chaoskey-v0.1/ao_pins.h | 5 +++++ 2 files changed, 13 insertions(+) (limited to 'src') diff --git a/src/chaoskey-v0.1/ao_chaoskey.c b/src/chaoskey-v0.1/ao_chaoskey.c index 48c8bf04..c9490184 100644 --- a/src/chaoskey-v0.1/ao_chaoskey.c +++ b/src/chaoskey-v0.1/ao_chaoskey.c @@ -20,6 +20,12 @@ #include #include +static void +ao_hv_init(void) +{ + ao_enable_output(AO_HV_ENABLE_PORT, AO_HV_ENABLE_BIT, AO_HV_ENABLE_PIN, 1); +} + void main(void) { ao_led_init(LEDS_AVAILABLE); @@ -33,6 +39,8 @@ void main(void) ao_usb_init(); + ao_hv_init(); + ao_trng_send_init(); ao_led_off(AO_LED_RED); diff --git a/src/chaoskey-v0.1/ao_pins.h b/src/chaoskey-v0.1/ao_pins.h index 72963dba..8f3eb7b1 100644 --- a/src/chaoskey-v0.1/ao_pins.h +++ b/src/chaoskey-v0.1/ao_pins.h @@ -57,6 +57,11 @@ #define AO_NUM_ADC 1 +/* HV enable */ + +#define AO_HV_ENABLE_PORT (&stm_gpioa) +#define AO_HV_ENABLE_BIT 8 + /* CRC */ #define AO_CRC_WIDTH 32 #define AO_CRC_INIT 0xffffffff -- cgit v1.2.3 From f2d3202de9a5847923f72afe2969eb7ccd7342c7 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 28 Jan 2016 00:14:36 -0800 Subject: altos/chaoskey: Add support for flipping between raw and cooked bits Plug the 'force bootloader' thing onto the board while it's running and it will generate raw bits instead of running them through the CRC to whiten. Useful for validating the raw hardware. Signed-off-by: Keith Packard --- ao-bringup/turnon_chaoskey | 50 +++++++++++++++++++++++++++++++++++++++++ src/chaoskey-v0.1/ao_pins.h | 7 +++++- src/drivers/ao_trng_send.c | 55 ++++++++++++++++++++++++++++++++++++--------- 3 files changed, 100 insertions(+), 12 deletions(-) create mode 100755 ao-bringup/turnon_chaoskey (limited to 'src') diff --git a/ao-bringup/turnon_chaoskey b/ao-bringup/turnon_chaoskey new file mode 100755 index 00000000..8c8a6758 --- /dev/null +++ b/ao-bringup/turnon_chaoskey @@ -0,0 +1,50 @@ +#!/bin/sh + +if [ -x /usr/bin/ao-flash-stm32f0x ]; then + FLASH_STM=/usr/bin/ao-flash-stm32f0x +else + echo "Can't find ao-flash-stm32f0x! Aborting." + exit 1 +fi + +if [ -x /usr/bin/ao-usbload ]; then + USBLOAD=/usr/bin/ao-usbload +else + echo "Can't find ao-usbload! Aborting." + exit 1 +fi + +VERSION=0.1 +PRODUCT=ChaosKey + +echo "ChaosKey v$VERSION Turn-On and Calibration Program" +echo "Copyright 2015 by Keith Packard. Released under GPL v2" +echo +echo "Expectations:" +echo "\tChaosKey v$VERSION powered from USB" +echo "\t\twith ST-Link-V2 cabled to debug header" +echo + + +case $# in + 1) + SERIAL="$1" + echo "$PRODUCT-$VERSION serial number: $SERIAL" + ;; + 0) + echo -n "$PRODUCT-$VERSION serial number: " + read SERIAL + ;; + *) + echo "Usage: $0 " 1>&2 + exit 1; + ;; +esac + +$FLASH_STM ../src/chaoskey-v$VERSION/flash-loader/chaoskey-v$VERSION-*.elf || exit 1 + +sleep 2 + +$USBLOAD --serial=$SERIAL ../src/chaoskey-v$VERSION/chaoskey-v$VERSION*.ihx || exit 1 + +exit $? diff --git a/src/chaoskey-v0.1/ao_pins.h b/src/chaoskey-v0.1/ao_pins.h index 8f3eb7b1..95d9a576 100644 --- a/src/chaoskey-v0.1/ao_pins.h +++ b/src/chaoskey-v0.1/ao_pins.h @@ -67,6 +67,11 @@ #define AO_CRC_INIT 0xffffffff /* TRNG */ -#define AO_LED_TRNG_ACTIVE AO_LED_GREEN +#define AO_LED_TRNG_COOKED AO_LED_GREEN +#define AO_LED_TRNG_RAW AO_LED_RED + +/* Mode pin */ +#define AO_RAW_PORT (&stm_gpioa) +#define AO_RAW_BIT 15 #endif /* _AO_PINS_H_ */ diff --git a/src/drivers/ao_trng_send.c b/src/drivers/ao_trng_send.c index bac6035c..64c016b2 100644 --- a/src/drivers/ao_trng_send.c +++ b/src/drivers/ao_trng_send.c @@ -19,17 +19,48 @@ #include #include #include +#include static void -ao_trng_send(void) +ao_trng_send_raw(uint16_t *buf) +{ + uint16_t i; + uint16_t t; + uint16_t *rnd = (uint16_t *) ao_adc_ring; + + t = ao_adc_get(AO_USB_IN_SIZE>>1); /* one 16-bit value per two output bytes */ + for (i = 0; i < AO_USB_IN_SIZE / sizeof (uint16_t); i++) { + *buf++ = rnd[t]; + t = (t + 1) & (AO_ADC_RING_SIZE - 1); + } +} + +static void +ao_trng_send_cooked(uint16_t *buf) { - static uint16_t *buffer[2]; - int usb_buf_id; uint16_t i; - uint16_t *buf; uint16_t t; uint32_t *rnd = (uint32_t *) ao_adc_ring; + t = ao_adc_get(AO_USB_IN_SIZE) >> 1; /* one 16-bit value per output byte */ + for (i = 0; i < AO_USB_IN_SIZE / sizeof (uint16_t); i++) { + *buf++ = ao_crc_in_32_out_16(rnd[t]); + t = (t + 1) & ((AO_ADC_RING_SIZE>>1) - 1); + } +} + +static inline int +ao_send_raw(void) +{ + return !ao_gpio_get(AO_RAW_PORT, AO_RAW_BIT, AO_RAW_PIN); +} + +static void +ao_trng_send(void) +{ + static uint16_t *buffer[2]; + int usb_buf_id; + if (!buffer[0]) { buffer[0] = ao_usb_alloc(); buffer[1] = ao_usb_alloc(); @@ -42,15 +73,16 @@ ao_trng_send(void) ao_crc_reset(); for (;;) { - ao_led_on(AO_LED_TRNG_ACTIVE); - t = ao_adc_get(AO_USB_IN_SIZE) >> 1; /* one 16-bit value per output byte */ - buf = buffer[usb_buf_id]; - for (i = 0; i < AO_USB_IN_SIZE / sizeof (uint16_t); i++) { - *buf++ = ao_crc_in_32_out_16(rnd[t]); - t = (t + 1) & ((AO_ADC_RING_SIZE>>1) - 1); + if (ao_send_raw()) { + ao_led_on(AO_LED_TRNG_RAW); + ao_trng_send_raw(buffer[usb_buf_id]); + ao_led_off(AO_LED_TRNG_RAW); + } else { + ao_led_on(AO_LED_TRNG_COOKED); + ao_trng_send_cooked(buffer[usb_buf_id]); + ao_led_off(AO_LED_TRNG_COOKED); } ao_adc_ack(AO_USB_IN_SIZE); - ao_led_off(AO_LED_TRNG_ACTIVE); ao_usb_write(buffer[usb_buf_id], AO_USB_IN_SIZE); usb_buf_id = 1-usb_buf_id; } @@ -61,5 +93,6 @@ static struct ao_task ao_trng_send_task; void ao_trng_send_init(void) { + ao_enable_input(AO_RAW_PORT, AO_RAW_BIT, AO_EXTI_MODE_PULL_UP); ao_add_task(&ao_trng_send_task, ao_trng_send, "trng_send"); } -- cgit v1.2.3 From 35407e664886bed21dcef7764843aac03be8490c Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 28 Jan 2016 13:58:43 -0800 Subject: altos/chaoskey: Delay ADC reading for 250ms at startup This lets the HV supply stabilize before we start sampling values. Signed-off-by: Keith Packard --- src/drivers/ao_trng_send.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'src') diff --git a/src/drivers/ao_trng_send.c b/src/drivers/ao_trng_send.c index 64c016b2..99994900 100644 --- a/src/drivers/ao_trng_send.c +++ b/src/drivers/ao_trng_send.c @@ -72,6 +72,11 @@ ao_trng_send(void) ao_crc_reset(); + /* Delay long enough for the HV power supply to stabilize so that the + * first bits we read aren't of poor quality + */ + ao_delay(AO_MS_TO_TICKS(250)); + for (;;) { if (ao_send_raw()) { ao_led_on(AO_LED_TRNG_RAW); -- cgit v1.2.3 From 1d7463befc18f415d8982f04e52729d3bf5b95a9 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 19 Jan 2016 23:55:32 -0800 Subject: altos: remove blank line in stmf0/ao_timer.c Signed-off-by: Keith Packard --- src/stmf0/ao_timer.c | 1 - 1 file changed, 1 deletion(-) (limited to 'src') diff --git a/src/stmf0/ao_timer.c b/src/stmf0/ao_timer.c index 3aae7e55..7d96542b 100644 --- a/src/stmf0/ao_timer.c +++ b/src/stmf0/ao_timer.c @@ -127,7 +127,6 @@ ao_clock_enable_crs(void) (0 << STM_CRS_CR_ERRIE) | (0 << STM_CRS_CR_SYNCWARNIE) | (0 << STM_CRS_CR_SYNCOKIE)); - } void -- cgit v1.2.3 From fbb07cf50ba7fa278d1f8201ef376ec12480e9aa Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 19 Jan 2016 23:55:52 -0800 Subject: altos/stmf0: Allow projects to specify non-default stack size 512 may not be suitable for everyone. Signed-off-by: Keith Packard --- src/stmf0/ao_arch.h | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src') diff --git a/src/stmf0/ao_arch.h b/src/stmf0/ao_arch.h index 6ee71ef9..45df0982 100644 --- a/src/stmf0/ao_arch.h +++ b/src/stmf0/ao_arch.h @@ -25,7 +25,9 @@ * STM32F0 definitions and code fragments for AltOS */ +#ifndef AO_STACK_SIZE #define AO_STACK_SIZE 512 +#endif #define AO_LED_TYPE uint16_t -- cgit v1.2.3 From 36c6d74048283d27c890054814eee2cb39b7cbb7 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 6 Feb 2016 22:47:23 +1100 Subject: altos: Add power management APIs This provides sequenced suspend/resume functionality, allowing modules to register for power management at configuration time. Signed-off-by: Keith Packard --- src/kernel/ao.h | 10 +++++++ src/kernel/ao_power.c | 80 +++++++++++++++++++++++++++++++++++++++++++++++++++ src/kernel/ao_power.h | 53 ++++++++++++++++++++++++++++++++++ 3 files changed, 143 insertions(+) create mode 100644 src/kernel/ao_power.c create mode 100644 src/kernel/ao_power.h (limited to 'src') diff --git a/src/kernel/ao.h b/src/kernel/ao.h index 59a469ae..a794ba71 100644 --- a/src/kernel/ao.h +++ b/src/kernel/ao.h @@ -124,6 +124,16 @@ ao_timer_init(void); void ao_clock_init(void); +#if AO_POWER_MANAGEMENT +/* Go to low power clock */ +void +ao_clock_suspend(void); + +/* Restart full-speed clock */ +void +ao_clock_resume(void); +#endif + /* * ao_mutex.c */ diff --git a/src/kernel/ao_power.c b/src/kernel/ao_power.c new file mode 100644 index 00000000..bead5944 --- /dev/null +++ b/src/kernel/ao_power.c @@ -0,0 +1,80 @@ +/* + * Copyright © 2016 Keith Packard + * + * 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 struct ao_power *head, *tail; + +void +ao_power_register(struct ao_power *power) +{ + if (power->registered) + return; + power->registered = TRUE; + if (tail) { + tail->next = power; + power->prev = tail; + tail = power; + } else { + head = tail = power; + } +#ifdef AO_LED_POWER + ao_led_on(AO_LED_POWER); +#endif +} + +void +ao_power_unregister(struct ao_power *power) +{ + if (!power->registered) + return; + power->registered = FALSE; + if (power->prev) + power->prev->next = power->next; + else + head = power->next; + if (power->next) + power->next->prev = power->prev; + else + tail = power->prev; +} + +void +ao_power_suspend(void) +{ + struct ao_power *p; + +#ifdef AO_LED_POWER + ao_led_off(AO_LED_POWER); +#endif + for (p = tail; p; p = p->prev) + p->suspend(p->arg); +} + +void +ao_power_resume(void) +{ + struct ao_power *p; + + for (p = head; p; p = p->next) + p->resume(p->arg); +#ifdef AO_LED_POWER + ao_led_on(AO_LED_POWER); +#endif +} + diff --git a/src/kernel/ao_power.h b/src/kernel/ao_power.h new file mode 100644 index 00000000..98a8c1c7 --- /dev/null +++ b/src/kernel/ao_power.h @@ -0,0 +1,53 @@ +/* + * Copyright © 2016 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#ifndef _AO_POWER_H_ +#define _AO_POWER_H_ + +#if AO_POWER_MANAGEMENT + +struct ao_power { + struct ao_power *prev, *next; + + void (*suspend)(void *arg); + void (*resume)(void *arg); + void *arg; + uint8_t registered; +}; + +void +ao_power_register(struct ao_power *power); + +void +ao_power_unregister(struct ao_power *power); + +void +ao_power_suspend(void); + +void +ao_power_resume(void); + +#else /* AO_POWER_MANAGEMENT */ + +#define ao_power_register(power) +#define ao_power_unregister(power) +#define ao_power_suspend() +#define ao_power_resume() + +#endif /* else AO_POWER_MANAGEMENT */ + +#endif /* _AO_POWER_H_ */ -- cgit v1.2.3 From a5607aad694c01c01c48229172b289f005a1b6bb Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 6 Feb 2016 22:51:32 +1100 Subject: altos/stmf0: Add suspend/resume support Allow USB suspend to suspend USB, GPIOs and master clock. Signed-off-by: Keith Packard --- src/stmf0/ao_arch_funcs.h | 62 ++++++++++++++++++++----------- src/stmf0/ao_timer.c | 94 ++++++++++++++++++++++++++++++++--------------- src/stmf0/ao_usb_stm.c | 58 ++++++++++++++++++++--------- 3 files changed, 145 insertions(+), 69 deletions(-) (limited to 'src') diff --git a/src/stmf0/ao_arch_funcs.h b/src/stmf0/ao_arch_funcs.h index 3db96be2..8d585f80 100644 --- a/src/stmf0/ao_arch_funcs.h +++ b/src/stmf0/ao_arch_funcs.h @@ -18,6 +18,8 @@ #ifndef _AO_ARCH_FUNCS_H_ #define _AO_ARCH_FUNCS_H_ +#include + /* ao_spi_stm.c */ @@ -118,27 +120,44 @@ ao_spi_try_get_mask(struct stm_gpio *reg, uint16_t mask, uint8_t bus, uint32_t s #define ao_spi_get_bit(reg,bit,pin,bus,speed) ao_spi_get_mask(reg,(1< 1 wait state */ @@ -227,29 +266,11 @@ ao_clock_init(void) stm_rcc.cfgr = cfgr; /* Switch to the desired system clock */ - - cfgr = stm_rcc.cfgr; - cfgr &= ~(STM_RCC_CFGR_SW_MASK << STM_RCC_CFGR_SW); - cfgr |= (STM_RCC_CFGR_SW_TARGET_CLOCK << STM_RCC_CFGR_SW); - stm_rcc.cfgr = cfgr; - for (;;) { - uint32_t c, part, mask, val; - - c = stm_rcc.cfgr; - mask = (STM_RCC_CFGR_SWS_MASK << STM_RCC_CFGR_SWS); - val = (STM_RCC_CFGR_SWS_TARGET_CLOCK << STM_RCC_CFGR_SWS); - part = c & mask; - if (part == val) - break; - } + ao_clock_normal_switch(); /* Clear reset flags */ stm_rcc.csr |= (1 << STM_RCC_CSR_RMVF); -#if !AO_HSI && !AO_NEED_HSI - /* Turn off the HSI clock */ - stm_rcc.cr &= ~(1 << STM_RCC_CR_HSION); -#endif #if DEBUG_THE_CLOCK /* Output SYSCLK on PA8 for measurments */ @@ -263,3 +284,18 @@ ao_clock_init(void) stm_rcc.cfgr |= (STM_RCC_CFGR_MCOSEL_HSE << STM_RCC_CFGR_MCOSEL); #endif } + +#if AO_POWER_MANAGEMENT +void +ao_clock_suspend(void) +{ + ao_clock_hsi(); +} + +void +ao_clock_resume(void) +{ + ao_clock_normal_start(); + ao_clock_normal_switch(); +} +#endif diff --git a/src/stmf0/ao_usb_stm.c b/src/stmf0/ao_usb_stm.c index b8146c21..691c2d56 100644 --- a/src/stmf0/ao_usb_stm.c +++ b/src/stmf0/ao_usb_stm.c @@ -18,8 +18,10 @@ #include "ao.h" #include "ao_usb.h" #include "ao_product.h" +#include "ao_power.h" #define USB_DEBUG 0 +#define USB_STATUS 0 #define USB_DEBUG_DATA 0 #define USB_ECHO 0 @@ -129,10 +131,9 @@ static uint8_t ao_usb_out_avail; uint8_t ao_usb_running; static uint8_t ao_usb_configuration; -#define AO_USB_EP0_GOT_RESET 1 -#define AO_USB_EP0_GOT_SETUP 2 -#define AO_USB_EP0_GOT_RX_DATA 4 -#define AO_USB_EP0_GOT_TX_ACK 8 +#define AO_USB_EP0_GOT_SETUP 1 +#define AO_USB_EP0_GOT_RX_DATA 2 +#define AO_USB_EP0_GOT_TX_ACK 4 static uint8_t ao_usb_ep0_receive; static uint8_t ao_usb_address; @@ -438,6 +439,7 @@ static uint16_t int_count; static uint16_t in_count; static uint16_t out_count; static uint16_t reset_count; +static uint16_t suspend_count; /* The USB memory must be accessed in 16-bit units */ @@ -686,11 +688,6 @@ static void ao_usb_ep0_handle(uint8_t receive) { ao_usb_ep0_receive = 0; - if (receive & AO_USB_EP0_GOT_RESET) { - debug ("\treset\n"); - ao_usb_set_ep0(); - return; - } if (receive & AO_USB_EP0_GOT_SETUP) { debug ("\tsetup\n"); ao_usb_ep0_setup(); @@ -721,6 +718,23 @@ ao_usb_ep0_handle(uint8_t receive) } } +void +ao_usb_suspend(void) +{ + stm_usb.cntr |= (1 << STM_USB_CNTR_FSUSP); + ao_power_suspend(); + stm_usb.cntr |= (1 << STM_USB_CNTR_LP_MODE); + ao_clock_suspend(); +} + +void +ao_usb_wakeup(void) +{ + ao_clock_resume(); + stm_usb.cntr &= ~(1 << STM_USB_CNTR_FSUSP); + ao_power_resume(); +} + void stm_usb_isr(void) { @@ -784,10 +798,18 @@ stm_usb_isr(void) if (istr & (1 << STM_USB_ISTR_RESET)) { ++reset_count; - ao_usb_ep0_receive |= AO_USB_EP0_GOT_RESET; - ao_usb_ep0_handle(ao_usb_ep0_receive); + debug ("\treset\n"); + ao_usb_set_ep0(); + } + if (istr & (1 << STM_USB_ISTR_SUSP)) { + ++suspend_count; + debug ("\tsuspend\n"); + ao_usb_suspend(); + } + if (istr & (1 << STM_USB_ISTR_WKUP)) { + debug ("\twakeup\n"); + ao_usb_wakeup(); } - } /* Queue the current IN buffer for transmission */ @@ -1050,8 +1072,8 @@ ao_usb_enable(void) stm_usb.cntr = ((1 << STM_USB_CNTR_CTRM) | (0 << STM_USB_CNTR_PMAOVRM) | (0 << STM_USB_CNTR_ERRM) | - (0 << STM_USB_CNTR_WKUPM) | - (0 << STM_USB_CNTR_SUSPM) | + (1 << STM_USB_CNTR_WKUPM) | + (1 << STM_USB_CNTR_SUSPM) | (1 << STM_USB_CNTR_RESETM) | (0 << STM_USB_CNTR_SOFM) | (0 << STM_USB_CNTR_ESOFM) | @@ -1086,12 +1108,12 @@ ao_usb_echo(void) } #endif -#if USB_DEBUG +#if USB_STATUS static void ao_usb_irq(void) { - printf ("control: %d out: %d in: %d int: %d reset: %d\n", - control_count, out_count, in_count, int_count, reset_count); + printf ("control: %d out: %d in: %d int: %d reset: %d suspend %d\n", + control_count, out_count, in_count, int_count, reset_count, suspend_count); } __code struct ao_cmds ao_usb_cmds[] = { @@ -1119,7 +1141,7 @@ ao_usb_init(void) #if USB_ECHO ao_add_task(&ao_usb_echo_task, ao_usb_echo, "usb echo"); #endif -#if USB_DEBUG +#if USB_STATUS ao_cmd_register(&ao_usb_cmds[0]); #endif #if !USB_ECHO -- cgit v1.2.3 From 2ad756bd1b63a2c8450edd7001628b92279fd1b8 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 7 Feb 2016 00:10:57 +1100 Subject: altos: Allow USB drivers to skip CDC-ACM -specific descriptors For devices not providing the standard CDC-ACM interface, let them skip the various descriptors and interfaces to provide a more limited set of capabilities. Signed-off-by: Keith Packard --- src/kernel/ao_product.c | 57 ++++++++++++++++++++++++++++++++++++------------- src/kernel/ao_usb.h | 12 +++++++++++ src/stmf0/ao_usb_stm.c | 24 +++++++++++++++------ 3 files changed, 72 insertions(+), 21 deletions(-) (limited to 'src') diff --git a/src/kernel/ao_product.c b/src/kernel/ao_product.c index c711a4d2..a1a9af09 100644 --- a/src/kernel/ao_product.c +++ b/src/kernel/ao_product.c @@ -33,11 +33,32 @@ const char ao_product[] = AO_iProduct_STRING; #define AO_USB_MAX_POWER 100 #endif -#ifndef AO_USB_INTERFACE_CLASS -#define AO_USB_INTERFACE_CLASS 0x02 +#ifndef AO_USB_SELF_POWER +#define AO_USB_SELF_POWER 1 +#endif + +#define AO_USB_DEVICE_CLASS_COMMUNICATION 0x02 +#define AO_USB_INTERFACE_CLASS_CONTROL_CDC 0x02 +#define AO_USB_INTERFACE_CLASS_DATA_CDC 0x0A + +#ifndef AO_USB_DEVICE_CLASS +#define AO_USB_DEVICE_CLASS AO_USB_DEVICE_CLASS_COMMUNICATION +#endif + +#ifndef AO_USB_INTERFACE_CLASS_DATA +#define AO_USB_INTERFACE_CLASS_CONTROL AO_USB_INTERFACE_CLASS_CONTROL_CDC +#define AO_USB_INTERFACE_CLASS_DATA AO_USB_INTERFACE_CLASS_DATA_CDC #endif #include "ao_usb.h" + +#define HEADER_LEN 9 +#define CONTROL_CLASS_LEN 35 +#define DATA_LEN (9 + 7 * AO_USB_HAS_OUT + 7 * AO_USB_HAS_IN) + +#define TOTAL_LENGTH (HEADER_LEN + AO_USB_HAS_INT * CONTROL_CLASS_LEN + DATA_LEN) +#define NUM_INTERFACES (AO_USB_HAS_INT + 1) + /* USB descriptors in one giant block of bytes */ AO_ROMCONFIG_SYMBOL(0x00aa) uint8_t ao_usb_descriptors [] = { @@ -45,7 +66,7 @@ AO_ROMCONFIG_SYMBOL(0x00aa) uint8_t ao_usb_descriptors [] = 0x12, AO_USB_DESC_DEVICE, LE_WORD(0x0110), /* bcdUSB */ - 0x02, /* bDeviceClass */ + AO_USB_DEVICE_CLASS, /* bDeviceClass */ 0x00, /* bDeviceSubClass */ 0x00, /* bDeviceProtocol */ AO_USB_CONTROL_SIZE, /* bMaxPacketSize */ @@ -60,20 +81,21 @@ AO_ROMCONFIG_SYMBOL(0x00aa) uint8_t ao_usb_descriptors [] = /* Configuration descriptor */ 0x09, AO_USB_DESC_CONFIGURATION, - LE_WORD(67), /* wTotalLength */ - 0x02, /* bNumInterfaces */ + LE_WORD(TOTAL_LENGTH), /* wTotalLength */ + NUM_INTERFACES, /* bNumInterfaces */ 0x01, /* bConfigurationValue */ 0x00, /* iConfiguration */ - 0xC0, /* bmAttributes */ + 0x80 | (AO_USB_SELF_POWER << 6), /* bmAttributes */ AO_USB_MAX_POWER >> 1, /* bMaxPower, 2mA units */ +#if AO_USB_HAS_INT /* Control class interface */ 0x09, AO_USB_DESC_INTERFACE, 0x00, /* bInterfaceNumber */ 0x00, /* bAlternateSetting */ 0x01, /* bNumEndPoints */ - AO_USB_INTERFACE_CLASS, /* bInterfaceClass */ + AO_USB_INTERFACE_CLASS_CONTROL, /* bInterfaceClass */ 0x02, /* bInterfaceSubClass */ 0x01, /* bInterfaceProtocol, linux requires value of 1 for the cdc_acm module */ 0x00, /* iInterface */ @@ -111,18 +133,20 @@ AO_ROMCONFIG_SYMBOL(0x00aa) uint8_t ao_usb_descriptors [] = 0x03, /* bmAttributes = intr */ LE_WORD(8), /* wMaxPacketSize */ 0xff, /* bInterval */ +#endif /* Data class interface descriptor */ 0x09, AO_USB_DESC_INTERFACE, - 0x01, /* bInterfaceNumber */ - 0x00, /* bAlternateSetting */ - 0x02, /* bNumEndPoints */ - 0x0A, /* bInterfaceClass = data */ - 0x00, /* bInterfaceSubClass */ - 0x00, /* bInterfaceProtocol */ - 0x00, /* iInterface */ - + 0x01, /* bInterfaceNumber */ + 0x00, /* bAlternateSetting */ + AO_USB_HAS_OUT + AO_USB_HAS_IN, /* bNumEndPoints */ + AO_USB_INTERFACE_CLASS_DATA, /* bInterfaceClass = data */ + 0x00, /* bInterfaceSubClass */ + 0x00, /* bInterfaceProtocol */ + 0x00, /* iInterface */ + +#if AO_USB_HAS_OUT /* Data EP OUT */ 0x07, AO_USB_DESC_ENDPOINT, @@ -130,7 +154,9 @@ AO_ROMCONFIG_SYMBOL(0x00aa) uint8_t ao_usb_descriptors [] = 0x02, /* bmAttributes = bulk */ LE_WORD(AO_USB_OUT_SIZE),/* wMaxPacketSize */ 0x00, /* bInterval */ +#endif +#if AO_USB_HAS_IN /* Data EP in */ 0x07, AO_USB_DESC_ENDPOINT, @@ -138,6 +164,7 @@ AO_ROMCONFIG_SYMBOL(0x00aa) uint8_t ao_usb_descriptors [] = 0x02, /* bmAttributes = bulk */ LE_WORD(AO_USB_IN_SIZE),/* wMaxPacketSize */ 0x00, /* bInterval */ +#endif /* String descriptors */ 0x04, diff --git a/src/kernel/ao_usb.h b/src/kernel/ao_usb.h index 1ce4f82f..773b5cb7 100644 --- a/src/kernel/ao_usb.h +++ b/src/kernel/ao_usb.h @@ -107,6 +107,18 @@ extern __code __at (0x00aa) uint8_t ao_usb_descriptors []; #define AO_USB_IN_EP 5 #endif +#ifndef AO_USB_HAS_OUT +#define AO_USB_HAS_OUT 1 +#endif + +#ifndef AO_USB_HAS_IN +#define AO_USB_HAS_IN 1 +#endif + +#ifndef AO_USB_HAS_INT +#define AO_USB_HAS_INT 1 +#endif + /* * USB bulk packets can only come in 8, 16, 32 and 64 * byte sizes, so we'll use 64 for everything diff --git a/src/stmf0/ao_usb_stm.c b/src/stmf0/ao_usb_stm.c index 691c2d56..b0f4c516 100644 --- a/src/stmf0/ao_usb_stm.c +++ b/src/stmf0/ao_usb_stm.c @@ -29,6 +29,10 @@ #error "must define AO_PA11_PA12_RMP" #endif +#ifndef AO_POWER_MANAGEMENT +#define AO_POWER_MANAGEMENT 0 +#endif + #ifndef USE_USB_STDIO #define USE_USB_STDIO 1 #endif @@ -397,6 +401,7 @@ ao_usb_set_configuration(void) { debug ("ao_usb_set_configuration\n"); +#if AO_USB_HAS_INT /* Set up the INT end point */ ao_usb_bdt[AO_USB_INT_EPR].single.addr_tx = ao_usb_int_tx_offset; ao_usb_bdt[AO_USB_INT_EPR].single.count_tx = 0; @@ -406,7 +411,9 @@ ao_usb_set_configuration(void) STM_USB_EPR_EP_TYPE_INTERRUPT, STM_USB_EPR_STAT_RX_DISABLED, STM_USB_EPR_STAT_TX_NAK); +#endif +#if AO_USB_HAS_OUT /* Set up the OUT end point */ ao_usb_bdt[AO_USB_OUT_EPR].single.addr_rx = ao_usb_out_rx_offset; ao_usb_bdt[AO_USB_OUT_EPR].single.count_rx = ((1 << STM_USB_BDT_COUNT_RX_BL_SIZE) | @@ -417,7 +424,9 @@ ao_usb_set_configuration(void) STM_USB_EPR_EP_TYPE_BULK, STM_USB_EPR_STAT_RX_VALID, STM_USB_EPR_STAT_TX_DISABLED); +#endif +#if AO_USB_HAS_IN /* Set up the IN end point */ ao_usb_bdt[AO_USB_IN_EPR].single.addr_tx = ao_usb_in_tx_offset; ao_usb_bdt[AO_USB_IN_EPR].single.count_tx = 0; @@ -427,6 +436,7 @@ ao_usb_set_configuration(void) STM_USB_EPR_EP_TYPE_BULK, STM_USB_EPR_STAT_RX_DISABLED, STM_USB_EPR_STAT_TX_NAK); +#endif ao_usb_running = 1; #if AO_USB_DIRECTIO @@ -439,7 +449,6 @@ static uint16_t int_count; static uint16_t in_count; static uint16_t out_count; static uint16_t reset_count; -static uint16_t suspend_count; /* The USB memory must be accessed in 16-bit units */ @@ -718,6 +727,7 @@ ao_usb_ep0_handle(uint8_t receive) } } +#if AO_POWER_MANAGEMENT void ao_usb_suspend(void) { @@ -734,6 +744,7 @@ ao_usb_wakeup(void) stm_usb.cntr &= ~(1 << STM_USB_CNTR_FSUSP); ao_power_resume(); } +#endif void stm_usb_isr(void) @@ -801,8 +812,8 @@ stm_usb_isr(void) debug ("\treset\n"); ao_usb_set_ep0(); } +#if AO_POWER_MANAGEMENT if (istr & (1 << STM_USB_ISTR_SUSP)) { - ++suspend_count; debug ("\tsuspend\n"); ao_usb_suspend(); } @@ -810,6 +821,7 @@ stm_usb_isr(void) debug ("\twakeup\n"); ao_usb_wakeup(); } +#endif } /* Queue the current IN buffer for transmission */ @@ -1072,8 +1084,8 @@ ao_usb_enable(void) stm_usb.cntr = ((1 << STM_USB_CNTR_CTRM) | (0 << STM_USB_CNTR_PMAOVRM) | (0 << STM_USB_CNTR_ERRM) | - (1 << STM_USB_CNTR_WKUPM) | - (1 << STM_USB_CNTR_SUSPM) | + (AO_POWER_MANAGEMENT << STM_USB_CNTR_WKUPM) | + (AO_POWER_MANAGEMENT << STM_USB_CNTR_SUSPM) | (1 << STM_USB_CNTR_RESETM) | (0 << STM_USB_CNTR_SOFM) | (0 << STM_USB_CNTR_ESOFM) | @@ -1112,8 +1124,8 @@ ao_usb_echo(void) static void ao_usb_irq(void) { - printf ("control: %d out: %d in: %d int: %d reset: %d suspend %d\n", - control_count, out_count, in_count, int_count, reset_count, suspend_count); + printf ("control: %d out: %d in: %d int: %d reset: %d\n", + control_count, out_count, in_count, int_count, reset_count); } __code struct ao_cmds ao_usb_cmds[] = { -- cgit v1.2.3 From 235198b85f1583d2792c7028decace61d1b4229e Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 7 Feb 2016 00:14:22 +1100 Subject: altos: Add power management to TRNG driver Support suspend/resume of the TRNG power supply, delaying after resume to wait for it to stabilize. Signed-off-by: Keith Packard --- src/drivers/ao_trng_send.c | 46 +++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 41 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/drivers/ao_trng_send.c b/src/drivers/ao_trng_send.c index 99994900..63366d3e 100644 --- a/src/drivers/ao_trng_send.c +++ b/src/drivers/ao_trng_send.c @@ -20,6 +20,9 @@ #include #include #include +#include + +static uint8_t trng_running; static void ao_trng_send_raw(uint16_t *buf) @@ -72,12 +75,15 @@ ao_trng_send(void) ao_crc_reset(); - /* Delay long enough for the HV power supply to stabilize so that the - * first bits we read aren't of poor quality - */ - ao_delay(AO_MS_TO_TICKS(250)); - for (;;) { + if (!trng_running) { + /* Delay long enough for the HV power supply + * to stabilize so that the first bits we read + * aren't of poor quality + */ + ao_delay(AO_MS_TO_TICKS(10)); + trng_running = TRUE; + } if (ao_send_raw()) { ao_led_on(AO_LED_TRNG_RAW); ao_trng_send_raw(buffer[usb_buf_id]); @@ -95,9 +101,39 @@ ao_trng_send(void) static struct ao_task ao_trng_send_task; +#if AO_POWER_MANAGEMENT + +static void ao_trng_suspend(void *arg) +{ + (void) arg; +#ifdef AO_TRNG_ENABLE_PORT + ao_gpio_set(AO_TRNG_ENABLE_PORT, AO_TRNG_ENABLE_BIT, AO_TRNG_ENABLE_PIN, 0); +#endif + trng_running = FALSE; +} + +static void ao_trng_resume(void *arg) +{ + (void) arg; +#ifdef AO_TRNG_ENABLE_PORT + ao_gpio_set(AO_TRNG_ENABLE_PORT, AO_TRNG_ENABLE_BIT, AO_TRNG_ENABLE_PIN, 1); +#endif +} + +static struct ao_power ao_trng_power = { + .suspend = ao_trng_suspend, + .resume = ao_trng_resume +}; + +#endif + void ao_trng_send_init(void) { +#ifdef AO_TRNG_ENABLE_PORT + ao_enable_output(AO_TRNG_ENABLE_PORT, AO_TRNG_ENABLE_BIT, AO_TRNG_ENABLE_PIN, 1); + ao_power_register(&ao_trng_power); +#endif ao_enable_input(AO_RAW_PORT, AO_RAW_BIT, AO_EXTI_MODE_PULL_UP); ao_add_task(&ao_trng_send_task, ao_trng_send, "trng_send"); } -- cgit v1.2.3 From 1473f9234ffd34d8f37bc489dfc9fc4d7f1b3eed Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 7 Feb 2016 00:15:47 +1100 Subject: altos/chaoskey-v0.1: Add power management and change USB classes Enable power management. Expose only a single IN endpoint. Signed-off-by: Keith Packard --- src/chaoskey-v0.1/Makefile | 3 +++ src/chaoskey-v0.1/ao_chaoskey.c | 8 -------- src/chaoskey-v0.1/ao_pins.h | 24 ++++++++++++++++-------- 3 files changed, 19 insertions(+), 16 deletions(-) (limited to 'src') diff --git a/src/chaoskey-v0.1/Makefile b/src/chaoskey-v0.1/Makefile index ac4a6788..4948a4c5 100644 --- a/src/chaoskey-v0.1/Makefile +++ b/src/chaoskey-v0.1/Makefile @@ -13,6 +13,7 @@ INC = \ ao_product.h \ ao_task.h \ ao_adc_fast.h \ + ao_power.h \ stm32f0.h # @@ -33,6 +34,8 @@ ALTOS_SRC = \ ao_usb_stm.c \ ao_trng_send.c \ ao_task.c \ + ao_power.c \ + ao_gpio.c \ ao_product.c PRODUCT=ChaosKey-v0.1 diff --git a/src/chaoskey-v0.1/ao_chaoskey.c b/src/chaoskey-v0.1/ao_chaoskey.c index c9490184..48c8bf04 100644 --- a/src/chaoskey-v0.1/ao_chaoskey.c +++ b/src/chaoskey-v0.1/ao_chaoskey.c @@ -20,12 +20,6 @@ #include #include -static void -ao_hv_init(void) -{ - ao_enable_output(AO_HV_ENABLE_PORT, AO_HV_ENABLE_BIT, AO_HV_ENABLE_PIN, 1); -} - void main(void) { ao_led_init(LEDS_AVAILABLE); @@ -39,8 +33,6 @@ void main(void) ao_usb_init(); - ao_hv_init(); - ao_trng_send_init(); ao_led_off(AO_LED_RED); diff --git a/src/chaoskey-v0.1/ao_pins.h b/src/chaoskey-v0.1/ao_pins.h index 95d9a576..a8109282 100644 --- a/src/chaoskey-v0.1/ao_pins.h +++ b/src/chaoskey-v0.1/ao_pins.h @@ -27,6 +27,9 @@ #define LEDS_AVAILABLE (AO_LED_RED | AO_LED_GREEN) +#define AO_POWER_MANAGEMENT 1 +#define AO_LED_POWER AO_LED_RED + #define HAS_BEEP 0 /* 48MHz clock based on USB */ @@ -40,10 +43,15 @@ #define AO_APB_PRESCALER 1 #define AO_RCC_CFGR_PPRE_DIV STM_RCC_CFGR_PPRE_DIV_1 -#define HAS_USB 1 -#define AO_USB_DIRECTIO 1 -#define AO_PA11_PA12_RMP 0 -#define AO_USB_INTERFACE_CLASS 0xff +#define HAS_USB 1 +#define AO_USB_DIRECTIO 1 +#define AO_PA11_PA12_RMP 0 +#define AO_USB_DEVICE_CLASS 0xff +#define AO_USB_INTERFACE_CLASS_DATA 0xff +#define AO_USB_HAS_OUT 0 +#define AO_USB_HAS_IN 1 +#define AO_USB_HAS_INT 0 +#define AO_USB_SELF_POWER 0 #define IS_FLASH_LOADER 0 @@ -57,10 +65,10 @@ #define AO_NUM_ADC 1 -/* HV enable */ +/* TRNG enable */ -#define AO_HV_ENABLE_PORT (&stm_gpioa) -#define AO_HV_ENABLE_BIT 8 +#define AO_TRNG_ENABLE_PORT (&stm_gpioa) +#define AO_TRNG_ENABLE_BIT 8 /* CRC */ #define AO_CRC_WIDTH 32 @@ -68,7 +76,7 @@ /* TRNG */ #define AO_LED_TRNG_COOKED AO_LED_GREEN -#define AO_LED_TRNG_RAW AO_LED_RED +#define AO_LED_TRNG_RAW AO_LED_GREEN /* Mode pin */ #define AO_RAW_PORT (&stm_gpioa) -- cgit v1.2.3 From 147f0df6a29b37fbfb0824ecd276482f0eecb397 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 7 Feb 2016 15:33:42 -0800 Subject: altos: Delay TRNG ADC long enough for HV supply to stabilize Looks like it takes about 70ms for the supply to start running right, so delay after powering it up for that long. Signed-off-by: Keith Packard --- src/drivers/ao_trng_send.c | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/drivers/ao_trng_send.c b/src/drivers/ao_trng_send.c index 63366d3e..11f441f8 100644 --- a/src/drivers/ao_trng_send.c +++ b/src/drivers/ao_trng_send.c @@ -22,7 +22,8 @@ #include #include -static uint8_t trng_running; +static uint8_t trng_running; +static AO_TICK_TYPE trng_power_time; static void ao_trng_send_raw(uint16_t *buf) @@ -45,7 +46,7 @@ ao_trng_send_cooked(uint16_t *buf) uint16_t t; uint32_t *rnd = (uint32_t *) ao_adc_ring; - t = ao_adc_get(AO_USB_IN_SIZE) >> 1; /* one 16-bit value per output byte */ + t = ao_adc_get(AO_USB_IN_SIZE) >> 1; /* two 16-bit values per two output bytes */ for (i = 0; i < AO_USB_IN_SIZE / sizeof (uint16_t); i++) { *buf++ = ao_crc_in_32_out_16(rnd[t]); t = (t + 1) & ((AO_ADC_RING_SIZE>>1) - 1); @@ -73,15 +74,26 @@ ao_trng_send(void) usb_buf_id = 0; +#ifdef AO_TRNG_ENABLE_PORT + ao_gpio_set(AO_TRNG_ENABLE_PORT, AO_TRNG_ENABLE_BIT, AO_TRNG_ENABLE_PIN, 1); +#endif + trng_power_time = ao_time(); + ao_crc_reset(); for (;;) { if (!trng_running) { + AO_TICK_TYPE delay; + + delay = trng_power_time + AO_MS_TO_TICKS(100) - ao_time(); + if (delay > AO_MS_TO_TICKS(100)) + delay = AO_MS_TO_TICKS(100); + /* Delay long enough for the HV power supply * to stabilize so that the first bits we read * aren't of poor quality */ - ao_delay(AO_MS_TO_TICKS(10)); + ao_delay(delay); trng_running = TRUE; } if (ao_send_raw()) { @@ -118,6 +130,7 @@ static void ao_trng_resume(void *arg) #ifdef AO_TRNG_ENABLE_PORT ao_gpio_set(AO_TRNG_ENABLE_PORT, AO_TRNG_ENABLE_BIT, AO_TRNG_ENABLE_PIN, 1); #endif + trng_power_time = ao_time(); } static struct ao_power ao_trng_power = { @@ -131,7 +144,7 @@ void ao_trng_send_init(void) { #ifdef AO_TRNG_ENABLE_PORT - ao_enable_output(AO_TRNG_ENABLE_PORT, AO_TRNG_ENABLE_BIT, AO_TRNG_ENABLE_PIN, 1); + ao_enable_output(AO_TRNG_ENABLE_PORT, AO_TRNG_ENABLE_BIT, AO_TRNG_ENABLE_PIN, 0); ao_power_register(&ao_trng_power); #endif ao_enable_input(AO_RAW_PORT, AO_RAW_BIT, AO_EXTI_MODE_PULL_UP); -- cgit v1.2.3 From bab082605e3fca6b6d11447c45cd948ddfe74bb9 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 7 Feb 2016 22:28:34 -0800 Subject: altos: Add simple stats test to TRNG code This detects broken hardware by making sure the standard deviation in the raw values used to compute each buffer is at least 128. Signed-off-by: Keith Packard --- src/drivers/ao_trng_send.c | 76 +++++++++++++++++++++++++++++++++++++--------- 1 file changed, 62 insertions(+), 14 deletions(-) (limited to 'src') diff --git a/src/drivers/ao_trng_send.c b/src/drivers/ao_trng_send.c index 11f441f8..f8222993 100644 --- a/src/drivers/ao_trng_send.c +++ b/src/drivers/ao_trng_send.c @@ -25,32 +25,68 @@ static uint8_t trng_running; static AO_TICK_TYPE trng_power_time; -static void +/* Make sure there's at least 8 bits of variance in the samples */ +#define MIN_VARIANCE (128 * 128) + +#define DECLARE_STATS int32_t sum = 0, sum2 = 0 + +#define ADD_STATS(value) do { \ + sum += (value); \ + sum2 += (value) * (value); \ + } while(0) + +#define GOOD_STATS(i) (((sum2 - (sum * sum) / i) / i) >= MIN_VARIANCE) + +#define TRNG_ENABLE_DELAY AO_MS_TO_TICKS(100) + +static int ao_trng_send_raw(uint16_t *buf) { uint16_t i; uint16_t t; - uint16_t *rnd = (uint16_t *) ao_adc_ring; + uint16_t v; + + DECLARE_STATS; t = ao_adc_get(AO_USB_IN_SIZE>>1); /* one 16-bit value per two output bytes */ for (i = 0; i < AO_USB_IN_SIZE / sizeof (uint16_t); i++) { - *buf++ = rnd[t]; + v = ao_adc_ring[t]; + *buf++ = v; t = (t + 1) & (AO_ADC_RING_SIZE - 1); + + ADD_STATS(v); } + return GOOD_STATS(AO_USB_IN_SIZE / sizeof (uint16_t)); } -static void +static int ao_trng_send_cooked(uint16_t *buf) { uint16_t i; uint16_t t; uint32_t *rnd = (uint32_t *) ao_adc_ring; - t = ao_adc_get(AO_USB_IN_SIZE) >> 1; /* two 16-bit values per two output bytes */ + DECLARE_STATS; + + t = ao_adc_get(AO_USB_IN_SIZE) >> 1; /* one 16-bit value per output byte */ + for (i = 0; i < AO_USB_IN_SIZE / sizeof (uint16_t); i++) { - *buf++ = ao_crc_in_32_out_16(rnd[t]); - t = (t + 1) & ((AO_ADC_RING_SIZE>>1) - 1); + uint32_t v; + uint16_t v1, v2; + + /* Fetch two values in one operation */ + v = rnd[t]; + t = (t + 1) & ((AO_ADC_RING_SIZE >> 1) - 1); + + *buf++ = ao_crc_in_32_out_16(v); + + v1 = v; + v2 = v >> 16; + + ADD_STATS(v1); + ADD_STATS(v2); } + return GOOD_STATS(2 * AO_USB_IN_SIZE / sizeof (uint16_t)); } static inline int @@ -64,6 +100,8 @@ ao_trng_send(void) { static uint16_t *buffer[2]; int usb_buf_id; + int good_bits; + int failed = 0; if (!buffer[0]) { buffer[0] = ao_usb_alloc(); @@ -85,9 +123,9 @@ ao_trng_send(void) if (!trng_running) { AO_TICK_TYPE delay; - delay = trng_power_time + AO_MS_TO_TICKS(100) - ao_time(); - if (delay > AO_MS_TO_TICKS(100)) - delay = AO_MS_TO_TICKS(100); + delay = trng_power_time + TRNG_ENABLE_DELAY - ao_time(); + if (delay > TRNG_ENABLE_DELAY) + delay = TRNG_ENABLE_DELAY; /* Delay long enough for the HV power supply * to stabilize so that the first bits we read @@ -98,16 +136,26 @@ ao_trng_send(void) } if (ao_send_raw()) { ao_led_on(AO_LED_TRNG_RAW); - ao_trng_send_raw(buffer[usb_buf_id]); + good_bits = ao_trng_send_raw(buffer[usb_buf_id]); ao_led_off(AO_LED_TRNG_RAW); } else { ao_led_on(AO_LED_TRNG_COOKED); - ao_trng_send_cooked(buffer[usb_buf_id]); + good_bits = ao_trng_send_cooked(buffer[usb_buf_id]); ao_led_off(AO_LED_TRNG_COOKED); } ao_adc_ack(AO_USB_IN_SIZE); - ao_usb_write(buffer[usb_buf_id], AO_USB_IN_SIZE); - usb_buf_id = 1-usb_buf_id; + if (good_bits) { + ao_usb_write(buffer[usb_buf_id], AO_USB_IN_SIZE); + usb_buf_id = 1-usb_buf_id; + failed = 0; + } else { + failed++; + ao_delay(AO_MS_TO_TICKS(10)); + if (failed > 10) { + ao_usb_disable(); + ao_panic(AO_PANIC_DMA); + } + } } } -- cgit v1.2.3 From 5ce26345784459f5864ef59c96c8aa633d2ddf64 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 7 Feb 2016 22:30:27 -0800 Subject: altos/stmf0: Add missing ao_gpio.c This contains the code for power managing the GPIO pins Signed-off-by: Keith Packard --- src/stmf0/ao_gpio.c | 71 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 71 insertions(+) create mode 100644 src/stmf0/ao_gpio.c (limited to 'src') diff --git a/src/stmf0/ao_gpio.c b/src/stmf0/ao_gpio.c new file mode 100644 index 00000000..c7bf0797 --- /dev/null +++ b/src/stmf0/ao_gpio.c @@ -0,0 +1,71 @@ +/* + * Copyright © 2016 Keith Packard + * + * 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 + +static void +ao_gpio_suspend(void *arg) +{ + struct stm_gpio *port = arg; + if (port == &stm_gpioa) + stm_rcc.ahbenr &= ~(1 << STM_RCC_AHBENR_IOPAEN); + else if ((port) == &stm_gpiob) + stm_rcc.ahbenr &= ~(1 << STM_RCC_AHBENR_IOPBEN); + else if ((port) == &stm_gpioc) + stm_rcc.ahbenr &= ~(1 << STM_RCC_AHBENR_IOPCEN); + else if ((port) == &stm_gpiof) + stm_rcc.ahbenr &= ~(1 << STM_RCC_AHBENR_IOPFEN); +} + +static void +ao_gpio_resume(void *arg) +{ + struct stm_gpio *port = arg; + if (port == &stm_gpioa) + stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_IOPAEN); + else if ((port) == &stm_gpiob) + stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_IOPBEN); + else if ((port) == &stm_gpioc) + stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_IOPCEN); + else if ((port) == &stm_gpiof) + stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_IOPFEN); +} + +struct ao_power ao_power_gpioa = { + .suspend = ao_gpio_suspend, + .resume = ao_gpio_resume, + .arg = &stm_gpioa +}; + +struct ao_power ao_power_gpiob = { + .suspend = ao_gpio_suspend, + .resume = ao_gpio_resume, + .arg = &stm_gpiob +}; + +struct ao_power ao_power_gpioc = { + .suspend = ao_gpio_suspend, + .resume = ao_gpio_resume, + .arg = &stm_gpioc +}; + +struct ao_power ao_power_gpiof = { + .suspend = ao_gpio_suspend, + .resume = ao_gpio_resume, + .arg = &stm_gpiof +}; + -- cgit v1.2.3 From e36117ccbf7cbe3704c6b44d3ad429e720a1e16c Mon Sep 17 00:00:00 2001 From: Bart Massey Date: Mon, 8 Feb 2016 18:55:28 -0800 Subject: Clean up stmf0 adc init. This better matches the documented cal sequence. Signed-off-by: Keith Packard --- src/stmf0/ao_adc_fast.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/stmf0/ao_adc_fast.c b/src/stmf0/ao_adc_fast.c index 26e6691c..f6740b0e 100644 --- a/src/stmf0/ao_adc_fast.c +++ b/src/stmf0/ao_adc_fast.c @@ -83,7 +83,6 @@ void ao_adc_init(void) { uint32_t chselr; - int i; /* Reset ADC */ stm_rcc.apb2rstr |= (1 << STM_RCC_APB2RSTR_ADCRST); @@ -157,12 +156,13 @@ ao_adc_init(void) /* Shortest sample time */ stm_adc.smpr = STM_ADC_SMPR_SMP_1_5 << STM_ADC_SMPR_SMP; + /* Turn off enable and start */ + stm_adc.cr &= ~((1 << STM_ADC_CR_ADEN) | (1 << STM_ADC_CR_ADSTART)); + /* Calibrate */ stm_adc.cr |= (1 << STM_ADC_CR_ADCAL); - for (i = 0; i < 0xf000; i++) { - if ((stm_adc.cr & (1 << STM_ADC_CR_ADCAL)) == 0) - break; - } + while ((stm_adc.cr & (1 << STM_ADC_CR_ADCAL)) != 0) + ; /* Enable */ stm_adc.cr |= (1 << STM_ADC_CR_ADEN); -- cgit v1.2.3 From 0bae4b25882983cd0b7950b3e80b6d93a72f0847 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 8 Feb 2016 19:15:31 -0800 Subject: altos: Another fix for non CDC-ACM devices Need to set the bInterfaceNumber for the actual interface to zero when there isn't an INT interface before it. Signed-off-by: Keith Packard --- src/kernel/ao_product.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/kernel/ao_product.c b/src/kernel/ao_product.c index a1a9af09..4769d86e 100644 --- a/src/kernel/ao_product.c +++ b/src/kernel/ao_product.c @@ -138,7 +138,7 @@ AO_ROMCONFIG_SYMBOL(0x00aa) uint8_t ao_usb_descriptors [] = /* Data class interface descriptor */ 0x09, AO_USB_DESC_INTERFACE, - 0x01, /* bInterfaceNumber */ + AO_USB_HAS_INT, /* bInterfaceNumber */ 0x00, /* bAlternateSetting */ AO_USB_HAS_OUT + AO_USB_HAS_IN, /* bNumEndPoints */ AO_USB_INTERFACE_CLASS_DATA, /* bInterfaceClass = data */ -- cgit v1.2.3 From afef70bb8f31075de364ddf713f3ccf1d9c6361d Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 15 Feb 2016 14:04:04 -0800 Subject: altos/stmf0: Fix location of device_id register Copied from stm32l and never fixed. Signed-off-by: Keith Packard --- src/stmf0/registers.ld | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/stmf0/registers.ld b/src/stmf0/registers.ld index 598fc1af..1f9862b1 100644 --- a/src/stmf0/registers.ld +++ b/src/stmf0/registers.ld @@ -54,4 +54,4 @@ stm_mpu = 0xe000ed90; /* calibration data in system memory */ stm_cal = 0x1ffff7b8; stm_flash_size_04x = 0x1ffff7cc; -stm_device_id = 0x1ff80050; +stm_device_id = 0x1ffff7ac; -- cgit v1.2.3 From e4006444d3d7b0c499139f58f13353988d38dbb4 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 15 Feb 2016 15:23:15 -0800 Subject: altos/chaoskey: Encode both hardware and software versions in product ID We have no other way of reporting the software version, so just encode it in the product ID. Signed-off-by: Keith Packard --- src/chaoskey-v0.1/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/chaoskey-v0.1/Makefile b/src/chaoskey-v0.1/Makefile index 4948a4c5..85392280 100644 --- a/src/chaoskey-v0.1/Makefile +++ b/src/chaoskey-v0.1/Makefile @@ -38,7 +38,7 @@ ALTOS_SRC = \ ao_gpio.c \ ao_product.c -PRODUCT=ChaosKey-v0.1 +PRODUCT=ChaosKey-hw-0.3-sw-$(VERSION) PRODUCT_DEF=-DCHAOSKEY_V_0_1 IDVENDOR=0x1d50 IDPRODUCT=0x60c6 -- cgit v1.2.3 From 5637c1b2fd7232842245af1437e33b5bb1583c7d Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 15 Feb 2016 15:24:35 -0800 Subject: altos/stmf0: Use device ID as usb serial number if requested This exposes the hardware device ID (which is unique per-chip) as the USB serial number, avoiding the need to create a custom ROM image for each device. Signed-off-by: Keith Packard --- src/stmf0/ao_usb_stm.c | 41 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) (limited to 'src') diff --git a/src/stmf0/ao_usb_stm.c b/src/stmf0/ao_usb_stm.c index b0f4c516..17e8709c 100644 --- a/src/stmf0/ao_usb_stm.c +++ b/src/stmf0/ao_usb_stm.c @@ -570,6 +570,36 @@ ao_usb_ep0_in_start(uint16_t max) static struct ao_usb_line_coding ao_usb_line_coding = {115200, 0, 0, 8}; +#if AO_USB_DEVICE_ID_SERIAL +static uint8_t ao_usb_serial[2 + 48]; + +/* Convert a 32-bit value to 8 hexidecimal UCS2 characters */ +static void +hex_to_ucs2(uint32_t in, uint8_t *out) +{ + int i; + + for (i = 28; i >= 0; i -= 4) { + uint8_t bits = (in >> i) & 0xf; + *out++ = (bits < 10) ? ('0' + bits) : ('a' + bits); + *out++ = 0; + } +} + +/* Encode the device ID (96 bits) in hexidecimal to use as a device + * serial number + */ +static void +ao_usb_serial_init(void) +{ + ao_usb_serial[0] = 50; /* length */ + ao_usb_serial[1] = AO_USB_DESC_STRING; + hex_to_ucs2(stm_device_id.u_id0, ao_usb_serial + 2 + 0); + hex_to_ucs2(stm_device_id.u_id1, ao_usb_serial + 2 + 16); + hex_to_ucs2(stm_device_id.u_id2, ao_usb_serial + 2 + 32); +} +#endif + /* Walk through the list of descriptors and find a match */ static void @@ -587,6 +617,13 @@ ao_usb_get_descriptor(uint16_t value) len = descriptor[2]; else len = descriptor[0]; +#if AO_USB_DEVICE_ID_SERIAL + /* Slightly hacky - the serial number is string 3 */ + if (type == AO_USB_DESC_STRING && (value & 0xff) == 3) { + descriptor = ao_usb_serial; + len = sizeof (ao_usb_serial); + } +#endif ao_usb_ep0_in_set(descriptor, len); break; } @@ -1145,6 +1182,10 @@ ao_usb_init(void) ao_usb_enable(); +#if AO_USB_DEVICE_ID_SERIAL + ao_usb_serial_init(); +#endif + debug ("ao_usb_init\n"); ao_usb_ep0_state = AO_USB_EP0_IDLE; -- cgit v1.2.3 From 05354b8fee6a9af05d66bb7f4761f597da038fdd Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 15 Feb 2016 15:26:00 -0800 Subject: altos/chaoskey: Use SoC device ID as serial number To make manufacturing these devices tractable, we don't want to require a custom firmware load for each device, but we still want a unique serial number. Fortunately, the SoC provides a 96-bit ID which we can use. Signed-off-by: Keith Packard --- src/chaoskey-v0.1/ao_pins.h | 1 + 1 file changed, 1 insertion(+) (limited to 'src') diff --git a/src/chaoskey-v0.1/ao_pins.h b/src/chaoskey-v0.1/ao_pins.h index a8109282..6ec582a9 100644 --- a/src/chaoskey-v0.1/ao_pins.h +++ b/src/chaoskey-v0.1/ao_pins.h @@ -52,6 +52,7 @@ #define AO_USB_HAS_IN 1 #define AO_USB_HAS_INT 0 #define AO_USB_SELF_POWER 0 +#define AO_USB_DEVICE_ID_SERIAL 1 #define IS_FLASH_LOADER 0 -- cgit v1.2.3 From 05fcb717bfc44aba3c1cfd43281e323505a46402 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 2 Mar 2016 13:54:58 -0800 Subject: altos/chaoskey: Add another USB endpoint to read raw data This replaces having the single output switch based on a pin value and allows us to box the device and still fetch raw data. For now, this will use a special libusb2 program, ao-chaosread, to pull bits as I haven't figure out how to make linux provide two /dev entries for one USB device. Signed-off-by: Keith Packard --- src/chaoskey-v0.1/ao_pins.h | 2 + src/drivers/ao_trng_send.c | 149 +++++++++++++++++++++++---------- src/kernel/ao_product.c | 14 +++- src/kernel/ao_usb.h | 5 ++ src/stmf0/ao_arch_funcs.h | 3 + src/stmf0/ao_usb_stm.c | 195 +++++++++++++++++++++++++++++++++++++++++++- 6 files changed, 321 insertions(+), 47 deletions(-) (limited to 'src') diff --git a/src/chaoskey-v0.1/ao_pins.h b/src/chaoskey-v0.1/ao_pins.h index 6ec582a9..73f76307 100644 --- a/src/chaoskey-v0.1/ao_pins.h +++ b/src/chaoskey-v0.1/ao_pins.h @@ -50,7 +50,9 @@ #define AO_USB_INTERFACE_CLASS_DATA 0xff #define AO_USB_HAS_OUT 0 #define AO_USB_HAS_IN 1 +#define AO_USB_HAS_IN2 1 #define AO_USB_HAS_INT 0 +#define USE_USB_STDIO 0 #define AO_USB_SELF_POWER 0 #define AO_USB_DEVICE_ID_SERIAL 1 diff --git a/src/drivers/ao_trng_send.c b/src/drivers/ao_trng_send.c index f8222993..171a345f 100644 --- a/src/drivers/ao_trng_send.c +++ b/src/drivers/ao_trng_send.c @@ -22,54 +22,97 @@ #include #include +static struct ao_task ao_trng_send_task, ao_trng_send_raw_task; static uint8_t trng_running; static AO_TICK_TYPE trng_power_time; -/* Make sure there's at least 8 bits of variance in the samples */ -#define MIN_VARIANCE (128 * 128) - -#define DECLARE_STATS int32_t sum = 0, sum2 = 0 - -#define ADD_STATS(value) do { \ - sum += (value); \ - sum2 += (value) * (value); \ - } while(0) - -#define GOOD_STATS(i) (((sum2 - (sum * sum) / i) / i) >= MIN_VARIANCE) - #define TRNG_ENABLE_DELAY AO_MS_TO_TICKS(100) -static int -ao_trng_send_raw(uint16_t *buf) +static uint8_t random_mutex; + +static void +ao_trng_get_raw(uint16_t *buf) { uint16_t i; uint16_t t; uint16_t v; - DECLARE_STATS; - t = ao_adc_get(AO_USB_IN_SIZE>>1); /* one 16-bit value per two output bytes */ for (i = 0; i < AO_USB_IN_SIZE / sizeof (uint16_t); i++) { v = ao_adc_ring[t]; *buf++ = v; t = (t + 1) & (AO_ADC_RING_SIZE - 1); + } + ao_adc_ack(AO_USB_IN_SIZE>>1); +} + +static void +ao_trng_send_raw(void) +{ + static uint16_t *buffer[2]; + int usb_buf_id; - ADD_STATS(v); + if (!buffer[0]) { + buffer[0] = ao_usb_alloc(); + buffer[1] = ao_usb_alloc(); + if (!buffer[0]) + ao_exit(); + } + + usb_buf_id = 0; + + for (;;) { + ao_mutex_get(&random_mutex); + if (!trng_running) { + AO_TICK_TYPE delay; + + delay = trng_power_time + TRNG_ENABLE_DELAY - ao_time(); + if (delay > TRNG_ENABLE_DELAY) + delay = TRNG_ENABLE_DELAY; + + /* Delay long enough for the HV power supply + * to stabilize so that the first bits we read + * aren't of poor quality + */ + ao_delay(delay); + trng_running = TRUE; + } +#ifdef AO_LED_TRNG_RAW + ao_led_on(AO_LED_TRNG_RAW); +#endif + ao_trng_get_raw(buffer[usb_buf_id]); +#ifdef AO_LED_TRNG_RAW + ao_led_off(AO_LED_TRNG_RAW); +#endif + ao_mutex_put(&random_mutex); + ao_usb_write2(buffer[usb_buf_id], AO_USB_IN_SIZE); + usb_buf_id = 1-usb_buf_id; } - return GOOD_STATS(AO_USB_IN_SIZE / sizeof (uint16_t)); } +/* Make sure there's at least 8 bits of variance in the samples */ +#define MIN_VARIANCE (128 * 128) + +/* Make sure the signal is spread around a bit */ +#define MAX_VARIANCE (512 * 512) + +#define ADD_STATS(value) do { \ + sum += (value); \ + sum2 += (value) * (value); \ + } while(0) + +#define VARIANCE(n) ((sum2 - (sum / (n) * sum)) / (n)) + static int -ao_trng_send_cooked(uint16_t *buf) +ao_trng_get_cooked(uint16_t *buf) { uint16_t i; uint16_t t; uint32_t *rnd = (uint32_t *) ao_adc_ring; + int32_t sum, sum2, var; - DECLARE_STATS; - + sum = sum2 = 0; t = ao_adc_get(AO_USB_IN_SIZE) >> 1; /* one 16-bit value per output byte */ - for (i = 0; i < AO_USB_IN_SIZE / sizeof (uint16_t); i++) { uint32_t v; uint16_t v1, v2; @@ -86,14 +129,13 @@ ao_trng_send_cooked(uint16_t *buf) ADD_STATS(v1); ADD_STATS(v2); } - return GOOD_STATS(2 * AO_USB_IN_SIZE / sizeof (uint16_t)); + ao_adc_ack(AO_USB_IN_SIZE); + var = VARIANCE(2 * AO_USB_IN_SIZE / sizeof (uint16_t)); + return var >= MIN_VARIANCE && var <= MAX_VARIANCE; } -static inline int -ao_send_raw(void) -{ - return !ao_gpio_get(AO_RAW_PORT, AO_RAW_BIT, AO_RAW_PIN); -} +#define AO_TRNG_START_WAIT 1024 +#define AO_TRNG_START_CHECK 32 static void ao_trng_send(void) @@ -101,13 +143,14 @@ ao_trng_send(void) static uint16_t *buffer[2]; int usb_buf_id; int good_bits; - int failed = 0; + int failed; + int s; if (!buffer[0]) { buffer[0] = ao_usb_alloc(); buffer[1] = ao_usb_alloc(); if (!buffer[0]) - return; + ao_exit(); } usb_buf_id = 0; @@ -119,7 +162,33 @@ ao_trng_send(void) ao_crc_reset(); + ao_delay(TRNG_ENABLE_DELAY); + + for (s = 0; s < AO_TRNG_START_WAIT; s++) { + if (ao_trng_get_cooked(buffer[0])) + break; + ao_delay(AO_MS_TO_TICKS(10)); + } + + /* Validate the hardware before enabling USB */ + failed = 0; + for (s = 0; s < AO_TRNG_START_CHECK; s++) { + if (!ao_trng_get_cooked(buffer[0])) { + failed++; + ao_delay(AO_MS_TO_TICKS(10)); + } + } + if (failed > AO_TRNG_START_CHECK / 4) + ao_panic(AO_PANIC_DMA); + + ao_add_task(&ao_trng_send_raw_task, ao_trng_send_raw, "trng_send_raw"); + +#ifdef AO_USB_START_DISABLED + ao_usb_enable(); +#endif + for (;;) { + ao_mutex_get(&random_mutex); if (!trng_running) { AO_TICK_TYPE delay; @@ -134,16 +203,14 @@ ao_trng_send(void) ao_delay(delay); trng_running = TRUE; } - if (ao_send_raw()) { - ao_led_on(AO_LED_TRNG_RAW); - good_bits = ao_trng_send_raw(buffer[usb_buf_id]); - ao_led_off(AO_LED_TRNG_RAW); - } else { - ao_led_on(AO_LED_TRNG_COOKED); - good_bits = ao_trng_send_cooked(buffer[usb_buf_id]); - ao_led_off(AO_LED_TRNG_COOKED); - } - ao_adc_ack(AO_USB_IN_SIZE); +#ifdef AO_LED_TRNG_COOKED + ao_led_on(AO_LED_TRNG_COOKED); +#endif + good_bits = ao_trng_get_cooked(buffer[usb_buf_id]); +#ifdef AO_LED_TRNG_COOKED + ao_led_off(AO_LED_TRNG_COOKED); +#endif + ao_mutex_put(&random_mutex); if (good_bits) { ao_usb_write(buffer[usb_buf_id], AO_USB_IN_SIZE); usb_buf_id = 1-usb_buf_id; @@ -159,8 +226,6 @@ ao_trng_send(void) } } -static struct ao_task ao_trng_send_task; - #if AO_POWER_MANAGEMENT static void ao_trng_suspend(void *arg) diff --git a/src/kernel/ao_product.c b/src/kernel/ao_product.c index 4769d86e..3a829b3a 100644 --- a/src/kernel/ao_product.c +++ b/src/kernel/ao_product.c @@ -54,7 +54,7 @@ const char ao_product[] = AO_iProduct_STRING; #define HEADER_LEN 9 #define CONTROL_CLASS_LEN 35 -#define DATA_LEN (9 + 7 * AO_USB_HAS_OUT + 7 * AO_USB_HAS_IN) +#define DATA_LEN (9 + 7 * AO_USB_HAS_OUT + 7 * AO_USB_HAS_IN + 7 * AO_USB_HAS_IN2) #define TOTAL_LENGTH (HEADER_LEN + AO_USB_HAS_INT * CONTROL_CLASS_LEN + DATA_LEN) #define NUM_INTERFACES (AO_USB_HAS_INT + 1) @@ -140,7 +140,7 @@ AO_ROMCONFIG_SYMBOL(0x00aa) uint8_t ao_usb_descriptors [] = AO_USB_DESC_INTERFACE, AO_USB_HAS_INT, /* bInterfaceNumber */ 0x00, /* bAlternateSetting */ - AO_USB_HAS_OUT + AO_USB_HAS_IN, /* bNumEndPoints */ + AO_USB_HAS_OUT + AO_USB_HAS_IN + AO_USB_HAS_IN2, /* bNumEndPoints */ AO_USB_INTERFACE_CLASS_DATA, /* bInterfaceClass = data */ 0x00, /* bInterfaceSubClass */ 0x00, /* bInterfaceProtocol */ @@ -166,6 +166,16 @@ AO_ROMCONFIG_SYMBOL(0x00aa) uint8_t ao_usb_descriptors [] = 0x00, /* bInterval */ #endif +#if AO_USB_HAS_IN2 + /* Data EP in 2 */ + 0x07, + AO_USB_DESC_ENDPOINT, + AO_USB_IN2_EP|0x80, /* bEndpointAddress */ + 0x02, /* bmAttributes = bulk */ + LE_WORD(AO_USB_IN_SIZE),/* wMaxPacketSize */ + 0x00, /* bInterval */ +#endif + /* String descriptors */ 0x04, AO_USB_DESC_STRING, diff --git a/src/kernel/ao_usb.h b/src/kernel/ao_usb.h index 773b5cb7..8f3e7813 100644 --- a/src/kernel/ao_usb.h +++ b/src/kernel/ao_usb.h @@ -105,6 +105,7 @@ extern __code __at (0x00aa) uint8_t ao_usb_descriptors []; #ifndef AO_USB_OUT_EP #define AO_USB_OUT_EP 4 #define AO_USB_IN_EP 5 +#define AO_USB_IN2_EP 6 #endif #ifndef AO_USB_HAS_OUT @@ -119,6 +120,10 @@ extern __code __at (0x00aa) uint8_t ao_usb_descriptors []; #define AO_USB_HAS_INT 1 #endif +#ifndef AO_USB_HAS_IN2 +#define AO_USB_HAS_IN2 0 +#endif + /* * USB bulk packets can only come in 8, 16, 32 and 64 * byte sizes, so we'll use 64 for everything diff --git a/src/stmf0/ao_arch_funcs.h b/src/stmf0/ao_arch_funcs.h index 8d585f80..4e3ef018 100644 --- a/src/stmf0/ao_arch_funcs.h +++ b/src/stmf0/ao_arch_funcs.h @@ -413,6 +413,9 @@ ao_usb_free(uint16_t *buffer); void ao_usb_write(uint16_t *buffer, uint16_t len); + +void +ao_usb_write2(uint16_t *buffer, uint16_t len); #endif /* AO_USB_DIRECTIO */ #endif /* _AO_ARCH_FUNCS_H_ */ diff --git a/src/stmf0/ao_usb_stm.c b/src/stmf0/ao_usb_stm.c index 17e8709c..e68da8eb 100644 --- a/src/stmf0/ao_usb_stm.c +++ b/src/stmf0/ao_usb_stm.c @@ -89,23 +89,42 @@ static uint16_t ao_usb_sram_addr; static uint16_t *ao_usb_ep0_tx_buffer; static uint16_t *ao_usb_ep0_rx_buffer; +#if AO_USB_HAS_INT /* Pointer to interrupt buffer in USB memory */ static uint16_t ao_usb_int_tx_offset; +#endif /* Pointer to bulk data tx/rx buffers in USB memory */ +#if AO_USB_HAS_IN static uint16_t ao_usb_in_tx_offset; static uint16_t *ao_usb_in_tx_buffer; -static uint16_t ao_usb_out_rx_offset; -static uint16_t *ao_usb_out_rx_buffer; /* System ram shadow of USB buffer; writing individual bytes is * too much of a pain (sigh) */ static uint8_t ao_usb_tx_buffer[AO_USB_IN_SIZE]; static uint8_t ao_usb_tx_count; +#endif +#if AO_USB_HAS_OUT +static uint16_t ao_usb_out_rx_offset; +static uint16_t *ao_usb_out_rx_buffer; + +/* System ram shadow of USB buffer; writing individual bytes is + * too much of a pain (sigh) */ static uint8_t ao_usb_rx_buffer[AO_USB_OUT_SIZE]; static uint8_t ao_usb_rx_count, ao_usb_rx_pos; +#endif +#if AO_USB_HAS_IN2 +static uint16_t ao_usb_in2_tx_offset; +static uint16_t *ao_usb_in2_tx_buffer; + +/* System ram shadow of USB buffer; writing individual bytes is + * too much of a pain (sigh) */ +static uint8_t ao_usb_tx2_buffer[AO_USB_IN_SIZE]; +static uint8_t ao_usb_tx2_count; +#endif + /* * End point register indices */ @@ -114,6 +133,7 @@ static uint8_t ao_usb_rx_count, ao_usb_rx_pos; #define AO_USB_INT_EPR 1 #define AO_USB_OUT_EPR 2 #define AO_USB_IN_EPR 3 +#define AO_USB_IN2_EPR 4 /* Marks when we don't need to send an IN packet. * This happens only when the last IN packet is not full, @@ -128,6 +148,16 @@ static uint8_t ao_usb_in_flushed; */ static uint8_t ao_usb_in_pending; +#if AO_USB_HAS_IN2 +/* Marks when we have delivered an IN packet to the hardware + * and it has not been received yet. ao_sleep on this address + * to wait for it to be delivered. + */ +static uint8_t ao_usb_in2_pending; +static uint16_t in2_count; +static uint8_t ao_usb_in2_flushed; +#endif + /* Marks when an OUT packet has been received by the hardware * but not pulled to the shadow buffer. */ @@ -343,16 +373,29 @@ ao_usb_alloc_buffers(void) ao_usb_ep0_rx_buffer = ao_usb_packet_buffer_addr(ao_usb_sram_addr); ao_usb_sram_addr += AO_USB_CONTROL_SIZE; + +#if AO_USB_HAS_INT ao_usb_int_tx_offset = ao_usb_sram_addr; ao_usb_sram_addr += AO_USB_INT_SIZE; +#endif +#if AO_USB_HAS_OUT ao_usb_out_rx_buffer = ao_usb_packet_buffer_addr(ao_usb_sram_addr); ao_usb_out_rx_offset = ao_usb_sram_addr; ao_usb_sram_addr += AO_USB_OUT_SIZE; +#endif +#if AO_USB_HAS_IN ao_usb_in_tx_buffer = ao_usb_packet_buffer_addr(ao_usb_sram_addr); ao_usb_in_tx_offset = ao_usb_sram_addr; ao_usb_sram_addr += AO_USB_IN_SIZE; +#endif + +#if AO_USB_HAS_IN2 + ao_usb_in2_tx_buffer = ao_usb_packet_buffer_addr(ao_usb_sram_addr); + ao_usb_in2_tx_offset = ao_usb_sram_addr; + ao_usb_sram_addr += AO_USB_IN_SIZE; +#endif } static void @@ -438,6 +481,18 @@ ao_usb_set_configuration(void) STM_USB_EPR_STAT_TX_NAK); #endif +#if AO_USB_HAS_IN2 + /* Set up the IN2 end point */ + ao_usb_bdt[AO_USB_IN2_EPR].single.addr_tx = ao_usb_in2_tx_offset; + ao_usb_bdt[AO_USB_IN2_EPR].single.count_tx = 0; + + ao_usb_init_ep(AO_USB_IN2_EPR, + AO_USB_IN2_EP, + STM_USB_EPR_EP_TYPE_BULK, + STM_USB_EPR_STAT_RX_DISABLED, + STM_USB_EPR_STAT_TX_NAK); +#endif + ao_usb_running = 1; #if AO_USB_DIRECTIO ao_wakeup(&ao_usb_running); @@ -581,7 +636,7 @@ hex_to_ucs2(uint32_t in, uint8_t *out) for (i = 28; i >= 0; i -= 4) { uint8_t bits = (in >> i) & 0xf; - *out++ = (bits < 10) ? ('0' + bits) : ('a' + bits); + *out++ = ((bits < 10) ? '0' : ('a' - 10)) + bits; *out++ = 0; } } @@ -835,6 +890,16 @@ stm_usb_isr(void) ao_wakeup(&ao_usb_in_pending); } break; +#if AO_USB_HAS_IN2 + case AO_USB_IN2_EPR: + ++in2_count; + _tx_dbg1("TX2 ISR", epr); + if (ao_usb_epr_ctr_tx(epr)) { + ao_usb_in2_pending = 0; + ao_wakeup(&ao_usb_in2_pending); + } + break; +#endif case AO_USB_INT_EPR: ++int_count; if (ao_usb_epr_ctr_tx(epr)) @@ -861,6 +926,7 @@ stm_usb_isr(void) #endif } +#if AO_USB_HAS_IN /* Queue the current IN buffer for transmission */ static void _ao_usb_in_send(void) @@ -939,7 +1005,90 @@ ao_usb_putchar(char c) } ao_arch_release_interrupts(); } +#endif + +#if AO_USB_HAS_IN +/* Queue the current IN buffer for transmission */ +static void +_ao_usb_in2_send(void) +{ + _tx_dbg0("in2_send start"); + debug ("send2 %d\n", ao_usb_tx_count); + while (ao_usb_in2_pending) + ao_sleep(&ao_usb_in2_pending); + ao_usb_in2_pending = 1; + if (ao_usb_tx2_count != AO_USB_IN_SIZE) + ao_usb_in2_flushed = 1; + ao_usb_copy_tx(ao_usb_tx2_buffer, ao_usb_in2_tx_buffer, ao_usb_tx2_count); + ao_usb_bdt[AO_USB_IN2_EPR].single.addr_tx = ao_usb_in_tx_offset; + ao_usb_bdt[AO_USB_IN2_EPR].single.count_tx = ao_usb_tx_count; + ao_usb_tx2_count = 0; + _ao_usb_set_stat_tx(AO_USB_IN2_EPR, STM_USB_EPR_STAT_TX_VALID); + _tx_dbg0("in2_send end"); +} + +/* Wait for a free IN buffer. Interrupts are blocked */ +static void +_ao_usb_in2_wait(void) +{ + for (;;) { + /* Check if the current buffer is writable */ + if (ao_usb_tx2_count < AO_USB_IN_SIZE) + break; + + _tx_dbg0("in2_wait top"); + /* Wait for an IN buffer to be ready */ + while (ao_usb_in2_pending) + ao_sleep(&ao_usb_in2_pending); + _tx_dbg0("in_wait bottom"); + } +} + +void +ao_usb_flush2(void) +{ + if (!ao_usb_running) + return; + + /* Anytime we've sent a character since + * the last time we flushed, we'll need + * to send a packet -- the only other time + * we would send a packet is when that + * packet was full, in which case we now + * want to send an empty packet + */ + ao_arch_block_interrupts(); + while (!ao_usb_in2_flushed) { + _tx_dbg0("flush2 top"); + _ao_usb_in2_send(); + _tx_dbg0("flush2 end"); + } + ao_arch_release_interrupts(); +} + +void +ao_usb_putchar2(char c) +{ + if (!ao_usb_running) + return; + + ao_arch_block_interrupts(); + _ao_usb_in2_wait(); + + ao_usb_in2_flushed = 0; + ao_usb_tx2_buffer[ao_usb_tx2_count++] = (uint8_t) c; + + /* Send the packet when full */ + if (ao_usb_tx2_count == AO_USB_IN_SIZE) { + _tx_dbg0("putchar2 full"); + _ao_usb_in2_send(); + _tx_dbg0("putchar2 flushed"); + } + ao_arch_release_interrupts(); +} +#endif +#if AO_USB_HAS_OUT static void _ao_usb_out_recv(void) { @@ -996,6 +1145,7 @@ ao_usb_getchar(void) ao_arch_release_interrupts(); return c; } +#endif #if AO_USB_DIRECTIO uint16_t * @@ -1050,6 +1200,43 @@ ao_usb_write(uint16_t *buffer, uint16_t len) _ao_usb_set_stat_tx(AO_USB_IN_EPR, STM_USB_EPR_STAT_TX_VALID); ao_arch_release_interrupts(); } + +#if AO_USB_HAS_IN2 +void +ao_usb_write2(uint16_t *buffer, uint16_t len) +{ + ao_arch_block_interrupts(); + + /* Wait for everything to be ready at the same time */ + for (;;) { + /* Make sure USB is connected */ + if (!ao_usb_running) { + ao_sleep(&ao_usb_running); + continue; + } + + /* Flush any pending regular I/O */ + if (ao_usb_tx2_count) { + _ao_usb_in2_send(); + continue; + } + + /* Wait for an idle IN buffer */ + if (ao_usb_in2_pending) { + ao_sleep(&ao_usb_in2_pending); + continue; + } + break; + } + + ao_usb_in2_pending = 1; + ao_usb_in2_flushed = (len != AO_USB_IN_SIZE); + ao_usb_bdt[AO_USB_IN2_EPR].single.addr_tx = ao_usb_packet_buffer_offset(buffer); + ao_usb_bdt[AO_USB_IN2_EPR].single.count_tx = len; + _ao_usb_set_stat_tx(AO_USB_IN2_EPR, STM_USB_EPR_STAT_TX_VALID); + ao_arch_release_interrupts(); +} +#endif #endif void @@ -1180,7 +1367,9 @@ ao_usb_init(void) /* Set PA11/PA12 remapping bit */ stm_syscfg.cfgr1 |= (AO_PA11_PA12_RMP << STM_SYSCFG_CFGR1_PA11_PA12_RMP); +#ifndef AO_USB_START_DISABLED ao_usb_enable(); +#endif #if AO_USB_DEVICE_ID_SERIAL ao_usb_serial_init(); -- cgit v1.2.3 From 3a355d5c84e9d975897fa69a103952a1f1558947 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 2 Mar 2016 14:00:06 -0800 Subject: altos: Add ChaosKey v1.0 product Much like ChaosKey v0.1, just different SoC package and a few wiring changes. Signed-off-by: Keith Packard --- src/Makefile | 3 +- src/chaoskey-v1.0/.gitignore | 2 + src/chaoskey-v1.0/Makefile | 73 +++++++++++++++++++++++++++ src/chaoskey-v1.0/ao_chaoskey.c | 38 ++++++++++++++ src/chaoskey-v1.0/ao_pins.h | 83 +++++++++++++++++++++++++++++++ src/chaoskey-v1.0/flash-loader/.gitignore | 2 + src/chaoskey-v1.0/flash-loader/Makefile | 8 +++ src/chaoskey-v1.0/flash-loader/ao_pins.h | 36 ++++++++++++++ 8 files changed, 244 insertions(+), 1 deletion(-) create mode 100644 src/chaoskey-v1.0/.gitignore create mode 100644 src/chaoskey-v1.0/Makefile create mode 100644 src/chaoskey-v1.0/ao_chaoskey.c create mode 100644 src/chaoskey-v1.0/ao_pins.h create mode 100644 src/chaoskey-v1.0/flash-loader/.gitignore create mode 100644 src/chaoskey-v1.0/flash-loader/Makefile create mode 100644 src/chaoskey-v1.0/flash-loader/ao_pins.h (limited to 'src') diff --git a/src/Makefile b/src/Makefile index ebe1df9c..98607031 100644 --- a/src/Makefile +++ b/src/Makefile @@ -43,7 +43,8 @@ ARMM3DIRS=\ ARMM0DIRS=\ easymini-v1.0 easymini-v1.0/flash-loader \ - chaoskey-v0.1 chaoskey-v0.1/flash-loader + chaoskey-v0.1 chaoskey-v0.1/flash-loader \ + chaoskey-v1.0 chaoskey-v1.0/flash-loader AVRDIRS=\ telescience-v0.1 telescience-pwm micropeak nanopeak-v0.1 microkite diff --git a/src/chaoskey-v1.0/.gitignore b/src/chaoskey-v1.0/.gitignore new file mode 100644 index 00000000..b0adba26 --- /dev/null +++ b/src/chaoskey-v1.0/.gitignore @@ -0,0 +1,2 @@ +ao_product.h +chaoskey-* diff --git a/src/chaoskey-v1.0/Makefile b/src/chaoskey-v1.0/Makefile new file mode 100644 index 00000000..d9944a12 --- /dev/null +++ b/src/chaoskey-v1.0/Makefile @@ -0,0 +1,73 @@ +# +# AltOS build +# +# + +include ../stmf0/Makefile.defs + +INC = \ + ao.h \ + ao_arch.h \ + ao_arch_funcs.h \ + ao_pins.h \ + ao_product.h \ + ao_task.h \ + ao_adc_fast.h \ + ao_power.h \ + stm32f0.h + +# +# Common AltOS sources +# +ALTOS_SRC = \ + ao_interrupt.c \ + ao_timer.c \ + ao_panic.c \ + ao_mutex.c \ + ao_dma_stm.c \ + ao_adc_fast.c \ + ao_crc_stm.c \ + ao_stdio.c \ + ao_led.c \ + ao_romconfig.c \ + ao_boot_chain.c \ + ao_usb_stm.c \ + ao_trng_send.c \ + ao_task.c \ + ao_power.c \ + ao_gpio.c \ + ao_product.c + +PRODUCT=ChaosKey-hw-1.0-sw-$(VERSION) +PRODUCT_DEF=-DCHAOSKEY_V_1_0 +IDVENDOR=0x1d50 +IDPRODUCT=0x60c6 + +CFLAGS = $(PRODUCT_DEF) $(STMF0_CFLAGS) -g -Os + +PROGNAME=chaoskey-v1.0 +PROG=$(PROGNAME)-$(VERSION).elf +HEX=$(PROGNAME)-$(VERSION).ihx + +SRC=$(ALTOS_SRC) ao_chaoskey.c +OBJ=$(SRC:.c=.o) + +all: $(PROG) $(HEX) + +$(PROG): Makefile $(OBJ) altos.ld + $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(OBJ) $(LIBS) + +ao_product.h: ao-make-product.5c ../Version + $(call quiet,NICKLE,$<) $< -m altusmetrum.org -V $(IDVENDOR) -i $(IDPRODUCT) -p $(PRODUCT) -v $(VERSION) -o $@ + +$(OBJ): $(INC) + +distclean: clean + +clean: + rm -f *.o $(PROGNAME)-*.elf $(PROGNAME)-*.ihx + rm -f ao_product.h + +install: + +uninstall: diff --git a/src/chaoskey-v1.0/ao_chaoskey.c b/src/chaoskey-v1.0/ao_chaoskey.c new file mode 100644 index 00000000..f887e601 --- /dev/null +++ b/src/chaoskey-v1.0/ao_chaoskey.c @@ -0,0 +1,38 @@ +/* + * Copyright © 2014 Keith Packard + * + * 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 + +void main(void) +{ + ao_led_init(LEDS_AVAILABLE); + ao_clock_init(); + ao_task_init(); + ao_timer_init(); + ao_dma_init(); + ao_adc_init(); + ao_crc_init(); + + ao_usb_init(); + + ao_trng_send_init(); + + ao_start_scheduler(); +} diff --git a/src/chaoskey-v1.0/ao_pins.h b/src/chaoskey-v1.0/ao_pins.h new file mode 100644 index 00000000..89a2cb08 --- /dev/null +++ b/src/chaoskey-v1.0/ao_pins.h @@ -0,0 +1,83 @@ +/* + * Copyright © 2015 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#ifndef _AO_PINS_H_ +#define _AO_PINS_H_ + +#define LED_PORT_ENABLE STM_RCC_AHBENR_IOPBEN +#define LED_PORT (&stm_gpiob) +#define LED_PIN_RED 4 +#define AO_LED_RED (1 << LED_PIN_RED) + +#define LEDS_AVAILABLE (AO_LED_RED) + +#define AO_POWER_MANAGEMENT 1 +#define AO_LED_POWER AO_LED_RED + +#define HAS_BEEP 0 + +/* 48MHz clock based on USB */ +#define AO_HSI48 1 + +/* HCLK = 48MHz */ +#define AO_AHB_PRESCALER 1 +#define AO_RCC_CFGR_HPRE_DIV STM_RCC_CFGR_HPRE_DIV_1 + +/* APB = 48MHz */ +#define AO_APB_PRESCALER 1 +#define AO_RCC_CFGR_PPRE_DIV STM_RCC_CFGR_PPRE_DIV_1 + +#define HAS_USB 1 +#define AO_USB_DIRECTIO 1 +#define AO_PA11_PA12_RMP 1 +#define AO_USB_DEVICE_CLASS 0xff +#define AO_USB_INTERFACE_CLASS_DATA 0xff +#define AO_USB_HAS_OUT 0 +#define AO_USB_HAS_IN 1 +#define AO_USB_HAS_IN2 1 +#define AO_USB_HAS_INT 0 +#define AO_USB_SELF_POWER 0 +#define AO_USB_DEVICE_ID_SERIAL 1 +#define AO_USB_START_DISABLED 1 +#define USE_USB_STDIO 0 + +#define IS_FLASH_LOADER 0 + +/* ADC */ + +#define AO_ADC_PIN0_PORT (&stm_gpioa) +#define AO_ADC_PIN0_PIN 0 +#define AO_ADC_PIN0_CH 0 + +#define AO_ADC_RCC_AHBENR ((1 << STM_RCC_AHBENR_IOPAEN)) + +#define AO_NUM_ADC 1 + +/* TRNG enable */ + +#define AO_TRNG_ENABLE_PORT (&stm_gpioa) +#define AO_TRNG_ENABLE_BIT 1 + +/* CRC */ +#define AO_CRC_WIDTH 32 +#define AO_CRC_INIT 0xffffffff + +/* Mode pin */ +#define AO_RAW_PORT (&stm_gpioa) +#define AO_RAW_BIT 15 + +#endif /* _AO_PINS_H_ */ diff --git a/src/chaoskey-v1.0/flash-loader/.gitignore b/src/chaoskey-v1.0/flash-loader/.gitignore new file mode 100644 index 00000000..a60a4945 --- /dev/null +++ b/src/chaoskey-v1.0/flash-loader/.gitignore @@ -0,0 +1,2 @@ +ao_product.h +chaoskey* diff --git a/src/chaoskey-v1.0/flash-loader/Makefile b/src/chaoskey-v1.0/flash-loader/Makefile new file mode 100644 index 00000000..4f84014a --- /dev/null +++ b/src/chaoskey-v1.0/flash-loader/Makefile @@ -0,0 +1,8 @@ +# +# AltOS flash loader build +# +# + +TOPDIR=../.. +HARDWARE=chaoskey-v1.0 +include $(TOPDIR)/stmf0/Makefile-flash.defs diff --git a/src/chaoskey-v1.0/flash-loader/ao_pins.h b/src/chaoskey-v1.0/flash-loader/ao_pins.h new file mode 100644 index 00000000..570800ca --- /dev/null +++ b/src/chaoskey-v1.0/flash-loader/ao_pins.h @@ -0,0 +1,36 @@ +/* + * Copyright © 2013 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#ifndef _AO_PINS_H_ +#define _AO_PINS_H_ + +#include + +/* Pin 5 on debug connector */ + +#define AO_BOOT_PIN 1 +#define AO_BOOT_APPLICATION_GPIO stm_gpioa +#define AO_BOOT_APPLICATION_PIN 15 +#define AO_BOOT_APPLICATION_VALUE 1 +#define AO_BOOT_APPLICATION_MODE AO_EXTI_MODE_PULL_UP + +/* USB */ +#define HAS_USB 1 +#define AO_USB_DIRECTIO 0 +#define AO_PA11_PA12_RMP 1 + +#endif /* _AO_PINS_H_ */ -- cgit v1.2.3 From 7cb388a33104fd78c8cb1fa08a6f114e3e1e372d Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 5 Mar 2016 14:37:40 -0800 Subject: altos/stmf0: Fix build without second USB IN endpoint The code for the second IN endpoint was using the wrong ifdef. Signed-off-by: Keith Packard --- src/stmf0/ao_usb_stm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/stmf0/ao_usb_stm.c b/src/stmf0/ao_usb_stm.c index e68da8eb..253506d5 100644 --- a/src/stmf0/ao_usb_stm.c +++ b/src/stmf0/ao_usb_stm.c @@ -1007,7 +1007,7 @@ ao_usb_putchar(char c) } #endif -#if AO_USB_HAS_IN +#if AO_USB_HAS_IN2 /* Queue the current IN buffer for transmission */ static void _ao_usb_in2_send(void) -- cgit v1.2.3 From d1af180c2d2a2caf1e13f00d83f2b86ba26de27f Mon Sep 17 00:00:00 2001 From: Bart Massey Date: Sat, 5 Mar 2016 17:38:19 -0800 Subject: altos: Fixed timing of panic display LED to be readable When we don't have a beeper, there's no way to signal a 'warble' for panic. So, elide that bit. Second, panic can't use the scheduler and timer because those may not be running (or may have failed), and so it uses a delay loop. Add a configurable scale value to the panic loop so that the LED blinks can be read. For stm32f0 devices, scale that by the sysclk value to automatically make them of reasonable length. --- src/kernel/ao_panic.c | 11 ++++++++--- src/stmf0/ao_arch.h | 1 + 2 files changed, 9 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/kernel/ao_panic.c b/src/kernel/ao_panic.c index c29cd8fe..e280f98c 100644 --- a/src/kernel/ao_panic.c +++ b/src/kernel/ao_panic.c @@ -38,10 +38,15 @@ ao_panic_delay(uint8_t n) { uint8_t i = 0, j = 0; - while (n--) + while (n--) { +#ifdef AO_PANIC_DELAY_SCALE + uint8_t s = AO_PANIC_DELAY_SCALE; + while (s--) +#endif while (--j) while (--i) ao_arch_nop(); + } } void @@ -56,16 +61,16 @@ ao_panic(uint8_t reason) ao_arch_block_interrupts(); for (;;) { ao_panic_delay(20); +#if HAS_BEEP for (n = 0; n < 5; n++) { - ao_led_on(AO_LED_PANIC); ao_beep(AO_BEEP_HIGH); ao_panic_delay(1); - ao_led_off(AO_LED_PANIC); ao_beep(AO_BEEP_LOW); ao_panic_delay(1); } ao_beep(AO_BEEP_OFF); ao_panic_delay(2); +#endif #ifdef SDCC #pragma disable_warning 126 diff --git a/src/stmf0/ao_arch.h b/src/stmf0/ao_arch.h index 45df0982..26a34c85 100644 --- a/src/stmf0/ao_arch.h +++ b/src/stmf0/ao_arch.h @@ -117,6 +117,7 @@ extern const uint32_t ao_radio_cal; #define AO_PCLK1 (AO_HCLK / AO_APB1_PRESCALER) #define AO_PCLK2 (AO_HCLK / AO_APB2_PRESCALER) #define AO_SYSTICK (AO_HCLK) +#define AO_PANIC_DELAY_SCALE (AO_SYSCLK / 12000000) #if AO_APB1_PRESCALER == 1 #define AO_TIM23467_CLK AO_PCLK1 -- cgit v1.2.3 From a7c7e10b3bbfbdf9667d071634cdd6fdf12a1f85 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 18 Mar 2016 10:17:24 -0700 Subject: altos: Expose fast timer API from kernel/ This allows multiple SoCs to provide the same driver interface Signed-off-by: Keith Packard --- src/kernel/ao_fast_timer.h | 34 ++++++++++++++++++++++++++++++++++ src/stm/ao_fast_timer.h | 34 ---------------------------------- 2 files changed, 34 insertions(+), 34 deletions(-) create mode 100644 src/kernel/ao_fast_timer.h delete mode 100644 src/stm/ao_fast_timer.h (limited to 'src') diff --git a/src/kernel/ao_fast_timer.h b/src/kernel/ao_fast_timer.h new file mode 100644 index 00000000..90fb3930 --- /dev/null +++ b/src/kernel/ao_fast_timer.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_FAST_TIMER_H_ +#define _AO_FAST_TIMER_H_ + +void +ao_fast_timer_init(void); + +#ifndef AO_FAST_TIMER_MAX +#define AO_FAST_TIMER_MAX 2 +#endif + +void +ao_fast_timer_on(void (*callback)(void)); + +void +ao_fast_timer_off(void (*callback)(void)); + +#endif /* _AO_FAST_TIMER_H_ */ diff --git a/src/stm/ao_fast_timer.h b/src/stm/ao_fast_timer.h deleted file mode 100644 index 90fb3930..00000000 --- a/src/stm/ao_fast_timer.h +++ /dev/null @@ -1,34 +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_FAST_TIMER_H_ -#define _AO_FAST_TIMER_H_ - -void -ao_fast_timer_init(void); - -#ifndef AO_FAST_TIMER_MAX -#define AO_FAST_TIMER_MAX 2 -#endif - -void -ao_fast_timer_on(void (*callback)(void)); - -void -ao_fast_timer_off(void (*callback)(void)); - -#endif /* _AO_FAST_TIMER_H_ */ -- cgit v1.2.3 From 4635203e9be530f53b697ac0349838916e146983 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 18 Mar 2016 11:16:59 -0700 Subject: altos/stmf0: Construct .bin files for flash loaders This builds a .bin file which can be used with dfu-util instead of using openocd to load the initial flash loader. Signed-off-by: Keith Packard --- src/stmf0/Makefile-flash.defs | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/stmf0/Makefile-flash.defs b/src/stmf0/Makefile-flash.defs index 706b93ee..29d6ae45 100644 --- a/src/stmf0/Makefile-flash.defs +++ b/src/stmf0/Makefile-flash.defs @@ -39,17 +39,24 @@ LDFLAGS=$(CFLAGS) -L$(TOPDIR)/stmf0 -Wl,-Taltos-loader.ld PROGNAME=altos-flash PROG=$(HARDWARE)-$(PROGNAME)-$(VERSION).elf +BIN=$(HARDWARE)-$(PROGNAME)-$(VERSION).bin + +MAKEBIN=$(TOPDIR)/../ao-tools/ao-makebin/ao-makebin +FLASH_ADDR=0x08000000 + +all: $(PROG) $(BIN) $(PROG): Makefile $(OBJ) altos-loader.ld $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(OBJ) $(LIBS) +$(BIN): $(PROG) + $(MAKEBIN) --output=$@ --base=$(FLASH_ADDR) $(PROG) + ao_product.h: ao-make-product.5c $(TOPDIR)/Version $(call quiet,NICKLE,$<) $< -m altusmetrum.org -i $(IDPRODUCT) -p $(PRODUCT) -v $(VERSION) > $@ $(OBJ): $(INC) -all: $(PROG) - distclean: clean clean: -- cgit v1.2.3 From 6a9546413d6a236c010e806b50506d870961d074 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 26 Mar 2016 15:49:59 -0700 Subject: altos/stm: Run scheduler code on interrupt stack This provides a bit more room for tasks on their stack Signed-off-by: Keith Packard --- src/stm/ao_arch_funcs.h | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/stm/ao_arch_funcs.h b/src/stm/ao_arch_funcs.h index 42f1a2e5..02b344b1 100644 --- a/src/stm/ao_arch_funcs.h +++ b/src/stm/ao_arch_funcs.h @@ -335,6 +335,13 @@ static inline void ao_arch_save_stack(void) { static inline void ao_arch_restore_stack(void) { uint32_t sp; + uint32_t control; + + asm("mrs %0,control" : "=&r" (control)); + control |= (1 << 1); + asm("msr control,%0" : : "r" (control)); + asm("isb"); + sp = (uint32_t) ao_cur_task->sp; /* Switch stacks */ @@ -375,7 +382,14 @@ static inline void ao_arch_start_scheduler(void) { } #endif -#define ao_arch_isr_stack() +static inline void ao_arch_isr_stack(void) { + uint32_t control; + + asm("mrs %0,control" : "=&r" (control)); + control &= ~(1 << 1); + asm("msr control,%0" : : "r" (control)); + asm("isb"); +} #endif -- cgit v1.2.3 From 4fa71ecf168e275b24534a5a20e3dd4e178c7bbd Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 26 Mar 2016 15:54:24 -0700 Subject: altos/stm: Validate current task SP in interrupt by looking at PSP We use a separate stack pointer for task code, which means we can verify that it is in range in any interrupt handler. This adds checks for the task stack (under #ifdef DEBUG) that run in ao_wakeup as well as at every timer interrupt. Signed-off-by: Keith Packard --- src/kernel/ao_task.c | 2 +- src/kernel/ao_task.h | 4 ++++ src/stm/ao_arch_funcs.h | 16 ++++++++++++++++ src/stm/ao_timer.c | 1 + 4 files changed, 22 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/kernel/ao_task.c b/src/kernel/ao_task.c index 55e423bb..104d1074 100644 --- a/src/kernel/ao_task.c +++ b/src/kernel/ao_task.c @@ -355,7 +355,6 @@ ao_yield(void) ao_arch_naked_define */ if (ao_cur_task->wchan == NULL) ao_task_to_run_queue(ao_cur_task); - ao_cur_task = NULL; for (;;) { ao_arch_memory_barrier(); if (!ao_list_is_empty(&run_queue)) @@ -425,6 +424,7 @@ ao_sleep(__xdata void *wchan) void ao_wakeup(__xdata void *wchan) __reentrant { + ao_validate_cur_stack(); #if HAS_TASK_QUEUE struct ao_task *sleep, *next; struct ao_list *sleep_queue; diff --git a/src/kernel/ao_task.h b/src/kernel/ao_task.h index c6bec0e3..0e353fe8 100644 --- a/src/kernel/ao_task.h +++ b/src/kernel/ao_task.h @@ -56,6 +56,10 @@ extern __data uint8_t ao_num_tasks; extern __xdata struct ao_task *__data ao_cur_task; extern __data uint8_t ao_task_minimize_latency; /* Reduce IRQ latency */ +#ifndef HAS_ARCH_VALIDATE_CUR_STACK +#define ao_validate_cur_stack() +#endif + /* ao_task.c */ diff --git a/src/stm/ao_arch_funcs.h b/src/stm/ao_arch_funcs.h index 02b344b1..6b38032c 100644 --- a/src/stm/ao_arch_funcs.h +++ b/src/stm/ao_arch_funcs.h @@ -366,6 +366,22 @@ static inline void ao_arch_restore_stack(void) { #define HAS_SAMPLE_PROFILE 0 #endif +#if DEBUG +#define HAS_ARCH_VALIDATE_CUR_STACK 1 + +static inline void +ao_validate_cur_stack(void) +{ + uint8_t *psp; + + asm("mrs %0,psp" : "=&r" (psp)); + if (ao_cur_task && + psp <= ao_cur_task->stack && + psp >= ao_cur_task->stack - 256) + ao_panic(AO_PANIC_STACK); +} +#endif + #if !HAS_SAMPLE_PROFILE #define HAS_ARCH_START_SCHEDULER 1 diff --git a/src/stm/ao_timer.c b/src/stm/ao_timer.c index 8db62e76..91ede84b 100644 --- a/src/stm/ao_timer.c +++ b/src/stm/ao_timer.c @@ -41,6 +41,7 @@ volatile __data uint8_t ao_data_count; void stm_systick_isr(void) { + ao_validate_cur_stack(); if (stm_systick.csr & (1 << STM_SYSTICK_CSR_COUNTFLAG)) { ++ao_tick_count; #if HAS_TASK_QUEUE -- cgit v1.2.3 From a86d98b708d84c6e0b85cb950e3f1ee16cfc56f5 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 26 Mar 2016 15:59:26 -0700 Subject: altos/stm: Allow apps to define different stack size While 512 bytes is a reasonable size, sometimes apps don't have that much stack space. Signed-off-by: Keith Packard --- src/stm/ao_arch.h | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src') diff --git a/src/stm/ao_arch.h b/src/stm/ao_arch.h index a6276c5a..f9508b8f 100644 --- a/src/stm/ao_arch.h +++ b/src/stm/ao_arch.h @@ -25,7 +25,9 @@ * STM32L definitions and code fragments for AltOS */ +#ifndef AO_STACK_SIZE #define AO_STACK_SIZE 512 +#endif #define AO_LED_TYPE uint16_t -- cgit v1.2.3 From b31c6fd153825ae5ad0fcea7189472af1a9cffff Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 24 Mar 2016 19:28:16 -0600 Subject: altos/lpc: Add fast timer This offers a faster timer callback for higher-precision operation Signed-off-by: Keith Packard --- src/lpc/ao_fast_timer_lpc.c | 110 ++++++++++++++++++++++++++++++++++++++++ src/lpc/ao_timer_lpc.c | 14 +++--- src/lpc/lpc.h | 120 ++++++++++++++++++++++++++++++++++++++++---- src/lpc/registers.ld | 2 + 4 files changed, 229 insertions(+), 17 deletions(-) create mode 100644 src/lpc/ao_fast_timer_lpc.c (limited to 'src') diff --git a/src/lpc/ao_fast_timer_lpc.c b/src/lpc/ao_fast_timer_lpc.c new file mode 100644 index 00000000..c4f26fc4 --- /dev/null +++ b/src/lpc/ao_fast_timer_lpc.c @@ -0,0 +1,110 @@ +/* + * Copyright © 2016 Keith Packard + * + * 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 void (*ao_fast_timer_callback[AO_FAST_TIMER_MAX])(void); +static uint8_t ao_fast_timer_count; +static uint8_t ao_fast_timer_users; + +static void +ao_fast_timer_enable(void) +{ + lpc_ct16b0.tcr = ((1 << LPC_CT16B_TCR_CEN) | + (1 << LPC_CT16B_TCR_CRST)); +} + +static void +ao_fast_timer_disable(void) +{ + lpc_ct16b0.tcr = ((0 << LPC_CT16B_TCR_CEN) | + (0 << LPC_CT16B_TCR_CRST)); +} + +void +ao_fast_timer_on(void (*callback)(void)) +{ + ao_fast_timer_callback[ao_fast_timer_count] = callback; + if (!ao_fast_timer_count++) + ao_fast_timer_enable(); +} + +void +ao_fast_timer_off(void (*callback)(void)) +{ + uint8_t n; + + for (n = 0; n < ao_fast_timer_count; n++) + if (ao_fast_timer_callback[n] == callback) { + for (; n < ao_fast_timer_count-1; n++) { + ao_fast_timer_callback[n] = ao_fast_timer_callback[n+1]; + } + if (!--ao_fast_timer_count) + ao_fast_timer_disable(); + break; + } +} + +void lpc_ct16b0_isr(void) +{ + uint32_t v = lpc_ct16b0.ir; + int i; + + lpc_ct16b0.ir = v; + if (v & (1 << LPC_CT16B_IR_MR0INT)) { + for (i = 0; i < ao_fast_timer_count; i++) + (*ao_fast_timer_callback[i])(); + } +} + +#ifndef FAST_TIMER_FREQ +#define FAST_TIMER_FREQ 10000 +#endif + +#define TIMER_FAST (AO_LPC_SYSCLK / FAST_TIMER_FREQ) + +void +ao_fast_timer_init(void) +{ + if (!ao_fast_timer_users) { + + lpc_nvic_set_enable(LPC_ISR_CT16B0_POS); + lpc_nvic_set_priority(LPC_ISR_CT16B0_POS, AO_LPC_NVIC_CLOCK_PRIORITY); + /* Turn on 16-bit timer CT16B0 */ + + lpc_scb.sysahbclkctrl |= 1 << LPC_SCB_SYSAHBCLKCTRL_CT16B0; + + /* Disable timer */ + lpc_ct16b0.tcr = 0; + + /* scale factor 1 */ + lpc_ct16b0.pr = 0; + lpc_ct16b0.pc = 0; + + lpc_ct16b0.mcr = ((1 << LPC_CT16B_MCR_MR0I) | + (1 << LPC_CT16B_MCR_MR0R)); + + lpc_ct16b0.mr[0] = TIMER_FAST; + + ao_fast_timer_disable(); + } + if (ao_fast_timer_users == AO_FAST_TIMER_MAX) + ao_panic(AO_PANIC_FAST_TIMER); + ao_fast_timer_users++; +} + diff --git a/src/lpc/ao_timer_lpc.c b/src/lpc/ao_timer_lpc.c index 44fb410e..623559eb 100644 --- a/src/lpc/ao_timer_lpc.c +++ b/src/lpc/ao_timer_lpc.c @@ -99,7 +99,7 @@ ao_clock_init(void) (1 << LPC_SCB_SYSAHBCLKCTRL_FLASHARRAY) | (1 << LPC_SCB_SYSAHBCLKCTRL_GPIO) | (1 << LPC_SCB_SYSAHBCLKCTRL_IOCON)); - + /* Enable the brown-out detection at the highest voltage to * make sure the flash part remains happy */ @@ -112,21 +112,21 @@ ao_clock_init(void) /* Turn the IRC clock back on */ lpc_scb.pdruncfg &= ~(1 << LPC_SCB_PDRUNCFG_IRC_PD); ao_clock_delay(); - + /* Switch to the IRC clock */ lpc_scb.mainclksel = LPC_SCB_MAINCLKSEL_SEL_IRC << LPC_SCB_MAINCLKSEL_SEL; lpc_scb.mainclkuen = (0 << LPC_SCB_MAINCLKUEN_ENA); lpc_scb.mainclkuen = (1 << LPC_SCB_MAINCLKUEN_ENA); while (!(lpc_scb.mainclkuen & (1 << LPC_SCB_MAINCLKUEN_ENA))) ; - + /* Switch USB to the main clock */ lpc_scb.usbclksel = (LPC_SCB_USBCLKSEL_SEL_MAIN_CLOCK << LPC_SCB_USBCLKSEL_SEL); lpc_scb.usbclkuen = (0 << LPC_SCB_USBCLKUEN_ENA); lpc_scb.usbclkuen = (1 << LPC_SCB_USBCLKUEN_ENA); while (!(lpc_scb.usbclkuen & (1 << LPC_SCB_USBCLKUEN_ENA))) ; - + /* Find a PLL post divider ratio that gets the FCCO in range */ for (p = 0; p < 4; p++) if (AO_LPC_CLKOUT << (1 + p) >= AO_LPC_FCCO_MIN) @@ -163,12 +163,12 @@ ao_clock_init(void) lpc_scb.syspllclkuen = (1 << LPC_SCB_SYSPLLCLKUEN_ENA); while (!(lpc_scb.syspllclkuen & (1 << LPC_SCB_SYSPLLCLKUEN_ENA))) ; - + /* Turn on the PLL */ lpc_scb.pdruncfg &= ~(1 << LPC_SCB_PDRUNCFG_SYSPLL_PD); /* Wait for it to lock */ - + for (i = 0; i < 20000; i++) if (lpc_scb.syspllstat & (1 << LPC_SCB_SYSPLLSTAT_LOCK)) break; @@ -199,7 +199,7 @@ ao_clock_init(void) lpc_scb.usbpllclkuen = (1 << LPC_SCB_USBPLLCLKUEN_ENA); while (!(lpc_scb.usbpllclkuen & (1 << LPC_SCB_USBPLLCLKUEN_ENA))) ; - + /* Power down everything we don't need */ lpc_scb.pdruncfg = ((1 << LPC_SCB_PDRUNCFG_IRCOUT_PD) | (1 << LPC_SCB_PDRUNCFG_IRC_PD) | diff --git a/src/lpc/lpc.h b/src/lpc/lpc.h index 9408ceab..40d412d0 100644 --- a/src/lpc/lpc.h +++ b/src/lpc/lpc.h @@ -411,7 +411,7 @@ struct lpc_scb { vuint32_t mainclksel; /* 0x70 */ vuint32_t mainclkuen; vuint32_t sysahbclkdiv; - uint32_t r7c; + uint32_t r7c; vuint32_t sysahbclkctrl; /* 0x80 */ uint32_t r84[3]; @@ -429,14 +429,14 @@ struct lpc_scb { uint32_t rcc; uint32_t rd0[4]; - + vuint32_t clkoutsel; /* 0xe0 */ vuint32_t clkoutuen; vuint32_t clkoutdiv; uint32_t rec; - + uint32_t rf0[4]; /* 0xf0 */ - + vuint32_t pioporcap0; /* 0x100 */ vuint32_t pioporcap1; uint32_t r102[2]; @@ -445,7 +445,7 @@ struct lpc_scb { uint32_t r120[4]; /* 0x120 */ uint32_t r130[4]; /* 0x130 */ uint32_t r140[4]; /* 0x140 */ - + vuint32_t bodctrl; /* 0x150 */ vuint32_t systckcal; uint32_t r158[2]; @@ -479,7 +479,7 @@ struct lpc_scb { uint32_t r240[12 * 4]; /* 0x240 */ uint32_t r300[15 * 4]; /* 0x300 */ - + uint32_t r3f0; /* 0x3f0 */ vuint32_t device_id; }; @@ -680,7 +680,7 @@ struct lpc_gpio { vuint32_t word[0x40]; /* 0x1000 */ uint8_t r1100[0x2000 - 0x1100]; - + vuint32_t dir[2]; /* 0x2000 */ uint8_t r2008[0x2080 - 0x2008]; @@ -1032,7 +1032,7 @@ lpc_nvic_enabled(int irq) { return (lpc_nvic.iser >> irq) & 1; } - + static inline void lpc_nvic_set_pending(int irq) { lpc_nvic.ispr = (1 << irq); @@ -1201,18 +1201,118 @@ extern struct lpc_adc lpc_adc; #define LPC_ADC_STAT_OVERRUN 8 #define LPC_ADC_STAT_ADINT 16 +struct lpc_ct16b { + vuint32_t ir; /* 0x00 */ + vuint32_t tcr; + vuint32_t tc; + vuint32_t pr; + + vuint32_t pc; /* 0x10 */ + vuint32_t mcr; + vuint32_t mr[4]; /* 0x18 */ + vuint32_t ccr; /* 0x28 */ + vuint32_t cr0; + + vuint32_t cr1_0; /* 0x30 (only for ct16b0 */ + vuint32_t cr1_1; /* 0x34 (only for ct16b1 */ + uint32_t r38; + vuint32_t emr; + + uint8_t r40[0x70 - 0x40]; + + vuint32_t ctcr; /* 0x70 */ + vuint32_t pwmc; +}; + +extern struct lpc_ct16b lpc_ct16b0, lpc_ct16b1; + +#define lpc_ct16b0 (*(struct lpc_ct16b *) 0x4000c000) +#define lpc_ct16b1 (*(struct lpc_ct16b *) 0x40010000) + +#define LPC_CT16B_IR_MR0INT 0 +#define LPC_CT16B_IR_MR1INT 1 +#define LPC_CT16B_IR_MR2INT 2 +#define LPC_CT16B_IR_MR3INT 3 +#define LPC_CT16B_IR_CR0INT 4 +#define LPC_CT16B0_IR_CR1INT 6 +#define LPC_CT16B1_IR_CR1INT 5 + +#define LPC_CT16B_TCR_CEN 0 +#define LPC_CT16B_TCR_CRST 1 + +#define LPC_CT16B_MCR_MR0I 0 +#define LPC_CT16B_MCR_MR0R 1 +#define LPC_CT16B_MCR_MR0S 2 +#define LPC_CT16B_MCR_MR1I 3 +#define LPC_CT16B_MCR_MR1R 4 +#define LPC_CT16B_MCR_MR1S 5 +#define LPC_CT16B_MCR_MR2I 6 +#define LPC_CT16B_MCR_MR2R 7 +#define LPC_CT16B_MCR_MR2S 8 +#define LPC_CT16B_MCR_MR3I 9 +#define LPC_CT16B_MCR_MR3R 10 +#define LPC_CT16B_MCR_MR3S 11 + +#define LPC_CT16B_CCR_CAP0RE 0 +#define LPC_CT16B_CCR_CAP0FE 1 +#define LPC_CT16B_CCR_CAP0I 2 +#define LPC_CT16B0_CCR_CAP1RE 6 +#define LPC_CT16B0_CCR_CAP1FE 7 +#define LPC_CT16B0_CCR_CAP1I 8 +#define LPC_CT16B1_CCR_CAP1RE 3 +#define LPC_CT16B1_CCR_CAP1FE 4 +#define LPC_CT16B1_CCR_CAP1I 5 + +#define LPC_CT16B_EMR_EM0 0 +#define LPC_CT16B_EMR_EM1 1 +#define LPC_CT16B_EMR_EM2 2 +#define LPC_CT16B_EMR_EM3 3 +#define LPC_CT16B_EMR_EMC0 4 +#define LPC_CT16B_EMR_EMC1 6 +#define LPC_CT16B_EMR_EMC2 8 +#define LPC_CT16B_EMR_EMC3 10 + +#define LPC_CT16B_EMR_EMC_NOTHING 0 +#define LPC_CT16B_EMR_EMC_CLEAR 1 +#define LPC_CT16B_EMR_EMC_SET 2 +#define LPC_CT16B_EMR_EMC_TOGGLE 3 + +#define LPC_CT16B_CCR_CTM 0 +#define LPC_CT16B_CCR_CTM_TIMER 0 +#define LPC_CT16B_CCR_CTM_COUNTER_RISING 1 +#define LPC_CT16B_CCR_CTM_COUNTER_FALLING 2 +#define LPC_CT16B_CCR_CTM_COUNTER_BOTH 3 +#define LPC_CT16B_CCR_CIS 2 +#define LPC_CT16B_CCR_CIS_CAP0 0 +#define LPC_CT16B0_CCR_CIS_CAP1 2 +#define LPC_CT16B1_CCR_CIS_CAP1 1 +#define LPC_CT16B_CCR_ENCC 4 +#define LPC_CT16B_CCR_SELCC 5 +#define LPC_CT16B_CCR_SELCC_RISING_CAP0 0 +#define LPC_CT16B_CCR_SELCC_FALLING_CAP0 1 +#define LPC_CT16B0_CCR_SELCC_RISING_CAP1 4 +#define LPC_CT16B0_CCR_SELCC_FALLING_CAP1 5 +#define LPC_CT16B1_CCR_SELCC_RISING_CAP1 2 +#define LPC_CT16B1_CCR_SELCC_FALLING_CAP1 3 +#define LPC_CT16B_CCR_ + +#define LPC_CT16B_PWMC_PWMEN0 0 +#define LPC_CT16B_PWMC_PWMEN1 1 +#define LPC_CT16B_PWMC_PWMEN2 2 +#define LPC_CT16B_PWMC_PWMEN3 3 + struct lpc_ct32b { vuint32_t ir; /* 0x00 */ vuint32_t tcr; vuint32_t tc; vuint32_t pr; - + vuint32_t pc; /* 0x10 */ vuint32_t mcr; vuint32_t mr[4]; /* 0x18 */ vuint32_t ccr; /* 0x28 */ vuint32_t cr0; - + vuint32_t cr1_0; /* 0x30 (only for ct32b0 */ vuint32_t cr1_1; /* 0x34 (only for ct32b1 */ uint32_t r38; diff --git a/src/lpc/registers.ld b/src/lpc/registers.ld index a523c39c..61dd9e70 100644 --- a/src/lpc/registers.ld +++ b/src/lpc/registers.ld @@ -1,6 +1,8 @@ lpc_usb_sram = 0x20004000; lpc_usb_endpoint = 0x20004700; lpc_usart = 0x40008000; +lpc_ct16b0 = 0x4000c000; +lpc_ct16b1 = 0x40010000; lpc_ct32b0 = 0x40014000; lpc_ct32b1 = 0x40018000; lpc_adc = 0x4001c000; -- cgit v1.2.3 From 7348cc4736c9a94f9ad299edd78199b544d0e95a Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 24 Mar 2016 19:25:33 -0600 Subject: altos: Add one-byte SPI output routine for LPC and STM cores This allows for SPI output at interrupt time, one byte at a time. Signed-off-by: Keith Packard --- src/lpc/ao_arch_funcs.h | 22 ++++++++++++++++++++++ src/stm/ao_arch_funcs.h | 28 ++++++++++++++++++++++++++++ 2 files changed, 50 insertions(+) (limited to 'src') diff --git a/src/lpc/ao_arch_funcs.h b/src/lpc/ao_arch_funcs.h index fbe641d8..dbb41538 100644 --- a/src/lpc/ao_arch_funcs.h +++ b/src/lpc/ao_arch_funcs.h @@ -227,6 +227,28 @@ ao_spi_duplex(const void *out, void *in, uint16_t len, uint8_t spi_index); void ao_spi_init(void); +static inline void +ao_spi_send_sync(const void *block, uint16_t len, uint8_t spi_index) +{ + ao_spi_send(block, len, spi_index); +} + +static inline void ao_spi_send_byte(uint8_t byte, uint8_t spi_index) +{ + struct lpc_ssp *lpc_ssp; + switch (spi_index) { + case 0: + lpc_ssp = &lpc_ssp0; + break; + case 1: + lpc_ssp = &lpc_ssp1; + break; + } + lpc_ssp->dr = byte; + while ((lpc_ssp->sr & (1 << LPC_SSP_SR_RNE)) == 0); + (void) lpc_ssp->dr; +} + #define ao_spi_init_cs(port, mask) do { \ uint8_t __bit__; \ for (__bit__ = 0; __bit__ < 32; __bit__++) { \ diff --git a/src/stm/ao_arch_funcs.h b/src/stm/ao_arch_funcs.h index 6b38032c..087e00d9 100644 --- a/src/stm/ao_arch_funcs.h +++ b/src/stm/ao_arch_funcs.h @@ -82,6 +82,34 @@ ao_spi_send_fixed(uint8_t value, uint16_t len, uint8_t spi_index); void ao_spi_send_sync(void *block, uint16_t len, uint8_t spi_index); +static inline void +ao_spi_send_byte(uint8_t byte, uint8_t spi_index) +{ + struct stm_spi *stm_spi; + + switch (AO_SPI_INDEX(spi_index)) { + case 0: + stm_spi = &stm_spi1; + break; + case 1: + stm_spi = &stm_spi2; + break; + } + + stm_spi->cr2 = ((0 << STM_SPI_CR2_TXEIE) | + (0 << STM_SPI_CR2_RXNEIE) | + (0 << STM_SPI_CR2_ERRIE) | + (0 << STM_SPI_CR2_SSOE) | + (0 << STM_SPI_CR2_TXDMAEN) | + (0 << STM_SPI_CR2_RXDMAEN)); + + /* Clear RXNE */ + (void) stm_spi->dr; + + while (!(stm_spi->sr & (1 << STM_SPI_SR_TXE))); + stm_spi->dr = byte; +} + void ao_spi_recv(void *block, uint16_t len, uint8_t spi_index); -- cgit v1.2.3 From 0ee235e1126f34987522fe852ba6ab3ac92d6cfd Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 2 Apr 2016 19:39:07 -0700 Subject: altos: Allow for flight hardware without any ADC values Detherm has no ADC connections, so we don't need to disable the ADC when going to landed state. Signed-off-by: Keith Packard --- src/kernel/ao_flight.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src') diff --git a/src/kernel/ao_flight.c b/src/kernel/ao_flight.c index 251dbc02..9ba02bb8 100644 --- a/src/kernel/ao_flight.c +++ b/src/kernel/ao_flight.c @@ -370,8 +370,10 @@ ao_flight(void) { ao_flight_state = ao_flight_landed; +#if HAS_ADC /* turn off the ADC capture */ ao_timer_set_adc_interval(0); +#endif ao_wakeup(DATA_TO_XDATA(&ao_flight_state)); } -- cgit v1.2.3 From 6ead4c570a264afdc4e45eed6e87bf541668be6f Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 2 Apr 2016 19:40:19 -0700 Subject: altos: Add Detherm log format (easymini without ADC) Signed-off-by: Keith Packard --- src/kernel/ao_log.h | 1 + 1 file changed, 1 insertion(+) (limited to 'src') diff --git a/src/kernel/ao_log.h b/src/kernel/ao_log.h index f86fb359..fdd428c2 100644 --- a/src/kernel/ao_log.h +++ b/src/kernel/ao_log.h @@ -49,6 +49,7 @@ extern __pdata enum ao_flight_state ao_log_state; #define AO_LOG_FORMAT_TELEMINI 8 /* 16-byte MS5607 baro only, 3.3V supply */ #define AO_LOG_FORMAT_TELEGPS 9 /* 32 byte telegps records */ #define AO_LOG_FORMAT_TELEMEGA 10 /* 32 byte typed telemega records with 32 bit gyro cal */ +#define AO_LOG_FORMAT_DETHERM 11 /* 16-byte MS5607 baro only, no ADC */ #define AO_LOG_FORMAT_NONE 127 /* No log at all */ extern __code uint8_t ao_log_format; -- cgit v1.2.3 From f5e6caab78f4ca0e5c8a2d96ef53b8752d64f4b3 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 2 Apr 2016 19:41:21 -0700 Subject: altos: Use mini logging for detherm, just without ADC Signed-off-by: Keith Packard --- src/kernel/ao_log_mini.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src') diff --git a/src/kernel/ao_log_mini.c b/src/kernel/ao_log_mini.c index 0ca3ed06..844f38aa 100644 --- a/src/kernel/ao_log_mini.c +++ b/src/kernel/ao_log_mini.c @@ -110,9 +110,11 @@ ao_log(void) ao_data_ring[ao_log_data_pos].ms5607_raw.pres); ao_log_pack24(log.u.sensor.temp, ao_data_ring[ao_log_data_pos].ms5607_raw.temp); +#if AO_LOG_FORMAT != AO_LOG_FORMAT_DETHERM log.u.sensor.sense_a = ao_data_ring[ao_log_data_pos].adc.sense_a; log.u.sensor.sense_m = ao_data_ring[ao_log_data_pos].adc.sense_m; log.u.sensor.v_batt = ao_data_ring[ao_log_data_pos].adc.v_batt; +#endif ao_log_mini(&log); if (ao_log_state <= ao_flight_coast) next_sensor = log.tick + AO_SENSOR_INTERVAL_ASCENT; -- cgit v1.2.3 From 9f9d77b6d025d8285e362e53a8f728ec47adb234 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 2 Apr 2016 19:42:44 -0700 Subject: altos/stmf0: Add SPI driver. This also changes the DMA interface a bit so we can select for interrupts on only the interesting channels. Signed-off-by: Keith Packard --- src/stmf0/ao_adc_fast.c | 4 +- src/stmf0/ao_dma_stm.c | 34 +++- src/stmf0/ao_spi_stm.c | 478 ++++++++++++++++++++++++++++++++++++++++++++++++ src/stmf0/stm32f0.h | 34 +++- 4 files changed, 535 insertions(+), 15 deletions(-) create mode 100644 src/stmf0/ao_spi_stm.c (limited to 'src') diff --git a/src/stmf0/ao_adc_fast.c b/src/stmf0/ao_adc_fast.c index f6740b0e..0a2e2c5c 100644 --- a/src/stmf0/ao_adc_fast.c +++ b/src/stmf0/ao_adc_fast.c @@ -72,7 +72,9 @@ _ao_adc_start(void) (1 << STM_DMA_CCR_MINC) | (0 << STM_DMA_CCR_PINC) | (0 << STM_DMA_CCR_CIRC) | - (STM_DMA_CCR_DIR_PER_TO_MEM << STM_DMA_CCR_DIR)); + (STM_DMA_CCR_DIR_PER_TO_MEM << STM_DMA_CCR_DIR) | + (1 << STM_DMA_CCR_TCIE)); + ao_dma_set_isr(STM_DMA_INDEX(STM_DMA_CHANNEL_ADC_1), ao_adc_dma_done); ao_dma_start(STM_DMA_INDEX(STM_DMA_CHANNEL_ADC_1)); diff --git a/src/stmf0/ao_dma_stm.c b/src/stmf0/ao_dma_stm.c index 78fabe18..e90c6bf8 100644 --- a/src/stmf0/ao_dma_stm.c +++ b/src/stmf0/ao_dma_stm.c @@ -28,9 +28,7 @@ static uint8_t ao_dma_allocated[STM_NUM_DMA]; static uint8_t ao_dma_mutex[STM_NUM_DMA]; static uint8_t ao_dma_active; -#define id(ch) STM_DMA_INDEX(ch) -#define id_mask(id) (STM_DMA_ISR_MASK << (id)) -#define ch_mask(ch) id_mask(id(ch)) +#define ch_mask(id) (STM_DMA_ISR_MASK << STM_DMA_ISR(id)) static void ao_dma_isr(uint8_t low_index, uint8_t high_index, uint32_t mask) { @@ -41,7 +39,7 @@ ao_dma_isr(uint8_t low_index, uint8_t high_index, uint32_t mask) { /* Ack them */ stm_dma.ifcr = isr; for (index = low_index; index <= high_index; index++) { - if (isr & id_mask(index)) { + if (isr & ch_mask(index)) { if (ao_dma_config[index].isr) (*ao_dma_config[index].isr)(index); else { @@ -52,9 +50,25 @@ ao_dma_isr(uint8_t low_index, uint8_t high_index, uint32_t mask) { } } -void stm_dma_ch1_isr(void) { ao_dma_isr(id(1), id(1), ch_mask(1)); } -void stm_dma_ch2_3_isr(void) { ao_dma_isr(id(2), id(3), ch_mask(2) | ch_mask(3)); } -void stm_dma1_ch4_5_6_isr(void) { ao_dma_isr(id(4), id(6), ch_mask(4) | ch_mask(5) | ch_mask(6)); } +void stm_dma_ch1_isr(void) { + ao_dma_isr(STM_DMA_INDEX(1), + STM_DMA_INDEX(1), + ch_mask(STM_DMA_INDEX(1))); +} + +void stm_dma_ch2_3_isr(void) { + ao_dma_isr(STM_DMA_INDEX(2), + STM_DMA_INDEX(3), + ch_mask(STM_DMA_INDEX(2)) | + ch_mask(STM_DMA_INDEX(3))); +} + +void stm_dma1_ch4_5_6_isr(void) { + ao_dma_isr(STM_DMA_INDEX(4), STM_DMA_INDEX(6), + ch_mask(STM_DMA_INDEX(4)) | + ch_mask(STM_DMA_INDEX(5)) | + ch_mask(STM_DMA_INDEX(6))); +} void ao_dma_set_transfer(uint8_t index, @@ -73,11 +87,12 @@ ao_dma_set_transfer(uint8_t index, if (ao_dma_active++ == 0) stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_DMAEN); ); - stm_dma.channel[index].ccr = ccr | (1 << STM_DMA_CCR_TCIE); + ao_dma_config[index].isr = NULL; + ao_dma_done[index] = 0; stm_dma.channel[index].cndtr = count; stm_dma.channel[index].cpar = peripheral; stm_dma.channel[index].cmar = memory; - ao_dma_config[index].isr = NULL; + stm_dma.channel[index].ccr = ccr; } void @@ -89,7 +104,6 @@ ao_dma_set_isr(uint8_t index, void (*isr)(int)) void ao_dma_start(uint8_t index) { - ao_dma_done[index] = 0; stm_dma.channel[index].ccr |= (1 << STM_DMA_CCR_EN); } diff --git a/src/stmf0/ao_spi_stm.c b/src/stmf0/ao_spi_stm.c new file mode 100644 index 00000000..55bf59d2 --- /dev/null +++ b/src/stmf0/ao_spi_stm.c @@ -0,0 +1,478 @@ +/* + * Copyright © 2016 Keith Packard + * + * 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_info { + uint8_t miso_dma_index; + uint8_t mosi_dma_index; + struct stm_spi *stm_spi; +}; + +static uint8_t ao_spi_mutex[STM_NUM_SPI]; +static uint8_t ao_spi_index[STM_NUM_SPI]; + +static const struct ao_spi_stm_info ao_spi_stm_info[STM_NUM_SPI] = { + { + .miso_dma_index = STM_DMA_INDEX(STM_DMA_CHANNEL_SPI1_RX), + .mosi_dma_index = STM_DMA_INDEX(STM_DMA_CHANNEL_SPI1_TX), + &stm_spi1 + }, + { + .miso_dma_index = STM_DMA_INDEX(STM_DMA_CHANNEL_SPI2_RX), + .mosi_dma_index = STM_DMA_INDEX(STM_DMA_CHANNEL_SPI2_TX), + &stm_spi2 + } +}; + +static uint8_t spi_dev_null; + + + +#define SPI_CR2 ((0 << STM_SPI_CR2_LDMA_TX) | \ + (0 << STM_SPI_CR2_LDMA_RX) | \ + (1 << STM_SPI_CR2_FRXTH) | \ + (STM_SPI_CR2_DS_8 << STM_SPI_CR2_DS) | \ + (0 << STM_SPI_CR2_TXEIE) | \ + (0 << STM_SPI_CR2_RXNEIE) | \ + (0 << STM_SPI_CR2_ERRIE) | \ + (STM_SPI_CR2_FRF_MOTOROLA << STM_SPI_CR2_FRF) | \ + (0 << STM_SPI_CR2_NSSP) | \ + (0 << STM_SPI_CR2_SSOE)) + +#define SPI_CR2_DMA (SPI_CR2 | \ + (1 << STM_SPI_CR2_TXDMAEN) | \ + (1 << STM_SPI_CR2_RXDMAEN)) + +#define SPI_CR2_SYNC (SPI_CR2 | \ + (0 << STM_SPI_CR2_TXDMAEN) | \ + (0 << STM_SPI_CR2_RXDMAEN)) + +void +ao_spi_send(const void *block, uint16_t len, uint8_t spi_index) +{ + struct stm_spi *stm_spi = ao_spi_stm_info[AO_SPI_INDEX(spi_index)].stm_spi; + uint8_t mosi_dma_index = ao_spi_stm_info[AO_SPI_INDEX(spi_index)].mosi_dma_index; + uint8_t miso_dma_index = ao_spi_stm_info[AO_SPI_INDEX(spi_index)].miso_dma_index; + + /* Set up the transmit DMA to deliver data */ + ao_dma_set_transfer(mosi_dma_index, + &stm_spi->dr, + (void *) block, + len, + (0 << STM_DMA_CCR_MEM2MEM) | + (STM_DMA_CCR_PL_MEDIUM << STM_DMA_CCR_PL) | + (STM_DMA_CCR_MSIZE_8 << STM_DMA_CCR_MSIZE) | + (STM_DMA_CCR_PSIZE_8 << STM_DMA_CCR_PSIZE) | + (1 << STM_DMA_CCR_MINC) | + (0 << STM_DMA_CCR_PINC) | + (0 << STM_DMA_CCR_CIRC) | + (STM_DMA_CCR_DIR_MEM_TO_PER << STM_DMA_CCR_DIR) | + (0 << STM_DMA_CCR_TCIE)); + + /* Clear RXNE */ + (void) stm_spi->dr; + + /* Set up the receive DMA -- when this is done, we know the SPI unit + * is idle. Without this, we'd have to poll waiting for the BSY bit to + * be cleared + */ + ao_dma_set_transfer(miso_dma_index, + &stm_spi->dr, + &spi_dev_null, + len, + (0 << STM_DMA_CCR_MEM2MEM) | + (STM_DMA_CCR_PL_MEDIUM << STM_DMA_CCR_PL) | + (STM_DMA_CCR_MSIZE_8 << STM_DMA_CCR_MSIZE) | + (STM_DMA_CCR_PSIZE_8 << STM_DMA_CCR_PSIZE) | + (0 << STM_DMA_CCR_MINC) | + (0 << STM_DMA_CCR_PINC) | + (0 << STM_DMA_CCR_CIRC) | + (STM_DMA_CCR_DIR_PER_TO_MEM << STM_DMA_CCR_DIR) | + (1 << STM_DMA_CCR_TCIE)); + + stm_spi->cr2 = SPI_CR2_DMA; + + ao_dma_start(miso_dma_index); + ao_dma_start(mosi_dma_index); + ao_arch_critical( + while (!ao_dma_done[miso_dma_index]) + ao_sleep(&ao_dma_done[miso_dma_index]); + ); + ao_dma_done_transfer(mosi_dma_index); + ao_dma_done_transfer(miso_dma_index); +} + +void +ao_spi_send_fixed(uint8_t value, uint16_t len, uint8_t spi_index) +{ + struct stm_spi *stm_spi = ao_spi_stm_info[AO_SPI_INDEX(spi_index)].stm_spi; + uint8_t mosi_dma_index = ao_spi_stm_info[AO_SPI_INDEX(spi_index)].mosi_dma_index; + uint8_t miso_dma_index = ao_spi_stm_info[AO_SPI_INDEX(spi_index)].miso_dma_index; + + /* Set up the transmit DMA to deliver data */ + ao_dma_set_transfer(mosi_dma_index, + &stm_spi->dr, + &value, + len, + (0 << STM_DMA_CCR_MEM2MEM) | + (STM_DMA_CCR_PL_MEDIUM << STM_DMA_CCR_PL) | + (STM_DMA_CCR_MSIZE_8 << STM_DMA_CCR_MSIZE) | + (STM_DMA_CCR_PSIZE_8 << STM_DMA_CCR_PSIZE) | + (0 << STM_DMA_CCR_MINC) | + (0 << STM_DMA_CCR_PINC) | + (0 << STM_DMA_CCR_CIRC) | + (STM_DMA_CCR_DIR_MEM_TO_PER << STM_DMA_CCR_DIR) | + (0 << STM_DMA_CCR_TCIE)); + + /* Clear RXNE */ + (void) stm_spi->dr; + + /* Set up the receive DMA -- when this is done, we know the SPI unit + * is idle. Without this, we'd have to poll waiting for the BSY bit to + * be cleared + */ + ao_dma_set_transfer(miso_dma_index, + &stm_spi->dr, + &spi_dev_null, + len, + (0 << STM_DMA_CCR_MEM2MEM) | + (STM_DMA_CCR_PL_MEDIUM << STM_DMA_CCR_PL) | + (STM_DMA_CCR_MSIZE_8 << STM_DMA_CCR_MSIZE) | + (STM_DMA_CCR_PSIZE_8 << STM_DMA_CCR_PSIZE) | + (0 << STM_DMA_CCR_MINC) | + (0 << STM_DMA_CCR_PINC) | + (0 << STM_DMA_CCR_CIRC) | + (STM_DMA_CCR_DIR_PER_TO_MEM << STM_DMA_CCR_DIR) | + (1 << STM_DMA_CCR_TCIE)); + + stm_spi->cr2 = SPI_CR2_DMA; + ao_dma_start(miso_dma_index); + ao_dma_start(mosi_dma_index); + ao_arch_critical( + while (!ao_dma_done[miso_dma_index]) + ao_sleep(&ao_dma_done[miso_dma_index]); + ); + ao_dma_done_transfer(mosi_dma_index); + ao_dma_done_transfer(miso_dma_index); +} + +void +ao_spi_send_sync(void *block, uint16_t len, uint8_t spi_index) +{ + uint8_t *b = block; + struct stm_spi *stm_spi = ao_spi_stm_info[AO_SPI_INDEX(spi_index)].stm_spi; + + stm_spi->cr2 = SPI_CR2_SYNC; + + /* Clear RXNE */ + (void) stm_spi->dr; + + while (len--) { + while (!(stm_spi->sr & (1 << STM_SPI_SR_TXE))); + stm_spi->dr = *b++; + } +} + +void +ao_spi_recv(void *block, uint16_t len, uint8_t spi_index) +{ + struct stm_spi *stm_spi = ao_spi_stm_info[AO_SPI_INDEX(spi_index)].stm_spi; + uint8_t mosi_dma_index = ao_spi_stm_info[AO_SPI_INDEX(spi_index)].mosi_dma_index; + uint8_t miso_dma_index = ao_spi_stm_info[AO_SPI_INDEX(spi_index)].miso_dma_index; + + spi_dev_null = 0xff; + + /* Set up transmit DMA to make the SPI hardware actually run */ + ao_dma_set_transfer(mosi_dma_index, + &stm_spi->dr, + &spi_dev_null, + len, + (0 << STM_DMA_CCR_MEM2MEM) | + (STM_DMA_CCR_PL_MEDIUM << STM_DMA_CCR_PL) | + (STM_DMA_CCR_MSIZE_8 << STM_DMA_CCR_MSIZE) | + (STM_DMA_CCR_PSIZE_8 << STM_DMA_CCR_PSIZE) | + (0 << STM_DMA_CCR_MINC) | + (0 << STM_DMA_CCR_PINC) | + (0 << STM_DMA_CCR_CIRC) | + (STM_DMA_CCR_DIR_MEM_TO_PER << STM_DMA_CCR_DIR) | + (0 << STM_DMA_CCR_TCIE)); + + /* Clear RXNE */ + (void) stm_spi->dr; + + /* Set up the receive DMA to capture data */ + ao_dma_set_transfer(miso_dma_index, + &stm_spi->dr, + block, + len, + (0 << STM_DMA_CCR_MEM2MEM) | + (STM_DMA_CCR_PL_MEDIUM << STM_DMA_CCR_PL) | + (STM_DMA_CCR_MSIZE_8 << STM_DMA_CCR_MSIZE) | + (STM_DMA_CCR_PSIZE_8 << STM_DMA_CCR_PSIZE) | + (1 << STM_DMA_CCR_MINC) | + (0 << STM_DMA_CCR_PINC) | + (0 << STM_DMA_CCR_CIRC) | + (STM_DMA_CCR_DIR_PER_TO_MEM << STM_DMA_CCR_DIR) | + (1 << STM_DMA_CCR_TCIE)); + + stm_spi->cr2 = SPI_CR2_DMA; + ao_dma_start(miso_dma_index); + ao_dma_start(mosi_dma_index); + + /* Wait until the SPI unit is done */ + ao_arch_critical( + while (!ao_dma_done[miso_dma_index]) + ao_sleep(&ao_dma_done[miso_dma_index]); + ); + + ao_dma_done_transfer(mosi_dma_index); + ao_dma_done_transfer(miso_dma_index); +} + +void +ao_spi_duplex(void *out, void *in, uint16_t len, uint8_t spi_index) +{ + struct stm_spi *stm_spi = ao_spi_stm_info[AO_SPI_INDEX(spi_index)].stm_spi; + uint8_t mosi_dma_index = ao_spi_stm_info[AO_SPI_INDEX(spi_index)].mosi_dma_index; + uint8_t miso_dma_index = ao_spi_stm_info[AO_SPI_INDEX(spi_index)].miso_dma_index; + + /* Set up transmit DMA to send data */ + ao_dma_set_transfer(mosi_dma_index, + &stm_spi->dr, + out, + len, + (0 << STM_DMA_CCR_MEM2MEM) | + (STM_DMA_CCR_PL_MEDIUM << STM_DMA_CCR_PL) | + (STM_DMA_CCR_MSIZE_8 << STM_DMA_CCR_MSIZE) | + (STM_DMA_CCR_PSIZE_8 << STM_DMA_CCR_PSIZE) | + (1 << STM_DMA_CCR_MINC) | + (0 << STM_DMA_CCR_PINC) | + (0 << STM_DMA_CCR_CIRC) | + (STM_DMA_CCR_DIR_MEM_TO_PER << STM_DMA_CCR_DIR) | + (0 << STM_DMA_CCR_TCIE)); + + /* Clear RXNE */ + (void) stm_spi->dr; + + /* Set up the receive DMA to capture data */ + ao_dma_set_transfer(miso_dma_index, + &stm_spi->dr, + in, + len, + (0 << STM_DMA_CCR_MEM2MEM) | + (STM_DMA_CCR_PL_MEDIUM << STM_DMA_CCR_PL) | + (STM_DMA_CCR_MSIZE_8 << STM_DMA_CCR_MSIZE) | + (STM_DMA_CCR_PSIZE_8 << STM_DMA_CCR_PSIZE) | + (1 << STM_DMA_CCR_MINC) | + (0 << STM_DMA_CCR_PINC) | + (0 << STM_DMA_CCR_CIRC) | + (STM_DMA_CCR_DIR_PER_TO_MEM << STM_DMA_CCR_DIR) | + (1 << STM_DMA_CCR_TCIE)); + + stm_spi->cr2 = SPI_CR2_DMA; + ao_dma_start(miso_dma_index); + ao_dma_start(mosi_dma_index); + + /* Wait until the SPI unit is done */ + ao_arch_critical( + while (!ao_dma_done[miso_dma_index]) + ao_sleep(&ao_dma_done[miso_dma_index]); + ); + + ao_dma_done_transfer(mosi_dma_index); + ao_dma_done_transfer(miso_dma_index); +} + +static void +ao_spi_disable_index(uint8_t spi_index) +{ + /* Disable current config + */ + switch (AO_SPI_INDEX(spi_index)) { + case STM_SPI_INDEX(1): + switch (spi_index) { + case AO_SPI_1_PA5_PA6_PA7: + stm_gpio_set(&stm_gpioa, 5, 1); + stm_moder_set(&stm_gpioa, 5, STM_MODER_OUTPUT); + stm_moder_set(&stm_gpioa, 6, STM_MODER_INPUT); + stm_moder_set(&stm_gpioa, 7, STM_MODER_OUTPUT); + break; + case AO_SPI_1_PB3_PB4_PB5: + stm_gpio_set(&stm_gpiob, 3, 1); + stm_moder_set(&stm_gpiob, 3, STM_MODER_OUTPUT); + stm_moder_set(&stm_gpiob, 4, STM_MODER_INPUT); + stm_moder_set(&stm_gpiob, 5, STM_MODER_OUTPUT); + break; + } + break; + case STM_SPI_INDEX(2): + switch (spi_index) { + case AO_SPI_2_PB13_PB14_PB15: + stm_gpio_set(&stm_gpiob, 13, 1); + stm_moder_set(&stm_gpiob, 13, STM_MODER_OUTPUT); + stm_moder_set(&stm_gpiob, 14, STM_MODER_INPUT); + stm_moder_set(&stm_gpiob, 15, STM_MODER_OUTPUT); + break; + } + break; + } +} + +static void +ao_spi_enable_index(uint8_t spi_index) +{ + switch (AO_SPI_INDEX(spi_index)) { + case STM_SPI_INDEX(1): + switch (spi_index) { + case AO_SPI_1_PA5_PA6_PA7: + stm_afr_set(&stm_gpioa, 5, STM_AFR_AF0); + stm_afr_set(&stm_gpioa, 6, STM_AFR_AF0); + stm_afr_set(&stm_gpioa, 7, STM_AFR_AF0); + break; + case AO_SPI_1_PB3_PB4_PB5: + stm_afr_set(&stm_gpiob, 3, STM_AFR_AF0); + stm_afr_set(&stm_gpiob, 4, STM_AFR_AF0); + stm_afr_set(&stm_gpiob, 5, STM_AFR_AF0); + break; + } + break; + case STM_SPI_INDEX(2): + switch (spi_index) { + case AO_SPI_2_PB13_PB14_PB15: + stm_afr_set(&stm_gpiob, 13, STM_AFR_AF0); + stm_afr_set(&stm_gpiob, 14, STM_AFR_AF0); + stm_afr_set(&stm_gpiob, 15, STM_AFR_AF0); + break; + } + break; + } +} + +static void +ao_spi_config(uint8_t spi_index, uint32_t speed) +{ + uint8_t id = AO_SPI_INDEX(spi_index); + struct stm_spi *stm_spi = ao_spi_stm_info[id].stm_spi; + + stm_spi->cr2 = SPI_CR2; + stm_spi->cr1 = ((0 << STM_SPI_CR1_BIDIMODE) | /* Three wire mode */ + (0 << STM_SPI_CR1_BIDIOE) | + (0 << STM_SPI_CR1_CRCEN) | /* CRC disabled */ + (0 << STM_SPI_CR1_CRCNEXT) | + (0 << STM_SPI_CR1_CRCL) | + (0 << STM_SPI_CR1_RXONLY) | + (1 << STM_SPI_CR1_SSM) | /* Software SS handling */ + (1 << STM_SPI_CR1_SSI) | /* ... */ + (0 << STM_SPI_CR1_LSBFIRST) | /* Big endian */ + (1 << STM_SPI_CR1_SPE) | /* Enable SPI unit */ + (speed << STM_SPI_CR1_BR) | /* baud rate to pclk/4 */ + (1 << STM_SPI_CR1_MSTR) | + (0 << STM_SPI_CR1_CPOL) | /* Format 0 */ + (0 << STM_SPI_CR1_CPHA)); + + if (spi_index != ao_spi_index[id]) { + + /* Disable old config + */ + ao_spi_disable_index(ao_spi_index[id]); + + /* Enable new config + */ + ao_spi_enable_index(spi_index); + + /* Remember current config + */ + ao_spi_index[id] = spi_index; + } +} + +uint8_t +ao_spi_try_get(uint8_t spi_index, uint32_t speed, uint8_t task_id) +{ + uint8_t id = AO_SPI_INDEX(spi_index); + + if (!ao_mutex_try(&ao_spi_mutex[id], task_id)) + return 0; + ao_spi_config(spi_index, speed); + return 1; +} + +void +ao_spi_get(uint8_t spi_index, uint32_t speed) +{ + uint8_t id = AO_SPI_INDEX(spi_index); + ao_mutex_get(&ao_spi_mutex[id]); + ao_spi_config(spi_index, speed); +} + +void +ao_spi_put(uint8_t spi_index) +{ + uint8_t id = AO_SPI_INDEX(spi_index); + struct stm_spi *stm_spi = ao_spi_stm_info[id].stm_spi; + + stm_spi->cr1 = 0; + ao_mutex_put(&ao_spi_mutex[id]); +} + +static void +ao_spi_channel_init(uint8_t spi_index) +{ + uint8_t id = AO_SPI_INDEX(spi_index); + struct stm_spi *stm_spi = ao_spi_stm_info[id].stm_spi; + + ao_spi_disable_index(spi_index); + + stm_spi->cr1 = 0; + (void) stm_spi->sr; + stm_spi->cr2 = SPI_CR2_SYNC; +} + +void +ao_spi_init(void) +{ +#if HAS_SPI_1 +# if SPI_1_PA5_PA6_PA7 + stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_IOPAEN); + stm_ospeedr_set(&stm_gpioa, 5, SPI_1_OSPEEDR); + stm_ospeedr_set(&stm_gpioa, 6, SPI_1_OSPEEDR); + stm_ospeedr_set(&stm_gpioa, 7, SPI_1_OSPEEDR); +# endif +# if SPI_1_PB3_PB4_PB5 + stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_IOPBEN); + stm_ospeedr_set(&stm_gpiob, 3, SPI_1_OSPEEDR); + stm_ospeedr_set(&stm_gpiob, 4, SPI_1_OSPEEDR); + stm_ospeedr_set(&stm_gpiob, 5, SPI_1_OSPEEDR); +# endif + stm_rcc.apb2enr |= (1 << STM_RCC_APB2ENR_SPI1EN); + ao_spi_index[0] = AO_SPI_CONFIG_NONE; + ao_spi_channel_init(STM_SPI_INDEX(1)); +#endif + +#if HAS_SPI_2 +# if SPI_2_PB10_PB13_PB14 + stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_IOPBEN); + stm_ospeedr_set(&stm_gpiob, 13, SPI_2_OSPEEDR); + stm_ospeedr_set(&stm_gpiob, 14, SPI_2_OSPEEDR); + stm_ospeedr_set(&stm_gpiob, 15, SPI_2_OSPEEDR); +# endif + stm_rcc.apb1enr |= (1 << STM_RCC_APB1ENR_SPI2EN); + ao_spi_index[1] = AO_SPI_CONFIG_NONE; + ao_spi_channel_init(STM_SPI_INDEX(2)); +#endif +} diff --git a/src/stmf0/stm32f0.h b/src/stmf0/stm32f0.h index ce8ca456..14be5fbb 100644 --- a/src/stmf0/stm32f0.h +++ b/src/stmf0/stm32f0.h @@ -795,7 +795,7 @@ isr(tim7) #define STM_ISR_TSC_POS 8 #define STM_ISR_DMA_CH1_POS 9 #define STM_ISR_DMA_CH2_3_DMA2_CH1_2_POS 10 -#define STM_ISR_DMA_CH44_5_6_7_DMA2_CH3_4_5_POS 11 +#define STM_ISR_DMA_CH4_5_6_7_DMA2_CH3_4_5_POS 11 #define STM_ISR_ADC_COMP_POS 12 #define STM_ISR_TIM1_BRK_UP_TRG_COM_POS 13 #define STM_ISR_TIM1_CC_POS 14 @@ -890,7 +890,7 @@ struct stm_dma_channel { vuint32_t reserved; }; -#define STM_NUM_DMA 6 +#define STM_NUM_DMA 5 struct stm_dma { vuint32_t isr; @@ -900,7 +900,7 @@ struct stm_dma { extern struct stm_dma stm_dma; -/* DMA channels go from 1 to 6, instead of 0 to 5 (sigh) +/* DMA channels go from 1 to 5, instead of 0 to 4 (sigh) */ #define STM_DMA_INDEX(channel) ((channel) - 1) @@ -1042,7 +1042,7 @@ extern struct stm_spi stm_spi1, stm_spi2, stm_spi3; #define STM_SPI_CR1_BIDIOE 14 #define STM_SPI_CR1_CRCEN 13 #define STM_SPI_CR1_CRCNEXT 12 -#define STM_SPI_CR1_DFF 11 +#define STM_SPI_CR1_CRCL 11 #define STM_SPI_CR1_RXONLY 10 #define STM_SPI_CR1_SSM 9 #define STM_SPI_CR1_SSI 8 @@ -1063,17 +1063,43 @@ extern struct stm_spi stm_spi1, stm_spi2, stm_spi3; #define STM_SPI_CR1_CPOL 1 #define STM_SPI_CR1_CPHA 0 +#define STM_SPI_CR2_LDMA_TX 14 +#define STM_SPI_CR2_LDMA_RX 13 +#define STM_SPI_CR2_FRXTH 12 +#define STM_SPI_CR2_DS 8 +#define STM_SPI_CR2_DS_4 0x3 +#define STM_SPI_CR2_DS_5 0x4 +#define STM_SPI_CR2_DS_6 0x5 +#define STM_SPI_CR2_DS_7 0x6 +#define STM_SPI_CR2_DS_8 0x7 +#define STM_SPI_CR2_DS_9 0x8 +#define STM_SPI_CR2_DS_10 0x9 +#define STM_SPI_CR2_DS_11 0xa +#define STM_SPI_CR2_DS_12 0xb +#define STM_SPI_CR2_DS_13 0xc +#define STM_SPI_CR2_DS_14 0xd +#define STM_SPI_CR2_DS_15 0xe +#define STM_SPI_CR2_DS_16 0xf #define STM_SPI_CR2_TXEIE 7 #define STM_SPI_CR2_RXNEIE 6 #define STM_SPI_CR2_ERRIE 5 +#define STM_SPI_CR2_FRF 4 +# define STM_SPI_CR2_FRF_MOTOROLA 0 +# define STM_SPI_CR2_FRF_TI 1 +#define STM_SPI_CR2_NSSP 3 #define STM_SPI_CR2_SSOE 2 #define STM_SPI_CR2_TXDMAEN 1 #define STM_SPI_CR2_RXDMAEN 0 +#define STM_SPI_SR_FTLVL 11 +#define STM_SPI_SR_FRLVL 9 +#define STM_SPI_SR_FRE 8 #define STM_SPI_SR_BSY 7 #define STM_SPI_SR_OVR 6 #define STM_SPI_SR_MODF 5 #define STM_SPI_SR_CRCERR 4 +#define STM_SPI_SR_UDR 3 +#define STM_SPI_SR_CHSIDE 2 #define STM_SPI_SR_TXE 1 #define STM_SPI_SR_RXNE 0 -- cgit v1.2.3 From f95c781bc16d332ea5442590521074396d6981ae Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 2 Apr 2016 19:43:32 -0700 Subject: altos/stmf0: Support HPE clock source Allows the use of crystals instead of requiring USB. Signed-off-by: Keith Packard --- src/stmf0/ao_timer.c | 39 ++++- src/stmf0/stm32f0.h | 423 +++++++++++++++++++++++++++------------------------ 2 files changed, 258 insertions(+), 204 deletions(-) (limited to 'src') diff --git a/src/stmf0/ao_timer.c b/src/stmf0/ao_timer.c index d3542a57..e5bf04a3 100644 --- a/src/stmf0/ao_timer.c +++ b/src/stmf0/ao_timer.c @@ -50,12 +50,14 @@ void stm_systick_isr(void) #if AO_DATA_ALL if (++ao_data_count == ao_data_interval) { ao_data_count = 0; +#if HAS_ADC #if HAS_FAKE_FLIGHT if (ao_fake_flight_active) ao_fake_flight_poll(); else #endif ao_adc_poll(); +#endif #if (AO_DATA_ALL & ~(AO_DATA_ADC)) ao_wakeup((void *) &ao_data_count); #endif @@ -92,6 +94,7 @@ ao_timer_init(void) #endif +#if AO_HSI48 static void ao_clock_enable_crs(void) { @@ -128,6 +131,7 @@ ao_clock_enable_crs(void) (0 << STM_CRS_CR_SYNCWARNIE) | (0 << STM_CRS_CR_SYNCOKIE)); } +#endif static void ao_clock_hsi(void) @@ -155,10 +159,11 @@ static void ao_clock_normal_start(void) { #if AO_HSE -#define STM_RCC_CFGR_SWS_TARGET_CLOCK STM_RCC_CFGR_SWS_HSE -#define STM_RCC_CFGR_SW_TARGET_CLOCK STM_RCC_CFGR_SW_HSE + uint32_t cfgr; +#define STM_RCC_CFGR_SWS_TARGET_CLOCK STM_RCC_CFGR_SWS_PLL +#define STM_RCC_CFGR_SW_TARGET_CLOCK STM_RCC_CFGR_SW_PLL #define STM_PLLSRC AO_HSE -#define STM_RCC_CFGR_PLLSRC_TARGET_CLOCK 1 +#define STM_RCC_CFGR_PLLSRC_TARGET_CLOCK STM_RCC_CFGR_PLLSRC_HSE #if AO_HSE_BYPASS stm_rcc.cr |= (1 << STM_RCC_CR_HSEBYP); @@ -171,7 +176,29 @@ ao_clock_normal_start(void) asm("nop"); #ifdef STM_PLLSRC -#error No code for PLL initialization yet + /* Disable the PLL */ + stm_rcc.cr &= ~(1 << STM_RCC_CR_PLLON); + while (stm_rcc.cr & (1 << STM_RCC_CR_PLLRDY)) + asm("nop"); + + /* PLLVCO to 48MHz (for USB) -> PLLMUL = 3 */ + cfgr = stm_rcc.cfgr; + cfgr &= ~(STM_RCC_CFGR_PLLMUL_MASK << STM_RCC_CFGR_PLLMUL); + cfgr |= (AO_RCC_CFGR_PLLMUL << STM_RCC_CFGR_PLLMUL); + + /* PLL source */ + cfgr &= ~(1 << STM_RCC_CFGR_PLLSRC); + cfgr |= (STM_RCC_CFGR_PLLSRC_TARGET_CLOCK << STM_RCC_CFGR_PLLSRC); + stm_rcc.cfgr = cfgr; + + /* Disable pre divider */ + stm_rcc.cfgr2 = (STM_RCC_CFGR2_PREDIV_1 << STM_RCC_CFGR2_PREDIV); + + /* Enable the PLL and wait for it */ + stm_rcc.cr |= (1 << STM_RCC_CR_PLLON); + while (!(stm_rcc.cr & (1 << STM_RCC_CR_PLLRDY))) + asm("nop"); + #endif #endif @@ -223,6 +250,10 @@ ao_clock_normal_switch(void) /* Turn off the HSI clock */ stm_rcc.cr &= ~(1 << STM_RCC_CR_HSION); #endif +#ifdef STM_PLLSRC + /* USB PLL source */ + stm_rcc.cfgr3 |= (1 << STM_RCC_CFGR3_USBSW); +#endif } void diff --git a/src/stmf0/stm32f0.h b/src/stmf0/stm32f0.h index 14be5fbb..30b45b15 100644 --- a/src/stmf0/stm32f0.h +++ b/src/stmf0/stm32f0.h @@ -475,6 +475,24 @@ extern struct stm_rcc stm_rcc; #define STM_RCC_CR2_HSI14RDY 1 #define STM_RCC_CR2_HSI14ON 0 +#define STM_RCC_CFGR2_PREDIV 0 +#define STM_RCC_CFGR2_PREDIV_1 0x0 +#define STM_RCC_CFGR2_PREDIV_2 0x1 +#define STM_RCC_CFGR2_PREDIV_3 0x2 +#define STM_RCC_CFGR2_PREDIV_4 0x3 +#define STM_RCC_CFGR2_PREDIV_5 0x4 +#define STM_RCC_CFGR2_PREDIV_6 0x5 +#define STM_RCC_CFGR2_PREDIV_7 0x6 +#define STM_RCC_CFGR2_PREDIV_8 0x7 +#define STM_RCC_CFGR2_PREDIV_9 0x8 +#define STM_RCC_CFGR2_PREDIV_10 0x9 +#define STM_RCC_CFGR2_PREDIV_11 0xa +#define STM_RCC_CFGR2_PREDIV_12 0xb +#define STM_RCC_CFGR2_PREDIV_13 0xc +#define STM_RCC_CFGR2_PREDIV_14 0xd +#define STM_RCC_CFGR2_PREDIV_15 0xe +#define STM_RCC_CFGR2_PREDIV_16 0xf + #define STM_RCC_CFGR3_USART3SW 18 #define STM_RCC_CFGR3_USART2SW 16 #define STM_RCC_CFGR3_ADCSW 8 @@ -858,7 +876,13 @@ extern struct stm_syscfg stm_syscfg; #define STM_SYSCFG_CFGR1_MEM_MODE_SRAM 3 #define STM_SYSCFG_CFGR1_MEM_MODE_MASK 3 -#if 0 +#define STM_SYSCFG_EXTICR_PA 0 +#define STM_SYSCFG_EXTICR_PB 1 +#define STM_SYSCFG_EXTICR_PC 2 +#define STM_SYSCFG_EXTICR_PD 3 +#define STM_SYSCFG_EXTICR_PE 4 +#define STM_SYSCFG_EXTICR_PF 5 + static inline void stm_exticr_set(struct stm_gpio *gpio, int pin) { uint8_t reg = pin >> 2; @@ -879,8 +903,6 @@ stm_exticr_set(struct stm_gpio *gpio, int pin) { stm_syscfg.exticr[reg] = (stm_syscfg.exticr[reg] & ~(0xf << shift)) | val << shift; } -#endif - struct stm_dma_channel { vuint32_t ccr; @@ -1319,7 +1341,7 @@ extern struct stm_i2c stm_i2c1, stm_i2c2; #define STM_I2C_CCR_CCR 0 #define STM_I2C_CCR_MASK 0x7ff -struct stm_tim234 { +struct stm_tim23 { vuint32_t cr1; vuint32_t cr2; vuint32_t smcr; @@ -1344,204 +1366,205 @@ struct stm_tim234 { uint32_t reserved_44; vuint32_t dcr; vuint32_t dmar; - - uint32_t reserved_50; }; -extern struct stm_tim234 stm_tim2, stm_tim3, stm_tim4; - -#define STM_TIM234_CR1_CKD 8 -#define STM_TIM234_CR1_CKD_1 0 -#define STM_TIM234_CR1_CKD_2 1 -#define STM_TIM234_CR1_CKD_4 2 -#define STM_TIM234_CR1_CKD_MASK 3 -#define STM_TIM234_CR1_ARPE 7 -#define STM_TIM234_CR1_CMS 5 -#define STM_TIM234_CR1_CMS_EDGE 0 -#define STM_TIM234_CR1_CMS_CENTER_1 1 -#define STM_TIM234_CR1_CMS_CENTER_2 2 -#define STM_TIM234_CR1_CMS_CENTER_3 3 -#define STM_TIM234_CR1_CMS_MASK 3 -#define STM_TIM234_CR1_DIR 4 -#define STM_TIM234_CR1_DIR_UP 0 -#define STM_TIM234_CR1_DIR_DOWN 1 -#define STM_TIM234_CR1_OPM 3 -#define STM_TIM234_CR1_URS 2 -#define STM_TIM234_CR1_UDIS 1 -#define STM_TIM234_CR1_CEN 0 - -#define STM_TIM234_CR2_TI1S 7 -#define STM_TIM234_CR2_MMS 4 -#define STM_TIM234_CR2_MMS_RESET 0 -#define STM_TIM234_CR2_MMS_ENABLE 1 -#define STM_TIM234_CR2_MMS_UPDATE 2 -#define STM_TIM234_CR2_MMS_COMPARE_PULSE 3 -#define STM_TIM234_CR2_MMS_COMPARE_OC1REF 4 -#define STM_TIM234_CR2_MMS_COMPARE_OC2REF 5 -#define STM_TIM234_CR2_MMS_COMPARE_OC3REF 6 -#define STM_TIM234_CR2_MMS_COMPARE_OC4REF 7 -#define STM_TIM234_CR2_MMS_MASK 7 -#define STM_TIM234_CR2_CCDS 3 - -#define STM_TIM234_SMCR_ETP 15 -#define STM_TIM234_SMCR_ECE 14 -#define STM_TIM234_SMCR_ETPS 12 -#define STM_TIM234_SMCR_ETPS_OFF 0 -#define STM_TIM234_SMCR_ETPS_DIV_2 1 -#define STM_TIM234_SMCR_ETPS_DIV_4 2 -#define STM_TIM234_SMCR_ETPS_DIV_8 3 -#define STM_TIM234_SMCR_ETPS_MASK 3 -#define STM_TIM234_SMCR_ETF 8 -#define STM_TIM234_SMCR_ETF_NONE 0 -#define STM_TIM234_SMCR_ETF_INT_N_2 1 -#define STM_TIM234_SMCR_ETF_INT_N_4 2 -#define STM_TIM234_SMCR_ETF_INT_N_8 3 -#define STM_TIM234_SMCR_ETF_DTS_2_N_6 4 -#define STM_TIM234_SMCR_ETF_DTS_2_N_8 5 -#define STM_TIM234_SMCR_ETF_DTS_4_N_6 6 -#define STM_TIM234_SMCR_ETF_DTS_4_N_8 7 -#define STM_TIM234_SMCR_ETF_DTS_8_N_6 8 -#define STM_TIM234_SMCR_ETF_DTS_8_N_8 9 -#define STM_TIM234_SMCR_ETF_DTS_16_N_5 10 -#define STM_TIM234_SMCR_ETF_DTS_16_N_6 11 -#define STM_TIM234_SMCR_ETF_DTS_16_N_8 12 -#define STM_TIM234_SMCR_ETF_DTS_32_N_5 13 -#define STM_TIM234_SMCR_ETF_DTS_32_N_6 14 -#define STM_TIM234_SMCR_ETF_DTS_32_N_8 15 -#define STM_TIM234_SMCR_ETF_MASK 15 -#define STM_TIM234_SMCR_MSM 7 -#define STM_TIM234_SMCR_TS 4 -#define STM_TIM234_SMCR_TS_ITR0 0 -#define STM_TIM234_SMCR_TS_ITR1 1 -#define STM_TIM234_SMCR_TS_ITR2 2 -#define STM_TIM234_SMCR_TS_ITR3 3 -#define STM_TIM234_SMCR_TS_TI1F_ED 4 -#define STM_TIM234_SMCR_TS_TI1FP1 5 -#define STM_TIM234_SMCR_TS_TI2FP2 6 -#define STM_TIM234_SMCR_TS_ETRF 7 -#define STM_TIM234_SMCR_TS_MASK 7 -#define STM_TIM234_SMCR_OCCS 3 -#define STM_TIM234_SMCR_SMS 0 -#define STM_TIM234_SMCR_SMS_DISABLE 0 -#define STM_TIM234_SMCR_SMS_ENCODER_MODE_1 1 -#define STM_TIM234_SMCR_SMS_ENCODER_MODE_2 2 -#define STM_TIM234_SMCR_SMS_ENCODER_MODE_3 3 -#define STM_TIM234_SMCR_SMS_RESET_MODE 4 -#define STM_TIM234_SMCR_SMS_GATED_MODE 5 -#define STM_TIM234_SMCR_SMS_TRIGGER_MODE 6 -#define STM_TIM234_SMCR_SMS_EXTERNAL_CLOCK 7 -#define STM_TIM234_SMCR_SMS_MASK 7 - -#define STM_TIM234_SR_CC4OF 12 -#define STM_TIM234_SR_CC3OF 11 -#define STM_TIM234_SR_CC2OF 10 -#define STM_TIM234_SR_CC1OF 9 -#define STM_TIM234_SR_TIF 6 -#define STM_TIM234_SR_CC4IF 4 -#define STM_TIM234_SR_CC3IF 3 -#define STM_TIM234_SR_CC2IF 2 -#define STM_TIM234_SR_CC1IF 1 -#define STM_TIM234_SR_UIF 0 - -#define STM_TIM234_EGR_TG 6 -#define STM_TIM234_EGR_CC4G 4 -#define STM_TIM234_EGR_CC3G 3 -#define STM_TIM234_EGR_CC2G 2 -#define STM_TIM234_EGR_CC1G 1 -#define STM_TIM234_EGR_UG 0 - -#define STM_TIM234_CCMR1_OC2CE 15 -#define STM_TIM234_CCMR1_OC2M 12 -#define STM_TIM234_CCMR1_OC2M_FROZEN 0 -#define STM_TIM234_CCMR1_OC2M_SET_HIGH_ON_MATCH 1 -#define STM_TIM234_CCMR1_OC2M_SET_LOW_ON_MATCH 2 -#define STM_TIM234_CCMR1_OC2M_TOGGLE 3 -#define STM_TIM234_CCMR1_OC2M_FORCE_LOW 4 -#define STM_TIM234_CCMR1_OC2M_FORCE_HIGH 5 -#define STM_TIM234_CCMR1_OC2M_PWM_MODE_1 6 -#define STM_TIM234_CCMR1_OC2M_PWM_MODE_2 7 -#define STM_TIM234_CCMR1_OC2M_MASK 7 -#define STM_TIM234_CCMR1_OC2PE 11 -#define STM_TIM234_CCMR1_OC2FE 10 -#define STM_TIM234_CCMR1_CC2S 8 -#define STM_TIM234_CCMR1_CC2S_OUTPUT 0 -#define STM_TIM234_CCMR1_CC2S_INPUT_TI2 1 -#define STM_TIM234_CCMR1_CC2S_INPUT_TI1 2 -#define STM_TIM234_CCMR1_CC2S_INPUT_TRC 3 -#define STM_TIM234_CCMR1_CC2S_MASK 3 - -#define STM_TIM234_CCMR1_OC1CE 7 -#define STM_TIM234_CCMR1_OC1M 4 -#define STM_TIM234_CCMR1_OC1M_FROZEN 0 -#define STM_TIM234_CCMR1_OC1M_SET_HIGH_ON_MATCH 1 -#define STM_TIM234_CCMR1_OC1M_SET_LOW_ON_MATCH 2 -#define STM_TIM234_CCMR1_OC1M_TOGGLE 3 -#define STM_TIM234_CCMR1_OC1M_FORCE_LOW 4 -#define STM_TIM234_CCMR1_OC1M_FORCE_HIGH 5 -#define STM_TIM234_CCMR1_OC1M_PWM_MODE_1 6 -#define STM_TIM234_CCMR1_OC1M_PWM_MODE_2 7 -#define STM_TIM234_CCMR1_OC1M_MASK 7 -#define STM_TIM234_CCMR1_OC1PE 11 -#define STM_TIM234_CCMR1_OC1FE 2 -#define STM_TIM234_CCMR1_CC1S 0 -#define STM_TIM234_CCMR1_CC1S_OUTPUT 0 -#define STM_TIM234_CCMR1_CC1S_INPUT_TI1 1 -#define STM_TIM234_CCMR1_CC1S_INPUT_TI2 2 -#define STM_TIM234_CCMR1_CC1S_INPUT_TRC 3 -#define STM_TIM234_CCMR1_CC1S_MASK 3 - -#define STM_TIM234_CCMR2_OC4CE 15 -#define STM_TIM234_CCMR2_OC4M 12 -#define STM_TIM234_CCMR2_OC4M_FROZEN 0 -#define STM_TIM234_CCMR2_OC4M_SET_HIGH_ON_MATCH 1 -#define STM_TIM234_CCMR2_OC4M_SET_LOW_ON_MATCH 2 -#define STM_TIM234_CCMR2_OC4M_TOGGLE 3 -#define STM_TIM234_CCMR2_OC4M_FORCE_LOW 4 -#define STM_TIM234_CCMR2_OC4M_FORCE_HIGH 5 -#define STM_TIM234_CCMR2_OC4M_PWM_MODE_1 6 -#define STM_TIM234_CCMR2_OC4M_PWM_MODE_2 7 -#define STM_TIM234_CCMR2_OC4M_MASK 7 -#define STM_TIM234_CCMR2_OC4PE 11 -#define STM_TIM234_CCMR2_OC4FE 10 -#define STM_TIM234_CCMR2_CC4S 8 -#define STM_TIM234_CCMR2_CC4S_OUTPUT 0 -#define STM_TIM234_CCMR2_CC4S_INPUT_TI4 1 -#define STM_TIM234_CCMR2_CC4S_INPUT_TI3 2 -#define STM_TIM234_CCMR2_CC4S_INPUT_TRC 3 -#define STM_TIM234_CCMR2_CC4S_MASK 3 - -#define STM_TIM234_CCMR2_OC3CE 7 -#define STM_TIM234_CCMR2_OC3M 4 -#define STM_TIM234_CCMR2_OC3M_FROZEN 0 -#define STM_TIM234_CCMR2_OC3M_SET_HIGH_ON_MATCH 1 -#define STM_TIM234_CCMR2_OC3M_SET_LOW_ON_MATCH 2 -#define STM_TIM234_CCMR2_OC3M_TOGGLE 3 -#define STM_TIM234_CCMR2_OC3M_FORCE_LOW 4 -#define STM_TIM234_CCMR2_OC3M_FORCE_HIGH 5 -#define STM_TIM234_CCMR2_OC3M_PWM_MODE_1 6 -#define STM_TIM234_CCMR2_OC3M_PWM_MODE_2 7 -#define STM_TIM234_CCMR2_OC3M_MASK 7 -#define STM_TIM234_CCMR2_OC3PE 11 -#define STM_TIM234_CCMR2_OC3FE 2 -#define STM_TIM234_CCMR2_CC3S 0 -#define STM_TIM234_CCMR2_CC3S_OUTPUT 0 -#define STM_TIM234_CCMR2_CC3S_INPUT_TI3 1 -#define STM_TIM234_CCMR2_CC3S_INPUT_TI4 2 -#define STM_TIM234_CCMR2_CC3S_INPUT_TRC 3 -#define STM_TIM234_CCMR2_CC3S_MASK 3 - -#define STM_TIM234_CCER_CC4NP 15 -#define STM_TIM234_CCER_CC4P 13 -#define STM_TIM234_CCER_CC4E 12 -#define STM_TIM234_CCER_CC3NP 11 -#define STM_TIM234_CCER_CC3P 9 -#define STM_TIM234_CCER_CC3E 8 -#define STM_TIM234_CCER_CC2NP 7 -#define STM_TIM234_CCER_CC2P 5 -#define STM_TIM234_CCER_CC2E 4 -#define STM_TIM234_CCER_CC1NP 3 -#define STM_TIM234_CCER_CC1P 1 -#define STM_TIM234_CCER_CC1E 0 +extern struct stm_tim23 stm_tim2, stm_tim3; + +#define stm_tim3 (*(struct stm_tim23 *) 0x40000400) +#define stm_tim2 (*(struct stm_tim23 *) 0x40000000) + +#define STM_TIM23_CR1_CKD 8 +#define STM_TIM23_CR1_CKD_1 0 +#define STM_TIM23_CR1_CKD_2 1 +#define STM_TIM23_CR1_CKD_4 2 +#define STM_TIM23_CR1_CKD_MASK 3 +#define STM_TIM23_CR1_ARPE 7 +#define STM_TIM23_CR1_CMS 5 +#define STM_TIM23_CR1_CMS_EDGE 0 +#define STM_TIM23_CR1_CMS_CENTER_1 1 +#define STM_TIM23_CR1_CMS_CENTER_2 2 +#define STM_TIM23_CR1_CMS_CENTER_3 3 +#define STM_TIM23_CR1_CMS_MASK 3 +#define STM_TIM23_CR1_DIR 4 +#define STM_TIM23_CR1_DIR_UP 0 +#define STM_TIM23_CR1_DIR_DOWN 1 +#define STM_TIM23_CR1_OPM 3 +#define STM_TIM23_CR1_URS 2 +#define STM_TIM23_CR1_UDIS 1 +#define STM_TIM23_CR1_CEN 0 + +#define STM_TIM23_CR2_TI1S 7 +#define STM_TIM23_CR2_MMS 4 +#define STM_TIM23_CR2_MMS_RESET 0 +#define STM_TIM23_CR2_MMS_ENABLE 1 +#define STM_TIM23_CR2_MMS_UPDATE 2 +#define STM_TIM23_CR2_MMS_COMPARE_PULSE 3 +#define STM_TIM23_CR2_MMS_COMPARE_OC1REF 4 +#define STM_TIM23_CR2_MMS_COMPARE_OC2REF 5 +#define STM_TIM23_CR2_MMS_COMPARE_OC3REF 6 +#define STM_TIM23_CR2_MMS_COMPARE_OC4REF 7 +#define STM_TIM23_CR2_MMS_MASK 7 +#define STM_TIM23_CR2_CCDS 3 + +#define STM_TIM23_SMCR_ETP 15 +#define STM_TIM23_SMCR_ECE 14 +#define STM_TIM23_SMCR_ETPS 12 +#define STM_TIM23_SMCR_ETPS_OFF 0 +#define STM_TIM23_SMCR_ETPS_DIV_2 1 +#define STM_TIM23_SMCR_ETPS_DIV_4 2 +#define STM_TIM23_SMCR_ETPS_DIV_8 3 +#define STM_TIM23_SMCR_ETPS_MASK 3 +#define STM_TIM23_SMCR_ETF 8 +#define STM_TIM23_SMCR_ETF_NONE 0 +#define STM_TIM23_SMCR_ETF_INT_N_2 1 +#define STM_TIM23_SMCR_ETF_INT_N_4 2 +#define STM_TIM23_SMCR_ETF_INT_N_8 3 +#define STM_TIM23_SMCR_ETF_DTS_2_N_6 4 +#define STM_TIM23_SMCR_ETF_DTS_2_N_8 5 +#define STM_TIM23_SMCR_ETF_DTS_4_N_6 6 +#define STM_TIM23_SMCR_ETF_DTS_4_N_8 7 +#define STM_TIM23_SMCR_ETF_DTS_8_N_6 8 +#define STM_TIM23_SMCR_ETF_DTS_8_N_8 9 +#define STM_TIM23_SMCR_ETF_DTS_16_N_5 10 +#define STM_TIM23_SMCR_ETF_DTS_16_N_6 11 +#define STM_TIM23_SMCR_ETF_DTS_16_N_8 12 +#define STM_TIM23_SMCR_ETF_DTS_32_N_5 13 +#define STM_TIM23_SMCR_ETF_DTS_32_N_6 14 +#define STM_TIM23_SMCR_ETF_DTS_32_N_8 15 +#define STM_TIM23_SMCR_ETF_MASK 15 +#define STM_TIM23_SMCR_MSM 7 +#define STM_TIM23_SMCR_TS 4 +#define STM_TIM23_SMCR_TS_ITR0 0 +#define STM_TIM23_SMCR_TS_ITR1 1 +#define STM_TIM23_SMCR_TS_ITR2 2 +#define STM_TIM23_SMCR_TS_ITR3 3 +#define STM_TIM23_SMCR_TS_TI1F_ED 4 +#define STM_TIM23_SMCR_TS_TI1FP1 5 +#define STM_TIM23_SMCR_TS_TI2FP2 6 +#define STM_TIM23_SMCR_TS_ETRF 7 +#define STM_TIM23_SMCR_TS_MASK 7 +#define STM_TIM23_SMCR_OCCS 3 +#define STM_TIM23_SMCR_SMS 0 +#define STM_TIM23_SMCR_SMS_DISABLE 0 +#define STM_TIM23_SMCR_SMS_ENCODER_MODE_1 1 +#define STM_TIM23_SMCR_SMS_ENCODER_MODE_2 2 +#define STM_TIM23_SMCR_SMS_ENCODER_MODE_3 3 +#define STM_TIM23_SMCR_SMS_RESET_MODE 4 +#define STM_TIM23_SMCR_SMS_GATED_MODE 5 +#define STM_TIM23_SMCR_SMS_TRIGGER_MODE 6 +#define STM_TIM23_SMCR_SMS_EXTERNAL_CLOCK 7 +#define STM_TIM23_SMCR_SMS_MASK 7 + +#define STM_TIM23_SR_CC4OF 12 +#define STM_TIM23_SR_CC3OF 11 +#define STM_TIM23_SR_CC2OF 10 +#define STM_TIM23_SR_CC1OF 9 +#define STM_TIM23_SR_TIF 6 +#define STM_TIM23_SR_CC4IF 4 +#define STM_TIM23_SR_CC3IF 3 +#define STM_TIM23_SR_CC2IF 2 +#define STM_TIM23_SR_CC1IF 1 +#define STM_TIM23_SR_UIF 0 + +#define STM_TIM23_EGR_TG 6 +#define STM_TIM23_EGR_CC4G 4 +#define STM_TIM23_EGR_CC3G 3 +#define STM_TIM23_EGR_CC2G 2 +#define STM_TIM23_EGR_CC1G 1 +#define STM_TIM23_EGR_UG 0 + +#define STM_TIM23_CCMR1_OC2CE 15 +#define STM_TIM23_CCMR1_OC2M 12 +#define STM_TIM23_CCMR1_OC2M_FROZEN 0 +#define STM_TIM23_CCMR1_OC2M_SET_HIGH_ON_MATCH 1 +#define STM_TIM23_CCMR1_OC2M_SET_LOW_ON_MATCH 2 +#define STM_TIM23_CCMR1_OC2M_TOGGLE 3 +#define STM_TIM23_CCMR1_OC2M_FORCE_LOW 4 +#define STM_TIM23_CCMR1_OC2M_FORCE_HIGH 5 +#define STM_TIM23_CCMR1_OC2M_PWM_MODE_1 6 +#define STM_TIM23_CCMR1_OC2M_PWM_MODE_2 7 +#define STM_TIM23_CCMR1_OC2M_MASK 7 +#define STM_TIM23_CCMR1_OC2PE 11 +#define STM_TIM23_CCMR1_OC2FE 10 +#define STM_TIM23_CCMR1_CC2S 8 +#define STM_TIM23_CCMR1_CC2S_OUTPUT 0 +#define STM_TIM23_CCMR1_CC2S_INPUT_TI2 1 +#define STM_TIM23_CCMR1_CC2S_INPUT_TI1 2 +#define STM_TIM23_CCMR1_CC2S_INPUT_TRC 3 +#define STM_TIM23_CCMR1_CC2S_MASK 3 + +#define STM_TIM23_CCMR1_OC1CE 7 +#define STM_TIM23_CCMR1_OC1M 4 +#define STM_TIM23_CCMR1_OC1M_FROZEN 0 +#define STM_TIM23_CCMR1_OC1M_SET_HIGH_ON_MATCH 1 +#define STM_TIM23_CCMR1_OC1M_SET_LOW_ON_MATCH 2 +#define STM_TIM23_CCMR1_OC1M_TOGGLE 3 +#define STM_TIM23_CCMR1_OC1M_FORCE_LOW 4 +#define STM_TIM23_CCMR1_OC1M_FORCE_HIGH 5 +#define STM_TIM23_CCMR1_OC1M_PWM_MODE_1 6 +#define STM_TIM23_CCMR1_OC1M_PWM_MODE_2 7 +#define STM_TIM23_CCMR1_OC1M_MASK 7 +#define STM_TIM23_CCMR1_OC1PE 11 +#define STM_TIM23_CCMR1_OC1FE 2 +#define STM_TIM23_CCMR1_CC1S 0 +#define STM_TIM23_CCMR1_CC1S_OUTPUT 0 +#define STM_TIM23_CCMR1_CC1S_INPUT_TI1 1 +#define STM_TIM23_CCMR1_CC1S_INPUT_TI2 2 +#define STM_TIM23_CCMR1_CC1S_INPUT_TRC 3 +#define STM_TIM23_CCMR1_CC1S_MASK 3 + +#define STM_TIM23_CCMR2_OC4CE 15 +#define STM_TIM23_CCMR2_OC4M 12 +#define STM_TIM23_CCMR2_OC4M_FROZEN 0 +#define STM_TIM23_CCMR2_OC4M_SET_HIGH_ON_MATCH 1 +#define STM_TIM23_CCMR2_OC4M_SET_LOW_ON_MATCH 2 +#define STM_TIM23_CCMR2_OC4M_TOGGLE 3 +#define STM_TIM23_CCMR2_OC4M_FORCE_LOW 4 +#define STM_TIM23_CCMR2_OC4M_FORCE_HIGH 5 +#define STM_TIM23_CCMR2_OC4M_PWM_MODE_1 6 +#define STM_TIM23_CCMR2_OC4M_PWM_MODE_2 7 +#define STM_TIM23_CCMR2_OC4M_MASK 7 +#define STM_TIM23_CCMR2_OC4PE 11 +#define STM_TIM23_CCMR2_OC4FE 10 +#define STM_TIM23_CCMR2_CC4S 8 +#define STM_TIM23_CCMR2_CC4S_OUTPUT 0 +#define STM_TIM23_CCMR2_CC4S_INPUT_TI4 1 +#define STM_TIM23_CCMR2_CC4S_INPUT_TI3 2 +#define STM_TIM23_CCMR2_CC4S_INPUT_TRC 3 +#define STM_TIM23_CCMR2_CC4S_MASK 3 + +#define STM_TIM23_CCMR2_OC3CE 7 +#define STM_TIM23_CCMR2_OC3M 4 +#define STM_TIM23_CCMR2_OC3M_FROZEN 0 +#define STM_TIM23_CCMR2_OC3M_SET_HIGH_ON_MATCH 1 +#define STM_TIM23_CCMR2_OC3M_SET_LOW_ON_MATCH 2 +#define STM_TIM23_CCMR2_OC3M_TOGGLE 3 +#define STM_TIM23_CCMR2_OC3M_FORCE_LOW 4 +#define STM_TIM23_CCMR2_OC3M_FORCE_HIGH 5 +#define STM_TIM23_CCMR2_OC3M_PWM_MODE_1 6 +#define STM_TIM23_CCMR2_OC3M_PWM_MODE_2 7 +#define STM_TIM23_CCMR2_OC3M_MASK 7 +#define STM_TIM23_CCMR2_OC3PE 11 +#define STM_TIM23_CCMR2_OC3FE 2 +#define STM_TIM23_CCMR2_CC3S 0 +#define STM_TIM23_CCMR2_CC3S_OUTPUT 0 +#define STM_TIM23_CCMR2_CC3S_INPUT_TI3 1 +#define STM_TIM23_CCMR2_CC3S_INPUT_TI4 2 +#define STM_TIM23_CCMR2_CC3S_INPUT_TRC 3 +#define STM_TIM23_CCMR2_CC3S_MASK 3 + +#define STM_TIM23_CCER_CC4NP 15 +#define STM_TIM23_CCER_CC4P 13 +#define STM_TIM23_CCER_CC4E 12 +#define STM_TIM23_CCER_CC3NP 11 +#define STM_TIM23_CCER_CC3P 9 +#define STM_TIM23_CCER_CC3E 8 +#define STM_TIM23_CCER_CC2NP 7 +#define STM_TIM23_CCER_CC2P 5 +#define STM_TIM23_CCER_CC2E 4 +#define STM_TIM23_CCER_CC1NP 3 +#define STM_TIM23_CCER_CC1P 1 +#define STM_TIM23_CCER_CC1E 0 struct stm_usb { struct { -- cgit v1.2.3 From 0f227683e29062224a612c4a2ab5c8b2fc166059 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 2 Apr 2016 22:40:23 -0700 Subject: altos: Add detherm product Signed-off-by: Keith Packard --- src/detherm/.gitignore | 2 + src/detherm/Makefile | 81 ++++++++++++++++++++++++++++ src/detherm/ao_detherm.c | 48 +++++++++++++++++ src/detherm/ao_pins.h | 105 ++++++++++++++++++++++++++++++++++++ src/detherm/flash-loader/.gitignore | 2 + src/detherm/flash-loader/Makefile | 8 +++ src/detherm/flash-loader/ao_pins.h | 36 +++++++++++++ 7 files changed, 282 insertions(+) create mode 100644 src/detherm/.gitignore create mode 100644 src/detherm/Makefile create mode 100644 src/detherm/ao_detherm.c create mode 100644 src/detherm/ao_pins.h create mode 100644 src/detherm/flash-loader/.gitignore create mode 100644 src/detherm/flash-loader/Makefile create mode 100644 src/detherm/flash-loader/ao_pins.h (limited to 'src') diff --git a/src/detherm/.gitignore b/src/detherm/.gitignore new file mode 100644 index 00000000..4f11d9a0 --- /dev/null +++ b/src/detherm/.gitignore @@ -0,0 +1,2 @@ +ao_product.h +detherm-* diff --git a/src/detherm/Makefile b/src/detherm/Makefile new file mode 100644 index 00000000..35df6c96 --- /dev/null +++ b/src/detherm/Makefile @@ -0,0 +1,81 @@ +# +# AltOS build +# +# + +include ../stmf0/Makefile.defs + +INC = \ + ao.h \ + ao_arch.h \ + ao_arch_funcs.h \ + ao_pins.h \ + ao_product.h \ + ao_task.h \ + stm32f0.h + +# +# Common AltOS sources +# +ALTOS_SRC = \ + ao_interrupt.c \ + ao_timer.c \ + ao_panic.c \ + ao_mutex.c \ + ao_dma_stm.c \ + ao_usb_stm.c \ + ao_spi_stm.c \ + ao_exti_stm.c \ + ao_stdio.c \ + ao_led.c \ + ao_log.c \ + ao_log_mini.c \ + ao_sample.c \ + ao_data.c \ + ao_kalman.c \ + ao_flight.c \ + ao_report.c \ + ao_storage.c \ + ao_m25.c \ + ao_romconfig.c \ + ao_boot_chain.c \ + ao_ms5607.c \ + ao_convert_pa.c \ + ao_pwm.c \ + ao_task.c \ + ao_config.c \ + ao_cmd.c \ + ao_product.c + +PRODUCT=Detherm-v1.0 +PRODUCT_DEF=-DDETHERM_V_1_0 +IDPRODUCT=0x0013 + +CFLAGS = $(PRODUCT_DEF) $(STMF0_CFLAGS) -g -Os + +PROGNAME=detherm-v1.0 +PROG=$(PROGNAME)-$(VERSION).elf +HEX=$(PROGNAME)-$(VERSION).ihx + +SRC=$(ALTOS_SRC) ao_detherm.c +OBJ=$(SRC:.c=.o) + +all: $(PROG) $(HEX) + +$(PROG): Makefile $(OBJ) altos.ld + $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(OBJ) $(LIBS) + +ao_product.h: ao-make-product.5c ../Version + $(call quiet,NICKLE,$<) $< -m altusmetrum.org -i $(IDPRODUCT) -p $(PRODUCT) -v $(VERSION) -o $@ + +$(OBJ): $(INC) + +distclean: clean + +clean: + rm -f *.o $(PROGNAME)-*.elf $(PROGNAME)-*.ihx + rm -f ao_product.h + +install: + +uninstall: diff --git a/src/detherm/ao_detherm.c b/src/detherm/ao_detherm.c new file mode 100644 index 00000000..cc013753 --- /dev/null +++ b/src/detherm/ao_detherm.c @@ -0,0 +1,48 @@ +/* + * Copyright © 2014 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 main(void) +{ + ao_led_init(LEDS_AVAILABLE); + + ao_led_on(AO_LED_RED); + + ao_clock_init(); + ao_task_init(); + ao_timer_init(); + ao_exti_init(); + + ao_dma_init(); + ao_spi_init(); + ao_usb_init(); + + ao_storage_init(); +// ao_flight_init(); +// ao_ms5607_init(); + ao_pwm_init(); + ao_log_init(); + ao_report_init(); + ao_config_init(); + + ao_cmd_init(); + + ao_start_scheduler(); +} diff --git a/src/detherm/ao_pins.h b/src/detherm/ao_pins.h new file mode 100644 index 00000000..9b623627 --- /dev/null +++ b/src/detherm/ao_pins.h @@ -0,0 +1,105 @@ +/* + * Copyright © 2015 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 LED_PORT_ENABLE STM_RCC_AHBENR_IOPAEN +#define LED_PORT (&stm_gpioa) +#define LED_PIN_RED 3 +#define AO_LED_RED (1 << LED_PIN_RED) + +#define LEDS_AVAILABLE (AO_LED_RED) + +#define HAS_BEEP 0 + +/* 48MHz clock based on USB */ +//#define AO_HSI48 1 +#define AO_HSE 16000000 +#define AO_RCC_CFGR_PLLMUL STM_RCC_CFGR_PLLMUL_3 +#define AO_PLLMUL 3 +#define AO_PLLDIV 1 + +/* HCLK = 48MHz */ +#define AO_AHB_PRESCALER 1 +#define AO_RCC_CFGR_HPRE_DIV STM_RCC_CFGR_HPRE_DIV_1 + +/* APB = 48MHz */ +#define AO_APB_PRESCALER 1 +#define AO_RCC_CFGR_PPRE_DIV STM_RCC_CFGR_PPRE_DIV_1 + +#define HAS_USB 1 +#define AO_USB_DIRECTIO 0 +#define AO_PA11_PA12_RMP 1 + +#define IS_FLASH_LOADER 0 + +#define AO_DATA_RING 16 + +#define HAS_ADC 0 +#define HAS_ACCEL 0 +#define HAS_GPS 0 +#define HAS_RADIO 0 +#define HAS_FLIGHT 1 +#define HAS_EEPROM 1 +#define HAS_LOG 1 + +#define AO_LOG_FORMAT AO_LOG_FORMAT_DETHERM + +#define USE_INTERNAL_FLASH 0 + +/* SPI */ +#define HAS_SPI_1 1 +#define HAS_SPI_2 0 +#define SPI_1_PA5_PA6_PA7 1 +#define SPI_1_PB3_PB4_PB5 1 +#define SPI_1_OSPEEDR STM_OSPEEDR_HIGH + +/* MS5607 */ +#define HAS_MS5607 1 + +#define AO_MS5607_CS_PORT (&stm_gpiob) +#define AO_MS5607_CS_PIN 6 +#define AO_MS5607_SPI_INDEX AO_SPI_1_PB3_PB4_PB5 +#define AO_MS5607_MISO_PORT (&stm_gpiob) +#define AO_MS5607_MISO_PIN 4 + +/* Flash */ + +#define M25_MAX_CHIPS 1 +#define AO_M25_SPI_CS_PORT (&stm_gpioa) +#define AO_M25_SPI_CS_MASK (1 << 4) +#define AO_M25_SPI_BUS AO_SPI_1_PA5_PA6_PA7 + +/* PWM */ + +#define NUM_PWM 1 +#define AO_PWM_TIMER (&stm_tim3) +#define AO_PWM_0_GPIO (&stm_gpiob) +#define AO_PWM_0_PIN 1 +#define AO_PWM_0_CH 4 +#define PWM_MAX 20000 +#define AO_PWM_TIMER_ENABLE STM_RCC_APB1ENR_TIM3EN +#define AO_PWM_TIMER_SCALE 32 + +/* Motor */ + +#define AO_MOTOR_DIR_GPIO (&stm_gpiob) +#define AO_MOTOR_DIR_PIN 0 +#define AO_MOTOR_SPEED_PWM 0 + +#endif /* _AO_PINS_H_ */ diff --git a/src/detherm/flash-loader/.gitignore b/src/detherm/flash-loader/.gitignore new file mode 100644 index 00000000..d0d4657e --- /dev/null +++ b/src/detherm/flash-loader/.gitignore @@ -0,0 +1,2 @@ +ao_product.h +detherm* diff --git a/src/detherm/flash-loader/Makefile b/src/detherm/flash-loader/Makefile new file mode 100644 index 00000000..5210aa09 --- /dev/null +++ b/src/detherm/flash-loader/Makefile @@ -0,0 +1,8 @@ +# +# AltOS flash loader build +# +# + +TOPDIR=../.. +HARDWARE=detherm-v1.0 +include $(TOPDIR)/stmf0/Makefile-flash.defs diff --git a/src/detherm/flash-loader/ao_pins.h b/src/detherm/flash-loader/ao_pins.h new file mode 100644 index 00000000..570800ca --- /dev/null +++ b/src/detherm/flash-loader/ao_pins.h @@ -0,0 +1,36 @@ +/* + * Copyright © 2013 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#ifndef _AO_PINS_H_ +#define _AO_PINS_H_ + +#include + +/* Pin 5 on debug connector */ + +#define AO_BOOT_PIN 1 +#define AO_BOOT_APPLICATION_GPIO stm_gpioa +#define AO_BOOT_APPLICATION_PIN 15 +#define AO_BOOT_APPLICATION_VALUE 1 +#define AO_BOOT_APPLICATION_MODE AO_EXTI_MODE_PULL_UP + +/* USB */ +#define HAS_USB 1 +#define AO_USB_DIRECTIO 0 +#define AO_PA11_PA12_RMP 1 + +#endif /* _AO_PINS_H_ */ -- cgit v1.2.3 From 097c156b13ae975c742f294b46429e8ff14c365b Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 2 Apr 2016 22:41:06 -0700 Subject: altos/stmf0: Add pwm and exti drivers Signed-off-by: Keith Packard --- src/stmf0/ao_exti_stm.c | 149 +++++++++++++++++++++++++++++++++ src/stmf0/ao_pwm.c | 214 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 363 insertions(+) create mode 100644 src/stmf0/ao_exti_stm.c create mode 100644 src/stmf0/ao_pwm.c (limited to 'src') diff --git a/src/stmf0/ao_exti_stm.c b/src/stmf0/ao_exti_stm.c new file mode 100644 index 00000000..906392e6 --- /dev/null +++ b/src/stmf0/ao_exti_stm.c @@ -0,0 +1,149 @@ +/* + * Copyright © 2016 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 void (*ao_exti_callback[16])(void); + +uint32_t ao_last_exti; + +static void ao_exti_range_isr(uint8_t first, uint8_t last, uint16_t mask) { + uint16_t pending = (ao_last_exti = stm_exti.pr) & mask; + uint8_t pin; + static uint16_t last_mask; + static uint8_t last_pin; + + if (pending == last_mask) { + stm_exti.pr = last_mask; + (*ao_exti_callback[last_pin])(); + return; + } + stm_exti.pr = pending; + for (pin = first; pin <= last; pin++) + if ((pending & ((uint32_t) 1 << pin)) && ao_exti_callback[pin]) { + last_mask = (1 << pin); + last_pin = pin; + (*ao_exti_callback[pin])(); + } +} + +void stm_exti0_1_isr(void) { ao_exti_range_isr(0, 1, 0x0003); } +void stm_exti2_3_isr(void) { ao_exti_range_isr(2, 3, 0x000c); } +void stm_exti4_15_isr(void) { ao_exti_range_isr(4, 15, 0xfff0); } + +void +ao_exti_setup (struct stm_gpio *gpio, uint8_t pin, uint8_t mode, void (*callback)(void)) { + uint32_t mask = 1 << pin; + uint32_t pupdr; + uint8_t irq; + uint8_t prio; + + ao_exti_callback[pin] = callback; + + /* configure gpio to interrupt routing */ + stm_exticr_set(gpio, pin); + + if (!(mode & AO_EXTI_PIN_NOCONFIGURE)) { + /* configure pin as input, setting selected pull-up/down mode */ + stm_moder_set(gpio, pin, STM_MODER_INPUT); + switch (mode & (AO_EXTI_MODE_PULL_UP|AO_EXTI_MODE_PULL_DOWN)) { + case 0: + default: + pupdr = STM_PUPDR_NONE; + break; + case AO_EXTI_MODE_PULL_UP: + pupdr = STM_PUPDR_PULL_UP; + break; + case AO_EXTI_MODE_PULL_DOWN: + pupdr = STM_PUPDR_PULL_DOWN; + break; + } + stm_pupdr_set(gpio, pin, pupdr); + } + + /* Set interrupt mask and rising/falling mode */ + stm_exti.imr &= ~mask; + if (mode & AO_EXTI_MODE_RISING) + stm_exti.rtsr |= mask; + else + stm_exti.rtsr &= ~mask; + if (mode & AO_EXTI_MODE_FALLING) + stm_exti.ftsr |= mask; + else + stm_exti.ftsr &= ~mask; + + if (pin <= 1) + irq = STM_ISR_EXTI0_1_POS; + else if (pin <= 3) + irq = STM_ISR_EXTI2_3_POS; + else + irq = STM_ISR_EXTI4_15_POS; + + /* Set priority */ + prio = AO_STM_NVIC_MED_PRIORITY; + if (mode & AO_EXTI_PRIORITY_LOW) + prio = AO_STM_NVIC_LOW_PRIORITY; + else if (mode & AO_EXTI_PRIORITY_HIGH) + prio = AO_STM_NVIC_HIGH_PRIORITY; + + stm_nvic_set_priority(irq, prio); + stm_nvic_set_enable(irq); +} + +void +ao_exti_set_mode(struct stm_gpio *gpio, uint8_t pin, uint8_t mode) { + (void) gpio; + + uint32_t mask = 1 << pin; + + if (mode & AO_EXTI_MODE_RISING) + stm_exti.rtsr |= mask; + else + stm_exti.rtsr &= ~mask; + if (mode & AO_EXTI_MODE_FALLING) + stm_exti.ftsr |= mask; + else + stm_exti.ftsr &= ~mask; +} + +void +ao_exti_set_callback(struct stm_gpio *gpio, uint8_t pin, void (*callback)()) { + (void) gpio; + ao_exti_callback[pin] = callback; +} + +void +ao_exti_enable(struct stm_gpio *gpio, uint8_t pin) { + uint32_t mask = (1 << pin); + (void) gpio; + stm_exti.pr = mask; + stm_exti.imr |= (1 << pin); +} + +void +ao_exti_disable(struct stm_gpio *gpio, uint8_t pin) { + uint32_t mask = (1 << pin); + (void) gpio; + stm_exti.imr &= ~mask; + stm_exti.pr = mask; +} + +void +ao_exti_init(void) +{ +} diff --git a/src/stmf0/ao_pwm.c b/src/stmf0/ao_pwm.c new file mode 100644 index 00000000..c1e157f5 --- /dev/null +++ b/src/stmf0/ao_pwm.c @@ -0,0 +1,214 @@ +/* + * Copyright © 2016 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include "ao.h" +#include "ao_pwm.h" + +static uint8_t pwm_running; + +static uint16_t pwm_value[NUM_PWM]; + +static void +ao_pwm_up(void) +{ + if (pwm_running++ == 0) { + struct stm_tim23 *tim = AO_PWM_TIMER; + + tim->ccr1 = 0; + tim->ccr2 = 0; + tim->ccr3 = 0; + tim->ccr4 = 0; + tim->arr = PWM_MAX - 1; /* turn on the timer */ + tim->cr1 = ((STM_TIM23_CR1_CKD_1 << STM_TIM23_CR1_CKD) | + (0 << STM_TIM23_CR1_ARPE) | + (STM_TIM23_CR1_CMS_EDGE << STM_TIM23_CR1_CMS) | + (STM_TIM23_CR1_DIR_UP << STM_TIM23_CR1_DIR) | + (0 << STM_TIM23_CR1_OPM) | + (0 << STM_TIM23_CR1_URS) | + (0 << STM_TIM23_CR1_UDIS) | + (1 << STM_TIM23_CR1_CEN)); + + /* Set the timer running */ + tim->egr = (1 << STM_TIM23_EGR_UG); + } +} + +static void +ao_pwm_down(void) +{ + if (--pwm_running == 0) { + struct stm_tim23 *tim = AO_PWM_TIMER; + + tim->arr = 0; + tim->cr1 = ((STM_TIM23_CR1_CKD_1 << STM_TIM23_CR1_CKD) | + (0 << STM_TIM23_CR1_ARPE) | + (STM_TIM23_CR1_CMS_EDGE << STM_TIM23_CR1_CMS) | + (STM_TIM23_CR1_DIR_UP << STM_TIM23_CR1_DIR) | + (0 << STM_TIM23_CR1_OPM) | + (0 << STM_TIM23_CR1_URS) | + (0 << STM_TIM23_CR1_UDIS) | + (0 << STM_TIM23_CR1_CEN)); + + /* Stop the timer */ + tim->egr = (1 << STM_TIM23_EGR_UG); + } +} + +void +ao_pwm_set(uint8_t pwm, uint16_t value) +{ + struct stm_tim23 *tim = AO_PWM_TIMER; + uint8_t ch = AO_PWM_0_CH; + + if (value > PWM_MAX) + value = PWM_MAX; + if (value != 0) { + if (pwm_value[pwm] == 0) + ao_pwm_up(); + } +#if NUM_PWM > 1 + switch (pwm) { + case 0: + ch = AO_PWM_0_CH; + break; + case 1: + ch = AO_PWM_0_CH; + break; +#if NUM_PWM > 2 + case 2: + ch = AO_PWM_0_CH; + break; +#endif +#if NUM_PWM > 3 + case 3: + ch = AO_PWM_0_CH; + break; +#endif + } +#endif + + switch (ch) { + case 1: + tim->ccr1 = value; + break; + case 2: + tim->ccr2 = value; + break; + case 3: + tim->ccr3 = value; + break; + case 4: + tim->ccr4 = value; + break; + } + if (value == 0) { + if (pwm_value[pwm] != 0) + ao_pwm_down(); + } + pwm_value[pwm] = value; +} + +static void +ao_pwm_cmd(void) +{ + uint8_t ch; + uint16_t val; + + ao_cmd_decimal(); + ch = ao_cmd_lex_u32; + ao_cmd_decimal(); + val = ao_cmd_lex_u32; + if (ao_cmd_status != ao_cmd_success) + return; + + printf("Set channel %d to %d\n", ch, val); + ao_pwm_set(ch, val); +} + +static const struct ao_cmds ao_pwm_cmds[] = { + { ao_pwm_cmd, "P \0Set PWM ch to val" }, + { 0, NULL }, +}; + +void +ao_pwm_init(void) +{ + struct stm_tim23 *tim = AO_PWM_TIMER; + + stm_rcc.apb1enr |= (1 << AO_PWM_TIMER_ENABLE); + + tim->cr1 = 0; + tim->psc = AO_PWM_TIMER_SCALE - 1; + tim->cnt = 0; + tim->ccer = ((1 << STM_TIM23_CCER_CC1E) | + (0 << STM_TIM23_CCER_CC1P) | + (1 << STM_TIM23_CCER_CC2E) | + (0 << STM_TIM23_CCER_CC2P) | + (1 << STM_TIM23_CCER_CC3E) | + (0 << STM_TIM23_CCER_CC3P) | + (1 << STM_TIM23_CCER_CC4E) | + (0 << STM_TIM23_CCER_CC4P)); + + tim->ccmr1 = ((0 << STM_TIM23_CCMR1_OC2CE) | + (STM_TIM23_CCMR1_OC2M_PWM_MODE_1 << STM_TIM23_CCMR1_OC2M) | + (0 << STM_TIM23_CCMR1_OC2PE) | + (0 << STM_TIM23_CCMR1_OC2FE) | + (STM_TIM23_CCMR1_CC2S_OUTPUT << STM_TIM23_CCMR1_CC2S) | + + (0 << STM_TIM23_CCMR1_OC1CE) | + (STM_TIM23_CCMR1_OC1M_PWM_MODE_1 << STM_TIM23_CCMR1_OC1M) | + (0 << STM_TIM23_CCMR1_OC1PE) | + (0 << STM_TIM23_CCMR1_OC1FE) | + (STM_TIM23_CCMR1_CC1S_OUTPUT << STM_TIM23_CCMR1_CC1S)); + + + tim->ccmr2 = ((0 << STM_TIM23_CCMR2_OC4CE) | + (STM_TIM23_CCMR2_OC4M_PWM_MODE_1 << STM_TIM23_CCMR2_OC4M) | + (0 << STM_TIM23_CCMR2_OC4PE) | + (0 << STM_TIM23_CCMR2_OC4FE) | + (STM_TIM23_CCMR2_CC4S_OUTPUT << STM_TIM23_CCMR2_CC4S) | + + (0 << STM_TIM23_CCMR2_OC3CE) | + (STM_TIM23_CCMR2_OC3M_PWM_MODE_1 << STM_TIM23_CCMR2_OC3M) | + (0 << STM_TIM23_CCMR2_OC3PE) | + (0 << STM_TIM23_CCMR2_OC3FE) | + (STM_TIM23_CCMR2_CC3S_OUTPUT << STM_TIM23_CCMR2_CC3S)); + tim->egr = 0; + + tim->sr = 0; + tim->dier = 0; + tim->smcr = 0; + tim->cr2 = ((0 << STM_TIM23_CR2_TI1S) | + (STM_TIM23_CR2_MMS_RESET<< STM_TIM23_CR2_MMS) | + (0 << STM_TIM23_CR2_CCDS)); + + stm_afr_set(AO_PWM_0_GPIO, AO_PWM_0_PIN, STM_AFR_AF1); + stm_ospeedr_set(AO_PWM_0_GPIO, AO_PWM_0_PIN, STM_OSPEEDR_MEDIUM); +#if NUM_PWM > 1 + stm_afr_set(AO_PWM_1_GPIO, AO_PWM_1_PIN, STM_AFR_AF1); + stm_ospeedr_set(AO_PWM_1_GPIO, AO_PWM_1_PIN, STM_OSPEEDR_MEDIUM); +#endif +#if NUM_PWM > 2 + stm_afr_set(AO_PWM_2_GPIO, AO_PWM_2_PIN, STM_AFR_AF1); + stm_ospeedr_set(AO_PWM_2_GPIO, AO_PWM_2_PIN, STM_OSPEEDR_MEDIUM); +#endif +#if NUM_PWM > 3 + stm_afr_set(AO_PWM_3_GPIO, AO_PWM_3_PIN, STM_AFR_AF1); + stm_ospeedr_set(AO_PWM_3_GPIO, AO_PWM_3_PIN, STM_OSPEEDR_MEDIUM); +#endif + ao_cmd_register(&ao_pwm_cmds[0]); +} -- cgit v1.2.3 From e3f0c5eb8e5d57cbd8882587477d1381e2a83226 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 17 Dec 2015 19:27:42 -0800 Subject: altos: Add ao_gpi_set/clr_bits functions These set or clear a group of bits in a single GPIO register all together. Signed-off-by: Keith Packard --- src/cc1111/ao_arch_funcs.h | 4 +++- src/stm/ao_arch_funcs.h | 5 +++++ src/stm/stm32l.h | 10 ++++++++++ 3 files changed, 18 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/cc1111/ao_arch_funcs.h b/src/cc1111/ao_arch_funcs.h index ea340dfd..1eb506cd 100644 --- a/src/cc1111/ao_arch_funcs.h +++ b/src/cc1111/ao_arch_funcs.h @@ -146,4 +146,6 @@ ao_spi_init(void); #define ao_enable_output(port,bit,pin,v) cc1111_enable_output(port,token_evaluator(port,DIR), token_evaluator(port,SEL), pin, bit, v) #define ao_gpio_set(port, bit, pin, v) ((pin) = (v)) #define ao_gpio_get(port, bit, pin) (pin) - +#define ao_gpio_get_bits(port) (port) +#define ao_gpio_set_bits(port, bits) ((port) |= bits) +#define ao_gpio_clr_bits(port, bits) ((port) &= ~bits) diff --git a/src/stm/ao_arch_funcs.h b/src/stm/ao_arch_funcs.h index 087e00d9..f1d17ed1 100644 --- a/src/stm/ao_arch_funcs.h +++ b/src/stm/ao_arch_funcs.h @@ -177,6 +177,11 @@ ao_spi_try_get_mask(struct stm_gpio *reg, uint16_t mask, uint8_t bus, uint32_t s #define ao_gpio_get(port, bit, pin) stm_gpio_get(port, bit) +#define ao_gpio_set_bits(port, bits) stm_gpio_set_bits(port, bits) + +#define ao_gpio_clr_bits(port, bits) stm_gpio_clr_bits(port, bits); + + #define ao_enable_output(port,bit,pin,v) do { \ ao_enable_port(port); \ ao_gpio_set(port, bit, pin, v); \ diff --git a/src/stm/stm32l.h b/src/stm/stm32l.h index 01afedc6..0b6b2798 100644 --- a/src/stm/stm32l.h +++ b/src/stm/stm32l.h @@ -166,6 +166,16 @@ stm_gpio_set(struct stm_gpio *gpio, int pin, uint8_t value) { gpio->bsrr = ((uint32_t) (value ^ 1) << (pin + 16)) | ((uint32_t) value << pin); } +static inline void +stm_gpio_set_bits(struct stm_gpio *gpio, uint16_t bits) { + gpio->bsrr = bits; +} + +static inline void +stm_gpio_clr_bits(struct stm_gpio *gpio, uint16_t bits) { + gpio->bsrr = ((uint32_t) bits) << 16; +} + static inline uint8_t stm_gpio_get(struct stm_gpio *gpio, int pin) { return (gpio->idr >> pin) & 1; -- cgit v1.2.3 From 8da29480a2fdf890d553b30eab58fc884210c1a5 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 23 Dec 2015 23:15:16 -0800 Subject: altos: Add easy mini plotting helper in test code Signed-off-by: Keith Packard --- src/test/plotem | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100755 src/test/plotem (limited to 'src') diff --git a/src/test/plotem b/src/test/plotem new file mode 100755 index 00000000..8bc392cf --- /dev/null +++ b/src/test/plotem @@ -0,0 +1,10 @@ +gnuplot -persist << EOF +set ylabel "altitude (m)" +set y2label "error" +set xlabel "time (s)" +set xtics border out nomirror +set ytics border out nomirror +set y2tics border out nomirror +plot "$1" using 1:3 with lines axes x1y1 title "raw height",\ +"$1" using 1:21 with lines axes x1y2 title "error" +EOF -- cgit v1.2.3 From cfb91ec7ef6ef485d813af96a0f206bb7a2204dd Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 5 Apr 2016 22:03:37 -0700 Subject: altos/detherm: Add ms5607 to detherm Signed-off-by: Keith Packard --- src/detherm/ao_detherm.c | 2 +- src/detherm/ao_pins.h | 6 ++++-- src/drivers/ao_ms5607.c | 6 +++++- src/stmf0/ao_arch_funcs.h | 22 +++++++++++----------- 4 files changed, 21 insertions(+), 15 deletions(-) (limited to 'src') diff --git a/src/detherm/ao_detherm.c b/src/detherm/ao_detherm.c index cc013753..64dee586 100644 --- a/src/detherm/ao_detherm.c +++ b/src/detherm/ao_detherm.c @@ -35,8 +35,8 @@ void main(void) ao_usb_init(); ao_storage_init(); + ao_ms5607_init(); // ao_flight_init(); -// ao_ms5607_init(); ao_pwm_init(); ao_log_init(); ao_report_init(); diff --git a/src/detherm/ao_pins.h b/src/detherm/ao_pins.h index 9b623627..8cd4a9c4 100644 --- a/src/detherm/ao_pins.h +++ b/src/detherm/ao_pins.h @@ -72,11 +72,13 @@ /* MS5607 */ #define HAS_MS5607 1 -#define AO_MS5607_CS_PORT (&stm_gpiob) -#define AO_MS5607_CS_PIN 6 +#define AO_MS5607_CS_PORT (&stm_gpioa) +#define AO_MS5607_CS_PIN 0 #define AO_MS5607_SPI_INDEX AO_SPI_1_PB3_PB4_PB5 #define AO_MS5607_MISO_PORT (&stm_gpiob) #define AO_MS5607_MISO_PIN 4 +#define AO_MS5607_PRIVATE_PINS 1 +#define AO_MS5607_SPI_SPEED AO_SPI_SPEED_6MHz /* Flash */ diff --git a/src/drivers/ao_ms5607.c b/src/drivers/ao_ms5607.c index 6098699e..ef31882e 100644 --- a/src/drivers/ao_ms5607.c +++ b/src/drivers/ao_ms5607.c @@ -24,9 +24,13 @@ __xdata struct ao_ms5607_prom ao_ms5607_prom; static __xdata uint8_t ms5607_configured; +#ifndef AO_MS5607_SPI_SPEED +#define AO_MS5607_SPI_SPEED AO_SPI_SPEED_FAST +#endif + static void ao_ms5607_start(void) { - ao_spi_get_bit(AO_MS5607_CS_PORT, AO_MS5607_CS_PIN, AO_MS5607_CS, AO_MS5607_SPI_INDEX, AO_SPI_SPEED_FAST); + ao_spi_get_bit(AO_MS5607_CS_PORT, AO_MS5607_CS_PIN, AO_MS5607_CS, AO_MS5607_SPI_INDEX, AO_MS5607_SPI_SPEED); } static void diff --git a/src/stmf0/ao_arch_funcs.h b/src/stmf0/ao_arch_funcs.h index 4e3ef018..ccfa3fc7 100644 --- a/src/stmf0/ao_arch_funcs.h +++ b/src/stmf0/ao_arch_funcs.h @@ -23,22 +23,22 @@ /* ao_spi_stm.c */ -/* PCLK is set to 16MHz (HCLK 32MHz, APB prescaler 2) */ +/* PCLK is set to 48MHz (HCLK 48MHz, HPRE 1, PPRE 1) */ -#define AO_SPI_SPEED_8MHz STM_SPI_CR1_BR_PCLK_2 -#define AO_SPI_SPEED_4MHz STM_SPI_CR1_BR_PCLK_4 -#define AO_SPI_SPEED_2MHz STM_SPI_CR1_BR_PCLK_8 -#define AO_SPI_SPEED_1MHz STM_SPI_CR1_BR_PCLK_16 -#define AO_SPI_SPEED_500kHz STM_SPI_CR1_BR_PCLK_32 -#define AO_SPI_SPEED_250kHz STM_SPI_CR1_BR_PCLK_64 -#define AO_SPI_SPEED_125kHz STM_SPI_CR1_BR_PCLK_128 -#define AO_SPI_SPEED_62500Hz STM_SPI_CR1_BR_PCLK_256 +#define AO_SPI_SPEED_24MHz STM_SPI_CR1_BR_PCLK_2 +#define AO_SPI_SPEED_12MHz STM_SPI_CR1_BR_PCLK_4 +#define AO_SPI_SPEED_6MHz STM_SPI_CR1_BR_PCLK_8 +#define AO_SPI_SPEED_3MHz STM_SPI_CR1_BR_PCLK_16 +#define AO_SPI_SPEED_1500kHz STM_SPI_CR1_BR_PCLK_32 +#define AO_SPI_SPEED_750kHz STM_SPI_CR1_BR_PCLK_64 +#define AO_SPI_SPEED_375kHz STM_SPI_CR1_BR_PCLK_128 +#define AO_SPI_SPEED_187500Hz STM_SPI_CR1_BR_PCLK_256 -#define AO_SPI_SPEED_FAST AO_SPI_SPEED_8MHz +#define AO_SPI_SPEED_FAST AO_SPI_SPEED_24MHz /* Companion bus wants something no faster than 200kHz */ -#define AO_SPI_SPEED_200kHz AO_SPI_SPEED_125kHz +#define AO_SPI_SPEED_200kHz AO_SPI_SPEED_187500Hz #define AO_SPI_CONFIG_1 0x00 #define AO_SPI_1_CONFIG_PA5_PA6_PA7 AO_SPI_CONFIG_1 -- cgit v1.2.3 From b8a19e83b7b1b8e2a1fcbdd58e41f9f974ae28ff Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 13 Apr 2016 06:16:01 -0700 Subject: altos/detherm: Add servo driver This just provides commands to test the servo with. Signed-off-by: Keith Packard --- src/detherm/Makefile | 1 + src/detherm/ao_detherm.c | 2 + src/detherm/ao_pins.h | 16 +++++-- src/drivers/ao_servo.c | 118 +++++++++++++++++++++++++++++++++++++++++++++++ src/drivers/ao_servo.h | 41 ++++++++++++++++ 5 files changed, 174 insertions(+), 4 deletions(-) create mode 100644 src/drivers/ao_servo.c create mode 100644 src/drivers/ao_servo.h (limited to 'src') diff --git a/src/detherm/Makefile b/src/detherm/Makefile index 35df6c96..6b0e0bf8 100644 --- a/src/detherm/Makefile +++ b/src/detherm/Makefile @@ -42,6 +42,7 @@ ALTOS_SRC = \ ao_ms5607.c \ ao_convert_pa.c \ ao_pwm.c \ + ao_servo.c \ ao_task.c \ ao_config.c \ ao_cmd.c \ diff --git a/src/detherm/ao_detherm.c b/src/detherm/ao_detherm.c index 64dee586..fba9195e 100644 --- a/src/detherm/ao_detherm.c +++ b/src/detherm/ao_detherm.c @@ -18,6 +18,7 @@ #include #include #include +#include void main(void) { @@ -38,6 +39,7 @@ void main(void) ao_ms5607_init(); // ao_flight_init(); ao_pwm_init(); + ao_servo_init(); ao_log_init(); ao_report_init(); ao_config_init(); diff --git a/src/detherm/ao_pins.h b/src/detherm/ao_pins.h index 8cd4a9c4..1c577b6e 100644 --- a/src/detherm/ao_pins.h +++ b/src/detherm/ao_pins.h @@ -98,10 +98,18 @@ #define AO_PWM_TIMER_ENABLE STM_RCC_APB1ENR_TIM3EN #define AO_PWM_TIMER_SCALE 32 -/* Motor */ +/* Servo */ -#define AO_MOTOR_DIR_GPIO (&stm_gpiob) -#define AO_MOTOR_DIR_PIN 0 -#define AO_MOTOR_SPEED_PWM 0 +#define AO_SERVO_DIR_PORT (&stm_gpiob) +#define AO_SERVO_DIR_BIT 0 +#define AO_SERVO_SPEED_PWM 0 + +/* limit 2 */ +#define AO_SERVO_LIMIT_FORE_PORT (&stm_gpiob) +#define AO_SERVO_LIMIT_FORE_BIT 6 + +/* limit 1 */ +#define AO_SERVO_LIMIT_BACK_PORT (&stm_gpiob) +#define AO_SERVO_LIMIT_BACK_BIT 7 #endif /* _AO_PINS_H_ */ diff --git a/src/drivers/ao_servo.c b/src/drivers/ao_servo.c new file mode 100644 index 00000000..b48a4112 --- /dev/null +++ b/src/drivers/ao_servo.c @@ -0,0 +1,118 @@ +/* + * Copyright © 2016 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include "ao.h" +#include "ao_servo.h" +#include "ao_pwm.h" +#include "ao_exti.h" + +static uint8_t limit_wakeup; + +static void +ao_limit_isr(void) +{ + ao_wakeup(&limit_wakeup); +} + +static void +ao_limit_enable(uint8_t dir) +{ + if (dir == AO_SERVO_FORE) + ao_exti_enable(AO_SERVO_LIMIT_FORE_PORT, AO_SERVO_LIMIT_FORE_BIT); + else + ao_exti_enable(AO_SERVO_LIMIT_BACK_PORT, AO_SERVO_LIMIT_BACK_BIT); +} + +static void +ao_limit_disable(uint8_t dir) +{ + if (dir == AO_SERVO_FORE) + ao_exti_disable(AO_SERVO_LIMIT_FORE_PORT, AO_SERVO_LIMIT_FORE_BIT); + else + ao_exti_disable(AO_SERVO_LIMIT_BACK_PORT, AO_SERVO_LIMIT_BACK_BIT); +} + +static uint8_t +ao_limit_get(uint8_t dir) +{ + if (dir == AO_SERVO_FORE) + return !ao_gpio_get(AO_SERVO_LIMIT_FORE_PORT, AO_SERVO_LIMIT_FORE_BIT, PIN); + else + return !ao_gpio_get(AO_SERVO_LIMIT_BACK_PORT, AO_SERVO_LIMIT_BACK_BIT, PIN); +} + +void +ao_servo_run(uint16_t speed, uint8_t dir, uint16_t timeout) +{ + printf ("speed %d dir %d\n", speed, dir); + + /* Turn on the motor */ + ao_gpio_set(AO_SERVO_DIR_PORT, AO_SERVO_DIR_BIT, AO_SERVO_DIR_PIN, dir); + ao_pwm_set(AO_SERVO_SPEED_PWM, speed); + + /* Wait until the limit sensor is triggered */ + ao_arch_block_interrupts(); + ao_limit_enable(dir); + while (!ao_limit_get(dir)) + if (ao_sleep_for(&limit_wakeup, timeout)) + break; + ao_limit_disable(dir); + ao_arch_release_interrupts(); + + /* Turn off the motor */ + ao_pwm_set(AO_SERVO_SPEED_PWM, 0); +} + +#define init_limit(p,b) do { \ + ao_enable_port(p); \ + ao_exti_setup(p, b, \ + AO_EXTI_MODE_PULL_UP|AO_EXTI_MODE_FALLING|AO_EXTI_PRIORITY_MED, \ + ao_limit_isr); \ + } while (0) + + +static void +ao_servo_cmd(void) +{ + uint8_t dir; + uint16_t speed; + + ao_cmd_decimal(); + dir = ao_cmd_lex_u32; + ao_cmd_decimal(); + speed = ao_cmd_lex_u32; + if (ao_cmd_status != ao_cmd_success) + return; + + printf("Run servo %d\n", dir); + ao_servo_run(speed, dir, AO_MS_TO_TICKS(200)); +} + +static const struct ao_cmds ao_servo_cmds[] = { + { ao_servo_cmd, "S \0Run servo in indicated direction" }, + { 0, NULL }, +}; + + +void +ao_servo_init(void) +{ + init_limit(AO_SERVO_LIMIT_FORE_PORT, AO_SERVO_LIMIT_FORE_BIT); + init_limit(AO_SERVO_LIMIT_BACK_PORT, AO_SERVO_LIMIT_BACK_BIT); + ao_enable_output(AO_SERVO_DIR_PORT, AO_SERVO_DIR_BIT, AO_SERVO_DIR_PIN, 0); + ao_cmd_register(&ao_servo_cmds[0]); +} diff --git a/src/drivers/ao_servo.h b/src/drivers/ao_servo.h new file mode 100644 index 00000000..e1df347a --- /dev/null +++ b/src/drivers/ao_servo.h @@ -0,0 +1,41 @@ +/* + * Copyright © 2016 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#ifndef _AO_SERVO_H_ +#define _AO_SERVO_H_ + +void +ao_servo_run(uint16_t speed, uint8_t dir, uint16_t timeout); + +void +ao_servo_init(void); + +#define AO_SERVO_FORE 0 +#define AO_SERVO_BACK 1 + +/* To configure the servo: + * + * #define AO_SERVO_PWM + * #define AO_SERVO_DIR_PORT + * #define AO_SERVO_DIR_PIN + * #define AO_SERVO_LIMIT_FORE_PORT + * #define AO_SERVO_LIMIT_FORE_PIN + * #define AO_SERVO_LIMIT_BACK_PORT + * #define AO_SERVO_LIMIT_BACK_PIN + */ + +#endif /* _AO_SERVO_H_ */ -- cgit v1.2.3 From 553c89f8c64398cb1a815b1fa248980cd3f62ef8 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 17 Dec 2015 19:29:36 -0800 Subject: altos: Support telefire products in cc1200 driver Need to disable the pad code while testing the radio. Signed-off-by: Keith Packard --- src/drivers/ao_cc1200.c | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'src') diff --git a/src/drivers/ao_cc1200.c b/src/drivers/ao_cc1200.c index 6547be39..6bccb188 100644 --- a/src/drivers/ao_cc1200.c +++ b/src/drivers/ao_cc1200.c @@ -20,6 +20,9 @@ #include #include #include +#if HAS_PAD +#include +#endif static uint8_t ao_radio_mutex; @@ -812,6 +815,9 @@ ao_radio_test_cmd(void) #endif #if PACKET_HAS_SLAVE ao_packet_slave_stop(); +#endif +#if HAS_PAD + ao_pad_disable(); #endif ao_radio_get(0xff); ao_radio_set_mode(AO_RADIO_MODE_TEST); @@ -837,6 +843,9 @@ ao_radio_test_cmd(void) radio_on = 0; #if HAS_MONITOR ao_monitor_enable(); +#endif +#if HAS_PAD + ao_pad_enable(); #endif } } -- cgit v1.2.3 From 26ce7a9a213bdd35a13937054988e7b8fa749632 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 17 Dec 2015 19:30:35 -0800 Subject: altos: Add pad support for new telefire versions Makes the voltage divider values configurable, and allows for pyro channels that don't have the resistors necessary to check for a stuck relay. Also supports STM32L processors with wider GPIO registers, and uses the new ao_gpio_set/clr_bits functions to fire igniters rather than cc1111-specific code. Signed-off-by: Keith Packard --- src/drivers/ao_pad.c | 57 +++++++++++++++++++++++++++++++++++++++------ src/telefire-v0.1/ao_pins.h | 2 ++ 2 files changed, 52 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/drivers/ao_pad.c b/src/drivers/ao_pad.c index 419ea8d3..e51d237b 100644 --- a/src/drivers/ao_pad.c +++ b/src/drivers/ao_pad.c @@ -50,7 +50,11 @@ ao_siren(uint8_t v) #ifdef AO_SIREN ao_gpio_set(AO_SIREN_PORT, AO_SIREN_PIN, AO_SIREN, v); #else +#if HAS_BEEP ao_beep(v ? AO_BEEP_MID : 0); +#else + (void) v; +#endif #endif } @@ -59,13 +63,15 @@ ao_strobe(uint8_t v) { #ifdef AO_STROBE ao_gpio_set(AO_STROBE_PORT, AO_STROBE_PIN, AO_STROBE, v); +#else + (void) v; #endif } static void ao_pad_run(void) { - uint8_t pins; + AO_PORT_TYPE pins; for (;;) { while (!ao_pad_ignite) @@ -90,18 +96,28 @@ ao_pad_run(void) if (ao_pad_ignite & (1 << 3)) pins |= (1 << AO_PAD_PIN_3); #endif - AO_PAD_PORT = (AO_PAD_PORT & (~AO_PAD_ALL_PINS)) | pins; + PRINTD("ignite pins 0x%x\n", pins); + ao_gpio_set_bits(AO_PAD_PORT, pins); while (ao_pad_ignite) { ao_pad_ignite = 0; ao_delay(AO_PAD_FIRE_TIME); } - AO_PAD_PORT &= ~(AO_PAD_ALL_PINS); + ao_gpio_clr_bits(AO_PAD_PORT, pins); + PRINTD("turn off pins 0x%x\n", pins); } } #define AO_PAD_ARM_SIREN_INTERVAL 200 +#ifndef AO_PYRO_R_PYRO_SENSE +#define AO_PYRO_R_PYRO_SENSE 100 +#define AO_PYRO_R_SENSE_GND 27 +#define AO_FIRE_R_POWER_FET 100 +#define AO_FIRE_R_FET_SENSE 100 +#define AO_FIRE_R_SENSE_GND 27 +#endif + static void ao_pad_monitor(void) { @@ -109,7 +125,7 @@ ao_pad_monitor(void) uint8_t sample; __pdata uint8_t prev = 0, cur = 0; __pdata uint8_t beeping = 0; - __xdata struct ao_data *packet; + __xdata volatile struct ao_data *packet; __pdata uint16_t arm_beep_time = 0; sample = ao_data_head; @@ -120,12 +136,18 @@ ao_pad_monitor(void) ao_sleep((void *) DATA_TO_XDATA(&ao_data_head)); ); + packet = &ao_data_ring[sample]; sample = ao_data_ring_next(sample); pyro = packet->adc.pyro; -#define VOLTS_TO_PYRO(x) ((int16_t) ((x) * 27.0 / 127.0 / 3.3 * 32767.0)) +#define VOLTS_TO_PYRO(x) ((int16_t) ((x) * ((1.0 * AO_PYRO_R_SENSE_GND) / \ + (1.0 * (AO_PYRO_R_SENSE_GND + AO_PYRO_R_PYRO_SENSE)) / 3.3 * AO_ADC_MAX))) + + +#define VOLTS_TO_FIRE(x) ((int16_t) ((x) * ((1.0 * AO_FIRE_R_SENSE_GND) / \ + (1.0 * (AO_FIRE_R_SENSE_GND + AO_FIRE_R_FET_SENSE)) / 3.3 * AO_ADC_MAX))) /* convert ADC value to voltage in tenths, then add .2 for the diode drop */ query.battery = (packet->adc.batt + 96) / 192 + 2; @@ -165,22 +187,39 @@ ao_pad_monitor(void) * 27k / * gnd --- * + * v_pyro \ + * 200k igniter + * output / + * 200k \ + * sense relay + * 22k / + * gnd --- + * * If the relay is closed, then sense will be 0 * If no igniter is present, then sense will be v_pyro * 27k/227k = pyro * 127 / 227 ~= pyro/2 * If igniter is present, then sense will be v_pyro * 27k/127k ~= v_pyro / 20 = pyro */ +#if AO_FIRE_R_POWER_FET if (sense <= pyro / 8) { status = AO_PAD_IGNITER_STATUS_NO_IGNITER_RELAY_CLOSED; if ((ao_time() % 100) < 50) cur |= AO_LED_CONTINUITY(c); - } - else if (pyro / 8 * 3 <= sense && sense <= pyro / 8 * 5) + } else + if (pyro / 8 * 3 <= sense && sense <= pyro / 8 * 5) status = AO_PAD_IGNITER_STATUS_NO_IGNITER_RELAY_OPEN; else if (pyro / 8 * 7 <= sense) { status = AO_PAD_IGNITER_STATUS_GOOD_IGNITER_RELAY_OPEN; cur |= AO_LED_CONTINUITY(c); } +#else + if (sense >= pyro / 8 * 5) { + status = AO_PAD_IGNITER_STATUS_GOOD_IGNITER_RELAY_OPEN; + cur |= AO_LED_CONTINUITY(c); + } else { + status = AO_PAD_IGNITER_STATUS_NO_IGNITER_RELAY_OPEN; + } +#endif query.igniter_status[c] = status; } if (cur != prev) { @@ -244,6 +283,10 @@ ao_pad_read_box(void) #define ao_pad_read_box() 0 #endif +#ifdef PAD_BOX +#define ao_pad_read_box() PAD_BOX +#endif + static void ao_pad(void) { diff --git a/src/telefire-v0.1/ao_pins.h b/src/telefire-v0.1/ao_pins.h index 47ae663f..1087c7c9 100644 --- a/src/telefire-v0.1/ao_pins.h +++ b/src/telefire-v0.1/ao_pins.h @@ -39,6 +39,8 @@ #define PACKET_HAS_MASTER 0 #define PACKET_HAS_SLAVE 0 +#define PAD_BOX 0 + #define AO_LED_CONTINUITY(c) (1 << ((c) + 2)) #define AO_LED_CONTINUITY_MASK (0xc) #define AO_LED_ARMED 0x10 -- cgit v1.2.3 From f2038dd2cfed5bbf049144172e3f7436b6cd3a55 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 17 Dec 2015 19:54:23 -0800 Subject: altos: telefiretwo-v0.1 bits Get this board running. Signed-off-by: Keith Packard --- src/telefiretwo-v0.1/.gitignore | 2 + src/telefiretwo-v0.1/Makefile | 89 ++++++++++++ src/telefiretwo-v0.1/ao_pins.h | 210 +++++++++++++++++++++++++++ src/telefiretwo-v0.1/ao_telefiretwo.c | 54 +++++++ src/telefiretwo-v0.1/flash-loader/.gitignore | 2 + src/telefiretwo-v0.1/flash-loader/Makefile | 8 + src/telefiretwo-v0.1/flash-loader/ao_pins.h | 28 ++++ 7 files changed, 393 insertions(+) create mode 100644 src/telefiretwo-v0.1/.gitignore create mode 100644 src/telefiretwo-v0.1/Makefile create mode 100644 src/telefiretwo-v0.1/ao_pins.h create mode 100644 src/telefiretwo-v0.1/ao_telefiretwo.c create mode 100644 src/telefiretwo-v0.1/flash-loader/.gitignore create mode 100644 src/telefiretwo-v0.1/flash-loader/Makefile create mode 100644 src/telefiretwo-v0.1/flash-loader/ao_pins.h (limited to 'src') diff --git a/src/telefiretwo-v0.1/.gitignore b/src/telefiretwo-v0.1/.gitignore new file mode 100644 index 00000000..4d4f4200 --- /dev/null +++ b/src/telefiretwo-v0.1/.gitignore @@ -0,0 +1,2 @@ +telefire-* +ao_product.h diff --git a/src/telefiretwo-v0.1/Makefile b/src/telefiretwo-v0.1/Makefile new file mode 100644 index 00000000..6454d6fd --- /dev/null +++ b/src/telefiretwo-v0.1/Makefile @@ -0,0 +1,89 @@ +# +# TeleFire build file +# + +include ../stm/Makefile.defs + +INC = \ + ao.h \ + ao_pins.h \ + ao_arch.h \ + ao_arch_funcs.h \ + ao_pad.h \ + ao_product.h \ + ao_radio_spi.h \ + ao_radio_cmac.h \ + ao_cc1200_CC1200.h \ + ao_cc1200.h \ + stm32l.h +# +# Common AltOS sources +# + +#PROFILE=ao_profile.c +#PROFILE_DEF=-DAO_PROFILE=1 + +ALTOS_SRC = \ + ao_boot_chain.c \ + ao_interrupt.c \ + ao_product.c \ + ao_romconfig.c \ + ao_cmd.c \ + ao_adc_stm.c \ + ao_data.c \ + ao_config.c \ + ao_task.c \ + ao_led.c \ + ao_stdio.c \ + ao_panic.c \ + ao_timer.c \ + ao_mutex.c \ + ao_freq.c \ + ao_dma_stm.c \ + ao_spi_stm.c \ + ao_eeprom_stm.c \ + ao_usb_stm.c \ + ao_exti_stm.c \ + ao_cc1200.c \ + ao_radio_cmac.c \ + ao_aes.c \ + ao_aes_tables.c \ + ao_pad.c \ + ao_radio_cmac_cmd.c + +PRODUCT_SRC = \ + ao_telefiretwo.c + +PRODUCT=TeleFire-v0.1 +PRODUCT_DEF=-DTELEFIRETWO_V_0_1 +IDPRODUCT=0x000f + +CFLAGS = $(PRODUCT_DEF) $(STM_CFLAGS) $(PROFILE_DEF) -Os -g + +PROGNAME = telefiretwo-v0.1 +PROG = $(PROGNAME)-$(VERSION).elf +HEX = $(PROGNAME)-$(VERSION).ihx + +SRC = $(ALTOS_SRC) $(PRODUCT_SRC) +OBJ=$(SRC:.c=.o) + +all: $(PROG) $(HEX) + +$(PROG): Makefile $(OBJ) altos.ld + $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(OBJ) $(LIBS) + +$(OBJ): $(INC) + +ao_product.h: ao-make-product.5c ../Version + $(call quiet,NICKLE,$<) $< -m altusmetrum.org -i $(IDPRODUCT) -p $(PRODUCT) -v $(VERSION) > $@ + +distclean: clean + +clean: + rm -f *.o $(PROGNAME)-*.elf $(PROGNAME)-*.ihx + rm -f ao_product.h + +install: + +uninstall: + diff --git a/src/telefiretwo-v0.1/ao_pins.h b/src/telefiretwo-v0.1/ao_pins.h new file mode 100644 index 00000000..e98b7dc7 --- /dev/null +++ b/src/telefiretwo-v0.1/ao_pins.h @@ -0,0 +1,210 @@ +/* + * Copyright © 2010 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_RADIO 1 +#define HAS_RADIO_RATE 1 +#define HAS_TELEMETRY 0 + +#define HAS_FLIGHT 0 +#define HAS_USB 1 +#define HAS_BEEP 0 +#define HAS_GPS 0 +#define HAS_SERIAL_1 0 +#define HAS_ADC 1 +#define HAS_DBG 0 +#define HAS_EEPROM 1 +#define HAS_LOG 0 +#define HAS_PAD 1 +#define USE_INTERNAL_FLASH 1 +#define IGNITE_ON_P0 0 +#define PACKET_HAS_MASTER 0 +#define PACKET_HAS_SLAVE 0 +#define AO_DATA_RING 32 + +/* 8MHz High speed external crystal */ +#define AO_HSE 8000000 + +/* PLLVCO = 96MHz (so that USB will work) */ +#define AO_PLLMUL 12 +#define AO_RCC_CFGR_PLLMUL (STM_RCC_CFGR_PLLMUL_12) + +#define AO_CC1200_FOSC 40000000 + +/* SYSCLK = 32MHz (no need to go faster than CPU) */ +#define AO_PLLDIV 3 +#define AO_RCC_CFGR_PLLDIV (STM_RCC_CFGR_PLLDIV_3) + +/* HCLK = 32MHz (CPU clock) */ +#define AO_AHB_PRESCALER 1 +#define AO_RCC_CFGR_HPRE_DIV STM_RCC_CFGR_HPRE_DIV_1 + +/* Run APB1 at 16MHz (HCLK/2) */ +#define AO_APB1_PRESCALER 2 +#define AO_RCC_CFGR_PPRE1_DIV STM_RCC_CFGR_PPRE2_DIV_2 + +/* Run APB2 at 16MHz (HCLK/2) */ +#define AO_APB2_PRESCALER 2 +#define AO_RCC_CFGR_PPRE2_DIV STM_RCC_CFGR_PPRE2_DIV_2 + +#define HAS_EEPROM 1 +#define USE_INTERNAL_FLASH 1 +#define USE_EEPROM_CONFIG 1 +#define USE_STORAGE_CONFIG 0 +#define HAS_USB 1 +#define HAS_BEEP 0 +#define HAS_RADIO 1 +#define HAS_RADIO_RATE 1 +#define HAS_TELEMETRY 0 +#define HAS_AES 1 + +#define HAS_SPI_1 0 +#define SPI_1_PA5_PA6_PA7 0 +#define SPI_1_PB3_PB4_PB5 0 +#define SPI_1_PE13_PE14_PE15 0 + +#define HAS_SPI_2 1 /* CC1200 */ +#define SPI_2_PB13_PB14_PB15 1 +#define SPI_2_PD1_PD3_PD4 0 +#define SPI_2_GPIO (&stm_gpiob) +#define SPI_2_SCK 13 +#define SPI_2_MISO 14 +#define SPI_2_MOSI 15 +#define SPI_2_OSPEEDR STM_OSPEEDR_10MHz + +#define HAS_I2C_1 0 + +#define HAS_I2C_2 0 + +#define PACKET_HAS_SLAVE 0 +#define PACKET_HAS_MASTER 0 + +#define FAST_TIMER_FREQ 10000 /* .1ms for debouncing */ + +/* + * Radio is a cc1200 connected via SPI + */ + +#define AO_RADIO_CAL_DEFAULT 5695733 + +#define AO_FEC_DEBUG 0 +#define AO_CC1200_SPI_CS_PORT (&stm_gpioa) +#define AO_CC1200_SPI_CS_PIN 7 +#define AO_CC1200_SPI_BUS AO_SPI_2_PB13_PB14_PB15 +#define AO_CC1200_SPI stm_spi2 + +#define AO_CC1200_INT_PORT (&stm_gpiob) +#define AO_CC1200_INT_PIN (11) + +#define AO_CC1200_INT_GPIO 2 +#define AO_CC1200_INT_GPIO_IOCFG CC1200_IOCFG2 + +#define LED_PORT_0 (&stm_gpioa) +#define LED_PORT_1 (&stm_gpiob) + +#define LED_PORT_0_ENABLE STM_RCC_AHBENR_GPIOAEN +#define LED_PORT_1_ENABLE STM_RCC_AHBENR_GPIOBEN + +/* Port A, pins 4-6 */ +#define LED_PORT_0_SHIFT 4 +#define LED_PORT_0_MASK 0x7 +#define LED_PIN_GREEN 0 +#define LED_PIN_AMBER 1 +#define LED_PIN_RED 2 +#define AO_LED_RED (1 << LED_PIN_RED) +#define AO_LED_AMBER (1 << LED_PIN_AMBER) +#define AO_LED_GREEN (1 << LED_PIN_GREEN) + +/* Port B, pins 3-5 */ +#define LED_PORT_1_SHIFT 0 +#define LED_PORT_1_MASK (0x7 << 3) +#define LED_PIN_CONT_1 3 +#define LED_PIN_CONT_0 4 +#define LED_PIN_ARMED 5 + +#define AO_LED_ARMED (1 << LED_PIN_ARMED) +#define AO_LED_CONTINUITY(c) (1 << (4 - (c))) +#define AO_LED_CONTINUITY_MASK (0x3 << 3) + +#define LEDS_AVAILABLE (LED_PORT_0_MASK|LED_PORT_1_MASK) + +#define SPI_CS_PORT P1 +#define SPI_CS_SEL P1SEL +#define SPI_CS_DIR P1DIR + +#define SPI_CONST 0x00 + +#define AO_PAD_NUM 2 +#define AO_PAD_PORT (&stm_gpiob) + +#define AO_PAD_PIN_0 9 +#define AO_PAD_ADC_0 0 + +#define AO_PAD_PIN_1 8 +#define AO_PAD_ADC_1 1 + +#define AO_PAD_ALL_PINS ((1 << AO_PAD_PIN_0) | (1 << AO_PAD_PIN_1)) +#define AO_PAD_ALL_CHANNELS ((1 << 0) | (1 << 1)) + +/* test these values with real igniters */ +#define AO_PAD_RELAY_CLOSED 3524 +#define AO_PAD_NO_IGNITER 16904 +#define AO_PAD_GOOD_IGNITER 22514 + +#define AO_PAD_ADC_PYRO 8 +#define AO_PAD_ADC_BATT 2 + +#define AO_ADC_FIRST_PIN 0 + +#define AO_NUM_ADC 4 + +#define AO_ADC_SQ1 AO_PAD_ADC_0 +#define AO_ADC_SQ2 AO_PAD_ADC_1 +#define AO_ADC_SQ3 AO_PAD_ADC_PYRO +#define AO_ADC_SQ4 AO_PAD_ADC_BATT + +#define AO_PYRO_R_PYRO_SENSE 200 +#define AO_PYRO_R_SENSE_GND 22 + +#define AO_FIRE_R_POWER_FET 0 +#define AO_FIRE_R_FET_SENSE 200 +#define AO_FIRE_R_SENSE_GND 22 + +#define HAS_ADC_TEMP 0 + +struct ao_adc { + int16_t sense[AO_PAD_NUM]; + int16_t pyro; + int16_t batt; +}; + +#define AO_ADC_DUMP(p) \ + printf ("tick: %5u 0: %5d 1: %5d pyro: %5d batt %5d\n", \ + (p)->tick, \ + (p)->adc.sense[0], \ + (p)->adc.sense[1], \ + (p)->adc.pyro, \ + (p)->adc.batt) + +#define AO_ADC_PINS ((1 << AO_PAD_ADC_0) | \ + (1 << AO_PAD_ADC_1) | \ + (1 << AO_PAD_ADC_PYRO) | \ + (1 << AO_PAD_ADC_BATT)) + +#endif /* _AO_PINS_H_ */ diff --git a/src/telefiretwo-v0.1/ao_telefiretwo.c b/src/telefiretwo-v0.1/ao_telefiretwo.c new file mode 100644 index 00000000..38629d86 --- /dev/null +++ b/src/telefiretwo-v0.1/ao_telefiretwo.c @@ -0,0 +1,54 @@ +/* + * Copyright © 2012 Keith Packard + * + * 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 + +void +main(void) +{ + ao_clock_init(); + + ao_led_init(LEDS_AVAILABLE); + + ao_task_init(); + + ao_timer_init(); + ao_spi_init(); + ao_dma_init(); + ao_exti_init(); + + ao_cmd_init(); + + ao_adc_init(); + + ao_eeprom_init(); + + ao_radio_init(); + + ao_usb_init(); + + ao_config_init(); + + ao_pad_init(); + +// ao_radio_cmac_cmd_init(); + + ao_start_scheduler(); +} diff --git a/src/telefiretwo-v0.1/flash-loader/.gitignore b/src/telefiretwo-v0.1/flash-loader/.gitignore new file mode 100644 index 00000000..65fe7eab --- /dev/null +++ b/src/telefiretwo-v0.1/flash-loader/.gitignore @@ -0,0 +1,2 @@ +*.elf +*.ihx diff --git a/src/telefiretwo-v0.1/flash-loader/Makefile b/src/telefiretwo-v0.1/flash-loader/Makefile new file mode 100644 index 00000000..108cd554 --- /dev/null +++ b/src/telefiretwo-v0.1/flash-loader/Makefile @@ -0,0 +1,8 @@ +# +# AltOS flash loader build +# +# + +TOPDIR=../.. +HARDWARE=telefiretwo-v0.1 +include $(TOPDIR)/stm/Makefile-flash.defs diff --git a/src/telefiretwo-v0.1/flash-loader/ao_pins.h b/src/telefiretwo-v0.1/flash-loader/ao_pins.h new file mode 100644 index 00000000..f6311267 --- /dev/null +++ b/src/telefiretwo-v0.1/flash-loader/ao_pins.h @@ -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. + */ + +#ifndef _AO_PINS_H_ +#define _AO_PINS_H_ + +/* External crystal at 8MHz */ +#define AO_HSE 8000000 + +#include + +#define AO_BOOT_PIN 0 + +#endif /* _AO_PINS_H_ */ -- cgit v1.2.3 From 93100ae8d4c8bd8fd6bdeff2cdc87b613c5d8058 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 21 Dec 2015 21:47:10 -0800 Subject: altos: Allow for pad boxes with different sensor configurations This allows for a pad box without a resistor from power to each FET. That resistor is needed to detect welded relays, but in a solid-state system, that's not a possibility. Signed-off-by: Keith Packard --- src/drivers/ao_pad.c | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/drivers/ao_pad.c b/src/drivers/ao_pad.c index e51d237b..99a90e77 100644 --- a/src/drivers/ao_pad.c +++ b/src/drivers/ao_pad.c @@ -155,14 +155,16 @@ ao_pad_monitor(void) if (pyro > VOLTS_TO_PYRO(10)) { query.arm_status = AO_PAD_ARM_STATUS_ARMED; cur |= AO_LED_ARMED; - } else if (pyro < VOLTS_TO_PYRO(5)) { - query.arm_status = AO_PAD_ARM_STATUS_DISARMED; - arm_beep_time = 0; - } else { +#if AO_FIRE_R_POWER_FET + } else if (pyro > VOLTS_TO_PYRO(5)) { if ((ao_time() % 100) < 50) cur |= AO_LED_ARMED; query.arm_status = AO_PAD_ARM_STATUS_UNKNOWN; arm_beep_time = 0; +#endif + } else { + query.arm_status = AO_PAD_ARM_STATUS_DISARMED; + arm_beep_time = 0; } if ((ao_time() - ao_pad_packet_time) > AO_SEC_TO_TICKS(2)) cur |= AO_LED_RED; @@ -279,8 +281,10 @@ ao_pad_read_box(void) l = byte & 0xf; return h * 10 + l; } -#else -#define ao_pad_read_box() 0 +#endif + +#if HAS_FIXED_PAD_BOX +#define ao_pad_read_box() ao_config.pad_box #endif #ifdef PAD_BOX -- cgit v1.2.3 From e6bad553009704af69b08b4a22fb5eb8ac6921f8 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 21 Dec 2015 21:48:37 -0800 Subject: altos: Support pad/lco boxes with fixed box numbers This allows for a configuration without adjustable box numbers on either end of the link, simplifying the UI. Signed-off-by: Keith Packard --- src/Makefile | 4 +++- src/kernel/ao_config.c | 27 +++++++++++++++++++++++++++ src/kernel/ao_config.h | 3 +++ src/telefiretwo-v0.1/ao_pins.h | 1 + src/telefiretwo-v0.1/flash-loader/ao_pins.h | 6 +++++- 5 files changed, 39 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/Makefile b/src/Makefile index 98607031..ecba2fbd 100644 --- a/src/Makefile +++ b/src/Makefile @@ -39,7 +39,9 @@ ARMM3DIRS=\ telescience-v0.2 telescience-v0.2/flash-loader \ teledongle-v3.0 teledongle-v3.0/flash-loader \ teleballoon-v2.0 \ - telebt-v3.0 telebt-v3.0/flash-loader + telebt-v3.0 telebt-v3.0/flash-loader \ + telelcotwo-v0.1 telelcotwo-v0.1/flash-loader \ + telefiretwo-v0.1 telefiretwo-v0.1/flash-loader \ ARMM0DIRS=\ easymini-v1.0 easymini-v1.0/flash-loader \ diff --git a/src/kernel/ao_config.c b/src/kernel/ao_config.c index b0d3e541..d51fbb41 100644 --- a/src/kernel/ao_config.c +++ b/src/kernel/ao_config.c @@ -223,6 +223,10 @@ _ao_config_get(void) #if HAS_APRS if (minor < 22) ao_config.aprs_format = AO_CONFIG_DEFAULT_APRS_FORMAT; +#endif +#if HAS_FIXED_PAD_BOX + if (minor < 22) + ao_config.pad_box = 1; #endif ao_config.minor = AO_CONFIG_MINOR; ao_config_dirty = 1; @@ -899,6 +903,25 @@ ao_config_aprs_format_show(void) } #endif /* HAS_APRS */ +#if HAS_FIXED_PAD_BOX +void +ao_config_pad_box_show(void) +{ + printf ("Pad box: %d\n", ao_config.pad_box); +} + +void +ao_config_pad_box_set(void) +{ + ao_cmd_decimal(); + if (ao_cmd_status != ao_cmd_success) + return; + _ao_config_edit_start(); + ao_config.pad_box = ao_cmd_lex_i; + _ao_config_edit_finish(); +} +#endif + struct ao_config_var { __code char *str; void (*set)(void) __reentrant; @@ -992,6 +1015,10 @@ __code struct ao_config_var ao_config_vars[] = { ao_config_aprs_ssid_set, ao_config_aprs_ssid_show }, { "C <0 compressed, 1 uncompressed>\0APRS format", ao_config_aprs_format_set, ao_config_aprs_format_show }, +#endif +#if HAS_FIXED_PAD_BOX + { "B \0Set pad box (1-99)", + ao_config_pad_box_set, ao_config_pad_box_show }, #endif { "s\0Show", ao_config_show, 0 }, diff --git a/src/kernel/ao_config.h b/src/kernel/ao_config.h index cfe8555c..f4e9af44 100644 --- a/src/kernel/ao_config.h +++ b/src/kernel/ao_config.h @@ -118,6 +118,9 @@ struct ao_config { #if HAS_APRS uint8_t aprs_format; /* minor version 22 */ #endif +#if HAS_FIXED_PAD_BOX + uint8_t pad_box; /* minor version 22 */ +#endif }; #define AO_APRS_FORMAT_COMPRESSED 0 diff --git a/src/telefiretwo-v0.1/ao_pins.h b/src/telefiretwo-v0.1/ao_pins.h index e98b7dc7..fd840f47 100644 --- a/src/telefiretwo-v0.1/ao_pins.h +++ b/src/telefiretwo-v0.1/ao_pins.h @@ -37,6 +37,7 @@ #define PACKET_HAS_MASTER 0 #define PACKET_HAS_SLAVE 0 #define AO_DATA_RING 32 +#define HAS_FIXED_PAD_BOX 1 /* 8MHz High speed external crystal */ #define AO_HSE 8000000 diff --git a/src/telefiretwo-v0.1/flash-loader/ao_pins.h b/src/telefiretwo-v0.1/flash-loader/ao_pins.h index f6311267..daa9048d 100644 --- a/src/telefiretwo-v0.1/flash-loader/ao_pins.h +++ b/src/telefiretwo-v0.1/flash-loader/ao_pins.h @@ -23,6 +23,10 @@ #include -#define AO_BOOT_PIN 0 +#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_ */ -- cgit v1.2.3 From 11f8ab90d2267715010e652d709beec363f74ed5 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 21 Dec 2015 21:50:43 -0800 Subject: altos: Add TeleLCOTwo firmware The LCO side of a two-channel launch controller setup. Signed-off-by: Keith Packard --- src/telelcotwo-v0.1/.gitignore | 2 + src/telelcotwo-v0.1/Makefile | 98 ++++++++++++++++ src/telelcotwo-v0.1/ao_pins.h | 172 +++++++++++++++++++++++++++++ src/telelcotwo-v0.1/ao_telelcotwo.c | 65 +++++++++++ src/telelcotwo-v0.1/flash-loader/Makefile | 8 ++ src/telelcotwo-v0.1/flash-loader/ao_pins.h | 34 ++++++ 6 files changed, 379 insertions(+) create mode 100644 src/telelcotwo-v0.1/.gitignore create mode 100644 src/telelcotwo-v0.1/Makefile create mode 100644 src/telelcotwo-v0.1/ao_pins.h create mode 100644 src/telelcotwo-v0.1/ao_telelcotwo.c create mode 100644 src/telelcotwo-v0.1/flash-loader/Makefile create mode 100644 src/telelcotwo-v0.1/flash-loader/ao_pins.h (limited to 'src') diff --git a/src/telelcotwo-v0.1/.gitignore b/src/telelcotwo-v0.1/.gitignore new file mode 100644 index 00000000..a32ec26e --- /dev/null +++ b/src/telelcotwo-v0.1/.gitignore @@ -0,0 +1,2 @@ +ao_product.h +telelco*.elf diff --git a/src/telelcotwo-v0.1/Makefile b/src/telelcotwo-v0.1/Makefile new file mode 100644 index 00000000..8ceb7d2c --- /dev/null +++ b/src/telelcotwo-v0.1/Makefile @@ -0,0 +1,98 @@ +# +# AltOS build for TeleLCO +# +# + +include ../stm/Makefile.defs + +INC = \ + ao.h \ + ao_arch.h \ + ao_arch_funcs.h \ + ao_boot.h \ + ao_companion.h \ + ao_data.h \ + ao_sample.h \ + ao_pins.h \ + ao_product.h \ + ao_radio_spi.h \ + ao_radio_cmac.h \ + ao_cc1200_CC1200.h \ + ao_cc1200.h \ + ao_debounce.h \ + stm32l.h + +# +# Common AltOS sources +# + +#PROFILE=ao_profile.c +#PROFILE_DEF=-DAO_PROFILE=1 + +ALTOS_SRC = \ + ao_boot_chain.c \ + ao_interrupt.c \ + ao_product.c \ + ao_romconfig.c \ + ao_cmd.c \ + ao_config.c \ + ao_task.c \ + ao_led.c \ + ao_stdio.c \ + ao_panic.c \ + ao_timer.c \ + ao_mutex.c \ + ao_freq.c \ + ao_dma_stm.c \ + ao_spi_stm.c \ + ao_beep_stm.c \ + ao_eeprom_stm.c \ + ao_fast_timer.c \ + ao_usb_stm.c \ + ao_exti_stm.c \ + ao_cc1200.c \ + ao_radio_cmac.c \ + ao_aes.c \ + ao_aes_tables.c \ + ao_fec_tx.c \ + ao_fec_rx.c \ + ao_debounce.c \ + ao_button.c \ + ao_event.c \ + ao_lco_two.c \ + ao_lco_func.c \ + ao_lco_cmd.c \ + ao_radio_cmac_cmd.c + +PRODUCT=TeleLCOTwo-v0.1 +PRODUCT_DEF=-DTELELCOTWO +IDPRODUCT=0x0023 + +CFLAGS = $(PRODUCT_DEF) $(STM_CFLAGS) $(PROFILE_DEF) -Os -g + +PROGNAME=telelcotwo-v0.1 +PROG=$(PROGNAME)-$(VERSION).elf +HEX=$(PROGNAME)-$(VERSION).ihx + +SRC=$(ALTOS_SRC) ao_telelcotwo.c +OBJ=$(SRC:.c=.o) + +all: $(PROG) $(HEX) + +$(PROG): Makefile $(OBJ) altos.ld + $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(OBJ) $(LIBS) + +$(OBJ): $(INC) + +ao_product.h: ao-make-product.5c ../Version + $(call quiet,NICKLE,$<) $< -m altusmetrum.org -i $(IDPRODUCT) -p $(PRODUCT) -v $(VERSION) > $@ + +distclean: clean + +clean: + rm -f *.o $(PROGNAME)-*.elf $(PROGNAME)-*.ihx + rm -f ao_product.h + +install: + +uninstall: diff --git a/src/telelcotwo-v0.1/ao_pins.h b/src/telelcotwo-v0.1/ao_pins.h new file mode 100644 index 00000000..ce797a38 --- /dev/null +++ b/src/telelcotwo-v0.1/ao_pins.h @@ -0,0 +1,172 @@ +/* + * Copyright © 2012 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#ifndef _AO_PINS_H_ +#define _AO_PINS_H_ + +/* 8MHz High speed external crystal */ +#define AO_HSE 8000000 + +/* PLLVCO = 96MHz (so that USB will work) */ +#define AO_PLLMUL 12 +#define AO_RCC_CFGR_PLLMUL (STM_RCC_CFGR_PLLMUL_12) + +#define AO_CC1200_FOSC 40000000 + +/* SYSCLK = 32MHz (no need to go faster than CPU) */ +#define AO_PLLDIV 3 +#define AO_RCC_CFGR_PLLDIV (STM_RCC_CFGR_PLLDIV_3) + +/* HCLK = 32MHz (CPU clock) */ +#define AO_AHB_PRESCALER 1 +#define AO_RCC_CFGR_HPRE_DIV STM_RCC_CFGR_HPRE_DIV_1 + +/* Run APB1 at 16MHz (HCLK/2) */ +#define AO_APB1_PRESCALER 2 +#define AO_RCC_CFGR_PPRE1_DIV STM_RCC_CFGR_PPRE2_DIV_2 + +/* Run APB2 at 16MHz (HCLK/2) */ +#define AO_APB2_PRESCALER 2 +#define AO_RCC_CFGR_PPRE2_DIV STM_RCC_CFGR_PPRE2_DIV_2 + +#define HAS_EEPROM 1 +#define USE_INTERNAL_FLASH 1 +#define USE_EEPROM_CONFIG 1 +#define USE_STORAGE_CONFIG 0 +#define HAS_USB 1 +#define HAS_BEEP 1 +#define BEEPER_CHANNEL 4 +#define HAS_RADIO 1 +#define HAS_RADIO_RATE 1 +#define HAS_TELEMETRY 0 +#define HAS_AES 1 +#define HAS_FIXED_PAD_BOX 1 + +#define HAS_SPI_1 0 +#define SPI_1_PA5_PA6_PA7 0 +#define SPI_1_PB3_PB4_PB5 0 +#define SPI_1_PE13_PE14_PE15 0 + +#define HAS_SPI_2 1 /* CC1200 */ +#define SPI_2_PB13_PB14_PB15 1 +#define SPI_2_PD1_PD3_PD4 0 +#define SPI_2_GPIO (&stm_gpiod) +#define SPI_2_SCK 13 +#define SPI_2_MISO 14 +#define SPI_2_MOSI 15 +#define SPI_2_OSPEEDR STM_OSPEEDR_10MHz + +#define HAS_I2C_1 0 + +#define HAS_I2C_2 0 + +#define PACKET_HAS_SLAVE 0 +#define PACKET_HAS_MASTER 0 + +#define FAST_TIMER_FREQ 10000 /* .1ms for debouncing */ + +/* + * Radio is a cc1200 connected via SPI + */ + +#define AO_RADIO_CAL_DEFAULT 5695733 + +#define AO_FEC_DEBUG 0 +#define AO_CC1200_SPI_CS_PORT (&stm_gpioa) +#define AO_CC1200_SPI_CS_PIN 7 +#define AO_CC1200_SPI_BUS AO_SPI_2_PB13_PB14_PB15 +#define AO_CC1200_SPI stm_spi2 + +#define AO_CC1200_INT_PORT (&stm_gpiob) +#define AO_CC1200_INT_PIN (11) + +#define AO_CC1200_INT_GPIO 2 +#define AO_CC1200_INT_GPIO_IOCFG CC1200_IOCFG2 + +#define LOW_LEVEL_DEBUG 0 + +#define LED_PORT_0 (&stm_gpioa) +#define LED_PORT_1 (&stm_gpiob) + +#define LED_PORT_0_ENABLE STM_RCC_AHBENR_GPIOAEN +#define LED_PORT_1_ENABLE STM_RCC_AHBENR_GPIOBEN + +/* Port A, pins 4-6 */ +#define LED_PORT_0_SHIFT 4 +#define LED_PORT_0_MASK 0x7 + +#define LED_PIN_GREEN 0 +#define LED_PIN_AMBER 1 +#define LED_PIN_RED 2 + +#define AO_LED_RED (1 << LED_PIN_RED) +#define AO_LED_AMBER (1 << LED_PIN_AMBER) +#define AO_LED_GREEN (1 << LED_PIN_GREEN) + +/* Port B, pins 3-5 */ +#define LED_PORT_1_SHIFT 0 +#define LED_PORT_1_MASK (0x7 << 3) + +#define LED_PIN_CONTINUITY_1 3 +#define LED_PIN_CONTINUITY_0 4 +#define LED_PIN_REMOTE_ARM 5 + +#define AO_LED_CONTINUITY_1 (1 << LED_PIN_CONTINUITY_1) +#define AO_LED_CONTINUITY_0 (1 << LED_PIN_CONTINUITY_0) + +#define AO_LED_CONTINUITY_NUM 2 + +#define AO_LED_REMOTE_ARM (1 << LED_PIN_REMOTE_ARM) + +#define LEDS_AVAILABLE (AO_LED_RED | \ + AO_LED_AMBER | \ + AO_LED_GREEN | \ + AO_LED_CONTINUITY_1 | \ + AO_LED_CONTINUITY_0 | \ + AO_LED_REMOTE_ARM) + +/* + * Use event queue for input devices + */ + +#define AO_EVENT 1 + +/* + * Buttons + */ + +#define AO_BUTTON_COUNT 3 +#define AO_BUTTON_MODE AO_EXTI_MODE_PULL_UP + +#define AO_BUTTON_0_PORT &stm_gpioa +#define AO_BUTTON_0 0 + +#define AO_BUTTON_ARM_0 0 + +#define AO_BUTTON_1_PORT &stm_gpioa +#define AO_BUTTON_1 1 + +#define AO_BUTTON_ARM_1 1 + +#define AO_BUTTON_ARM_NUM 2 + +#define AO_BUTTON_2_PORT &stm_gpioa +#define AO_BUTTON_2 2 + +#define AO_BUTTON_FIRE 2 + +#endif /* _AO_PINS_H_ */ diff --git a/src/telelcotwo-v0.1/ao_telelcotwo.c b/src/telelcotwo-v0.1/ao_telelcotwo.c new file mode 100644 index 00000000..318875e3 --- /dev/null +++ b/src/telelcotwo-v0.1/ao_telelcotwo.c @@ -0,0 +1,65 @@ +/* + * Copyright © 2011 Keith Packard + * + * 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 +#include +#include +#include + +int +main(void) +{ + ao_clock_init(); + + ao_led_init(LEDS_AVAILABLE); + ao_led_on(AO_LED_GREEN); + ao_beep_init(); + ao_task_init(); + + ao_timer_init(); + + ao_spi_init(); + ao_dma_init(); + ao_exti_init(); + + ao_cmd_init(); + + ao_button_init(); + + ao_eeprom_init(); + + ao_radio_init(); + + ao_usb_init(); + + ao_config_init(); + + ao_lco_init(); + ao_lco_cmd_init(); +// ao_radio_cmac_cmd_init(); + + ao_start_scheduler(); + return 0; +} diff --git a/src/telelcotwo-v0.1/flash-loader/Makefile b/src/telelcotwo-v0.1/flash-loader/Makefile new file mode 100644 index 00000000..69833314 --- /dev/null +++ b/src/telelcotwo-v0.1/flash-loader/Makefile @@ -0,0 +1,8 @@ +# +# AltOS flash loader build +# +# + +TOPDIR=../.. +HARDWARE=telelcotwo-v0.1 +include $(TOPDIR)/stm/Makefile-flash.defs diff --git a/src/telelcotwo-v0.1/flash-loader/ao_pins.h b/src/telelcotwo-v0.1/flash-loader/ao_pins.h new file mode 100644 index 00000000..266bff6c --- /dev/null +++ b/src/telelcotwo-v0.1/flash-loader/ao_pins.h @@ -0,0 +1,34 @@ +/* + * Copyright © 2013 Keith Packard + * + * 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 + +/* Fire switch. Press at power on to get boot loader */ + +#define AO_BOOT_PIN 1 +#define AO_BOOT_APPLICATION_GPIO stm_gpioa +#define AO_BOOT_APPLICATION_PIN 2 +#define AO_BOOT_APPLICATION_VALUE 1 +#define AO_BOOT_APPLICATION_MODE AO_EXTI_MODE_PULL_UP + +#endif /* _AO_PINS_H_ */ -- cgit v1.2.3 From 26023cfbf7e117114a4d62b7dbfc0f907efdfb47 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 21 Dec 2015 21:52:31 -0800 Subject: altos: Fix telefiretwo .gitignore Was ignoring the wrong built files Signed-off-by: Keith Packard --- src/telefiretwo-v0.1/.gitignore | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/telefiretwo-v0.1/.gitignore b/src/telefiretwo-v0.1/.gitignore index 4d4f4200..e89f9fd7 100644 --- a/src/telefiretwo-v0.1/.gitignore +++ b/src/telefiretwo-v0.1/.gitignore @@ -1,2 +1,2 @@ -telefire-* +telefiretwo-* ao_product.h -- cgit v1.2.3 From 4c2a7503373c0584de77f9b0e5632a58ab8bbd1f Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 25 Dec 2015 11:26:34 -0800 Subject: altos: Add ao_lco_two.c; alternate LCO interface code The LCO interface is likely to end up very device specific as the interactions depends on the input devices. Here's a version for TeleLCOTwo, which has two arming switches and a firing button. Signed-off-by: Keith Packard --- src/drivers/ao_lco_two.c | 271 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 271 insertions(+) create mode 100644 src/drivers/ao_lco_two.c (limited to 'src') diff --git a/src/drivers/ao_lco_two.c b/src/drivers/ao_lco_two.c new file mode 100644 index 00000000..0fd8e362 --- /dev/null +++ b/src/drivers/ao_lco_two.c @@ -0,0 +1,271 @@ +/* + * 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 +#include + +#define DEBUG 1 + +#if DEBUG +static uint8_t ao_lco_debug; +#define DEBUG_EVENT 1 +#define DEBUG_STATUS 2 +#define PRINTD(l, ...) do { if (!(ao_lco_debug & l)) break; printf ("\r%5u %s: ", ao_tick_count, __func__); printf(__VA_ARGS__); flush(); } while(0) +#else +#define PRINTD(l,...) +#endif + +#define AO_LCO_VALID_LAST 1 +#define AO_LCO_VALID_EVER 2 + +static uint8_t ao_lco_selected; +static uint8_t ao_lco_valid; +static uint8_t ao_lco_channels; +static uint16_t ao_lco_tick_offset; + +/* UI values */ +static uint8_t ao_lco_armed; +static uint8_t ao_lco_firing; +static uint8_t ao_lco_fire_down; + +#define ao_lco_box (ao_config.pad_box) + +static struct ao_pad_query ao_pad_query; + +#define MASK_SIZE(n) (((n) + 7) >> 3) +#define MASK_ID(n) ((n) >> 3) +#define MASK_SHIFT(n) ((n) & 7) + +static void +ao_lco_set_armed(int pad, int armed) +{ + uint8_t bit = (1 << pad); + + if (armed) { + ao_lco_selected |= bit; + ao_lco_armed |= bit; + } else { + ao_lco_selected &= ~bit; + ao_lco_armed &= ~bit; + } + PRINTD(DEBUG_EVENT, "pad %d bit 0x%x armed %d ao_lco_selected 0x%x ao_lco_armed 0x%x\n", + pad, bit, armed, ao_lco_selected, ao_lco_armed); + ao_wakeup(&ao_lco_armed); +} + +static void +ao_lco_input(void) +{ + static struct ao_event event; + + for (;;) { + ao_event_get(&event); + PRINTD(DEBUG_EVENT, "event type %d unit %d value %d\n", + event.type, event.unit, event.value); + switch (event.type) { + case AO_EVENT_BUTTON: + switch (event.unit) { + case AO_BUTTON_ARM_0: + ao_lco_set_armed(0, event.value); + break; +#if AO_BUTTON_ARM_NUM > 1 + case AO_BUTTON_ARM_1: + ao_lco_set_armed(1, event.value); + break; +#endif + case AO_BUTTON_FIRE: + if (ao_lco_armed) { + ao_lco_fire_down = 0; + ao_lco_firing = event.value; + PRINTD(DEBUG_EVENT, "Firing %d\n", ao_lco_firing); + ao_wakeup(&ao_lco_armed); + } + break; + } + break; + } + } +} + +static AO_LED_TYPE continuity_led[AO_LED_CONTINUITY_NUM] = { +#ifdef AO_LED_CONTINUITY_0 + AO_LED_CONTINUITY_0, +#endif +#ifdef AO_LED_CONTINUITY_1 + AO_LED_CONTINUITY_1, +#endif +#ifdef AO_LED_CONTINUITY_2 + AO_LED_CONTINUITY_2, +#endif +#ifdef AO_LED_CONTINUITY_3 + AO_LED_CONTINUITY_3, +#endif +#ifdef AO_LED_CONTINUITY_4 + AO_LED_CONTINUITY_4, +#endif +#ifdef AO_LED_CONTINUITY_5 + AO_LED_CONTINUITY_5, +#endif +#ifdef AO_LED_CONTINUITY_6 + AO_LED_CONTINUITY_6, +#endif +#ifdef AO_LED_CONTINUITY_7 + AO_LED_CONTINUITY_7, +#endif +}; + +static uint8_t +ao_lco_get_channels(void) +{ + int8_t r; + + r = ao_lco_query(ao_lco_box, &ao_pad_query, &ao_lco_tick_offset); + if (r == AO_RADIO_CMAC_OK) { + ao_lco_channels = ao_pad_query.channels; + ao_lco_valid = AO_LCO_VALID_LAST | AO_LCO_VALID_EVER; + } else + ao_lco_valid &= ~AO_LCO_VALID_LAST; + PRINTD(DEBUG_STATUS, "ao_lco_get_channels() rssi %d valid %d ret %d offset %d\n", ao_radio_cmac_rssi, ao_lco_valid, r, ao_lco_tick_offset); + ao_wakeup(&ao_pad_query); + return ao_lco_valid; +} + +static void +ao_lco_igniter_status(void) +{ + uint8_t c; + uint8_t t = 0; + + for (;;) { + ao_sleep(&ao_pad_query); + PRINTD(DEBUG_STATUS, "RSSI %d VALID %d\n", ao_radio_cmac_rssi, ao_lco_valid); + if (!(ao_lco_valid & AO_LCO_VALID_LAST)) { + ao_led_on(AO_LED_RED); + ao_led_off(AO_LED_GREEN|AO_LED_AMBER); + continue; + } + if (ao_radio_cmac_rssi < -90) { + ao_led_on(AO_LED_AMBER); + ao_led_off(AO_LED_RED|AO_LED_GREEN); + } else { + ao_led_on(AO_LED_GREEN); + ao_led_off(AO_LED_RED|AO_LED_AMBER); + } + if (ao_pad_query.arm_status) + ao_led_on(AO_LED_REMOTE_ARM); + else + ao_led_off(AO_LED_REMOTE_ARM); + + for (c = 0; c < AO_LED_CONTINUITY_NUM; c++) { + uint8_t status; + + if (ao_pad_query.channels & (1 << c)) + status = ao_pad_query.igniter_status[c]; + else + status = AO_PAD_IGNITER_STATUS_NO_IGNITER_RELAY_OPEN; + PRINTD(DEBUG_STATUS, "\tchannel %d status %d\n", c, status); + if (status == AO_PAD_IGNITER_STATUS_GOOD_IGNITER_RELAY_OPEN) + ao_led_on(continuity_led[c]); + else + ao_led_off(continuity_led[c]); + } + t = 1-t; + } +} + +static void +ao_lco_arm_warn(void) +{ + int i; + for (;;) { + while (!ao_lco_armed) + ao_sleep(&ao_lco_armed); + for (i = 0; i < ao_lco_armed; i++) { + ao_beep_for(AO_BEEP_MID, AO_MS_TO_TICKS(100)); + ao_delay(AO_MS_TO_TICKS(100)); + } + ao_delay(AO_MS_TO_TICKS(300)); + } +} + +static struct ao_task ao_lco_input_task; +static struct ao_task ao_lco_monitor_task; +static struct ao_task ao_lco_arm_warn_task; +static struct ao_task ao_lco_igniter_status_task; + +static void +ao_lco_monitor(void) +{ + uint16_t delay; + + ao_add_task(&ao_lco_input_task, ao_lco_input, "lco input"); + ao_add_task(&ao_lco_arm_warn_task, ao_lco_arm_warn, "lco arm warn"); + ao_add_task(&ao_lco_igniter_status_task, ao_lco_igniter_status, "lco igniter status"); + ao_beep_for(AO_BEEP_MID, AO_MS_TO_TICKS(200)); + for (;;) { + PRINTD(DEBUG_STATUS, "monitor armed %d firing %d\n", + ao_lco_armed, ao_lco_firing); + + if (ao_lco_armed && ao_lco_firing) { + ao_lco_ignite(); + } else { + ao_lco_get_channels(); + if (ao_lco_armed) { + if (ao_lco_selected) { + PRINTD(DEBUG_STATUS, "Arming pads %x\n", + ao_lco_selected); + if (ao_lco_valid & AO_LCO_VALID_EVER) { + ao_lco_arm(ao_lco_box, ao_lco_selected, ao_lco_tick_offset); + ao_delay(AO_MS_TO_TICKS(10)); + } + } + } + } + if (ao_lco_armed && ao_lco_firing) + delay = AO_MS_TO_TICKS(100); + else + delay = AO_SEC_TO_TICKS(1); + ao_sleep_for(&ao_lco_armed, delay); + } +} + +#if DEBUG +void +ao_lco_set_debug(void) +{ + ao_cmd_decimal(); + if (ao_cmd_status == ao_cmd_success) + ao_lco_debug = ao_cmd_lex_i; +} + +__code struct ao_cmds ao_lco_cmds[] = { + { ao_lco_set_debug, "D <0 off, 1 on>\0Debug" }, + { 0, NULL } +}; +#endif + +void +ao_lco_init(void) +{ + ao_add_task(&ao_lco_monitor_task, ao_lco_monitor, "lco monitor"); +#if DEBUG + ao_cmd_register(&ao_lco_cmds[0]); +#endif +} -- cgit v1.2.3 From aef5049cf8311927fada922730f85f31c8ddf177 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 25 Dec 2015 20:46:40 -0800 Subject: altos: Use simpler debounce logic for buttons Instead of waiting for a while after the transition to decide if it has stuck, signal the event right away and then ignore other transitions for the debounce interval. This seems to work just as reliably, but has the benefit of eliminating button latency at press time. Signed-off-by: Keith Packard --- src/drivers/ao_button.c | 52 ++++++++++++++++++++++++++------------------ src/telelco-v0.2/Makefile | 2 -- src/telelco-v0.3/Makefile | 2 -- src/telelcotwo-v0.1/Makefile | 2 -- 4 files changed, 31 insertions(+), 27 deletions(-) (limited to 'src') diff --git a/src/drivers/ao_button.c b/src/drivers/ao_button.c index cdf07352..8e7dead7 100644 --- a/src/drivers/ao_button.c +++ b/src/drivers/ao_button.c @@ -18,7 +18,6 @@ #include #include #include -#include #if AO_EVENT #include #define ao_button_queue(b,v) ao_event_put_isr(AO_EVENT_BUTTON, b, v) @@ -26,9 +25,14 @@ #define ao_button_queue(b,v) #endif -#define AO_BUTTON_DEBOUNCE_HOLD 10 +#define AO_BUTTON_DEBOUNCE_INTERVAL AO_MS_TO_TICKS(50) -static struct ao_debounce ao_button_debounce[AO_BUTTON_COUNT]; +struct ao_button_state { + AO_TICK_TYPE time; + uint8_t value; +}; + +static struct ao_button_state ao_button_state[AO_BUTTON_COUNT]; #define port(q) AO_BUTTON_ ## q ## _PORT #define bit(q) AO_BUTTON_ ## q @@ -38,10 +42,8 @@ static struct ao_debounce ao_button_debounce[AO_BUTTON_COUNT]; #define ao_button_value(b) !ao_gpio_get(port(b), bit(b), pin(b)) static uint8_t -_ao_button_get(struct ao_debounce *debounce) +_ao_button_get(uint8_t b) { - uint8_t b = debounce - ao_button_debounce; - switch (b) { #if AO_BUTTON_COUNT > 0 case 0: return ao_button_value(0); @@ -63,22 +65,31 @@ _ao_button_get(struct ao_debounce *debounce) } static void -_ao_button_set(struct ao_debounce *debounce, uint8_t value) +_ao_button_check(uint8_t b) { - uint8_t b = debounce - ao_button_debounce; - - ao_button_queue(b, value); -} + uint8_t value = _ao_button_get(b); + if (value != ao_button_state[b].value) { + AO_TICK_TYPE now = ao_time(); -#define ao_button_update(b) ao_button_do(b, ao_gpio_get(port(b), bit(b), pin(b))) + if ((now - ao_button_state[b].time) >= AO_BUTTON_DEBOUNCE_INTERVAL) { + ao_button_state[b].value = value; + ao_button_queue(b, value); + } + ao_button_state[b].time = now; + } +} static void -ao_button_debounce_init(struct ao_debounce *debounce) { - ao_debounce_config(debounce, - _ao_button_get, - _ao_button_set, - AO_BUTTON_DEBOUNCE_HOLD); +_ao_button_init(uint8_t b) +{ + uint8_t m = ao_arch_irqsave(); + uint8_t value = _ao_button_get(b); + ao_button_state[b].value = value; + ao_button_state[b].time = ao_time(); + ao_button_queue(b, value); + ao_arch_irqrestore(m); + } static void @@ -87,17 +98,17 @@ ao_button_isr(void) uint8_t b; for (b = 0; b < AO_BUTTON_COUNT; b++) - _ao_debounce_start(&ao_button_debounce[b]); + _ao_button_check(b); } #define init(b) do { \ - ao_button_debounce_init(&ao_button_debounce[b]); \ ao_enable_port(port(b)); \ \ ao_exti_setup(port(b), bit(b), \ AO_BUTTON_MODE|AO_EXTI_MODE_FALLING|AO_EXTI_MODE_RISING|AO_EXTI_PRIORITY_MED, \ - ao_button_isr); \ + ao_button_isr); \ ao_exti_enable(port(b), bit(b)); \ + _ao_button_init(b); \ } while (0) void @@ -118,5 +129,4 @@ ao_button_init(void) #if AO_BUTTON_COUNT > 4 init(4); #endif - ao_debounce_init(); } diff --git a/src/telelco-v0.2/Makefile b/src/telelco-v0.2/Makefile index 7a21f099..8c1ced6c 100644 --- a/src/telelco-v0.2/Makefile +++ b/src/telelco-v0.2/Makefile @@ -22,7 +22,6 @@ INC = \ ao_radio_spi.h \ ao_radio_cmac.h \ ao_cc1120_CC1120.h \ - ao_debounce.h \ stm32l.h # @@ -61,7 +60,6 @@ ALTOS_SRC = \ ao_fec_tx.c \ ao_fec_rx.c \ ao_seven_segment.c \ - ao_debounce.c \ ao_quadrature.c \ ao_button.c \ ao_event.c \ diff --git a/src/telelco-v0.3/Makefile b/src/telelco-v0.3/Makefile index 83d3fc43..0bb0f9dc 100644 --- a/src/telelco-v0.3/Makefile +++ b/src/telelco-v0.3/Makefile @@ -23,7 +23,6 @@ INC = \ ao_radio_cmac.h \ ao_cc1200_CC1200.h \ ao_cc1200.h \ - ao_debounce.h \ stm32l.h # @@ -62,7 +61,6 @@ ALTOS_SRC = \ ao_fec_tx.c \ ao_fec_rx.c \ ao_seven_segment.c \ - ao_debounce.c \ ao_quadrature.c \ ao_button.c \ ao_event.c \ diff --git a/src/telelcotwo-v0.1/Makefile b/src/telelcotwo-v0.1/Makefile index 8ceb7d2c..42188bb2 100644 --- a/src/telelcotwo-v0.1/Makefile +++ b/src/telelcotwo-v0.1/Makefile @@ -19,7 +19,6 @@ INC = \ ao_radio_cmac.h \ ao_cc1200_CC1200.h \ ao_cc1200.h \ - ao_debounce.h \ stm32l.h # @@ -56,7 +55,6 @@ ALTOS_SRC = \ ao_aes_tables.c \ ao_fec_tx.c \ ao_fec_rx.c \ - ao_debounce.c \ ao_button.c \ ao_event.c \ ao_lco_two.c \ -- cgit v1.2.3 From 70e46100acf597014ce54cf3b642254ce1cba59b Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 5 Apr 2016 23:45:52 -0700 Subject: altos/telelcotwo: Add idle timeout MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Puts TeleLCOTwo in a low power state (drawing about 80µA) after a timeout (default two minutes) to keep from killing the battery if the device is left turned on. Signed-off-by: Keith Packard --- src/drivers/ao_event.c | 16 +++++++++++++++ src/drivers/ao_event.h | 3 +++ src/drivers/ao_lco_two.c | 53 +++++++++++++++++++++++++++++++++++++++++++----- src/kernel/ao_config.c | 21 +++++++++++++++++++ src/kernel/ao_config.h | 3 ++- 5 files changed, 90 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/drivers/ao_event.c b/src/drivers/ao_event.c index 5c0d2863..8f88d778 100644 --- a/src/drivers/ao_event.c +++ b/src/drivers/ao_event.c @@ -41,6 +41,22 @@ ao_event_get(struct ao_event *ev) ); } +uint8_t +ao_event_get_for(struct ao_event *ev, uint16_t timeout) +{ + uint8_t empty = 1; + ao_arch_critical( + while ((empty = ao_event_queue_empty())) + if (ao_sleep_for(&ao_event_queue, timeout)) + break; + if (!empty) { + *ev = ao_event_queue[ao_event_queue_remove]; + ao_event_queue_remove = ao_event_queue_next(ao_event_queue_remove); + } + ); + return empty; +} + /* called with interrupts disabled */ void ao_event_put_isr(uint8_t type, uint8_t unit, int32_t value) diff --git a/src/drivers/ao_event.h b/src/drivers/ao_event.h index 584a845a..ea89da23 100644 --- a/src/drivers/ao_event.h +++ b/src/drivers/ao_event.h @@ -32,6 +32,9 @@ struct ao_event { void ao_event_get(struct ao_event *ev); +uint8_t +ao_event_get_for(struct ao_event *ev, uint16_t timeout); + void ao_event_put_isr(uint8_t type, uint8_t unit, int32_t value); diff --git a/src/drivers/ao_lco_two.c b/src/drivers/ao_lco_two.c index 0fd8e362..f53fef7d 100644 --- a/src/drivers/ao_lco_two.c +++ b/src/drivers/ao_lco_two.c @@ -29,12 +29,13 @@ static uint8_t ao_lco_debug; #define DEBUG_STATUS 2 #define PRINTD(l, ...) do { if (!(ao_lco_debug & l)) break; printf ("\r%5u %s: ", ao_tick_count, __func__); printf(__VA_ARGS__); flush(); } while(0) #else -#define PRINTD(l,...) +#define PRINTD(l,...) #endif #define AO_LCO_VALID_LAST 1 #define AO_LCO_VALID_EVER 2 +static uint8_t ao_lco_suspended; static uint8_t ao_lco_selected; static uint8_t ao_lco_valid; static uint8_t ao_lco_channels; @@ -43,7 +44,6 @@ static uint16_t ao_lco_tick_offset; /* UI values */ static uint8_t ao_lco_armed; static uint8_t ao_lco_firing; -static uint8_t ao_lco_fire_down; #define ao_lco_box (ao_config.pad_box) @@ -70,13 +70,45 @@ ao_lco_set_armed(int pad, int armed) ao_wakeup(&ao_lco_armed); } +static void +ao_lco_suspend(void) +{ + if (!ao_lco_suspended) { + PRINTD(DEBUG_EVENT, "suspend\n"); + ao_lco_suspended = 1; + ao_lco_selected = 0; + ao_lco_armed = 0; + ao_wakeup(&ao_pad_query); + } +} + +static void +ao_lco_wakeup(void) +{ + if (ao_lco_suspended) { + ao_lco_suspended = 0; + ao_wakeup(&ao_lco_suspended); + } +} + static void ao_lco_input(void) { static struct ao_event event; + uint8_t timeout; + ao_config_get(); for (;;) { - ao_event_get(&event); + if (ao_config.pad_idle && !ao_lco_suspended) { + timeout = ao_event_get_for(&event, AO_SEC_TO_TICKS(ao_config.pad_idle)); + if (timeout) { + ao_lco_suspend(); + continue; + } + } else { + ao_event_get(&event); + } + ao_lco_wakeup(); PRINTD(DEBUG_EVENT, "event type %d unit %d value %d\n", event.type, event.unit, event.value); switch (event.type) { @@ -92,7 +124,6 @@ ao_lco_input(void) #endif case AO_BUTTON_FIRE: if (ao_lco_armed) { - ao_lco_fire_down = 0; ao_lco_firing = event.value; PRINTD(DEBUG_EVENT, "Firing %d\n", ao_lco_firing); ao_wakeup(&ao_lco_armed); @@ -155,6 +186,12 @@ ao_lco_igniter_status(void) for (;;) { ao_sleep(&ao_pad_query); + while (ao_lco_suspended) { + ao_led_off(AO_LED_GREEN|AO_LED_AMBER|AO_LED_RED|AO_LED_REMOTE_ARM); + for (c = 0; c < AO_LED_CONTINUITY_NUM; c++) + ao_led_off(continuity_led[c]); + ao_sleep(&ao_lco_suspended); + } PRINTD(DEBUG_STATUS, "RSSI %d VALID %d\n", ao_radio_cmac_rssi, ao_lco_valid); if (!(ao_lco_valid & AO_LCO_VALID_LAST)) { ao_led_on(AO_LED_RED); @@ -195,6 +232,8 @@ ao_lco_arm_warn(void) { int i; for (;;) { + while (ao_lco_suspended) + ao_sleep(&ao_lco_suspended); while (!ao_lco_armed) ao_sleep(&ao_lco_armed); for (i = 0; i < ao_lco_armed; i++) { @@ -220,6 +259,9 @@ ao_lco_monitor(void) ao_add_task(&ao_lco_igniter_status_task, ao_lco_igniter_status, "lco igniter status"); ao_beep_for(AO_BEEP_MID, AO_MS_TO_TICKS(200)); for (;;) { + while (ao_lco_suspended) + ao_sleep(&ao_lco_suspended); + PRINTD(DEBUG_STATUS, "monitor armed %d firing %d\n", ao_lco_armed, ao_lco_firing); @@ -240,8 +282,9 @@ ao_lco_monitor(void) } if (ao_lco_armed && ao_lco_firing) delay = AO_MS_TO_TICKS(100); - else + else { delay = AO_SEC_TO_TICKS(1); + } ao_sleep_for(&ao_lco_armed, delay); } } diff --git a/src/kernel/ao_config.c b/src/kernel/ao_config.c index d51fbb41..f95ca893 100644 --- a/src/kernel/ao_config.c +++ b/src/kernel/ao_config.c @@ -227,6 +227,8 @@ _ao_config_get(void) #if HAS_FIXED_PAD_BOX if (minor < 22) ao_config.pad_box = 1; + if (minor < 23) + ao_config.pad_idle = 120; #endif ao_config.minor = AO_CONFIG_MINOR; ao_config_dirty = 1; @@ -920,6 +922,23 @@ ao_config_pad_box_set(void) ao_config.pad_box = ao_cmd_lex_i; _ao_config_edit_finish(); } + +void +ao_config_pad_idle_show(void) +{ + printf ("Idle timeout: %d\n", ao_config.pad_idle); +} + +void +ao_config_pad_idle_set(void) +{ + ao_cmd_decimal(); + if (ao_cmd_status != ao_cmd_success) + return; + _ao_config_edit_start(); + ao_config.pad_idle = ao_cmd_lex_i; + _ao_config_edit_finish(); +} #endif struct ao_config_var { @@ -1019,6 +1038,8 @@ __code struct ao_config_var ao_config_vars[] = { #if HAS_FIXED_PAD_BOX { "B \0Set pad box (1-99)", ao_config_pad_box_set, ao_config_pad_box_show }, + { "i \0Set idle timeout (0 disable)", + ao_config_pad_idle_set, ao_config_pad_idle_show }, #endif { "s\0Show", ao_config_show, 0 }, diff --git a/src/kernel/ao_config.h b/src/kernel/ao_config.h index f4e9af44..3c73ea49 100644 --- a/src/kernel/ao_config.h +++ b/src/kernel/ao_config.h @@ -57,7 +57,7 @@ #endif #define AO_CONFIG_MAJOR 1 -#define AO_CONFIG_MINOR 22 +#define AO_CONFIG_MINOR 23 #define AO_AES_LEN 16 @@ -120,6 +120,7 @@ struct ao_config { #endif #if HAS_FIXED_PAD_BOX uint8_t pad_box; /* minor version 22 */ + uint8_t pad_idle; /* minor version 23 */ #endif }; -- cgit v1.2.3 From 14fecd672807982ce6232fa3b4bdce0aebe132e8 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 6 Apr 2016 22:32:36 -0700 Subject: Add TeleFireTwo v0.2 project This is much like TeleFireTwo v0.1, with only one pyro channel and added siren and strobe Signed-off-by: Keith Packard --- src/telefiretwo-v0.2/.gitignore | 2 + src/telefiretwo-v0.2/Makefile | 90 ++++++++++++ src/telefiretwo-v0.2/ao_pins.h | 210 +++++++++++++++++++++++++++ src/telefiretwo-v0.2/ao_telefiretwo.c | 54 +++++++ src/telefiretwo-v0.2/flash-loader/.gitignore | 2 + src/telefiretwo-v0.2/flash-loader/Makefile | 8 + src/telefiretwo-v0.2/flash-loader/ao_pins.h | 32 ++++ 7 files changed, 398 insertions(+) create mode 100644 src/telefiretwo-v0.2/.gitignore create mode 100644 src/telefiretwo-v0.2/Makefile create mode 100644 src/telefiretwo-v0.2/ao_pins.h create mode 100644 src/telefiretwo-v0.2/ao_telefiretwo.c create mode 100644 src/telefiretwo-v0.2/flash-loader/.gitignore create mode 100644 src/telefiretwo-v0.2/flash-loader/Makefile create mode 100644 src/telefiretwo-v0.2/flash-loader/ao_pins.h (limited to 'src') diff --git a/src/telefiretwo-v0.2/.gitignore b/src/telefiretwo-v0.2/.gitignore new file mode 100644 index 00000000..e89f9fd7 --- /dev/null +++ b/src/telefiretwo-v0.2/.gitignore @@ -0,0 +1,2 @@ +telefiretwo-* +ao_product.h diff --git a/src/telefiretwo-v0.2/Makefile b/src/telefiretwo-v0.2/Makefile new file mode 100644 index 00000000..30985f9c --- /dev/null +++ b/src/telefiretwo-v0.2/Makefile @@ -0,0 +1,90 @@ +# +# TeleFire build file +# + +include ../stm/Makefile.defs + +INC = \ + ao.h \ + ao_pins.h \ + ao_arch.h \ + ao_arch_funcs.h \ + ao_pad.h \ + ao_product.h \ + ao_radio_spi.h \ + ao_radio_cmac.h \ + ao_cc1200_CC1200.h \ + ao_cc1200.h \ + stm32l.h +# +# Common AltOS sources +# + +#PROFILE=ao_profile.c +#PROFILE_DEF=-DAO_PROFILE=1 + +ALTOS_SRC = \ + ao_boot_chain.c \ + ao_interrupt.c \ + ao_product.c \ + ao_romconfig.c \ + ao_cmd.c \ + ao_adc_stm.c \ + ao_data.c \ + ao_config.c \ + ao_task.c \ + ao_led.c \ + ao_stdio.c \ + ao_panic.c \ + ao_timer.c \ + ao_mutex.c \ + ao_freq.c \ + ao_dma_stm.c \ + ao_spi_stm.c \ + ao_beep_stm.c \ + ao_eeprom_stm.c \ + ao_usb_stm.c \ + ao_exti_stm.c \ + ao_cc1200.c \ + ao_radio_cmac.c \ + ao_aes.c \ + ao_aes_tables.c \ + ao_pad.c \ + ao_radio_cmac_cmd.c + +PRODUCT_SRC = \ + ao_telefiretwo.c + +PRODUCT=TeleFire-v0.2 +PRODUCT_DEF=-DTELEFIRETWO_V_0_2 +IDPRODUCT=0x000f + +CFLAGS = $(PRODUCT_DEF) $(STM_CFLAGS) $(PROFILE_DEF) -Os -g + +PROGNAME = telefiretwo-v0.2 +PROG = $(PROGNAME)-$(VERSION).elf +HEX = $(PROGNAME)-$(VERSION).ihx + +SRC = $(ALTOS_SRC) $(PRODUCT_SRC) +OBJ=$(SRC:.c=.o) + +all: $(PROG) $(HEX) + +$(PROG): Makefile $(OBJ) altos.ld + $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(OBJ) $(LIBS) + +$(OBJ): $(INC) + +ao_product.h: ao-make-product.5c ../Version + $(call quiet,NICKLE,$<) $< -m altusmetrum.org -i $(IDPRODUCT) -p $(PRODUCT) -v $(VERSION) > $@ + +distclean: clean + +clean: + rm -f *.o $(PROGNAME)-*.elf $(PROGNAME)-*.ihx + rm -f ao_product.h + +install: + +uninstall: + diff --git a/src/telefiretwo-v0.2/ao_pins.h b/src/telefiretwo-v0.2/ao_pins.h new file mode 100644 index 00000000..f6656f16 --- /dev/null +++ b/src/telefiretwo-v0.2/ao_pins.h @@ -0,0 +1,210 @@ +/* + * Copyright © 2010 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_RADIO 1 +#define HAS_RADIO_RATE 1 +#define HAS_TELEMETRY 0 + +#define HAS_FLIGHT 0 +#define HAS_USB 1 +#define HAS_BEEP 1 +#define BEEPER_CHANNEL 4 +#define HAS_GPS 0 +#define HAS_SERIAL_1 0 +#define HAS_ADC 1 +#define HAS_DBG 0 +#define HAS_EEPROM 1 +#define HAS_LOG 0 +#define HAS_PAD 1 +#define USE_INTERNAL_FLASH 1 +#define IGNITE_ON_P0 0 +#define PACKET_HAS_MASTER 0 +#define PACKET_HAS_SLAVE 0 +#define AO_DATA_RING 32 +#define HAS_FIXED_PAD_BOX 1 + +/* 8MHz High speed external crystal */ +#define AO_HSE 8000000 + +/* PLLVCO = 96MHz (so that USB will work) */ +#define AO_PLLMUL 12 +#define AO_RCC_CFGR_PLLMUL (STM_RCC_CFGR_PLLMUL_12) + +#define AO_CC1200_FOSC 40000000 + +/* SYSCLK = 32MHz (no need to go faster than CPU) */ +#define AO_PLLDIV 3 +#define AO_RCC_CFGR_PLLDIV (STM_RCC_CFGR_PLLDIV_3) + +/* HCLK = 32MHz (CPU clock) */ +#define AO_AHB_PRESCALER 1 +#define AO_RCC_CFGR_HPRE_DIV STM_RCC_CFGR_HPRE_DIV_1 + +/* Run APB1 at 16MHz (HCLK/2) */ +#define AO_APB1_PRESCALER 2 +#define AO_RCC_CFGR_PPRE1_DIV STM_RCC_CFGR_PPRE2_DIV_2 + +/* Run APB2 at 16MHz (HCLK/2) */ +#define AO_APB2_PRESCALER 2 +#define AO_RCC_CFGR_PPRE2_DIV STM_RCC_CFGR_PPRE2_DIV_2 + +#define HAS_EEPROM 1 +#define USE_INTERNAL_FLASH 1 +#define USE_EEPROM_CONFIG 1 +#define USE_STORAGE_CONFIG 0 +#define HAS_USB 1 +#define HAS_RADIO 1 +#define HAS_RADIO_RATE 1 +#define HAS_TELEMETRY 0 +#define HAS_AES 1 + +#define HAS_SPI_1 0 +#define SPI_1_PA5_PA6_PA7 0 +#define SPI_1_PB3_PB4_PB5 0 +#define SPI_1_PE13_PE14_PE15 0 + +#define HAS_SPI_2 1 /* CC1200 */ +#define SPI_2_PB13_PB14_PB15 1 +#define SPI_2_PD1_PD3_PD4 0 +#define SPI_2_GPIO (&stm_gpiob) +#define SPI_2_SCK 13 +#define SPI_2_MISO 14 +#define SPI_2_MOSI 15 +#define SPI_2_OSPEEDR STM_OSPEEDR_10MHz + +#define HAS_I2C_1 0 + +#define HAS_I2C_2 0 + +#define PACKET_HAS_SLAVE 0 +#define PACKET_HAS_MASTER 0 + +#define FAST_TIMER_FREQ 10000 /* .1ms for debouncing */ + +/* + * Radio is a cc1200 connected via SPI + */ + +#define AO_RADIO_CAL_DEFAULT 5695733 + +#define AO_FEC_DEBUG 0 +#define AO_CC1200_SPI_CS_PORT (&stm_gpioa) +#define AO_CC1200_SPI_CS_PIN 7 +#define AO_CC1200_SPI_BUS AO_SPI_2_PB13_PB14_PB15 +#define AO_CC1200_SPI stm_spi2 + +#define AO_CC1200_INT_PORT (&stm_gpiob) +#define AO_CC1200_INT_PIN (11) + +#define AO_CC1200_INT_GPIO 2 +#define AO_CC1200_INT_GPIO_IOCFG CC1200_IOCFG2 + +#define LED_PORT_0 (&stm_gpioa) +#define LED_PORT_1 (&stm_gpiob) + +#define LED_PORT_0_ENABLE STM_RCC_AHBENR_GPIOAEN +#define LED_PORT_1_ENABLE STM_RCC_AHBENR_GPIOBEN + +/* Port A, pins 4-6 */ +#define LED_PORT_0_SHIFT 4 +#define LED_PORT_0_MASK 0x7 +#define LED_PIN_GREEN 0 +#define LED_PIN_AMBER 1 +#define LED_PIN_RED 2 +#define AO_LED_RED (1 << LED_PIN_RED) +#define AO_LED_AMBER (1 << LED_PIN_AMBER) +#define AO_LED_GREEN (1 << LED_PIN_GREEN) + +/* Port B, pins 4-5 */ +#define LED_PORT_1_SHIFT 0 +#define LED_PORT_1_MASK (0x3 << 4) +#define LED_PIN_CONT_0 4 +#define LED_PIN_ARMED 5 + +#define AO_LED_ARMED (1 << LED_PIN_ARMED) +#define AO_LED_CONTINUITY(c) (1 << (4 - (c))) +#define AO_LED_CONTINUITY_MASK (0x1 << 4) + +#define LEDS_AVAILABLE (LED_PORT_0_MASK|LED_PORT_1_MASK) + +/* Alarm 2 */ +#define AO_SIREN +#define AO_SIREN_PORT (&stm_gpiob) +#define AO_SIREN_PIN 8 + +/* Alarm 1 */ +#define AO_STROBE +#define AO_STROBE_PORT (&stm_gpiob) +#define AO_STROBE_PIN 9 + +#define SPI_CONST 0x00 + +#define AO_PAD_NUM 1 +#define AO_PAD_PORT (&stm_gpioa) + +#define AO_PAD_PIN_0 1 +#define AO_PAD_ADC_0 0 + +#define AO_PAD_ALL_PINS ((1 << AO_PAD_PIN_0)) +#define AO_PAD_ALL_CHANNELS ((1 << 0)) + +/* test these values with real igniters */ +#define AO_PAD_RELAY_CLOSED 3524 +#define AO_PAD_NO_IGNITER 16904 +#define AO_PAD_GOOD_IGNITER 22514 + +#define AO_PAD_ADC_PYRO 2 +#define AO_PAD_ADC_BATT 8 + +#define AO_ADC_FIRST_PIN 0 + +#define AO_NUM_ADC 3 + +#define AO_ADC_SQ1 AO_PAD_ADC_0 +#define AO_ADC_SQ2 AO_PAD_ADC_PYRO +#define AO_ADC_SQ3 AO_PAD_ADC_BATT + +#define AO_PYRO_R_PYRO_SENSE 200 +#define AO_PYRO_R_SENSE_GND 22 + +#define AO_FIRE_R_POWER_FET 0 +#define AO_FIRE_R_FET_SENSE 200 +#define AO_FIRE_R_SENSE_GND 22 + +#define HAS_ADC_TEMP 0 + +struct ao_adc { + int16_t sense[AO_PAD_NUM]; + int16_t pyro; + int16_t batt; +}; + +#define AO_ADC_DUMP(p) \ + printf ("tick: %5u 0: %5d pyro: %5d batt %5d\n", \ + (p)->tick, \ + (p)->adc.sense[0], \ + (p)->adc.pyro, \ + (p)->adc.batt) + +#define AO_ADC_PINS ((1 << AO_PAD_ADC_0) | \ + (1 << AO_PAD_ADC_PYRO) | \ + (1 << AO_PAD_ADC_BATT)) + +#endif /* _AO_PINS_H_ */ diff --git a/src/telefiretwo-v0.2/ao_telefiretwo.c b/src/telefiretwo-v0.2/ao_telefiretwo.c new file mode 100644 index 00000000..38629d86 --- /dev/null +++ b/src/telefiretwo-v0.2/ao_telefiretwo.c @@ -0,0 +1,54 @@ +/* + * Copyright © 2012 Keith Packard + * + * 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 + +void +main(void) +{ + ao_clock_init(); + + ao_led_init(LEDS_AVAILABLE); + + ao_task_init(); + + ao_timer_init(); + ao_spi_init(); + ao_dma_init(); + ao_exti_init(); + + ao_cmd_init(); + + ao_adc_init(); + + ao_eeprom_init(); + + ao_radio_init(); + + ao_usb_init(); + + ao_config_init(); + + ao_pad_init(); + +// ao_radio_cmac_cmd_init(); + + ao_start_scheduler(); +} diff --git a/src/telefiretwo-v0.2/flash-loader/.gitignore b/src/telefiretwo-v0.2/flash-loader/.gitignore new file mode 100644 index 00000000..65fe7eab --- /dev/null +++ b/src/telefiretwo-v0.2/flash-loader/.gitignore @@ -0,0 +1,2 @@ +*.elf +*.ihx diff --git a/src/telefiretwo-v0.2/flash-loader/Makefile b/src/telefiretwo-v0.2/flash-loader/Makefile new file mode 100644 index 00000000..2b029ee0 --- /dev/null +++ b/src/telefiretwo-v0.2/flash-loader/Makefile @@ -0,0 +1,8 @@ +# +# AltOS flash loader build +# +# + +TOPDIR=../.. +HARDWARE=telefiretwo-v0.2 +include $(TOPDIR)/stm/Makefile-flash.defs diff --git a/src/telefiretwo-v0.2/flash-loader/ao_pins.h b/src/telefiretwo-v0.2/flash-loader/ao_pins.h new file mode 100644 index 00000000..daa9048d --- /dev/null +++ b/src/telefiretwo-v0.2/flash-loader/ao_pins.h @@ -0,0 +1,32 @@ +/* + * Copyright © 2013 Keith Packard + * + * 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 + +#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_ */ -- cgit v1.2.3 From 3abc0fc5e4484d862709501133d35563aa0c25fa Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 13 Apr 2016 06:11:44 -0700 Subject: altos/stmf0: Fix external interrupts Missing a reserved address in the registers broke everything nicely, but the priority values were also wrong - stm32f0 exposes 8 bits per priority, like the stm32l, but it uses only the top two bits. Signed-off-by: Keith Packard --- src/stmf0/ao_arch.h | 8 ++++---- src/stmf0/ao_exti.h | 2 +- src/stmf0/ao_exti_stm.c | 2 +- src/stmf0/stm32f0.h | 3 +++ 4 files changed, 9 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/stmf0/ao_arch.h b/src/stmf0/ao_arch.h index 26a34c85..2597cadc 100644 --- a/src/stmf0/ao_arch.h +++ b/src/stmf0/ao_arch.h @@ -131,10 +131,10 @@ extern const uint32_t ao_radio_cal; #define AO_TIM91011_CLK (2 * AO_PCLK2) #endif -#define AO_STM_NVIC_HIGH_PRIORITY 4 -#define AO_STM_NVIC_CLOCK_PRIORITY 6 -#define AO_STM_NVIC_MED_PRIORITY 8 -#define AO_STM_NVIC_LOW_PRIORITY 10 +#define AO_STM_NVIC_HIGH_PRIORITY (0 << 6) +#define AO_STM_NVIC_CLOCK_PRIORITY (1 << 6) +#define AO_STM_NVIC_MED_PRIORITY (2 << 6) +#define AO_STM_NVIC_LOW_PRIORITY (3 << 6) void ao_lcd_stm_init(void); diff --git a/src/stmf0/ao_exti.h b/src/stmf0/ao_exti.h index ebea224d..192611bd 100644 --- a/src/stmf0/ao_exti.h +++ b/src/stmf0/ao_exti.h @@ -28,7 +28,7 @@ #define AO_EXTI_PIN_NOCONFIGURE 64 void -ao_exti_setup(struct stm_gpio *gpio, uint8_t pin, uint8_t mode, void (*callback)()); +ao_exti_setup(struct stm_gpio *gpio, uint8_t pin, uint8_t mode, void (*callback)(void)); void ao_exti_set_mode(struct stm_gpio *gpio, uint8_t pin, uint8_t mode); diff --git a/src/stmf0/ao_exti_stm.c b/src/stmf0/ao_exti_stm.c index 906392e6..910afcf7 100644 --- a/src/stmf0/ao_exti_stm.c +++ b/src/stmf0/ao_exti_stm.c @@ -110,7 +110,7 @@ ao_exti_set_mode(struct stm_gpio *gpio, uint8_t pin, uint8_t mode) { (void) gpio; uint32_t mask = 1 << pin; - + if (mode & AO_EXTI_MODE_RISING) stm_exti.rtsr |= mask; else diff --git a/src/stmf0/stm32f0.h b/src/stmf0/stm32f0.h index 30b45b15..33eb9c88 100644 --- a/src/stmf0/stm32f0.h +++ b/src/stmf0/stm32f0.h @@ -837,8 +837,11 @@ isr(tim7) struct stm_syscfg { vuint32_t cfgr1; + uint32_t reserved_04; vuint32_t exticr[4]; vuint32_t cfgr2; + uint8_t reserved_1c[0x80-0x1c]; + vuint32_t itline[31]; }; extern struct stm_syscfg stm_syscfg; -- cgit v1.2.3 From fd0ca040a5cccae18145bd29b3e4c09f14df3865 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 13 Apr 2016 06:14:33 -0700 Subject: altos/telefiretwo-v0.2: Change alarm names in comment The PCB is labeled 'A' and 'B'. Signed-off-by: Keith Packard --- src/telefiretwo-v0.2/ao_pins.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/telefiretwo-v0.2/ao_pins.h b/src/telefiretwo-v0.2/ao_pins.h index f6656f16..0fddc6df 100644 --- a/src/telefiretwo-v0.2/ao_pins.h +++ b/src/telefiretwo-v0.2/ao_pins.h @@ -144,12 +144,12 @@ #define LEDS_AVAILABLE (LED_PORT_0_MASK|LED_PORT_1_MASK) -/* Alarm 2 */ +/* Alarm A */ #define AO_SIREN #define AO_SIREN_PORT (&stm_gpiob) #define AO_SIREN_PIN 8 -/* Alarm 1 */ +/* Alarm B */ #define AO_STROBE #define AO_STROBE_PORT (&stm_gpiob) #define AO_STROBE_PIN 9 -- cgit v1.2.3 From 4db6074bb15c66bd23c513e1e41b408e5408cff8 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 19 Apr 2016 23:19:59 -0400 Subject: altos: avoid mixed declarations and code in ao_task.c sdcc can't handle this. Signed-off-by: Keith Packard --- src/kernel/ao_task.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src') diff --git a/src/kernel/ao_task.c b/src/kernel/ao_task.c index 104d1074..e430edc6 100644 --- a/src/kernel/ao_task.c +++ b/src/kernel/ao_task.c @@ -442,10 +442,12 @@ ao_wakeup(__xdata void *wchan) __reentrant } ao_arch_irqrestore(flags); #else + { uint8_t i; for (i = 0; i < ao_num_tasks; i++) if (ao_tasks[i]->wchan == wchan) ao_tasks[i]->wchan = NULL; + } #endif ao_check_stack(); } -- cgit v1.2.3 From eee2ca7fa7fd77be8ca5806cad7e250053465048 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 25 Apr 2016 11:47:45 -0400 Subject: Debug bits for telebt --- src/stm/ao_serial_stm.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'src') diff --git a/src/stm/ao_serial_stm.c b/src/stm/ao_serial_stm.c index 88f2d029..9959e460 100644 --- a/src/stm/ao_serial_stm.c +++ b/src/stm/ao_serial_stm.c @@ -70,6 +70,7 @@ _ao_usart_pollchar(struct ao_stm_usart *usart) uint8_t u; ao_fifo_remove(usart->rx_fifo,u); c = u; + ao_usb_putchar(c); ao_usb_flush(); } return c; } @@ -82,6 +83,7 @@ ao_usart_getchar(struct ao_stm_usart *usart) while ((c = _ao_usart_pollchar(usart)) == AO_READ_AGAIN) ao_sleep(&usart->rx_fifo); ao_arch_release_interrupts(); + ao_usb_putchar(c); ao_usb_flush(); return (char) c; } @@ -94,6 +96,7 @@ _ao_usart_sleep_for(struct ao_stm_usart *usart, uint16_t timeout) void ao_usart_putchar(struct ao_stm_usart *usart, char c) { + ao_usb_putchar(c); ao_usb_flush(); ao_arch_block_interrupts(); while (ao_fifo_full(usart->tx_fifo)) ao_sleep(&usart->tx_fifo); -- cgit v1.2.3 From 7c9a111ac1c88467ce28e03b4a9d3eabc9d7015b Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 19 Jan 2016 23:53:27 -0800 Subject: altos: Use TXE instead of TC for serial on STM32l Using TXE allows for full-speed communication, rather than waiting for each byte to be transmitted before inserting the next into the queue. Signed-off-by: Keith Packard --- src/stm/ao_arch_funcs.h | 2 ++ src/stm/ao_serial_stm.c | 38 +++++++++++++++++++++++++++++++------- 2 files changed, 33 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/stm/ao_arch_funcs.h b/src/stm/ao_arch_funcs.h index f1d17ed1..6fcfd5f8 100644 --- a/src/stm/ao_arch_funcs.h +++ b/src/stm/ao_arch_funcs.h @@ -284,6 +284,8 @@ struct ao_stm_usart { struct ao_fifo tx_fifo; struct stm_usart *reg; uint8_t tx_started; + uint8_t tx_running; + uint8_t draining; }; #if HAS_SERIAL_1 diff --git a/src/stm/ao_serial_stm.c b/src/stm/ao_serial_stm.c index 9959e460..e7b6ab78 100644 --- a/src/stm/ao_serial_stm.c +++ b/src/stm/ao_serial_stm.c @@ -26,14 +26,19 @@ ao_debug_out(char c) stm_usart1.dr = c; } -static void +static int _ao_usart_tx_start(struct ao_stm_usart *usart) { if (!ao_fifo_empty(usart->tx_fifo) && !usart->tx_started) { usart->tx_started = 1; + usart->tx_running = 1; + usart->reg->cr1 |= (1 << STM_USART_CR1_TXEIE) | (1 << STM_USART_CR1_TCIE); ao_fifo_remove(usart->tx_fifo, usart->reg->dr); + ao_wakeup(&usart->tx_fifo); + return 1; } + return 0; } static void @@ -52,10 +57,18 @@ ao_usart_isr(struct ao_stm_usart *usart, int stdin) if (stdin) ao_wakeup(&ao_stdin_ready); } - if (sr & (1 << STM_USART_SR_TC)) { + if (sr & (1 << STM_USART_SR_TXE)) { usart->tx_started = 0; - _ao_usart_tx_start(usart); - ao_wakeup(&usart->tx_fifo); + if (!_ao_usart_tx_start(usart)) + usart->reg->cr1 &= ~(1<< STM_USART_CR1_TXEIE); + } + if (sr & (1 << STM_USART_SR_TC)) { + usart->tx_running = 0; + usart->reg->cr1 &= ~(1 << STM_USART_CR1_TCIE); + if (usart->draining) { + usart->draining = 0; + ao_wakeup(&usart->tx_fifo); + } } } @@ -105,12 +118,14 @@ ao_usart_putchar(struct ao_stm_usart *usart, char c) ao_arch_release_interrupts(); } -void +static void ao_usart_drain(struct ao_stm_usart *usart) { ao_arch_block_interrupts(); - while (!ao_fifo_empty(usart->tx_fifo)) + while (!ao_fifo_empty(usart->tx_fifo) || usart->tx_running) { + usart->draining = 1; ao_sleep(&usart->tx_fifo); + } ao_arch_release_interrupts(); } @@ -153,7 +168,7 @@ ao_usart_init(struct ao_stm_usart *usart) (0 << STM_USART_CR1_PS) | (0 << STM_USART_CR1_PEIE) | (0 << STM_USART_CR1_TXEIE) | - (1 << STM_USART_CR1_TCIE) | + (0 << STM_USART_CR1_TCIE) | (1 << STM_USART_CR1_RXNEIE) | (0 << STM_USART_CR1_IDLEIE) | (1 << STM_USART_CR1_TE) | @@ -234,6 +249,7 @@ ao_serial1_drain(void) void ao_serial1_set_speed(uint8_t speed) { + ao_usart_drain(&ao_stm_usart1); ao_usart_set_speed(&ao_stm_usart1, speed); } #endif /* HAS_SERIAL_1 */ @@ -277,6 +293,7 @@ ao_serial2_drain(void) void ao_serial2_set_speed(uint8_t speed) { + ao_usart_drain(&ao_stm_usart2); ao_usart_set_speed(&ao_stm_usart2, speed); } #endif /* HAS_SERIAL_2 */ @@ -314,8 +331,15 @@ _ao_serial3_sleep_for(uint16_t timeout) void ao_serial3_set_speed(uint8_t speed) { + ao_usart_drain(&ao_stm_usart3); ao_usart_set_speed(&ao_stm_usart3, speed); } + +void +ao_serial3_drain(void) +{ + ao_usart_drain(&ao_stm_usart3); +} #endif /* HAS_SERIAL_3 */ void -- cgit v1.2.3 From 27319e4edbc503f193475b437fa5fe2937d47cbe Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 25 Apr 2016 18:48:47 -0400 Subject: altos/stm32l: Add support for software-driven HW flow control This allows applications to request that the flow control bits be driven from software rather than hardware, permitting more flexible pin configuration. Signed-off-by: Keith Packard --- src/kernel/ao.h | 2 + src/stm/ao_arch_funcs.h | 23 +++++++- src/stm/ao_serial_stm.c | 154 ++++++++++++++++++++++++++++++++++++------------ 3 files changed, 140 insertions(+), 39 deletions(-) (limited to 'src') diff --git a/src/kernel/ao.h b/src/kernel/ao.h index a794ba71..6ed0299e 100644 --- a/src/kernel/ao.h +++ b/src/kernel/ao.h @@ -820,6 +820,8 @@ struct ao_fifo { } while(0) #define ao_fifo_full(f) ((((f).insert + 1) & (AO_FIFO_SIZE-1)) == (f).remove) +#define ao_fifo_mostly(f) ((((f).insert - (f).remove) & (AO_FIFO_SIZE-1)) >= (AO_FIFO_SIZE * 3 / 4)) +#define ao_fifo_barely(f) ((((f).insert - (f).remove) & (AO_FIFO_SIZE-1)) >= (AO_FIFO_SIZE * 1 / 4)) #define ao_fifo_empty(f) ((f).insert == (f).remove) #if PACKET_HAS_MASTER || PACKET_HAS_SLAVE diff --git a/src/stm/ao_arch_funcs.h b/src/stm/ao_arch_funcs.h index 6fcfd5f8..5a7782de 100644 --- a/src/stm/ao_arch_funcs.h +++ b/src/stm/ao_arch_funcs.h @@ -278,14 +278,35 @@ ao_i2c_recv(void *block, uint16_t len, uint8_t i2c_index, uint8_t stop); void ao_i2c_init(void); +#if USE_SERIAL_1_SW_FLOW || USE_SERIAL_2_SW_FLOW || USE_SERIAL_3_SW_FLOW +#define HAS_SERIAL_SW_FLOW 1 +#else +#define HAS_SERIAL_SW_FLOW 0 +#endif + +#if USE_SERIAL_1_FLOW && !USE_SERIAL_1_SW_FLOW || USE_SERIAL_2_FLOW && !USE_SERIAL_2_SW_FLOW || USE_SERIAL_3_FLOW && !USE_SERIAL_3_SW_FLOW +#define HAS_SERIAL_HW_FLOW 1 +#else +#define HAS_SERIAL_HW_FLOW 0 +#endif + /* ao_serial_stm.c */ struct ao_stm_usart { struct ao_fifo rx_fifo; struct ao_fifo tx_fifo; struct stm_usart *reg; - uint8_t tx_started; uint8_t tx_running; uint8_t draining; +#if HAS_SERIAL_SW_FLOW + /* RTS - 0 if we have FIFO space, 1 if not + * CTS - 0 if we can send, 0 if not + */ + struct stm_gpio *gpio_rts; + struct stm_gpio *gpio_cts; + uint8_t pin_rts; + uint8_t pin_cts; + uint8_t rts; +#endif }; #if HAS_SERIAL_1 diff --git a/src/stm/ao_serial_stm.c b/src/stm/ao_serial_stm.c index e7b6ab78..bf079060 100644 --- a/src/stm/ao_serial_stm.c +++ b/src/stm/ao_serial_stm.c @@ -16,6 +16,7 @@ */ #include +#include void ao_debug_out(char c) @@ -29,40 +30,67 @@ ao_debug_out(char c) static int _ao_usart_tx_start(struct ao_stm_usart *usart) { - if (!ao_fifo_empty(usart->tx_fifo) && !usart->tx_started) - { - usart->tx_started = 1; - usart->tx_running = 1; - usart->reg->cr1 |= (1 << STM_USART_CR1_TXEIE) | (1 << STM_USART_CR1_TCIE); - ao_fifo_remove(usart->tx_fifo, usart->reg->dr); - ao_wakeup(&usart->tx_fifo); - return 1; + if (!ao_fifo_empty(usart->tx_fifo)) { +#if HAS_SERIAL_SW_FLOW + if (usart->gpio_cts && ao_gpio_get(usart->gpio_cts, usart->pin_cts, foo) == 1) { + ao_exti_enable(usart->gpio_cts, usart->pin_cts); + return 0; + } +#endif + if (usart->reg->sr & (1 << STM_USART_SR_TXE)) + { + usart->tx_running = 1; + usart->reg->cr1 |= (1 << STM_USART_CR1_TXEIE) | (1 << STM_USART_CR1_TCIE); + ao_fifo_remove(usart->tx_fifo, usart->reg->dr); + ao_wakeup(&usart->tx_fifo); + return 1; + } } return 0; } +#if HAS_SERIAL_SW_FLOW +static void +_ao_usart_cts(struct ao_stm_usart *usart) +{ + if (_ao_usart_tx_start(usart)) + ao_exti_disable(usart->gpio_cts, usart->pin_cts); +} +#endif + +static void +_ao_usart_rx(struct ao_stm_usart *usart, int stdin) +{ + if (usart->reg->sr & (1 << STM_USART_SR_RXNE)) { + if (!ao_fifo_full(usart->rx_fifo)) { + ao_fifo_insert(usart->rx_fifo, usart->reg->dr); + ao_wakeup(&usart->rx_fifo); + if (stdin) + ao_wakeup(&ao_stdin_ready); +#if HAS_SERIAL_SW_FLOW + /* If the fifo is nearly full, turn off RTS and wait + * for it to drain a bunch + */ + if (usart->gpio_rts && ao_fifo_mostly(usart->rx_fifo)) { + ao_gpio_set(usart->gpio_rts, usart->pin_rts, usart->pin_rts, 1); + usart->rts = 0; + } +#endif + } else { + usart->reg->cr1 &= ~(1 << STM_USART_CR1_RXNEIE); + } + } +} + static void ao_usart_isr(struct ao_stm_usart *usart, int stdin) { - uint32_t sr; + _ao_usart_rx(usart, stdin); - sr = usart->reg->sr; - usart->reg->sr = 0; + if (!_ao_usart_tx_start(usart)) + usart->reg->cr1 &= ~(1<< STM_USART_CR1_TXEIE); - if (sr & (1 << STM_USART_SR_RXNE)) { - char c = usart->reg->dr; - if (!ao_fifo_full(usart->rx_fifo)) - ao_fifo_insert(usart->rx_fifo, c); - ao_wakeup(&usart->rx_fifo); - if (stdin) - ao_wakeup(&ao_stdin_ready); - } - if (sr & (1 << STM_USART_SR_TXE)) { - usart->tx_started = 0; - if (!_ao_usart_tx_start(usart)) - usart->reg->cr1 &= ~(1<< STM_USART_CR1_TXEIE); - } - if (sr & (1 << STM_USART_SR_TC)) { + if (usart->reg->sr & (1 << STM_USART_SR_TC)) { usart->tx_running = 0; usart->reg->cr1 &= ~(1 << STM_USART_CR1_TCIE); if (usart->draining) { @@ -72,7 +100,7 @@ ao_usart_isr(struct ao_stm_usart *usart, int stdin) } } -int +static int _ao_usart_pollchar(struct ao_stm_usart *usart) { int c; @@ -82,13 +110,23 @@ _ao_usart_pollchar(struct ao_stm_usart *usart) else { uint8_t u; ao_fifo_remove(usart->rx_fifo,u); + if ((usart->reg->cr1 & (1 << STM_USART_CR1_RXNEIE)) == 0) { + if (ao_fifo_barely(usart->rx_fifo)) + usart->reg->cr1 |= (1 << STM_USART_CR1_RXNEIE); + } +#if HAS_SERIAL_SW_FLOW + /* If we've cleared RTS, check if there's space now and turn it back on */ + if (usart->gpio_rts && usart->rts == 0 && ao_fifo_barely(usart->rx_fifo)) { + ao_gpio_set(usart->gpio_rts, usart->pin_rts, foo, 0); + usart->rts = 1; + } +#endif c = u; - ao_usb_putchar(c); ao_usb_flush(); } return c; } -char +static char ao_usart_getchar(struct ao_stm_usart *usart) { int c; @@ -96,7 +134,6 @@ ao_usart_getchar(struct ao_stm_usart *usart) while ((c = _ao_usart_pollchar(usart)) == AO_READ_AGAIN) ao_sleep(&usart->rx_fifo); ao_arch_release_interrupts(); - ao_usb_putchar(c); ao_usb_flush(); return (char) c; } @@ -106,10 +143,9 @@ _ao_usart_sleep_for(struct ao_stm_usart *usart, uint16_t timeout) return ao_sleep_for(&usart->rx_fifo, timeout); } -void +static void ao_usart_putchar(struct ao_stm_usart *usart, char c) { - ao_usb_putchar(c); ao_usb_flush(); ao_arch_block_interrupts(); while (ao_fifo_full(usart->tx_fifo)) ao_sleep(&usart->tx_fifo); @@ -149,7 +185,7 @@ static const struct { }, }; -void +static void ao_usart_set_speed(struct ao_stm_usart *usart, uint8_t speed) { if (speed > AO_SERIAL_SPEED_115200) @@ -157,7 +193,7 @@ ao_usart_set_speed(struct ao_stm_usart *usart, uint8_t speed) usart->reg->brr = ao_usart_speeds[speed].brr; } -void +static void ao_usart_init(struct ao_stm_usart *usart) { usart->reg->cr1 = ((0 << STM_USART_CR1_OVER8) | @@ -203,12 +239,14 @@ ao_usart_init(struct ao_stm_usart *usart) ao_usart_set_speed(usart, AO_SERIAL_SPEED_9600); } -void +#if HAS_SERIAL_HW_FLOW +static void ao_usart_set_flow(struct ao_stm_usart *usart) { usart->reg->cr3 |= ((1 << STM_USART_CR3_CTSE) | (1 << STM_USART_CR3_RTSE)); } +#endif #if HAS_SERIAL_1 @@ -296,13 +334,22 @@ ao_serial2_set_speed(uint8_t speed) ao_usart_drain(&ao_stm_usart2); ao_usart_set_speed(&ao_stm_usart2, speed); } + +#if HAS_SERIAL_SW_FLOW +void +ao_serial2_cts(void) +{ + _ao_usart_cts(&ao_stm_usart2); +} +#endif + #endif /* HAS_SERIAL_2 */ #if HAS_SERIAL_3 struct ao_stm_usart ao_stm_usart3; -void stm_usart3_isr(void) { ao_usart_isr(&ao_stm_usart3, USE_SERIAL_2_STDIN); } +void stm_usart3_isr(void) { ao_usart_isr(&ao_stm_usart3, USE_SERIAL_3_STDIN); } char ao_serial3_getchar(void) @@ -342,6 +389,28 @@ ao_serial3_drain(void) } #endif /* HAS_SERIAL_3 */ +#if HAS_SERIAL_SW_FLOW +static void +ao_serial_set_sw_rts_cts(struct ao_stm_usart *usart, + void (*isr)(void), + struct stm_gpio *port_rts, + int pin_rts, + struct stm_gpio *port_cts, + int pin_cts) +{ + /* Pull RTS low to note that there's space in the FIFO + */ + ao_enable_output(port_rts, pin_rts, foo, 0); + usart->gpio_rts = port_rts; + usart->pin_rts = pin_rts; + usart->rts = 1; + + ao_exti_setup(port_cts, pin_cts, AO_EXTI_MODE_FALLING|AO_EXTI_PRIORITY_MED, isr); + usart->gpio_cts = port_cts; + usart->pin_cts = pin_cts; +} +#endif + void ao_serial_init(void) { @@ -394,10 +463,19 @@ ao_serial_init(void) stm_afr_set(&stm_gpioa, 2, STM_AFR_AF7); stm_afr_set(&stm_gpioa, 3, STM_AFR_AF7); -#if USE_SERIAL_2_FLOW +# if USE_SERIAL_2_FLOW +# if USE_SERIAL_2_SW_FLOW + ao_serial_set_sw_rts_cts(&ao_stm_usart2, + ao_serial2_cts, + SERIAL_2_PORT_RTS, + SERIAL_2_PIN_RTS, + SERIAL_2_PORT_CTS, + SERIAL_2_PIN_CTS); +# else stm_afr_set(&stm_gpioa, 0, STM_AFR_AF7); stm_afr_set(&stm_gpioa, 1, STM_AFR_AF7); -#endif +# endif +# endif #else #if SERIAL_2_PD5_PD6 stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_GPIODEN); @@ -416,7 +494,7 @@ ao_serial_init(void) ao_stm_usart2.reg = &stm_usart2; ao_usart_init(&ao_stm_usart2); -#if USE_SERIAL_2_FLOW +#if USE_SERIAL_2_FLOW && !USE_SERIAL_2_SW_FLOW ao_usart_set_flow(&ao_stm_usart2); #endif -- cgit v1.2.3 From c816bea3536d025568dab313d7c8944a56ba0801 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 25 Apr 2016 18:49:45 -0400 Subject: altos/telebt-v3.0: Flip CTS/RTS pins for BT module These are wired backwards, so ask that the right pins be used, which requires switching to software control of the pins. Signed-off-by: Keith Packard --- src/telebt-v3.0/ao_pins.h | 5 +++++ src/telebt-v3.0/ao_telebt.c | 1 - 2 files changed, 5 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/telebt-v3.0/ao_pins.h b/src/telebt-v3.0/ao_pins.h index a6a01662..50584940 100644 --- a/src/telebt-v3.0/ao_pins.h +++ b/src/telebt-v3.0/ao_pins.h @@ -52,8 +52,13 @@ #define USE_SERIAL_2_STDIN 1 #define DELAY_SERIAL_2_STDIN 1 #define USE_SERIAL_2_FLOW 1 +#define USE_SERIAL_2_SW_FLOW 1 #define SERIAL_2_PA2_PA3 1 #define SERIAL_2_PD5_PD6 0 +#define SERIAL_2_PORT_RTS (&stm_gpioa) +#define SERIAL_2_PIN_RTS 0 +#define SERIAL_2_PORT_CTS (&stm_gpioa) +#define SERIAL_2_PIN_CTS 1 #define HAS_SERIAL_3 0 #define USE_SERIAL_3_STDIN 0 diff --git a/src/telebt-v3.0/ao_telebt.c b/src/telebt-v3.0/ao_telebt.c index 44ee4f3d..1fe06b1a 100644 --- a/src/telebt-v3.0/ao_telebt.c +++ b/src/telebt-v3.0/ao_telebt.c @@ -31,7 +31,6 @@ main(void) ao_clock_init(); ao_task_init(); - ao_serial_init(); ao_led_init(LEDS_AVAILABLE); ao_led_on(AO_LED_RED); ao_timer_init(); -- cgit v1.2.3 From 565404599fe9edf9ba16aec348eeb19ea31af743 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 25 Apr 2016 18:50:58 -0400 Subject: altos: Clear packet queue when starting packet master This avoids overfilling the packet buffer when disconnected. Applications using packet mode shouldn't expect that output be saved across master sessions. Signed-off-by: Keith Packard --- src/drivers/ao_packet_master.c | 1 + 1 file changed, 1 insertion(+) (limited to 'src') diff --git a/src/drivers/ao_packet_master.c b/src/drivers/ao_packet_master.c index 5e440db0..2beda4cb 100644 --- a/src/drivers/ao_packet_master.c +++ b/src/drivers/ao_packet_master.c @@ -117,6 +117,7 @@ ao_packet_forward(void) __reentrant { char c; ao_packet_enable = 1; + ao_packet_tx_used = 0; ao_cmd_white(); flush(); -- cgit v1.2.3 From 7695da327ff8861a858b6695f4849fa1399548d8 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 30 Apr 2016 08:46:52 -0700 Subject: Revert "altos/stm: Run scheduler code on interrupt stack" This reverts commit 6a9546413d6a236c010e806b50506d870961d074. This causes the device to stop reliably handling interrupts. --- src/stm/ao_arch_funcs.h | 16 +--------------- 1 file changed, 1 insertion(+), 15 deletions(-) (limited to 'src') diff --git a/src/stm/ao_arch_funcs.h b/src/stm/ao_arch_funcs.h index 5a7782de..2c017c79 100644 --- a/src/stm/ao_arch_funcs.h +++ b/src/stm/ao_arch_funcs.h @@ -391,13 +391,6 @@ static inline void ao_arch_save_stack(void) { static inline void ao_arch_restore_stack(void) { uint32_t sp; - uint32_t control; - - asm("mrs %0,control" : "=&r" (control)); - control |= (1 << 1); - asm("msr control,%0" : : "r" (control)); - asm("isb"); - sp = (uint32_t) ao_cur_task->sp; /* Switch stacks */ @@ -454,14 +447,7 @@ static inline void ao_arch_start_scheduler(void) { } #endif -static inline void ao_arch_isr_stack(void) { - uint32_t control; - - asm("mrs %0,control" : "=&r" (control)); - control &= ~(1 << 1); - asm("msr control,%0" : : "r" (control)); - asm("isb"); -} +#define ao_arch_isr_stack() #endif -- cgit v1.2.3 From b540f6f5b034f33b8e1d1c3b91e2403a56479caa Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 2 May 2016 16:19:39 -0700 Subject: altos: Make sure AO_MMA655X_INVERT is declared where needed Add #define AO_MMA655X_INVERT 0 to existing products which didn't declare it at all. This will make sure the value is set correctly for each new board. Signed-off-by: Keith Packard --- src/easymega-v1.0/ao_pins.h | 1 + src/kernel/ao_data.h | 4 ++++ src/telemega-v0.1/ao_pins.h | 1 + src/telemega-v1.0/ao_pins.h | 1 + src/telemega-v2.0/ao_pins.h | 1 + 5 files changed, 8 insertions(+) (limited to 'src') diff --git a/src/easymega-v1.0/ao_pins.h b/src/easymega-v1.0/ao_pins.h index a5e55638..773e58d9 100644 --- a/src/easymega-v1.0/ao_pins.h +++ b/src/easymega-v1.0/ao_pins.h @@ -321,6 +321,7 @@ struct ao_adc { */ #define HAS_MMA655X 1 +#define AO_MMA655X_INVERT 0 #define AO_MMA655X_SPI_INDEX AO_SPI_1_PB3_PB4_PB5 #define AO_MMA655X_CS_PORT (&stm_gpioc) #define AO_MMA655X_CS_PIN 12 diff --git a/src/kernel/ao_data.h b/src/kernel/ao_data.h index 8f75ad87..6ee0965d 100644 --- a/src/kernel/ao_data.h +++ b/src/kernel/ao_data.h @@ -269,6 +269,10 @@ typedef int16_t accel_t; #define AO_ACCEL_INVERT 4095 +#ifndef AO_MMA655X_INVERT +#error AO_MMA655X_INVERT not defined +#endif + #define ao_data_accel(packet) ((packet)->mma655x) #if AO_MMA655X_INVERT #define ao_data_accel_cook(packet) (AO_ACCEL_INVERT - (packet)->mma655x) diff --git a/src/telemega-v0.1/ao_pins.h b/src/telemega-v0.1/ao_pins.h index 7ccc6085..1815ef54 100644 --- a/src/telemega-v0.1/ao_pins.h +++ b/src/telemega-v0.1/ao_pins.h @@ -346,6 +346,7 @@ struct ao_adc { */ #define HAS_MMA655X 1 +#define AO_MMA655X_INVERT 0 #define AO_MMA655X_SPI_INDEX AO_SPI_1_PE13_PE14_PE15 #define AO_MMA655X_CS_PORT (&stm_gpiod) #define AO_MMA655X_CS_PIN 4 diff --git a/src/telemega-v1.0/ao_pins.h b/src/telemega-v1.0/ao_pins.h index 664546c2..b81e59a9 100644 --- a/src/telemega-v1.0/ao_pins.h +++ b/src/telemega-v1.0/ao_pins.h @@ -348,6 +348,7 @@ struct ao_adc { */ #define HAS_MMA655X 1 +#define AO_MMA655X_INVERT 0 #define AO_MMA655X_SPI_INDEX AO_SPI_1_PE13_PE14_PE15 #define AO_MMA655X_CS_PORT (&stm_gpiod) #define AO_MMA655X_CS_PIN 4 diff --git a/src/telemega-v2.0/ao_pins.h b/src/telemega-v2.0/ao_pins.h index 9095a350..242f0ab2 100644 --- a/src/telemega-v2.0/ao_pins.h +++ b/src/telemega-v2.0/ao_pins.h @@ -348,6 +348,7 @@ struct ao_adc { */ #define HAS_MMA655X 1 +#define AO_MMA655X_INVERT 0 #define AO_MMA655X_SPI_INDEX AO_SPI_1_PE13_PE14_PE15 #define AO_MMA655X_CS_PORT (&stm_gpiod) #define AO_MMA655X_CS_PIN 4 -- cgit v1.2.3