summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/cc1111/ao_pins.h3
-rw-r--r--src/drivers/ao_cc1120.c160
-rw-r--r--src/kernel/ao.h3
-rw-r--r--src/kernel/ao_mutex.c23
-rw-r--r--src/lpc/ao_arch_funcs.h17
-rw-r--r--src/stm/ao_arch_funcs.h25
-rw-r--r--src/stm/ao_spi_stm.c51
7 files changed, 208 insertions, 74 deletions
diff --git a/src/cc1111/ao_pins.h b/src/cc1111/ao_pins.h
index 83a3c774..1bc3d716 100644
--- a/src/cc1111/ao_pins.h
+++ b/src/cc1111/ao_pins.h
@@ -58,6 +58,7 @@
#define HAS_MONITOR 0
#define HAS_TELEMETRY 1
#define HAS_RADIO_RATE 0 /* not enough space for this */
+ #define HAS_MUTEX_TRY 0
#endif
#if defined(TELEMETRUM_V_1_1)
@@ -100,6 +101,7 @@
#define HAS_MONITOR 0
#define HAS_TELEMETRY 1
#define HAS_RADIO_RATE 0 /* not enough space for this */
+ #define HAS_MUTEX_TRY 0
#endif
#if defined(TELEMETRUM_V_1_2)
@@ -142,6 +144,7 @@
#define HAS_MONITOR 0
#define HAS_TELEMETRY 1
#define HAS_RADIO_RATE 0 /* not enough space for this */
+ #define HAS_MUTEX_TRY 0
#endif
#if defined(TELEDONGLE_V_0_2)
diff --git a/src/drivers/ao_cc1120.c b/src/drivers/ao_cc1120.c
index 5d51fbcd..1b907940 100644
--- a/src/drivers/ao_cc1120.c
+++ b/src/drivers/ao_cc1120.c
@@ -41,8 +41,10 @@ extern const uint32_t ao_radio_cal;
#define FOSC 32000000
+#define ao_radio_try_select(task_id) ao_spi_try_get_mask(AO_CC1120_SPI_CS_PORT,(1 << AO_CC1120_SPI_CS_PIN),AO_CC1120_SPI_BUS,AO_SPI_SPEED_4MHz, task_id)
#define ao_radio_select() ao_spi_get_mask(AO_CC1120_SPI_CS_PORT,(1 << AO_CC1120_SPI_CS_PIN),AO_CC1120_SPI_BUS,AO_SPI_SPEED_4MHz)
#define ao_radio_deselect() ao_spi_put_mask(AO_CC1120_SPI_CS_PORT,(1 << AO_CC1120_SPI_CS_PIN),AO_CC1120_SPI_BUS)
+#define ao_radio_spi_send_sync(d,l) ao_spi_send_sync((d), (l), AO_CC1120_SPI_BUS)
#define ao_radio_spi_send(d,l) ao_spi_send((d), (l), AO_CC1120_SPI_BUS)
#define ao_radio_spi_send_fixed(d,l) ao_spi_send_fixed((d), (l), AO_CC1120_SPI_BUS)
#define ao_radio_spi_recv(d,l) ao_spi_recv((d), (l), AO_CC1120_SPI_BUS)
@@ -107,7 +109,7 @@ ao_radio_reg_write(uint16_t addr, uint8_t value)
}
static void
-ao_radio_burst_read_start (uint16_t addr)
+_ao_radio_burst_read_start (uint16_t addr)
{
uint8_t data[2];
uint8_t d;
@@ -124,8 +126,8 @@ ao_radio_burst_read_start (uint16_t addr)
addr);
d = 1;
}
- ao_radio_select();
- ao_radio_spi_send(data, d);
+
+ ao_radio_spi_send_sync(data, d);
}
static void
@@ -209,7 +211,7 @@ ao_radio_tx_fifo_space(void)
return CC1120_FIFO_SIZE - ao_radio_reg_read(CC1120_NUM_TXBYTES);
}
-#if 0
+#if CC1120_DEBUG
static uint8_t
ao_radio_status(void)
{
@@ -275,11 +277,13 @@ static void
ao_radio_idle(void)
{
for (;;) {
- uint8_t state = ao_radio_strobe(CC1120_SIDLE);
- if ((state >> CC1120_STATUS_STATE) == CC1120_STATUS_STATE_IDLE)
+ uint8_t state = (ao_radio_strobe(CC1120_SIDLE) >> CC1120_STATUS_STATE) & CC1120_STATUS_STATE_MASK;
+ if (state == CC1120_STATUS_STATE_IDLE)
break;
- if ((state >> CC1120_STATUS_STATE) == CC1120_STATUS_STATE_TX_FIFO_ERROR)
+ if (state == CC1120_STATUS_STATE_TX_FIFO_ERROR)
ao_radio_strobe(CC1120_SFTX);
+ if (state == CC1120_STATUS_STATE_RX_FIFO_ERROR)
+ ao_radio_strobe(CC1120_SFRX);
}
/* Flush any pending TX bytes */
ao_radio_strobe(CC1120_SFTX);
@@ -948,6 +952,11 @@ static uint16_t rx_data_consumed;
static uint16_t rx_data_cur;
static uint8_t rx_ignore;
static uint8_t rx_waiting;
+static uint8_t rx_starting;
+static uint8_t rx_task_id;
+static uint32_t rx_fast_start;
+static uint32_t rx_slow_start;
+static uint32_t rx_missed;
#if AO_PROFILE
static uint32_t rx_start_tick, rx_packet_tick, rx_done_tick, rx_last_done_tick;
@@ -962,13 +971,34 @@ ao_radio_rx_isr(void)
{
uint8_t d;
+ if (rx_task_id) {
+ if (ao_radio_try_select(rx_task_id)) {
+ ++rx_fast_start;
+ rx_task_id = 0;
+ _ao_radio_burst_read_start(CC1120_SOFT_RX_DATA_OUT);
+ } else {
+ if (rx_ignore)
+ --rx_ignore;
+ else {
+ ao_radio_abort = 1;
+ rx_missed++;
+ }
+ return;
+ }
+ }
+ if (rx_starting) {
+ rx_starting = 0;
+ ao_wakeup(&ao_radio_wake);
+ }
d = AO_CC1120_SPI.dr;
AO_CC1120_SPI.dr = 0;
if (rx_ignore == 0) {
- if (rx_data_cur >= rx_data_count)
- ao_exti_disable(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN);
- else
+ if (rx_data_cur < rx_data_count)
rx_data[rx_data_cur++] = d;
+ if (rx_data_cur >= rx_data_count) {
+ ao_spi_clr_cs(AO_CC1120_SPI_CS_PORT,(1 << AO_CC1120_SPI_CS_PIN));
+ ao_exti_disable(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN);
+ }
if (rx_waiting && rx_data_cur - rx_data_consumed >= AO_FEC_DECODE_BLOCK) {
#if AO_PROFILE
if (!rx_packet_tick)
@@ -987,24 +1017,20 @@ ao_radio_rx_isr(void)
static uint16_t
ao_radio_rx_wait(void)
{
- do {
- if (ao_radio_mcu_wake)
- ao_radio_check_marc_status();
- ao_alarm(AO_MS_TO_TICKS(100));
- ao_arch_block_interrupts();
- rx_waiting = 1;
- while (rx_data_cur - rx_data_consumed < AO_FEC_DECODE_BLOCK &&
- !ao_radio_abort &&
- !ao_radio_mcu_wake)
- {
- if (ao_sleep(&ao_radio_wake))
- ao_radio_abort = 1;
- }
- rx_waiting = 0;
- ao_arch_release_interrupts();
- ao_clear_alarm();
- } while (ao_radio_mcu_wake);
- if (ao_radio_abort)
+ ao_alarm(AO_MS_TO_TICKS(100));
+ ao_arch_block_interrupts();
+ rx_waiting = 1;
+ while (rx_data_cur - rx_data_consumed < AO_FEC_DECODE_BLOCK &&
+ !ao_radio_abort &&
+ !ao_radio_mcu_wake)
+ {
+ if (ao_sleep(&ao_radio_wake))
+ ao_radio_abort = 1;
+ }
+ rx_waiting = 0;
+ ao_arch_release_interrupts();
+ ao_clear_alarm();
+ if (ao_radio_abort || ao_radio_mcu_wake)
return 0;
rx_data_consumed += AO_FEC_DECODE_BLOCK;
#if AO_PROFILE
@@ -1044,48 +1070,67 @@ ao_radio_recv(__xdata void *d, uint8_t size, uint8_t timeout)
*/
ao_radio_abort = 0;
- /* configure interrupt pin */
ao_radio_get(len);
- ao_radio_set_mode(AO_RADIO_MODE_PACKET_RX);
ao_radio_wake = 0;
ao_radio_mcu_wake = 0;
- AO_CC1120_SPI.cr2 = 0;
-
- /* clear any RXNE */
- (void) AO_CC1120_SPI.dr;
+ ao_radio_set_mode(AO_RADIO_MODE_PACKET_RX);
- /* Have the radio signal when the preamble quality goes high */
- ao_radio_reg_write(AO_CC1120_INT_GPIO_IOCFG, CC1120_IOCFG_GPIO_CFG_PQT_REACHED);
+ /* configure interrupt pin */
+ ao_radio_reg_write(AO_CC1120_INT_GPIO_IOCFG, CC1120_IOCFG_GPIO_CFG_CLKEN_SOFT);
ao_exti_set_mode(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN,
- AO_EXTI_MODE_RISING|AO_EXTI_PRIORITY_HIGH);
- ao_exti_set_callback(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN, ao_radio_isr);
+ AO_EXTI_MODE_FALLING|AO_EXTI_PRIORITY_HIGH);
+
+ ao_exti_set_callback(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN, ao_radio_rx_isr);
ao_exti_enable(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN);
- ao_exti_enable(AO_CC1120_MCU_WAKEUP_PORT, AO_CC1120_MCU_WAKEUP_PIN);
+
+ rx_starting = 1;
+ rx_task_id = ao_cur_task->task_id;
ao_radio_strobe(CC1120_SRX);
- /* Wait for the preamble to appear */
- ao_radio_wait_isr(timeout);
+ if (timeout)
+ ao_alarm(timeout);
+ ao_arch_block_interrupts();
+ while (rx_starting && !ao_radio_abort) {
+ if (ao_sleep(&ao_radio_wake))
+ ao_radio_abort = 1;
+ }
+ uint8_t rx_task_id_save = rx_task_id;
+ rx_task_id = 0;
+ rx_starting = 0;
+ ao_arch_release_interrupts();
+ if (timeout)
+ ao_clear_alarm();
+
if (ao_radio_abort) {
ret = 0;
+ rx_task_id = 0;
goto abort;
}
- ao_radio_reg_write(AO_CC1120_INT_GPIO_IOCFG, CC1120_IOCFG_GPIO_CFG_CLKEN_SOFT);
- ao_exti_set_mode(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN,
- AO_EXTI_MODE_FALLING|AO_EXTI_PRIORITY_HIGH);
-
- ao_exti_set_callback(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN, ao_radio_rx_isr);
- ao_exti_enable(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN);
-
- ao_radio_burst_read_start(CC1120_SOFT_RX_DATA_OUT);
+ if (rx_task_id_save) {
+ ++rx_slow_start;
+ ao_radio_select();
+ _ao_radio_burst_read_start(CC1120_SOFT_RX_DATA_OUT);
+ if (rx_ignore) {
+ uint8_t ignore = AO_CC1120_SPI.dr;
+ (void) ignore;
+ AO_CC1120_SPI.dr = 0;
+ --rx_ignore;
+ }
+ }
ret = ao_fec_decode(rx_data, rx_data_count, d, size + 2, ao_radio_rx_wait);
ao_radio_burst_read_stop();
+ if (ao_radio_mcu_wake)
+ ao_radio_check_marc_status();
+ if (ao_radio_abort)
+ ret = 0;
+
abort:
/* Convert from 'real' rssi to cc1111-style values */
@@ -1100,7 +1145,7 @@ abort:
radio_rssi = AO_RADIO_FROM_RSSI (rssi);
}
- ao_radio_strobe(CC1120_SIDLE);
+ ao_radio_idle();
ao_radio_put();
@@ -1139,7 +1184,7 @@ struct ao_cc1120_reg {
char *name;
};
-const static struct ao_cc1120_reg ao_cc1120_reg[] = {
+static const struct ao_cc1120_reg ao_cc1120_reg[] = {
{ .addr = CC1120_IOCFG3, .name = "IOCFG3" },
{ .addr = CC1120_IOCFG2, .name = "IOCFG2" },
{ .addr = CC1120_IOCFG1, .name = "IOCFG1" },
@@ -1320,7 +1365,7 @@ const static struct ao_cc1120_reg ao_cc1120_reg[] = {
static void ao_radio_show(void) {
uint8_t status = ao_radio_status();
- int i;
+ unsigned int i;
ao_radio_get(0xff);
status = ao_radio_status();
@@ -1331,6 +1376,10 @@ static void ao_radio_show(void) {
for (i = 0; i < AO_NUM_CC1120_REG; i++)
printf ("\t%02x %-20.20s\n", ao_radio_reg_read(ao_cc1120_reg[i].addr), ao_cc1120_reg[i].name);
+
+ printf("RX fast start: %u\n", rx_fast_start);
+ printf("RX slow start: %u\n", rx_slow_start);
+ printf("RX missed: %u\n", rx_missed);
ao_radio_put();
}
@@ -1354,12 +1403,12 @@ static void ao_radio_packet(void) {
}
void
-ao_radio_test_recv()
+ao_radio_test_recv(void)
{
uint8_t bytes[34];
uint8_t b;
- if (ao_radio_recv(bytes, 34)) {
+ if (ao_radio_recv(bytes, 34, 0)) {
if (bytes[33] & 0x80)
printf ("CRC OK");
else
@@ -1375,13 +1424,12 @@ ao_radio_test_recv()
#include <ao_aprs.h>
static void
-ao_radio_aprs()
+ao_radio_aprs(void)
{
ao_packet_slave_stop();
ao_aprs_send();
}
#endif
-
#endif
static const struct ao_cmds ao_radio_cmds[] = {
diff --git a/src/kernel/ao.h b/src/kernel/ao.h
index c11aa028..a225bc4a 100644
--- a/src/kernel/ao.h
+++ b/src/kernel/ao.h
@@ -132,6 +132,9 @@ ao_clock_init(void);
*/
#ifndef ao_mutex_get
+uint8_t
+ao_mutex_try(__xdata uint8_t *ao_mutex, uint8_t task_id) __reentrant;
+
void
ao_mutex_get(__xdata uint8_t *ao_mutex) __reentrant;
diff --git a/src/kernel/ao_mutex.c b/src/kernel/ao_mutex.c
index 952ff462..a36fe939 100644
--- a/src/kernel/ao_mutex.c
+++ b/src/kernel/ao_mutex.c
@@ -17,6 +17,29 @@
#include "ao.h"
+#ifndef HAS_MUTEX_TRY
+#define HAS_MUTEX_TRY 1
+#endif
+
+#if HAS_MUTEX_TRY
+
+uint8_t
+ao_mutex_try(__xdata uint8_t *mutex, uint8_t task_id) __reentrant
+{
+ uint8_t ret;
+ if (*mutex == task_id)
+ ao_panic(AO_PANIC_MUTEX);
+ ao_arch_critical(
+ if (*mutex)
+ ret = 0;
+ else {
+ *mutex = task_id;
+ ret = 1;
+ });
+ return ret;
+}
+#endif
+
void
ao_mutex_get(__xdata uint8_t *mutex) __reentrant
{
diff --git a/src/lpc/ao_arch_funcs.h b/src/lpc/ao_arch_funcs.h
index 0891903e..21a7a8e5 100644
--- a/src/lpc/ao_arch_funcs.h
+++ b/src/lpc/ao_arch_funcs.h
@@ -161,16 +161,17 @@ static inline void ao_arch_restore_stack(void) {
#endif /* HAS_TASK */
-#define ao_arch_wait_interrupt() do { \
- asm(".global ao_idle_loc\n\twfi\nao_idle_loc:"); \
- ao_arch_release_interrupts(); \
- ao_arch_block_interrupts(); \
+#define ao_arch_wait_interrupt() do { \
+ asm("\twfi\n"); \
+ ao_arch_release_interrupts(); \
+ asm(".global ao_idle_loc\n\nao_idle_loc:"); \
+ ao_arch_block_interrupts(); \
} while (0)
-#define ao_arch_critical(b) do { \
- ao_arch_block_interrupts(); \
- do { b } while (0); \
- ao_arch_release_interrupts(); \
+#define ao_arch_critical(b) do { \
+ uint32_t __mask = ao_arch_irqsave(); \
+ do { b } while (0); \
+ ao_arch_irqrestore(__mask); \
} while (0)
/*
diff --git a/src/stm/ao_arch_funcs.h b/src/stm/ao_arch_funcs.h
index b461cd3f..7ad3b4b8 100644
--- a/src/stm/ao_arch_funcs.h
+++ b/src/stm/ao_arch_funcs.h
@@ -64,6 +64,9 @@
#define AO_SPI_INDEX(id) ((id) & AO_SPI_INDEX_MASK)
#define AO_SPI_CONFIG(id) ((id) & AO_SPI_CONFIG_MASK)
+uint8_t
+ao_spi_try_get(uint8_t spi_index, uint32_t speed, uint8_t task_id);
+
void
ao_spi_get(uint8_t spi_index, uint32_t speed);
@@ -77,6 +80,9 @@ void
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);
+
+void
ao_spi_recv(void *block, uint16_t len, uint8_t spi_index);
void
@@ -95,6 +101,15 @@ ao_spi_init(void);
ao_spi_set_cs(reg,mask); \
} while (0)
+static inline uint8_t
+ao_spi_try_get_mask(struct stm_gpio *reg, uint16_t mask, uint8_t bus, uint32_t speed, uint8_t task_id)
+{
+ if (!ao_spi_try_get(bus, speed, task_id))
+ return 0;
+ ao_spi_set_cs(reg, mask);
+ return 1;
+}
+
#define ao_spi_put_mask(reg,mask,bus) do { \
ao_spi_clr_cs(reg,mask); \
ao_spi_put(bus); \
@@ -252,6 +267,8 @@ extern struct ao_stm_usart ao_stm_usart3;
#define ARM_PUSH32(stack, val) (*(--(stack)) = (val))
+typedef uint32_t ao_arch_irq_t;
+
static inline uint32_t
ao_arch_irqsave(void) {
uint32_t primask;
@@ -369,10 +386,10 @@ static inline void ao_arch_start_scheduler(void) {
ao_arch_block_interrupts(); \
} while (0)
-#define ao_arch_critical(b) do { \
- ao_arch_block_interrupts(); \
- do { b } while (0); \
- ao_arch_release_interrupts(); \
+#define ao_arch_critical(b) do { \
+ uint32_t __mask = ao_arch_irqsave(); \
+ do { b } while (0); \
+ ao_arch_irqrestore(__mask); \
} while (0)
#endif /* _AO_ARCH_FUNCS_H_ */
diff --git a/src/stm/ao_spi_stm.c b/src/stm/ao_spi_stm.c
index 56329c24..885af544 100644
--- a/src/stm/ao_spi_stm.c
+++ b/src/stm/ao_spi_stm.c
@@ -154,6 +154,28 @@ 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)
+{
+ uint8_t *b = block;
+ struct stm_spi *stm_spi = ao_spi_stm_info[AO_SPI_INDEX(spi_index)].stm_spi;
+
+ 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 (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;
@@ -356,13 +378,11 @@ ao_spi_enable_index(uint8_t spi_index)
}
}
-void
-ao_spi_get(uint8_t spi_index, uint32_t speed)
+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;
-
- ao_mutex_get(&ao_spi_mutex[id]);
stm_spi->cr1 = ((0 << STM_SPI_CR1_BIDIMODE) | /* Three wire mode */
(0 << STM_SPI_CR1_BIDIOE) |
(0 << STM_SPI_CR1_CRCEN) | /* CRC disabled */
@@ -378,7 +398,7 @@ ao_spi_get(uint8_t spi_index, uint32_t speed)
(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]);
@@ -386,13 +406,32 @@ ao_spi_get(uint8_t spi_index, uint32_t speed)
/* 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)
{