summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--altosdroid/Makefile.am2
-rw-r--r--altosui/altos-windows.nsi.in2
-rw-r--r--ao-tools/ao-chaosread/ao-chaosread.14
-rw-r--r--configure.ac4
-rw-r--r--debian/control2
-rw-r--r--doc/Makefile1
-rw-r--r--doc/altusmetrum-docinfo.xml10
-rwxr-xr-xdoc/install-html32
-rw-r--r--doc/release-notes-1.6.5.inc24
-rw-r--r--doc/release-notes.inc5
-rw-r--r--src/cc1111/ao_pins.h1
-rw-r--r--src/drivers/ao_cc1120.c173
-rw-r--r--src/drivers/ao_cc1200.c105
-rw-r--r--src/kernel/ao.h1
-rw-r--r--src/kernel/ao_flight.c2
-rw-r--r--src/kernel/ao_task.c41
-rw-r--r--src/stm/ao_arch_funcs.h55
-rw-r--r--src/stm/ao_dma_stm.c47
-rw-r--r--src/stm/ao_exti_stm.c2
-rw-r--r--src/stm/ao_spi_stm.c438
-rw-r--r--src/stm/stm32l.h3
-rw-r--r--src/telemega-v1.0/ao_pins.h1
-rw-r--r--src/telemini-v2.0/ao_pins.h1
23 files changed, 571 insertions, 385 deletions
diff --git a/altosdroid/Makefile.am b/altosdroid/Makefile.am
index 295abbc5..686aeabf 100644
--- a/altosdroid/Makefile.am
+++ b/altosdroid/Makefile.am
@@ -15,7 +15,7 @@ ADB=$(SDK)/platform-tools/adb
AAPT=$(SDK)/platform-tools/aapt
APKBUILDER=$(SDK)/tools/apkbuilder
ZIPALIGN_A=$(SDK)/tools/zipalign
-ZIPALIGN_B=$(SDK)/build-tools/*/zipalign
+ZIPALIGN_B=$(shell ls $(SDK)/build-tools/*/zipalign | tail -1)
JAVA_SRC_DIR=src/org/altusmetrum/AltosDroid
EXT_LIBDIR=libs
diff --git a/altosui/altos-windows.nsi.in b/altosui/altos-windows.nsi.in
index c88b9e34..c85e2ac8 100644
--- a/altosui/altos-windows.nsi.in
+++ b/altosui/altos-windows.nsi.in
@@ -129,7 +129,9 @@ Section "Firmware"
File "../src/teledongle-v0.2/teledongle-v0.2-${VERSION}.ihx"
File "../src/teledongle-v3.0/teledongle-v3.0-${VERSION}.ihx"
File "../src/telebt-v1.0/telebt-v1.0-${VERSION}.ihx"
+ File "../src/telebt-v3.0/telebt-v3.0-${VERSION}.ihx"
File "../src/telemega-v1.0/telemega-v1.0-${VERSION}.ihx"
+ File "../src/telemega-v2.0/telemega-v2.0-${VERSION}.ihx"
File "../src/easymini-v1.0/easymini-v1.0-${VERSION}.ihx"
File "../src/easymega-v1.0/easymega-v1.0-${VERSION}.ihx"
diff --git a/ao-tools/ao-chaosread/ao-chaosread.1 b/ao-tools/ao-chaosread/ao-chaosread.1
index d8ed6cb3..ead8afb2 100644
--- a/ao-tools/ao-chaosread/ao-chaosread.1
+++ b/ao-tools/ao-chaosread/ao-chaosread.1
@@ -29,6 +29,10 @@ reads ADC values from the noise source on the attached ChaosKey device.
\-s serial | --serial serial
This selects a ChaosKey by serial number instead of using the first
one found.
+.TP
+\-l length | --length length
+Set the amount of data to read. Suffixes 'k', 'M' and 'G' are
+supported. The default is 1k.
.SH USAGE
.I ao-chaosread
reads noise data.
diff --git a/configure.ac b/configure.ac
index 6745b012..001449a7 100644
--- a/configure.ac
+++ b/configure.ac
@@ -18,8 +18,8 @@ dnl
dnl Process this file with autoconf to create configure.
AC_PREREQ(2.57)
-AC_INIT([altos], 1.6.4)
-ANDROID_VERSION=12
+AC_INIT([altos], 1.6.5)
+ANDROID_VERSION=13
AC_CONFIG_SRCDIR([src/kernel/ao.h])
AM_INIT_AUTOMAKE([foreign dist-bzip2])
AM_MAINTAINER_MODE
diff --git a/debian/control b/debian/control
index 426fb777..e20a54a2 100644
--- a/debian/control
+++ b/debian/control
@@ -20,7 +20,7 @@ Build-Depends: asciidoc,
icoutils,
libbluetooth-dev,
libelf-dev,
- libgtk-3-bin,
+ gtk-update-icon-cache,
libjfreechart-java,
libreadline-dev,
librsvg2-bin,
diff --git a/doc/Makefile b/doc/Makefile
index 31bc08d8..707a4428 100644
--- a/doc/Makefile
+++ b/doc/Makefile
@@ -3,6 +3,7 @@
#
RELNOTES_INC=\
+ release-notes-1.6.5.inc \
release-notes-1.6.4.inc \
release-notes-1.6.3.inc \
release-notes-1.6.2.inc \
diff --git a/doc/altusmetrum-docinfo.xml b/doc/altusmetrum-docinfo.xml
index 1b8ff68d..fbd14c5a 100644
--- a/doc/altusmetrum-docinfo.xml
+++ b/doc/altusmetrum-docinfo.xml
@@ -47,6 +47,16 @@
<revhistory>
<?dbhtml filename="altusmetrum-revhistory.html"?>
<revision>
+ <revnumber>1.6.5</revnumber>
+ <date>8 Jul 2016</date>
+ <revremark>
+ Minor release fixing TeleMega and TeleMetrum v2.0 bug which
+ would often result in loss of data logging and telemetry in
+ flight. Thanks to Chuck Haskin for help characterizing the bug
+ and testing this release.
+ </revremark>
+ </revision>
+ <revision>
<revnumber>1.6.4</revnumber>
<date>10 May 2016</date>
<revremark>
diff --git a/doc/install-html b/doc/install-html
new file mode 100755
index 00000000..71c7933c
--- /dev/null
+++ b/doc/install-html
@@ -0,0 +1,32 @@
+#!/bin/sh
+destination=
+state=arg
+for file in "$@"; do
+ case $state in
+ arg)
+ case $file in
+ -d)
+ state=destination
+ ;;
+ *)
+ base=`basename $file`
+ case "$destination" in
+ "")
+ echo "Need -d destination option before files" 1>&2
+ exit 1
+ ;;
+ *)
+ sed \
+ -e 's/<[?]xml [^>]*>//' \
+ -e 's/<!DOCTYPE [^>]*>//' "$file" > "$destination/$base"
+ ;;
+ esac
+ ;;
+ esac
+ ;;
+ destination)
+ destination=$file
+ state=arg
+ ;;
+ esac
+done
diff --git a/doc/release-notes-1.6.5.inc b/doc/release-notes-1.6.5.inc
new file mode 100644
index 00000000..9f3ae281
--- /dev/null
+++ b/doc/release-notes-1.6.5.inc
@@ -0,0 +1,24 @@
+= Release Notes for Version 1.6.5
+:toc!:
+:doctype: article
+
+ Version 1.6.5 fixes a TeleMega and TeleMetrum v2.0 bug where
+ the device would often stop logging data and transmitting
+ telemetry in flight. All TeleMega v1.0, v2.0 and TeleMetrum
+ v2.0 users should update their flight firmware.
+
+ == AltOS
+
+ AltOS fixes:
+
+ * Fix STM32L SPI driver to prevent lock-up in the logging or
+ radio code, either of which could stop data logging and
+ telemetry. Found and characterized by Chuck Haskin, who also
+ tested the new firmware before release.
+
+ == AltosUI, TeleGPS and AltosDroid Applications
+
+ AltosUI fixes:
+
+ * Deliver firmward for TeleMega v2.0 and TeleBT v3.0 with
+ Windows package.
diff --git a/doc/release-notes.inc b/doc/release-notes.inc
index 6ac90cfd..b8b34e7b 100644
--- a/doc/release-notes.inc
+++ b/doc/release-notes.inc
@@ -2,10 +2,13 @@
== Release Notes
:leveloffset: 2
- include::release-notes-1.6.4.raw[]
+ include::release-notes-1.6.5.raw[]
<<<<
+ :leveloffset: 2
+ include::release-notes-1.6.4.raw[]
+ <<<<
:leveloffset: 2
include::release-notes-1.6.3.raw[]
diff --git a/src/cc1111/ao_pins.h b/src/cc1111/ao_pins.h
index e12f813f..9cbb0a7b 100644
--- a/src/cc1111/ao_pins.h
+++ b/src/cc1111/ao_pins.h
@@ -61,6 +61,7 @@
#define HAS_TELEMETRY 1
#define HAS_RADIO_RATE 0 /* not enough space for this */
#define HAS_MUTEX_TRY 0
+ #define HAS_TASK_INFO 0 /* not enough space for this either */
#endif
#if defined(TELEMETRUM_V_1_1)
diff --git a/src/drivers/ao_cc1120.c b/src/drivers/ao_cc1120.c
index 5b814667..6b800585 100644
--- a/src/drivers/ao_cc1120.c
+++ b/src/drivers/ao_cc1120.c
@@ -44,7 +44,10 @@ extern const uint32_t ao_radio_cal;
#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_start_bytes() ao_spi_start_bytes(AO_CC1120_SPI_BUS)
+#define ao_radio_spi_stop_bytes() ao_spi_stop_bytes(AO_CC1120_SPI_BUS)
+#define ao_radio_spi_send_byte(b) ao_spi_send_byte(b, AO_CC1120_SPI_BUS)
+#define ao_radio_spi_recv_byte() ao_spi_recv_byte(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)
@@ -111,28 +114,23 @@ ao_radio_reg_write(uint16_t addr, uint8_t value)
static void
_ao_radio_burst_read_start (uint16_t addr)
{
- uint8_t data[2];
- uint8_t d;
+ ao_radio_spi_start_bytes();
if (CC1120_IS_EXTENDED(addr)) {
- data[0] = ((1 << CC1120_READ) |
- (1 << CC1120_BURST) |
- CC1120_EXTENDED);
- data[1] = addr;
- d = 2;
+ ao_radio_spi_send_byte((1 << CC1120_READ) |
+ (1 << CC1120_BURST) |
+ CC1120_EXTENDED);
} else {
- data[0] = ((1 << CC1120_READ) |
- (1 << CC1120_BURST) |
- addr);
- d = 1;
+ addr |= ((1 << CC1120_READ) |
+ (1 << CC1120_BURST));
}
-
- ao_radio_spi_send_sync(data, d);
+ ao_radio_spi_send_byte(addr);
}
static void
ao_radio_burst_read_stop (void)
{
+ ao_radio_spi_stop_bytes();
ao_radio_deselect();
}
@@ -206,9 +204,9 @@ ao_radio_fifo_write_fixed(uint8_t data, uint8_t len)
}
static uint8_t
-ao_radio_tx_fifo_space(void)
+ao_radio_int_pin(void)
{
- return CC1120_FIFO_SIZE - ao_radio_reg_read(CC1120_NUM_TXBYTES);
+ return ao_gpio_get(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN, AO_CC1120_INT);
}
#if CC1120_DEBUG
@@ -264,11 +262,16 @@ ao_radio_isr(void)
}
static void
-ao_radio_start_tx(void)
+ao_radio_enable_isr(void)
{
- ao_exti_set_callback(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN, ao_radio_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);
+}
+
+static void
+ao_radio_start_tx(void)
+{
+ ao_exti_set_callback(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN, ao_radio_isr);
ao_radio_tx_finished = 0;
ao_radio_strobe(CC1120_STX);
}
@@ -424,10 +427,13 @@ static const uint16_t packet_setup_24[] = {
CC1120_PA_CFG0, 0x7e,
};
+#define AO_CC1120_TX_BUFFER 64
+
static const uint16_t packet_tx_setup[] = {
CC1120_PKT_CFG2, ((CC1120_PKT_CFG2_CCA_MODE_ALWAYS_CLEAR << CC1120_PKT_CFG2_CCA_MODE) |
(CC1120_PKT_CFG2_PKT_FORMAT_NORMAL << CC1120_PKT_CFG2_PKT_FORMAT)),
- AO_CC1120_INT_GPIO_IOCFG, CC1120_IOCFG_GPIO_CFG_RX0TX1_CFG,
+ CC1120_FIFO_CFG, ((0 << CC1120_FIFO_CFG_CRC_AUTOFLUSH) |
+ (AO_CC1120_TX_BUFFER << CC1120_FIFO_CFG_FIFO_THR)),
};
static const uint16_t packet_rx_setup[] = {
@@ -534,6 +540,8 @@ static const uint16_t aprs_setup[] = {
CC1120_PREAMBLE_CFG1, ((CC1120_PREAMBLE_CFG1_NUM_PREAMBLE_NONE << CC1120_PREAMBLE_CFG1_NUM_PREAMBLE) |
(CC1120_PREAMBLE_CFG1_PREAMBLE_WORD_AA << CC1120_PREAMBLE_CFG1_PREAMBLE_WORD)),
CC1120_PA_CFG0, 0x7d,
+ CC1120_FIFO_CFG, ((0 << CC1120_FIFO_CFG_CRC_AUTOFLUSH) |
+ (AO_CC1120_TX_BUFFER << CC1120_FIFO_CFG_FIFO_THR)),
};
/*
@@ -739,8 +747,10 @@ ao_rdf_run(void)
ao_radio_start_tx();
ao_arch_block_interrupts();
- while (!ao_radio_wake && !ao_radio_abort && !ao_radio_mcu_wake)
+ while (!ao_radio_wake && !ao_radio_abort && !ao_radio_mcu_wake) {
+ ao_radio_enable_isr();
ao_sleep(&ao_radio_wake);
+ }
ao_arch_release_interrupts();
if (ao_radio_mcu_wake)
ao_radio_check_marc_status();
@@ -846,18 +856,14 @@ ao_radio_wait_isr(uint16_t timeout)
ao_radio_check_marc_status();
}
-static uint8_t
-ao_radio_wait_tx(uint8_t wait_fifo)
+static void
+ao_radio_wait_fifo(void)
{
- uint8_t fifo_space = 0;
-
- do {
+ while (ao_radio_int_pin() != 0 && !ao_radio_abort) {
+ ao_radio_wake = 0;
+ ao_radio_enable_isr();
ao_radio_wait_isr(0);
- if (!wait_fifo)
- return 0;
- fifo_space = ao_radio_tx_fifo_space();
- } while (!fifo_space && !ao_radio_abort);
- return fifo_space;
+ }
}
static uint8_t tx_data[(AO_RADIO_MAX_SEND + 4) * 2];
@@ -869,7 +875,6 @@ ao_radio_send(const void *d, uint8_t size)
uint8_t encode_len;
uint8_t this_len;
uint8_t started = 0;
- uint8_t fifo_space;
encode_len = ao_fec_encode(d, size, tx_data);
@@ -880,14 +885,17 @@ ao_radio_send(const void *d, uint8_t size)
/* Flush any pending TX bytes */
ao_radio_strobe(CC1120_SFTX);
- started = 0;
- fifo_space = CC1120_FIFO_SIZE;
while (encode_len) {
this_len = encode_len;
- ao_radio_wake = 0;
- if (this_len > fifo_space) {
- this_len = fifo_space;
+ if (started) {
+ ao_radio_wait_fifo();
+ if (ao_radio_abort)
+ break;
+ }
+
+ if (this_len > AO_CC1120_TX_BUFFER) {
+ this_len = AO_CC1120_TX_BUFFER;
ao_radio_set_mode(AO_RADIO_MODE_PACKET_TX_BUF);
} else {
ao_radio_set_mode(AO_RADIO_MODE_PACKET_TX_FINISH);
@@ -900,35 +908,32 @@ ao_radio_send(const void *d, uint8_t size)
if (!started) {
ao_radio_start_tx();
started = 1;
- } else {
- ao_exti_enable(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN);
- }
-
- fifo_space = ao_radio_wait_tx(encode_len != 0);
- if (ao_radio_abort) {
- ao_radio_idle();
- break;
}
}
- while (started && !ao_radio_abort && !ao_radio_tx_finished)
+ while (started && !ao_radio_abort && !ao_radio_tx_finished) {
+ ao_radio_wake = 0;
+ ao_radio_enable_isr();
ao_radio_wait_isr(0);
+ }
+ if (ao_radio_abort)
+ ao_radio_idle();
ao_radio_put();
}
-#define AO_RADIO_LOTS 64
-
void
ao_radio_send_aprs(ao_radio_fill_func fill)
{
- uint8_t buf[AO_RADIO_LOTS], *b;
+ uint8_t buf[AO_CC1120_TX_BUFFER];
int cnt;
int total = 0;
uint8_t done = 0;
uint8_t started = 0;
- uint8_t fifo_space;
ao_radio_get(0xff);
- fifo_space = CC1120_FIFO_SIZE;
+
+ ao_radio_abort = 0;
+
+ ao_exti_set_callback(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN, ao_radio_isr);
while (!done) {
cnt = (*fill)(buf, sizeof(buf));
if (cnt < 0) {
@@ -937,51 +942,34 @@ ao_radio_send_aprs(ao_radio_fill_func fill)
}
total += cnt;
- /* At the last buffer, set the total length */
- if (done)
- ao_radio_set_len(total & 0xff);
-
- b = buf;
- while (cnt) {
- uint8_t this_len = cnt;
-
- /* Wait for some space in the fifo */
- while (!ao_radio_abort && (fifo_space = ao_radio_tx_fifo_space()) == 0) {
- ao_radio_wake = 0;
- ao_radio_wait_isr(0);
- }
+ /* Wait for some space in the fifo */
+ if (started) {
+ ao_radio_wait_fifo();
if (ao_radio_abort)
break;
- if (this_len > fifo_space)
- this_len = fifo_space;
-
- cnt -= this_len;
-
- if (done) {
- if (cnt)
- ao_radio_set_mode(AO_RADIO_MODE_APRS_LAST_BUF);
- else
- ao_radio_set_mode(AO_RADIO_MODE_APRS_FINISH);
- } else
- ao_radio_set_mode(AO_RADIO_MODE_APRS_BUF);
-
- ao_radio_fifo_write(b, this_len);
- b += this_len;
-
- if (!started) {
- ao_radio_start_tx();
- started = 1;
- } else
- ao_exti_enable(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN);
}
- if (ao_radio_abort) {
- ao_radio_idle();
- break;
+
+ if (done) {
+ ao_radio_set_len(total & 0xff);
+ ao_radio_set_mode(AO_RADIO_MODE_APRS_FINISH);
+ } else
+ ao_radio_set_mode(AO_RADIO_MODE_APRS_BUF);
+
+ ao_radio_fifo_write(buf, cnt);
+
+ if (!started) {
+ ao_radio_start_tx();
+ started = 1;
}
- /* Wait for the transmitter to go idle */
+ }
+ /* Wait for the transmitter to go idle */
+ while (started && ao_radio_int_pin() != 0 && !ao_radio_abort) {
ao_radio_wake = 0;
+ ao_radio_enable_isr();
ao_radio_wait_isr(0);
}
+ if (ao_radio_abort)
+ ao_radio_idle();
ao_radio_put();
}
@@ -1029,8 +1017,7 @@ ao_radio_rx_isr(void)
rx_starting = 0;
ao_wakeup(&ao_radio_wake);
}
- d = AO_CC1120_SPI.dr;
- AO_CC1120_SPI.dr = 0;
+ d = ao_radio_spi_recv_byte();
if (rx_ignore == 0) {
if (rx_data_cur < rx_data_count)
rx_data[rx_data_cur++] = d;
@@ -1099,7 +1086,7 @@ ao_radio_recv(__xdata void *d, uint8_t size, uint8_t timeout)
rx_data_count = len * 8; /* bytes to bits */
rx_data_cur = 0;
rx_data_consumed = 0;
- rx_ignore = 2;
+ rx_ignore = 1;
/* Must be set before changing the frequency; any abort
* after the frequency is set needs to terminate the read
@@ -1149,9 +1136,7 @@ ao_radio_recv(__xdata void *d, uint8_t size, uint8_t timeout)
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;
+ (void) ao_radio_spi_recv_byte();
--rx_ignore;
}
}
diff --git a/src/drivers/ao_cc1200.c b/src/drivers/ao_cc1200.c
index 6bccb188..cd85f208 100644
--- a/src/drivers/ao_cc1200.c
+++ b/src/drivers/ao_cc1200.c
@@ -185,9 +185,9 @@ ao_radio_fifo_write_fixed(uint8_t data, uint8_t len)
}
static uint8_t
-ao_radio_tx_fifo_space(void)
+ao_radio_int_pin(void)
{
- return CC1200_FIFO_SIZE - ao_radio_reg_read(CC1200_NUM_TXBYTES);
+ return ao_gpio_get(AO_CC1200_INT_PORT, AO_CC1200_INT_PIN, AO_CC1200_INT);
}
static uint8_t
@@ -482,6 +482,7 @@ static const uint16_t rdf_setup[] = {
*/
#define APRS_SYMBOL_RATE_E 6
#define APRS_SYMBOL_RATE_M 1013008
+#define APRS_BUFFER_SIZE 64
static const uint16_t aprs_setup[] = {
CC1200_DEVIATION_M, APRS_DEV_M,
@@ -516,6 +517,9 @@ static const uint16_t aprs_setup[] = {
(CC1200_MDMCFG2_SYMBOL_MAP_CFG_MODE_0 << CC1200_MDMCFG2_SYMBOL_MAP_CFG) |
(CC1200_MDMCFG2_UPSAMPLER_P_8 << CC1200_MDMCFG2_UPSAMPLER_P) |
(0 << CC1200_MDMCFG2_CFM_DATA_EN)),
+ CC1200_FIFO_CFG,
+ ((0 << CC1200_FIFO_CFG_CRC_AUTOFLUSH) |
+ (APRS_BUFFER_SIZE << CC1200_FIFO_CFG_FIFO_THR)),
};
/*
@@ -861,105 +865,58 @@ ao_radio_send(const void *d, uint8_t size)
ao_radio_run();
}
-
-#define AO_RADIO_LOTS 64
-
void
ao_radio_send_aprs(ao_radio_fill_func fill)
{
- uint8_t buf[AO_RADIO_LOTS], *b;
+ uint8_t buf[APRS_BUFFER_SIZE];
int cnt;
int total = 0;
uint8_t done = 0;
uint8_t started = 0;
- uint8_t fifo_space;
ao_radio_abort = 0;
ao_radio_get(0xff);
- fifo_space = CC1200_FIFO_SIZE;
- while (!done) {
+ ao_radio_wake = 0;
+ while (!done && !ao_radio_abort) {
cnt = (*fill)(buf, sizeof(buf));
if (cnt < 0) {
done = 1;
cnt = -cnt;
}
-#if CC1200_APRS_TRACE
- printf("APRS fill %d bytes done %d\n", cnt, done);
-#endif
total += cnt;
/* At the last buffer, set the total length */
if (done)
ao_radio_set_len(total & 0xff);
- b = buf;
- while (cnt) {
- uint8_t this_len = cnt;
-
- /* Wait for some space in the fifo */
- while (!ao_radio_abort && (fifo_space = ao_radio_tx_fifo_space()) == 0) {
-#if CC1200_APRS_TRACE
- printf("APRS space %d cnt %d\n", fifo_space, cnt); flush();
-#endif
- ao_radio_wake = 0;
- ao_radio_wait_isr(AO_MS_TO_TICKS(1000));
- }
- if (ao_radio_abort)
- break;
- if (this_len > fifo_space)
- this_len = fifo_space;
-
- cnt -= this_len;
-
- if (done) {
- if (cnt)
- ao_radio_set_mode(AO_RADIO_MODE_APRS_LAST_BUF);
- else
- ao_radio_set_mode(AO_RADIO_MODE_APRS_FINISH);
- } else
- ao_radio_set_mode(AO_RADIO_MODE_APRS_BUF);
-
+ /* Wait for some space in the fifo */
+ while (started && ao_radio_int_pin() != 0 && !ao_radio_abort) {
+ ao_radio_wake = 0;
ao_exti_enable(AO_CC1200_INT_PORT, AO_CC1200_INT_PIN);
-
- ao_radio_fifo_write(b, this_len);
- b += this_len;
-#if CC1200_APRS_TRACE
- printf("APRS write fifo %d space now %d\n", this_len, ao_radio_tx_fifo_space());
-#endif
- if (!started) {
-#if CC1200_APRS_TRACE
- printf("APRS start\n");
-#endif
- ao_radio_strobe(CC1200_STX);
-#if CC1200_APRS_TRACE
- { int t;
- for (t = 0; t < 20; t++) {
- uint8_t status = ao_radio_status();
- uint8_t space = ao_radio_tx_fifo_space();
- printf ("status: %02x fifo %d\n", status, space);
- if ((status >> 4) == 2)
- break;
- ao_delay(AO_MS_TO_TICKS(0));
- }
- }
-#endif
- started = 1;
- }
+ ao_radio_wait_isr(AO_MS_TO_TICKS(1000));
}
- if (ao_radio_abort) {
- ao_radio_idle();
+ if (ao_radio_abort)
break;
+
+ if (done)
+ ao_radio_set_mode(AO_RADIO_MODE_APRS_FINISH);
+ else
+ ao_radio_set_mode(AO_RADIO_MODE_APRS_BUF);
+
+ ao_radio_fifo_write(buf, cnt);
+ if (!started) {
+ ao_radio_strobe(CC1200_STX);
+ started = 1;
}
}
/* Wait for the transmitter to go idle */
- ao_radio_wake = 0;
-#if CC1200_APRS_TRACE
- printf("APRS wait idle\n"); flush();
-#endif
- ao_radio_wait_isr(AO_MS_TO_TICKS(1000));
-#if CC1200_APRS_TRACE
- printf("APRS abort %d\n", ao_radio_abort);
-#endif
+ while (started && ao_radio_int_pin() != 0 && !ao_radio_abort) {
+ ao_radio_wake = 0;
+ ao_exti_enable(AO_CC1200_INT_PORT, AO_CC1200_INT_PIN);
+ ao_radio_wait_isr(AO_MS_TO_TICKS(1000));
+ }
+ if (ao_radio_abort)
+ ao_radio_idle();
ao_radio_put();
}
diff --git a/src/kernel/ao.h b/src/kernel/ao.h
index 6ed0299e..27a16606 100644
--- a/src/kernel/ao.h
+++ b/src/kernel/ao.h
@@ -73,6 +73,7 @@ typedef AO_PORT_TYPE ao_port_t;
#define AO_PANIC_EXTI 16 /* Mis-using exti API */
#define AO_PANIC_FAST_TIMER 17 /* Mis-using fast timer API */
#define AO_PANIC_ADC 18 /* Mis-using ADC interface */
+#define AO_PANIC_IRQ 19 /* interrupts not blocked */
#define AO_PANIC_SELF_TEST_CC1120 0x40 | 1 /* Self test failure */
#define AO_PANIC_SELF_TEST_HMC5883 0x40 | 2 /* Self test failure */
#define AO_PANIC_SELF_TEST_MPU6000 0x40 | 3 /* Self test failure */
diff --git a/src/kernel/ao_flight.c b/src/kernel/ao_flight.c
index 9ba02bb8..9031a54a 100644
--- a/src/kernel/ao_flight.c
+++ b/src/kernel/ao_flight.c
@@ -130,7 +130,7 @@ ao_flight(void)
{
/* Set pad mode - we can fly! */
ao_flight_state = ao_flight_pad;
-#if HAS_USB && !HAS_FLIGHT_DEBUG && !HAS_SAMPLE_PROFILE
+#if HAS_USB && !HAS_FLIGHT_DEBUG && !HAS_SAMPLE_PROFILE && !DEBUG
/* Disable the USB controller in flight mode
* to save power
*/
diff --git a/src/kernel/ao_task.c b/src/kernel/ao_task.c
index e430edc6..cf0b58ed 100644
--- a/src/kernel/ao_task.c
+++ b/src/kernel/ao_task.c
@@ -54,6 +54,12 @@ static inline void ao_check_stack(void) {
#define ao_check_stack()
#endif
+#if DEBUG
+#define ao_task_irq_check() ao_arch_irq_check()
+#else
+#define ao_task_irq_check()
+#endif
+
#if HAS_TASK_QUEUE
#define SLEEP_HASH_SIZE 17
@@ -65,6 +71,7 @@ static struct ao_list sleep_queue[SLEEP_HASH_SIZE];
static void
ao_task_to_run_queue(struct ao_task *task)
{
+ ao_task_irq_check();
ao_list_del(&task->queue);
ao_list_append(&task->queue, &run_queue);
}
@@ -78,6 +85,7 @@ ao_task_sleep_queue(void *wchan)
static void
ao_task_to_sleep_queue(struct ao_task *task, void *wchan)
{
+ ao_task_irq_check();
ao_list_del(&task->queue);
ao_list_append(&task->queue, ao_task_sleep_queue(wchan));
}
@@ -122,6 +130,7 @@ static void
ao_task_to_alarm_queue(struct ao_task *task)
{
struct ao_task *alarm;
+ ao_task_irq_check();
ao_list_for_each_entry(alarm, &alarm_queue, struct ao_task, alarm_queue) {
if ((int16_t) (alarm->alarm - task->alarm) >= 0) {
ao_list_insert(&task->alarm_queue, alarm->alarm_queue.prev);
@@ -138,6 +147,7 @@ ao_task_to_alarm_queue(struct ao_task *task)
static void
ao_task_from_alarm_queue(struct ao_task *task)
{
+ ao_task_irq_check();
ao_list_del(&task->alarm_queue);
if (ao_list_is_empty(&alarm_queue))
ao_task_alarm_tick = 0;
@@ -156,6 +166,7 @@ ao_task_init_queue(struct ao_task *task)
static void
ao_task_exit_queue(struct ao_task *task)
{
+ ao_task_irq_check();
ao_list_del(&task->queue);
ao_list_del(&task->alarm_queue);
}
@@ -165,13 +176,14 @@ ao_task_check_alarm(uint16_t tick)
{
struct ao_task *alarm, *next;
- ao_list_for_each_entry_safe(alarm, next, &alarm_queue, struct ao_task, alarm_queue) {
- if ((int16_t) (tick - alarm->alarm) < 0)
- break;
- alarm->alarm = 0;
- ao_task_from_alarm_queue(alarm);
- ao_task_to_run_queue(alarm);
- }
+ ao_arch_critical(
+ ao_list_for_each_entry_safe(alarm, next, &alarm_queue, struct ao_task, alarm_queue) {
+ if ((int16_t) (tick - alarm->alarm) < 0)
+ break;
+ alarm->alarm = 0;
+ ao_task_from_alarm_queue(alarm);
+ ao_task_to_run_queue(alarm);
+ });
}
void
@@ -459,11 +471,11 @@ ao_sleep_for(__xdata void *wchan, uint16_t timeout)
if (timeout) {
#if HAS_TASK_QUEUE
uint32_t flags;
+ flags = ao_arch_irqsave();
+#endif
/* Make sure we sleep *at least* delay ticks, which means adding
* one to account for the fact that we may be close to the next tick
*/
- flags = ao_arch_irqsave();
-#endif
if (!(ao_cur_task->alarm = ao_time() + timeout + 1))
ao_cur_task->alarm = 1;
#if HAS_TASK_QUEUE
@@ -492,6 +504,8 @@ static __xdata uint8_t ao_forever;
void
ao_delay(uint16_t ticks)
{
+ if (!ticks)
+ ticks = 1;
ao_sleep_for(&ao_forever, ticks);
}
@@ -523,12 +537,15 @@ ao_task_info(void)
{
uint8_t i;
__xdata struct ao_task *task;
+ uint16_t now = ao_time();
for (i = 0; i < ao_num_tasks; i++) {
task = ao_tasks[i];
- printf("%12s: wchan %04x\n",
- task->name,
- (int) task->wchan);
+ printf("%2d: wchan %08x alarm %5d %s\n",
+ task->task_id,
+ (int) task->wchan,
+ task->alarm ? (int16_t) (task->alarm - now) : 9999,
+ task->name);
}
#if HAS_TASK_QUEUE && DEBUG
ao_task_validate();
diff --git a/src/stm/ao_arch_funcs.h b/src/stm/ao_arch_funcs.h
index 2c017c79..a796891d 100644
--- a/src/stm/ao_arch_funcs.h
+++ b/src/stm/ao_arch_funcs.h
@@ -80,7 +80,13 @@ 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);
+ao_spi_send_sync(const void *block, uint16_t len, uint8_t spi_index);
+
+void
+ao_spi_start_bytes(uint8_t spi_index);
+
+void
+ao_spi_stop_bytes(uint8_t spi_index);
static inline void
ao_spi_send_byte(uint8_t byte, uint8_t spi_index)
@@ -96,18 +102,34 @@ ao_spi_send_byte(uint8_t byte, uint8_t spi_index)
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 */
+ while (!(stm_spi->sr & (1 << STM_SPI_SR_TXE)))
+ ;
+ stm_spi->dr = byte;
+ while (!(stm_spi->sr & (1 << STM_SPI_SR_RXNE)))
+ ;
(void) stm_spi->dr;
+}
- while (!(stm_spi->sr & (1 << STM_SPI_SR_TXE)));
- stm_spi->dr = byte;
+static inline uint8_t
+ao_spi_recv_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;
+ }
+
+ while (!(stm_spi->sr & (1 << STM_SPI_SR_TXE)))
+ ;
+ stm_spi->dr = 0xff;
+ while (!(stm_spi->sr & (1 << STM_SPI_SR_RXNE)))
+ ;
+ return stm_spi->dr;
}
void
@@ -250,9 +272,6 @@ void
ao_dma_done_transfer(uint8_t index);
void
-ao_dma_abort(uint8_t index);
-
-void
ao_dma_alloc(uint8_t index);
void
@@ -343,6 +362,14 @@ ao_arch_memory_barrier() {
asm volatile("" ::: "memory");
}
+static inline void
+ao_arch_irq_check(void) {
+ uint32_t primask;
+ asm("mrs %0,primask" : "=&r" (primask));
+ if ((primask & 1) == 0)
+ ao_panic(AO_PANIC_IRQ);
+}
+
#if HAS_TASK
static inline void
ao_arch_init_stack(struct ao_task *task, void *start)
diff --git a/src/stm/ao_dma_stm.c b/src/stm/ao_dma_stm.c
index 8379a1a5..0135de48 100644
--- a/src/stm/ao_dma_stm.c
+++ b/src/stm/ao_dma_stm.c
@@ -64,7 +64,7 @@ ao_dma_set_transfer(uint8_t index,
if (ao_dma_allocated[index]) {
if (ao_dma_mutex[index])
ao_panic(AO_PANIC_DMA);
- ao_dma_mutex[index] = 1;
+ ao_dma_mutex[index] = 0xff;
} else
ao_mutex_get(&ao_dma_mutex[index]);
ao_arch_critical(
@@ -106,13 +106,6 @@ ao_dma_done_transfer(uint8_t index)
}
void
-ao_dma_abort(uint8_t index)
-{
- stm_dma.channel[index].ccr &= ~(1 << STM_DMA_CCR_EN);
- ao_wakeup(&ao_dma_done[index]);
-}
-
-void
ao_dma_alloc(uint8_t index)
{
if (ao_dma_allocated[index])
@@ -120,6 +113,40 @@ ao_dma_alloc(uint8_t index)
ao_dma_allocated[index] = 1;
}
+#if DEBUG
+void
+ao_dma_dump_cmd(void)
+{
+ int i;
+
+ ao_arch_critical(
+ if (ao_dma_active++ == 0)
+ stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_DMA1EN);
+ );
+ printf ("isr %08x ifcr%08x\n", stm_dma.isr, stm_dma.ifcr);
+ for (i = 0; i < NUM_DMA; i++)
+ printf("%d: done %d allocated %d mutex %2d ccr %04x cndtr %04x cpar %08x cmar %08x isr %08x\n",
+ i,
+ ao_dma_done[i],
+ ao_dma_allocated[i],
+ ao_dma_mutex[i],
+ stm_dma.channel[i].ccr,
+ stm_dma.channel[i].cndtr,
+ stm_dma.channel[i].cpar,
+ stm_dma.channel[i].cmar,
+ ao_dma_config[i].isr);
+ ao_arch_critical(
+ if (--ao_dma_active == 0)
+ stm_rcc.ahbenr &= ~(1 << STM_RCC_AHBENR_DMA1EN);
+ );
+}
+
+static const struct ao_cmds ao_dma_cmds[] = {
+ { ao_dma_dump_cmd, "D\0Dump DMA status" },
+ { 0, NULL }
+};
+#endif
+
void
ao_dma_init(void)
{
@@ -131,5 +158,7 @@ ao_dma_init(void)
ao_dma_allocated[index] = 0;
ao_dma_mutex[index] = 0;
}
-
+#if DEBUG
+ ao_cmd_register(&ao_dma_cmds[0]);
+#endif
}
diff --git a/src/stm/ao_exti_stm.c b/src/stm/ao_exti_stm.c
index 35958cf8..925f9a22 100644
--- a/src/stm/ao_exti_stm.c
+++ b/src/stm/ao_exti_stm.c
@@ -144,7 +144,7 @@ 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);
+ stm_exti.imr |= mask;
}
void
diff --git a/src/stm/ao_spi_stm.c b/src/stm/ao_spi_stm.c
index 7eaa3924..214092f6 100644
--- a/src/stm/ao_spi_stm.c
+++ b/src/stm/ao_spi_stm.c
@@ -41,12 +41,91 @@ static const struct ao_spi_stm_info ao_spi_stm_info[STM_NUM_SPI] = {
static uint8_t spi_dev_null;
+#if DEBUG
+static struct {
+ uint8_t task;
+ uint8_t which;
+ AO_TICK_TYPE tick;
+ uint16_t len;
+} spi_tasks[64];
+static uint8_t spi_task_index;
+
+static void
+validate_spi(struct stm_spi *stm_spi, int which, uint16_t len)
+{
+ uint32_t sr = stm_spi->sr;
+
+ if (stm_spi != &stm_spi2)
+ return;
+ spi_tasks[spi_task_index].task = ao_cur_task ? ao_cur_task->task_id : 0;
+ spi_tasks[spi_task_index].which = which;
+ spi_tasks[spi_task_index].tick = ao_time();
+ spi_tasks[spi_task_index].len = len;
+ spi_task_index = (spi_task_index + 1) & (63);
+ if (sr & (1 << STM_SPI_SR_FRE))
+ ao_panic(0x40 | 1);
+ if (sr & (1 << STM_SPI_SR_BSY))
+ ao_panic(0x40 | 2);
+ if (sr & (1 << STM_SPI_SR_OVR))
+ ao_panic(0x40 | 3);
+ if (sr & (1 << STM_SPI_SR_MODF))
+ ao_panic(0x40 | 4);
+ if (sr & (1 << STM_SPI_SR_UDR))
+ ao_panic(0x40 | 5);
+ if ((sr & (1 << STM_SPI_SR_TXE)) == 0)
+ ao_panic(0x40 | 6);
+ if (sr & (1 << STM_SPI_SR_RXNE))
+ ao_panic(0x40 | 7);
+ if (which != 5 && which != 6 && which != 13)
+ if (ao_cur_task->task_id != ao_spi_mutex[1])
+ ao_panic(0x40 | 8);
+}
+#else
+#define validate_spi(stm_spi, which, len) do { (void) (which); (void) (len); } while (0)
+#endif
+
+static void
+ao_spi_run(uint8_t id, uint8_t which, uint16_t len)
+{
+ struct stm_spi *stm_spi = ao_spi_stm_info[id].stm_spi;
+ uint8_t mosi_dma_index = ao_spi_stm_info[id].mosi_dma_index;
+ uint8_t miso_dma_index = ao_spi_stm_info[id].miso_dma_index;
+
+ validate_spi(stm_spi, which, len);
+
+ stm_spi->cr2 = ((0 << STM_SPI_CR2_TXEIE) |
+ (0 << STM_SPI_CR2_RXNEIE) |
+ (0 << STM_SPI_CR2_ERRIE) |
+ (0 << STM_SPI_CR2_SSOE) |
+ (1 << STM_SPI_CR2_TXDMAEN) |
+ (1 << STM_SPI_CR2_RXDMAEN));
+
+ ao_dma_start(miso_dma_index);
+ ao_dma_start(mosi_dma_index);
+
+ ao_arch_critical(
+ while (!ao_dma_done[miso_dma_index])
+ ao_sleep(&ao_dma_done[miso_dma_index]);
+ );
+
+ while ((stm_spi->sr & (1 << STM_SPI_SR_TXE)) == 0);
+ while (stm_spi->sr & (1 << STM_SPI_SR_BSY));
+
+ validate_spi(stm_spi, which+1, len);
+
+ stm_spi->cr2 = 0;
+
+ ao_dma_done_transfer(mosi_dma_index);
+ ao_dma_done_transfer(miso_dma_index);
+}
+
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;
+ uint8_t id = AO_SPI_INDEX(spi_index);
+ struct stm_spi *stm_spi = ao_spi_stm_info[id].stm_spi;
+ uint8_t mosi_dma_index = ao_spi_stm_info[id].mosi_dma_index;
+ uint8_t miso_dma_index = ao_spi_stm_info[id].miso_dma_index;
/* Set up the transmit DMA to deliver data */
ao_dma_set_transfer(mosi_dma_index,
@@ -62,9 +141,6 @@ ao_spi_send(const void *block, uint16_t len, uint8_t spi_index)
(0 << STM_DMA_CCR_CIRC) |
(STM_DMA_CCR_DIR_MEM_TO_PER << STM_DMA_CCR_DIR));
- /* Clear RXNE */
- (void) stm_spi->dr;
-
/* Set up the receive DMA -- when this is done, we know the SPI unit
* is idle. Without this, we'd have to poll waiting for the BSY bit to
* be cleared
@@ -81,28 +157,17 @@ ao_spi_send(const void *block, uint16_t len, uint8_t spi_index)
(0 << STM_DMA_CCR_PINC) |
(0 << STM_DMA_CCR_CIRC) |
(STM_DMA_CCR_DIR_PER_TO_MEM << STM_DMA_CCR_DIR));
- stm_spi->cr2 = ((0 << STM_SPI_CR2_TXEIE) |
- (0 << STM_SPI_CR2_RXNEIE) |
- (0 << STM_SPI_CR2_ERRIE) |
- (0 << STM_SPI_CR2_SSOE) |
- (1 << STM_SPI_CR2_TXDMAEN) |
- (1 << STM_SPI_CR2_RXDMAEN));
- ao_dma_start(miso_dma_index);
- ao_dma_start(mosi_dma_index);
- ao_arch_critical(
- while (!ao_dma_done[miso_dma_index])
- ao_sleep(&ao_dma_done[miso_dma_index]);
- );
- ao_dma_done_transfer(mosi_dma_index);
- ao_dma_done_transfer(miso_dma_index);
+
+ ao_spi_run(id, 1, len);
}
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;
+ uint8_t id = AO_SPI_INDEX(spi_index);
+ struct stm_spi *stm_spi = ao_spi_stm_info[id].stm_spi;
+ uint8_t mosi_dma_index = ao_spi_stm_info[id].mosi_dma_index;
+ uint8_t miso_dma_index = ao_spi_stm_info[id].miso_dma_index;
/* Set up the transmit DMA to deliver data */
ao_dma_set_transfer(mosi_dma_index,
@@ -118,9 +183,6 @@ ao_spi_send_fixed(uint8_t value, uint16_t len, uint8_t spi_index)
(0 << STM_DMA_CCR_CIRC) |
(STM_DMA_CCR_DIR_MEM_TO_PER << STM_DMA_CCR_DIR));
- /* Clear RXNE */
- (void) stm_spi->dr;
-
/* Set up the receive DMA -- when this is done, we know the SPI unit
* is idle. Without this, we'd have to poll waiting for the BSY bit to
* be cleared
@@ -137,27 +199,48 @@ ao_spi_send_fixed(uint8_t value, uint16_t len, uint8_t spi_index)
(0 << STM_DMA_CCR_PINC) |
(0 << STM_DMA_CCR_CIRC) |
(STM_DMA_CCR_DIR_PER_TO_MEM << STM_DMA_CCR_DIR));
+
+ ao_spi_run(id, 3, len);
+}
+
+void
+ao_spi_start_bytes(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->cr2 = ((0 << STM_SPI_CR2_TXEIE) |
(0 << STM_SPI_CR2_RXNEIE) |
(0 << STM_SPI_CR2_ERRIE) |
(0 << STM_SPI_CR2_SSOE) |
- (1 << STM_SPI_CR2_TXDMAEN) |
- (1 << STM_SPI_CR2_RXDMAEN));
- ao_dma_start(miso_dma_index);
- ao_dma_start(mosi_dma_index);
- ao_arch_critical(
- while (!ao_dma_done[miso_dma_index])
- ao_sleep(&ao_dma_done[miso_dma_index]);
- );
- ao_dma_done_transfer(mosi_dma_index);
- ao_dma_done_transfer(miso_dma_index);
+ (0 << STM_SPI_CR2_TXDMAEN) |
+ (0 << STM_SPI_CR2_RXDMAEN));
+ validate_spi(stm_spi, 5, 0xffff);
}
void
-ao_spi_send_sync(void *block, uint16_t len, uint8_t spi_index)
+ao_spi_stop_bytes(uint8_t spi_index)
{
- uint8_t *b = block;
- struct stm_spi *stm_spi = ao_spi_stm_info[AO_SPI_INDEX(spi_index)].stm_spi;
+ uint8_t id = AO_SPI_INDEX(spi_index);
+ struct stm_spi *stm_spi = ao_spi_stm_info[id].stm_spi;
+
+ while ((stm_spi->sr & (1 << STM_SPI_SR_TXE)) == 0)
+ ;
+ while (stm_spi->sr & (1 << STM_SPI_SR_BSY))
+ ;
+ /* Clear the OVR flag */
+ (void) stm_spi->dr;
+ (void) stm_spi->sr;
+ validate_spi(stm_spi, 6, 0xffff);
+ stm_spi->cr2 = 0;
+}
+
+void
+ao_spi_send_sync(const void *block, uint16_t len, uint8_t spi_index)
+{
+ uint8_t id = AO_SPI_INDEX(spi_index);
+ const uint8_t *b = block;
+ struct stm_spi *stm_spi = ao_spi_stm_info[id].stm_spi;
stm_spi->cr2 = ((0 << STM_SPI_CR2_TXEIE) |
(0 << STM_SPI_CR2_RXNEIE) |
@@ -165,22 +248,28 @@ ao_spi_send_sync(void *block, uint16_t len, uint8_t spi_index)
(0 << STM_SPI_CR2_SSOE) |
(0 << STM_SPI_CR2_TXDMAEN) |
(0 << STM_SPI_CR2_RXDMAEN));
-
- /* Clear RXNE */
- (void) stm_spi->dr;
-
+ validate_spi(stm_spi, 7, len);
while (len--) {
while (!(stm_spi->sr & (1 << STM_SPI_SR_TXE)));
stm_spi->dr = *b++;
}
+ while ((stm_spi->sr & (1 << STM_SPI_SR_TXE)) == 0)
+ ;
+ while (stm_spi->sr & (1 << STM_SPI_SR_BSY))
+ ;
+ /* Clear the OVR flag */
+ (void) stm_spi->dr;
+ (void) stm_spi->sr;
+ validate_spi(stm_spi, 8, len);
}
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;
+ uint8_t id = AO_SPI_INDEX(spi_index);
+ struct stm_spi *stm_spi = ao_spi_stm_info[id].stm_spi;
+ uint8_t mosi_dma_index = ao_spi_stm_info[id].mosi_dma_index;
+ uint8_t miso_dma_index = ao_spi_stm_info[id].miso_dma_index;
spi_dev_null = 0xff;
@@ -198,9 +287,6 @@ ao_spi_recv(void *block, uint16_t len, uint8_t spi_index)
(0 << STM_DMA_CCR_CIRC) |
(STM_DMA_CCR_DIR_MEM_TO_PER << STM_DMA_CCR_DIR));
- /* Clear RXNE */
- (void) stm_spi->dr;
-
/* Set up the receive DMA to capture data */
ao_dma_set_transfer(miso_dma_index,
&stm_spi->dr,
@@ -215,31 +301,16 @@ ao_spi_recv(void *block, uint16_t len, uint8_t spi_index)
(0 << STM_DMA_CCR_CIRC) |
(STM_DMA_CCR_DIR_PER_TO_MEM << STM_DMA_CCR_DIR));
- stm_spi->cr2 = ((0 << STM_SPI_CR2_TXEIE) |
- (0 << STM_SPI_CR2_RXNEIE) |
- (0 << STM_SPI_CR2_ERRIE) |
- (0 << STM_SPI_CR2_SSOE) |
- (1 << STM_SPI_CR2_TXDMAEN) |
- (1 << STM_SPI_CR2_RXDMAEN));
- ao_dma_start(miso_dma_index);
- ao_dma_start(mosi_dma_index);
-
- /* Wait until the SPI unit is done */
- ao_arch_critical(
- while (!ao_dma_done[miso_dma_index])
- ao_sleep(&ao_dma_done[miso_dma_index]);
- );
-
- ao_dma_done_transfer(mosi_dma_index);
- ao_dma_done_transfer(miso_dma_index);
+ ao_spi_run(id, 9, len);
}
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;
+ uint8_t id = AO_SPI_INDEX(spi_index);
+ struct stm_spi *stm_spi = ao_spi_stm_info[id].stm_spi;
+ uint8_t mosi_dma_index = ao_spi_stm_info[id].mosi_dma_index;
+ uint8_t miso_dma_index = ao_spi_stm_info[id].miso_dma_index;
/* Set up transmit DMA to send data */
ao_dma_set_transfer(mosi_dma_index,
@@ -255,9 +326,6 @@ ao_spi_duplex(void *out, void *in, uint16_t len, uint8_t spi_index)
(0 << STM_DMA_CCR_CIRC) |
(STM_DMA_CCR_DIR_MEM_TO_PER << STM_DMA_CCR_DIR));
- /* Clear RXNE */
- (void) stm_spi->dr;
-
/* Set up the receive DMA to capture data */
ao_dma_set_transfer(miso_dma_index,
&stm_spi->dr,
@@ -271,24 +339,7 @@ ao_spi_duplex(void *out, void *in, uint16_t len, uint8_t spi_index)
(0 << STM_DMA_CCR_PINC) |
(0 << STM_DMA_CCR_CIRC) |
(STM_DMA_CCR_DIR_PER_TO_MEM << STM_DMA_CCR_DIR));
-
- stm_spi->cr2 = ((0 << STM_SPI_CR2_TXEIE) |
- (0 << STM_SPI_CR2_RXNEIE) |
- (0 << STM_SPI_CR2_ERRIE) |
- (0 << STM_SPI_CR2_SSOE) |
- (1 << STM_SPI_CR2_TXDMAEN) |
- (1 << STM_SPI_CR2_RXDMAEN));
- ao_dma_start(miso_dma_index);
- ao_dma_start(mosi_dma_index);
-
- /* Wait until the SPI unit is done */
- ao_arch_critical(
- while (!ao_dma_done[miso_dma_index])
- ao_sleep(&ao_dma_done[miso_dma_index]);
- );
-
- ao_dma_done_transfer(mosi_dma_index);
- ao_dma_done_transfer(miso_dma_index);
+ ao_spi_run(id, 11, len);
}
static void
@@ -296,44 +347,36 @@ 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;
- case AO_SPI_1_PE13_PE14_PE15:
- stm_gpio_set(&stm_gpioe, 13, 1);
- stm_moder_set(&stm_gpioe, 13, STM_MODER_OUTPUT);
- stm_moder_set(&stm_gpioe, 14, STM_MODER_INPUT);
- stm_moder_set(&stm_gpioe, 15, STM_MODER_OUTPUT);
- break;
- }
+ 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 STM_SPI_INDEX(2):
- switch (spi_index) {
- case AO_SPI_2_PB13_PB14_PB15:
- stm_gpio_set(&stm_gpiob, 13, 1);
- stm_moder_set(&stm_gpiob, 13, STM_MODER_OUTPUT);
- stm_moder_set(&stm_gpiob, 14, STM_MODER_INPUT);
- stm_moder_set(&stm_gpiob, 15, STM_MODER_OUTPUT);
- break;
- case AO_SPI_2_PD1_PD3_PD4:
- stm_gpio_set(&stm_gpiod, 1, 1);
- stm_moder_set(&stm_gpiod, 1, STM_MODER_OUTPUT);
- stm_moder_set(&stm_gpiod, 3, STM_MODER_INPUT);
- stm_moder_set(&stm_gpiod, 4, STM_MODER_OUTPUT);
- break;
- }
+ case AO_SPI_1_PB3_PB4_PB5:
+ stm_gpio_set(&stm_gpiob, 3, 1);
+ stm_moder_set(&stm_gpiob, 3, STM_MODER_OUTPUT);
+ stm_moder_set(&stm_gpiob, 4, STM_MODER_INPUT);
+ stm_moder_set(&stm_gpiob, 5, STM_MODER_OUTPUT);
+ break;
+ case AO_SPI_1_PE13_PE14_PE15:
+ stm_gpio_set(&stm_gpioe, 13, 1);
+ stm_moder_set(&stm_gpioe, 13, STM_MODER_OUTPUT);
+ stm_moder_set(&stm_gpioe, 14, STM_MODER_INPUT);
+ stm_moder_set(&stm_gpioe, 15, STM_MODER_OUTPUT);
+ break;
+ case AO_SPI_2_PB13_PB14_PB15:
+ stm_gpio_set(&stm_gpiob, 13, 1);
+ stm_moder_set(&stm_gpiob, 13, STM_MODER_OUTPUT);
+ stm_moder_set(&stm_gpiob, 14, STM_MODER_INPUT);
+ stm_moder_set(&stm_gpiob, 15, STM_MODER_OUTPUT);
+ break;
+ case AO_SPI_2_PD1_PD3_PD4:
+ stm_gpio_set(&stm_gpiod, 1, 1);
+ stm_moder_set(&stm_gpiod, 1, STM_MODER_OUTPUT);
+ stm_moder_set(&stm_gpiod, 3, STM_MODER_INPUT);
+ stm_moder_set(&stm_gpiod, 4, STM_MODER_OUTPUT);
break;
}
}
@@ -341,39 +384,33 @@ ao_spi_disable_index(uint8_t spi_index)
static void
ao_spi_enable_index(uint8_t spi_index)
{
- switch (AO_SPI_INDEX(spi_index)) {
- case STM_SPI_INDEX(1):
- switch (spi_index) {
- case AO_SPI_1_PA5_PA6_PA7:
- stm_afr_set(&stm_gpioa, 5, STM_AFR_AF5);
- stm_afr_set(&stm_gpioa, 6, STM_AFR_AF5);
- stm_afr_set(&stm_gpioa, 7, STM_AFR_AF5);
- break;
- case AO_SPI_1_PB3_PB4_PB5:
- stm_afr_set(&stm_gpiob, 3, STM_AFR_AF5);
- stm_afr_set(&stm_gpiob, 4, STM_AFR_AF5);
- stm_afr_set(&stm_gpiob, 5, STM_AFR_AF5);
- break;
- case AO_SPI_1_PE13_PE14_PE15:
- stm_afr_set(&stm_gpioe, 13, STM_AFR_AF5);
- stm_afr_set(&stm_gpioe, 14, STM_AFR_AF5);
- stm_afr_set(&stm_gpioe, 15, STM_AFR_AF5);
- break;
- }
+ /* Enable new config
+ */
+ switch (spi_index) {
+ case AO_SPI_1_PA5_PA6_PA7:
+ stm_afr_set(&stm_gpioa, 5, STM_AFR_AF5);
+ stm_afr_set(&stm_gpioa, 6, STM_AFR_AF5);
+ stm_afr_set(&stm_gpioa, 7, STM_AFR_AF5);
break;
- case STM_SPI_INDEX(2):
- switch (spi_index) {
- case AO_SPI_2_PB13_PB14_PB15:
- stm_afr_set(&stm_gpiob, 13, STM_AFR_AF5);
- stm_afr_set(&stm_gpiob, 14, STM_AFR_AF5);
- stm_afr_set(&stm_gpiob, 15, STM_AFR_AF5);
- break;
- case AO_SPI_2_PD1_PD3_PD4:
- stm_afr_set(&stm_gpiod, 1, STM_AFR_AF5);
- stm_afr_set(&stm_gpiod, 3, STM_AFR_AF5);
- stm_afr_set(&stm_gpiod, 4, STM_AFR_AF5);
- break;
- }
+ case AO_SPI_1_PB3_PB4_PB5:
+ stm_afr_set(&stm_gpiob, 3, STM_AFR_AF5);
+ stm_afr_set(&stm_gpiob, 4, STM_AFR_AF5);
+ stm_afr_set(&stm_gpiob, 5, STM_AFR_AF5);
+ break;
+ case AO_SPI_1_PE13_PE14_PE15:
+ stm_afr_set(&stm_gpioe, 13, STM_AFR_AF5);
+ stm_afr_set(&stm_gpioe, 14, STM_AFR_AF5);
+ stm_afr_set(&stm_gpioe, 15, STM_AFR_AF5);
+ break;
+ case AO_SPI_2_PB13_PB14_PB15:
+ stm_afr_set(&stm_gpiob, 13, STM_AFR_AF5);
+ stm_afr_set(&stm_gpiob, 14, STM_AFR_AF5);
+ stm_afr_set(&stm_gpiob, 15, STM_AFR_AF5);
+ break;
+ case AO_SPI_2_PD1_PD3_PD4:
+ stm_afr_set(&stm_gpiod, 1, STM_AFR_AF5);
+ stm_afr_set(&stm_gpiod, 3, STM_AFR_AF5);
+ stm_afr_set(&stm_gpiod, 4, STM_AFR_AF5);
break;
}
}
@@ -383,20 +420,7 @@ 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->cr1 = ((0 << STM_SPI_CR1_BIDIMODE) | /* Three wire mode */
- (0 << STM_SPI_CR1_BIDIOE) |
- (0 << STM_SPI_CR1_CRCEN) | /* CRC disabled */
- (0 << STM_SPI_CR1_CRCNEXT) |
- (0 << STM_SPI_CR1_DFF) |
- (0 << STM_SPI_CR1_RXONLY) |
- (1 << STM_SPI_CR1_SSM) | /* Software SS handling */
- (1 << STM_SPI_CR1_SSI) | /* ... */
- (0 << STM_SPI_CR1_LSBFIRST) | /* Big endian */
- (1 << STM_SPI_CR1_SPE) | /* Enable SPI unit */
- (speed << STM_SPI_CR1_BR) | /* baud rate to pclk/4 */
- (1 << STM_SPI_CR1_MSTR) |
- (0 << STM_SPI_CR1_CPOL) | /* Format 0 */
- (0 << STM_SPI_CR1_CPHA));
+
if (spi_index != ao_spi_index[id]) {
/* Disable old config
@@ -411,6 +435,21 @@ ao_spi_config(uint8_t spi_index, uint32_t speed)
*/
ao_spi_index[id] = spi_index;
}
+ stm_spi->cr1 = ((0 << STM_SPI_CR1_BIDIMODE) | /* Three wire mode */
+ (0 << STM_SPI_CR1_BIDIOE) |
+ (0 << STM_SPI_CR1_CRCEN) | /* CRC disabled */
+ (0 << STM_SPI_CR1_CRCNEXT) |
+ (0 << STM_SPI_CR1_DFF) |
+ (0 << STM_SPI_CR1_RXONLY) |
+ (1 << STM_SPI_CR1_SSM) | /* Software SS handling */
+ (1 << STM_SPI_CR1_SSI) | /* ... */
+ (0 << STM_SPI_CR1_LSBFIRST) | /* Big endian */
+ (1 << STM_SPI_CR1_SPE) | /* Enable SPI unit */
+ (speed << STM_SPI_CR1_BR) | /* baud rate to pclk/4 */
+ (1 << STM_SPI_CR1_MSTR) |
+ (0 << STM_SPI_CR1_CPOL) | /* Format 0 */
+ (0 << STM_SPI_CR1_CPHA));
+ validate_spi(stm_spi, 13, 0);
}
uint8_t
@@ -428,6 +467,7 @@ 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);
}
@@ -451,15 +491,62 @@ ao_spi_channel_init(uint8_t spi_index)
ao_spi_disable_index(spi_index);
stm_spi->cr1 = 0;
- (void) stm_spi->sr;
stm_spi->cr2 = ((0 << STM_SPI_CR2_TXEIE) |
(0 << STM_SPI_CR2_RXNEIE) |
(0 << STM_SPI_CR2_ERRIE) |
(0 << STM_SPI_CR2_SSOE) |
(0 << STM_SPI_CR2_TXDMAEN) |
(0 << STM_SPI_CR2_RXDMAEN));
+
+ /* Clear any pending data and error flags */
+ (void) stm_spi->dr;
+ (void) stm_spi->sr;
}
+#if DEBUG
+void
+ao_spi_dump_cmd(void)
+{
+ int s;
+
+ for (s = 0; s < 64; s++) {
+ int i = (spi_task_index + s) & 63;
+ if (spi_tasks[i].which) {
+ int t;
+ const char *name = "(none)";
+ for (t = 0; t < ao_num_tasks; t++)
+ if (ao_tasks[t]->task_id == spi_tasks[i].task) {
+ name = ao_tasks[t]->name;
+ break;
+ }
+ printf("%2d: %5d task %2d which %2d len %5d %s\n",
+ s,
+ spi_tasks[i].tick,
+ spi_tasks[i].task,
+ spi_tasks[i].which,
+ spi_tasks[i].len,
+ name);
+ }
+ }
+ for (s = 0; s < STM_NUM_SPI; s++) {
+ struct stm_spi *spi = ao_spi_stm_info[s].stm_spi;
+
+ printf("%1d: mutex %2d index %3d miso dma %3d mosi dma %3d",
+ s, ao_spi_mutex[s], ao_spi_index[s],
+ ao_spi_stm_info[s].miso_dma_index,
+ ao_spi_stm_info[s].mosi_dma_index);
+ printf(" cr1 %04x cr2 %02x sr %03x\n",
+ spi->cr1, spi->cr2, spi->sr);
+ }
+
+}
+
+static const struct ao_cmds ao_spi_cmds[] = {
+ { ao_spi_dump_cmd, "S\0Dump SPI status" },
+ { 0, NULL }
+};
+#endif
+
void
ao_spi_init(void)
{
@@ -504,4 +591,7 @@ ao_spi_init(void)
ao_spi_index[1] = AO_SPI_CONFIG_NONE;
ao_spi_channel_init(1);
#endif
+#if DEBUG
+ ao_cmd_register(&ao_spi_cmds[0]);
+#endif
}
diff --git a/src/stm/stm32l.h b/src/stm/stm32l.h
index 0b6b2798..352214ff 100644
--- a/src/stm/stm32l.h
+++ b/src/stm/stm32l.h
@@ -1359,10 +1359,13 @@ extern struct stm_spi stm_spi1, stm_spi2, stm_spi3;
#define STM_SPI_CR2_TXDMAEN 1
#define STM_SPI_CR2_RXDMAEN 0
+#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
diff --git a/src/telemega-v1.0/ao_pins.h b/src/telemega-v1.0/ao_pins.h
index b81e59a9..58b4d61a 100644
--- a/src/telemega-v1.0/ao_pins.h
+++ b/src/telemega-v1.0/ao_pins.h
@@ -307,7 +307,6 @@ struct ao_adc {
#define AO_CC1120_SPI_CS_PORT (&stm_gpioc)
#define AO_CC1120_SPI_CS_PIN 5
#define AO_CC1120_SPI_BUS AO_SPI_2_PB13_PB14_PB15
-#define AO_CC1120_SPI stm_spi2
#define AO_CC1120_INT_PORT (&stm_gpioe)
#define AO_CC1120_INT_PIN 1
diff --git a/src/telemini-v2.0/ao_pins.h b/src/telemini-v2.0/ao_pins.h
index ed911798..e75adc07 100644
--- a/src/telemini-v2.0/ao_pins.h
+++ b/src/telemini-v2.0/ao_pins.h
@@ -44,6 +44,7 @@
#define PACKET_HAS_SLAVE 1
#define HAS_RADIO_RATE 1
#define HAS_TELEMETRY 1
+#define HAS_TASK_INFO 0
#define AO_LED_RED 2
#define LEDS_AVAILABLE AO_LED_RED