diff options
author | Bdale Garbee <bdale@gag.com> | 2016-07-04 23:48:32 +0200 |
---|---|---|
committer | Bdale Garbee <bdale@gag.com> | 2016-07-04 23:48:32 +0200 |
commit | 06c3d5420080bc1c6fdfb213a9d616b75611c159 (patch) | |
tree | e882a83c3a76c82e3a8e832eb3805c0c5c010d0d | |
parent | eb5bd00b1c5045e64753ba9d066ef5cfce9d5a1e (diff) | |
parent | ea1ff225f1f450ee3fc377807d1bb7b982bf792d (diff) |
Merge branch 'branch-1.6' into debian
-rw-r--r-- | ChangeLog | 338 | ||||
-rw-r--r-- | altosdroid/Makefile.am | 2 | ||||
-rw-r--r-- | altosui/altos-windows.nsi.in | 2 | ||||
-rw-r--r-- | ao-tools/ao-chaosread/ao-chaosread.1 | 4 | ||||
-rw-r--r-- | configure.ac | 4 | ||||
-rw-r--r-- | debian/control | 2 | ||||
-rw-r--r-- | doc/Makefile | 1 | ||||
-rw-r--r-- | doc/altusmetrum-docinfo.xml | 10 | ||||
-rwxr-xr-x | doc/install-html | 32 | ||||
-rw-r--r-- | doc/release-notes-1.6.5.inc | 24 | ||||
-rw-r--r-- | doc/release-notes.inc | 5 | ||||
-rw-r--r-- | src/cc1111/ao_pins.h | 1 | ||||
-rw-r--r-- | src/drivers/ao_cc1120.c | 173 | ||||
-rw-r--r-- | src/drivers/ao_cc1200.c | 105 | ||||
-rw-r--r-- | src/kernel/ao.h | 1 | ||||
-rw-r--r-- | src/kernel/ao_flight.c | 2 | ||||
-rw-r--r-- | src/kernel/ao_task.c | 41 | ||||
-rw-r--r-- | src/stm/ao_arch_funcs.h | 55 | ||||
-rw-r--r-- | src/stm/ao_dma_stm.c | 47 | ||||
-rw-r--r-- | src/stm/ao_exti_stm.c | 2 | ||||
-rw-r--r-- | src/stm/ao_spi_stm.c | 438 | ||||
-rw-r--r-- | src/stm/stm32l.h | 3 | ||||
-rw-r--r-- | src/telemega-v1.0/ao_pins.h | 1 | ||||
-rw-r--r-- | src/telemini-v2.0/ao_pins.h | 1 |
24 files changed, 909 insertions, 385 deletions
@@ -1,3 +1,341 @@ +commit 2e26d1ab42163988dc26b06b016c3b05efe17659 +Merge: 639e461 65ed2f5 +Author: Bdale Garbee <bdale@gag.com> +Date: Mon Jul 4 23:47:24 2016 +0200 + + Merge branch 'master' into branch-1.6 + +commit 65ed2f588ca596fe9aa559bebd590a2a11b9859b +Author: Keith Packard <keithp@keithp.com> +Date: Sun Jul 3 12:00:10 2016 +0200 + + doc: Build 1.6.5 release notes + + Signed-off-by: Keith Packard <keithp@keithp.com> + +commit d60133c65b4592f0f8c832135664a8e0c922b4f0 +Author: Keith Packard <keithp@keithp.com> +Date: Sat Jul 2 22:52:38 2016 +0200 + + Credit Chuck Haskin for helping fix the SPI bug. + + Signed-off-by: Keith Packard <keithp@keithp.com> + +commit 14e73d89d7dbb44e9ffab2820aefb693b6e8ef24 +Author: Keith Packard <keithp@keithp.com> +Date: Sat Jul 2 22:08:58 2016 +0200 + + Bump to 1.6.5. Add preliminary release notes + + Signed-off-by: Keith Packard <keithp@keithp.com> + +commit 8a6a95bb24517af00717fd377bad82ddb2289cf0 +Author: Keith Packard <keithp@keithp.com> +Date: Thu Jun 30 20:43:03 2016 -0700 + + altos/cc1111: Remove 'show tasks' command + + This saves space on cc1111 parts. + + Signed-off-by: Keith Packard <keithp@keithp.com> + +commit d2e286f66d2b15df128ffe9b40a201242fc4a10a +Author: Keith Packard <keithp@keithp.com> +Date: Wed Jun 29 14:22:32 2016 -0700 + + Bump to testing version 1.6.4.2 + + Signed-off-by: Keith Packard <keithp@keithp.com> + +commit a04830a636a71808ea8ef5ac5dfa59d6978d9f3b +Author: Keith Packard <keithp@keithp.com> +Date: Wed Jun 29 18:41:24 2016 -0700 + + altos: Use FIFO_THR pin for cc1120 transmit buffering + + Instead of reading NUM_TXBYTES, set the FIFO_THR pin to indicate when + 64 bytes are available in the buffer. + + Signed-off-by: Keith Packard <keithp@keithp.com> + +commit caf3fc2628c13ff38ffbaabda8aa8d146cda748e +Author: Keith Packard <keithp@keithp.com> +Date: Wed Jun 29 18:33:56 2016 -0700 + + altos: Leave USB enabled in flight with -DDEBUG=1 + + This leaves the command line available for diagnostics when debugging. + + Signed-off-by: Keith Packard <keithp@keithp.com> + +commit c6c250711355ae8060e956e786702be250ef4527 +Author: Keith Packard <keithp@keithp.com> +Date: Wed Jun 29 12:55:30 2016 -0700 + + altos/stm: clean up ao_exti_enable + + Was computing (1 << pin) twice for no good reason. + + Signed-off-by: Keith Packard <keithp@keithp.com> + +commit a35424cd48205af89ba023db979959dc75b06706 +Author: Keith Packard <keithp@keithp.com> +Date: Wed Jun 29 12:54:31 2016 -0700 + + altos: Make task list output more useful + + Add the timeout value and task id + + Signed-off-by: Keith Packard <keithp@keithp.com> + +commit 6c022e094f6f3c551355742a6f9c3deb6e554fe1 +Author: Keith Packard <keithp@keithp.com> +Date: Wed Jun 29 16:07:22 2016 -0700 + + altos/telemini-v2.0: Remove show tasks command + + There's not enough memory for this command, and it isn't necessary. + + Signed-off-by: Keith Packard <keithp@keithp.com> + +commit 349a63aeed6cdeb89bf18c7b2e2c40782c79cc00 +Author: Keith Packard <keithp@keithp.com> +Date: Wed Jun 29 12:52:37 2016 -0700 + + altos: Make ao_delay(0) not wait forever + + ao_delay() is implemented on top of ao_sleep_for, and ao_sleep_for + uses the timeout value of 0 to indicate an infinite timeout. Calls to + ao_delay for 0 ticks would unintentionally hit this case and end up + waiting forever.x + + Signed-off-by: Keith Packard <keithp@keithp.com> + +commit 3b3a24f5f39a1b72cc8947c33b609f454b46aff8 +Author: Keith Packard <keithp@keithp.com> +Date: Wed Jun 29 12:49:16 2016 -0700 + + altos: cc1200: use FIFO threshold pin output for APRS buffering + + Instead of polling the device for fifo space, just use the available + pin configuration to figure out if there is enough space for a single + APRS buffer. Then set the APRS buffer size to match the fifo threshold + setting in the chip so that we know we can write the whole APRS buffer + once the pin says there's space. + + Signed-off-by: Keith Packard <keithp@keithp.com> + +commit 658d8be170f9aea683fe62b68368736a177411a5 +Author: Keith Packard <keithp@keithp.com> +Date: Tue Jun 28 17:03:34 2016 -0700 + + altos: Add debug check for irq block when editing task queues + + List manipulation operations are not atomic, so interrupts need to be + blocked while changing them. + + Signed-off-by: Keith Packard <keithp@keithp.com> + +commit 30eb5d2fa77e036690170e7057fa9df669375ae5 +Author: Keith Packard <keithp@keithp.com> +Date: Tue Jun 28 18:40:46 2016 -0700 + + altos/drivers: Use more reliable byte interface for CC1120 reception + + This replaces direct register access with function calls to allow that + code to respect the hardware requirements. + + Signed-off-by: Keith Packard <keithp@keithp.com> + +commit 61ad8e5bf428246ac89cad7cb9a1edf2ef735fd5 +Author: Keith Packard <keithp@keithp.com> +Date: Tue Jun 28 18:39:31 2016 -0700 + + altos/stm: Add better byte-level SPI api + + This provides inline functions for sending and receiving individual + bytes, and setup/finish functions to wrap them in. This make the byte + sending respect the SPI hardware interface requirements. + + Signed-off-by: Keith Packard <keithp@keithp.com> + +commit 5866d191cee56949ccab4c154a14604e83163d42 +Author: Keith Packard <keithp@keithp.com> +Date: Tue Jun 28 18:37:49 2016 -0700 + + altos/stm: Clean up spi_enable/disable_index functions + + These had an extra level of switch nesting for no good reason. + + Signed-off-by: Keith Packard <keithp@keithp.com> + +commit 5ab4a8b911e254dc829b61cb0abc9fd0b46b84b3 +Author: Keith Packard <keithp@keithp.com> +Date: Mon Jun 27 23:25:01 2016 -0700 + + altos/stm: move spi execution to common ao_spi_run + + This regularizes SPI hardware use and ensures that the device is + turned off after it has been used and that the status register is back + to 'normal' the next time through. + + Signed-off-by: Keith Packard <keithp@keithp.com> + +commit 69791ef235161fef404f682fd6955e7eed8dc125 +Author: Keith Packard <keithp@keithp.com> +Date: Mon Jun 27 23:26:20 2016 -0700 + + altos: Add STM SPI debugging + + This dumps out the SPI hardware state and history of SPI operations + when compiled with -DDEBUG=1. Without that, this patch does nothing. + + Signed-off-by: Keith Packard <keithp@keithp.com> + +commit f418584d4d225827e08f56de86055eb3f074f8d1 +Author: Keith Packard <keithp@keithp.com> +Date: Mon Jun 27 17:26:19 2016 -0700 + + altos: Add STM DMA debugging + + This provides a command that shows current DMA operations when + compiled with -DDEBUG=1. Without that, this patch has no effect. + + Signed-off-by: Keith Packard <keithp@keithp.com> + +commit 2e60cd22f6789c94343e6432822cedab028dc1ba +Author: Keith Packard <keithp@keithp.com> +Date: Tue Jun 28 18:25:44 2016 -0700 + + altos/stm: Change ao_spi_send_sync definition to take const source + + Provides for a bit better error checking. + + Signed-off-by: Keith Packard <keithp@keithp.com> + +commit 21a29c7452398e0cca0fb90f99fa42a2a0684668 +Author: Keith Packard <keithp@keithp.com> +Date: Tue Jun 28 17:15:27 2016 -0700 + + altos/stm: Add more SPI status register bits + + These weren't the original version of the docs that we had. + + Signed-off-by: Keith Packard <keithp@keithp.com> + +commit 785d2697376ebd20531d22441a60c41bd927b42a +Author: Keith Packard <keithp@keithp.com> +Date: Tue Jun 28 17:12:48 2016 -0700 + + altos/stm: use 0xff for dma mutex value for allocated mutexes + + DMA channels which are 'allocated' can't be shared. Instead of using + the value '1' in the related 'mutex', use 0xff which won't match any task. + + Signed-off-by: Keith Packard <keithp@keithp.com> + +commit 0dec7d0885970a7d73468dd77220bae78e161b40 +Author: Keith Packard <keithp@keithp.com> +Date: Tue Jun 28 17:11:38 2016 -0700 + + altos/stm: remove ao_dma_abort + + This function isn't used anywhere. + + Signed-off-by: Keith Packard <keithp@keithp.com> + +commit 974aaf73cbb720f1b1183cc239001528b6c7a5b9 +Author: Keith Packard <keithp@keithp.com> +Date: Tue Jun 28 17:09:00 2016 -0700 + + altos: Move comment in ao_sleep_for next to related code + + The comment got moved to the wrong place + + Signed-off-by: Keith Packard <keithp@keithp.com> + +commit a7e0bb5eb661cfde31c383d605cb9cb8ca568bc7 +Author: Keith Packard <keithp@keithp.com> +Date: Tue Jun 28 17:04:59 2016 -0700 + + altos: Block interrupts while waking tasks sleeping on timers. + + Interrupts may not be blocked in the timer ISR, but they need to be + while walking the pending timer list and moving tasks back to the run + queue. + + Signed-off-by: Keith Packard <keithp@keithp.com> + +commit 40abb0d1e2f43a60ffa34b055ebb913ee3e20faf +Author: Keith Packard <keithp@keithp.com> +Date: Tue Jun 28 00:07:23 2016 -0700 + + altosui: Deliver firmware for Tmega 2.0 and TBT 3.0 for Windows too + + 1.6.4 added Tmega 2.0 and TBT 3.0 firmware to linux and mac, but + neglected windows. + + Signed-off-by: Keith Packard <keithp@keithp.com> + +commit 5b7e81628437389014fdd39e323a6f0176e02ba6 +Author: Keith Packard <keithp@keithp.com> +Date: Mon Jun 27 23:28:28 2016 -0700 + + Mark testing version 1.6.4.1 + + Signed-off-by: Keith Packard <keithp@keithp.com> + +commit 6d15cf1580563aea90e9c47f5b268c9c7bb9ba26 +Author: Keith Packard <keithp@keithp.com> +Date: Fri Jun 24 12:07:36 2016 -0700 + + altosdroid: Deal with multiple installed android SDKs + + Use the latest SDK's zipalign + + Signed-off-by: Keith Packard <keithp@keithp.com> + +commit 3374a9069618658a33af54472d8670e3086af1e0 +Author: Keith Packard <keithp@keithp.com> +Date: Fri Jun 24 12:06:32 2016 -0700 + + ao-tools/ao-chaosread: Document length (-l) option + + Signed-off-by: Keith Packard <keithp@keithp.com> + +commit ca59786b5022f592f6516a3ac54708789db14c94 +Author: Keith Packard <keithp@keithp.com> +Date: Mon Jun 20 10:19:32 2016 -0700 + + Bump android version to 13 + + Need to update the maps API key in the package + + Signed-off-by: Keith Packard <keithp@keithp.com> + +commit 10fa950cb9fee0ba28adfc5ead108657655bb289 +Author: Bdale Garbee <bdale@gag.com> +Date: Wed Jun 22 15:01:09 2016 -0600 + + switch libgtk-3-bin build-dep to gtk-update-icon-cache, closes: #825455 + +commit ed6eb010614b5b27757619fc629d7330fc8c4122 +Author: Keith Packard <keithp@keithp.com> +Date: Fri Jun 17 10:18:20 2016 -0700 + + doc: Add install-html script + + This script strips the XML-ish bits from html files so that ikiwiki + can parse them correctly + + Signed-off-by: Keith Packard <keithp@keithp.com> + +commit 639e461ded29a48c155afea12171cbfc191ccfd7 +Author: Bdale Garbee <bdale@gag.com> +Date: Fri Jun 17 10:01:17 2016 -0600 + + releasing 1.6.4 + commit 31cf047113ec72a78f4b500223a2c6be23bc86fd Merge: 2f0c977 afe74c0 Author: Bdale Garbee <bdale@gag.com> 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 |