From: Bdale Garbee Date: Wed, 30 Sep 2020 06:19:12 +0000 (-0600) Subject: Merge branch 'branch-1.9' into debian X-Git-Tag: debian/1.9.5-1~1 X-Git-Url: https://git.gag.com/?a=commitdiff_plain;h=b146cf617d2798ab3339eeecac884c11bd91727a;hp=3458a5db7e8456495b25963a15b80ff804a09f05;p=fw%2Faltos Merge branch 'branch-1.9' into debian --- diff --git a/ChangeLog b/ChangeLog index 139409b0..39adbf91 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,761 @@ +commit f763dfe6a684a16ec40503149adefdc074a63ad0 +Merge: bfe338d1 a1779f94 +Author: Bdale Garbee +Date: Wed Sep 30 00:17:03 2020 -0600 + + Merge branch 'master' into branch-1.9 + +commit a1779f9442787dbd5c40edbb476e6b765392196e +Author: Keith Packard +Date: Tue Sep 29 20:10:38 2020 -0700 + + Version 1.9.5 + + Signed-off-by: Keith Packard + +commit 67e8e9b5b51e259eda4a669de527111851bab78f +Author: Keith Packard +Date: Tue Sep 29 22:02:56 2020 -0700 + + altosui: Work around lack of actual USB product names on Windows + + Windows doesn't provide an API to get the USB product name for + attached devices, it only provides the name listed in the .inf file + for each vid/pid. This means that you get 'TeleMega', or 'TeleMega + can't isolate the list to the correct version. + + With this fix, at least the '#2' is stripped off, and the matching + code restricts itself to showing only TeleMega files instead of all + filenames starting with 'tele'. + + Signed-off-by: Keith Packard + +commit 9bee7d9b6be861909d8c89767f6eabf007f76612 +Author: Keith Packard +Date: Tue Sep 29 20:08:31 2020 -0700 + + altosdroid: Copy generated .apks to bin directory + + This places them in the same location as the previous build system. + + Signed-off-by: Keith Packard + +commit 1fa1ba86f6e6e4ff469f0680cdbc39bc806474a4 +Author: Keith Packard +Date: Fri Sep 25 20:06:18 2020 -0700 + + doc: Add 1.9.5 release notes + + Signed-off-by: Keith Packard + +commit 2d239b9bf600fac46717980f45de3ca7a242236f +Author: Keith Packard +Date: Tue Sep 1 18:47:23 2020 -0700 + + altoslib: Print more helpful debug messages when checking rom version + + Make sure success and failure include enough info to debug what + happened. + + Signed-off-by: Keith Packard + +commit 5bdc63a2086c1ffd4c34c9a503af638a47a1d98b +Author: Keith Packard +Date: Tue Sep 1 18:31:03 2020 -0700 + + libaltos: Update to support Mac OS X 10.15 (catalina) + + They decided to break device names reported by USB for some reason, + but at least the real names are still available under a different + name. + + Also updated the Makefile-standalone to work on my current box; + presumably the next time I build this I'll have to update again... + + Signed-off-by: Keith Packard + +commit 583a749724700845d2d3552a0d3a759f16b25cfe +Author: Keith Packard +Date: Mon Aug 31 20:52:43 2020 -0700 + + macosx: Update macosx install script + + Use dialog engine to monitor progress and get sudo password + + Signed-off-by: Keith Packard + +commit ffbd99545ca0462161c24e0ed86978544f2c28f6 +Author: Keith Packard +Date: Mon Aug 31 15:08:08 2020 -0700 + + altosuilib: Make dialogs mostly scrollable + + When screens are too small, some dialogs aren't usable. Fix that by + wrapping them all with a scrollable pane. + + Signed-off-by: Keith Packard + +commit 521dc6dbf9aa5f7aad7829cd98a815031725ac24 +Author: Keith Packard +Date: Mon Aug 31 15:07:13 2020 -0700 + + windows: Point windows users at adoptopenjdk.net by default + + This gives them a free software java which works fine with altosui. + + Signed-off-by: Keith Packard + +commit 7fc37f145a6ec3f913e908b6500d1e2c6dd405c8 +Author: Keith Packard +Date: Mon Aug 31 15:05:41 2020 -0700 + + macosx: Hack JavaApplicationStub to set freetype properties + + Set the FREETYPE_PROPERTIES environment variable to revert to + non-fuzzy text. + + Signed-off-by: Keith Packard + +commit 075999e274dd1815b15c0d717d1af4e7717e5da9 +Author: Keith Packard +Date: Mon Aug 31 15:03:57 2020 -0700 + + altoslib: Set default logging directory to $HOME/AltusMetrum + + Change from ~/TeleMetrum + + Signed-off-by: Keith Packard + +commit 4e07392c65ec512e3309d89c7465c1406a941b66 +Author: Keith Packard +Date: Mon Aug 31 15:01:18 2020 -0700 + + libaltos: Map generic windows device names to actual names + + When we signed the .ini file for our windows 'driver', IDs 28 and 2c + hadn't been assigned to EasyMega and EasyMotor, so that file has + generic 'AltusMetrum28' and 'AltusMetrum2c' instead. Updating that + file is 'hard', so just map the names in the driver instead. + + Signed-off-by: Keith Packard + +commit 0d298df9e4cf945f3d0dfdb583af07e498c685a0 +Author: Bdale Garbee +Date: Fri Sep 18 11:38:06 2020 -0600 + + docs: add explicit admonition about avoiding 'c f' when configuring TeleLaunch + +commit 95b31cb200d59917fd3ad03c5c3a0ad99c8a140d +Author: Bdale Garbee +Date: Fri Sep 18 11:34:56 2020 -0600 + + docs: fix horrible typo in TeleLaunch configuration section + +commit 23e148bb3379969935bcbbbeb6c8dc66c0474f6d +Author: Keith Packard +Date: Sun Aug 23 15:34:26 2020 -0700 + + altosuilib: Allow config to be missing in rom config dialog + + If the configuration data can't be fetched from the target board, it + will be missing while building the dialog box. Deal with that. + + Signed-off-by: Keith Packard + +commit 2289fd36f7ba76692fe07d2ebc8d7eda33750180 +Author: Keith Packard +Date: Sun Aug 23 15:32:57 2020 -0700 + + altoslib: Deal with reflashing EasyMega boards with ancient firmware + + Ancient EasyMega firmware included radio calibration data in the + romconfig bits, which has since been removed. That means the config + data from those boards will be at a different location than current + firmware. Deal with that by poking around in firmware looking for + valid bits. + + Signed-off-by: Keith Packard + +commit 335e40873c238a67cea2c63d62b73fd9d29e94d2 +Author: Keith Packard +Date: Sun Aug 23 10:55:30 2020 -0700 + + doc: Fix spelling error in updating-firmware section. + + Thanks to Timothy Dixon for catching this (copy-and-pasted many times) + typo -- could sequentially -> count sequentially. + + Signed-off-by: Keith Packard + +commit c1b754c12ac32ed38a561d8b35dcbdf82beea896 +Author: Keith Packard +Date: Sun Aug 23 10:53:25 2020 -0700 + + altosui: Improve configuration save feedback + + Mark window title as (modified) with any unsaved changes. Disable the + 'Save' button while the save is happening. Wait for the re-load of + configuration values before clearing the '(modified)' state. This lets + you see when the flight computer has accepted the updated values. + + Signed-off-by: Keith Packard + +commit 10a10667a28f82c24d895e44617e68c7c1848c45 +Author: Keith Packard +Date: Sun Aug 23 10:51:00 2020 -0700 + + altoslib: Improve configuration performance over remote link + + Avoid re-setting dongle radio parameters when they haven't changed + during device configuration setting. This avoids flipping back and + forth from remote to local mode three times during config save. + + Wait for remote end to say 'Saved' before dropping radio link. This + ensures that the remote end actually gets the save command before the + link is terminated. + + Signed-off-by: Keith Packard + +commit b3297909e58a2709d340f65181c22ef82341afb9 +Author: Bdale Garbee +Date: Wed Aug 19 14:38:04 2020 -0600 + + fix broken TeleBT turnon script + +commit f82e0c5e3a3b3a505e35df23301cdc7dd4b1a869 +Author: Keith Packard +Date: Fri Aug 7 21:51:39 2020 -0700 + + altoslib: Flush output when disabling remote + + This speeds up sending data to the other end. + + Signed-off-by: Keith Packard + +commit 783a541d661f24f2df1dee86bad2e47950bee9da +Author: Keith Packard +Date: Fri Aug 7 21:50:38 2020 -0700 + + altoslib: Don't fetch config data for every idle status + + This makes fetching data during idle monitor much faster, especially + now that fetching the list of stored flights takes so long. + + Signed-off-by: Keith Packard + +commit bbd052c0ad5b99673cf583198e50e6ed351fdfb7 +Author: Keith Packard +Date: Fri Aug 7 21:49:37 2020 -0700 + + altos: Allow multiple manual firing of main/drogue channels + + Reset the 'fired' status so that you can trigger these multiple times + without needing to reboot. + + Signed-off-by: Keith Packard + +commit f3c8946d992889edabffbab40aead578963de75f +Author: Keith Packard +Date: Fri Aug 7 21:48:09 2020 -0700 + + altos: Don't report inhibited pyro channels as fired + + Inhibiting channels happens when the channel conditions change during + the delay period and was done by marking them as already fired. This + worked, but the log file would then indicate that the channel had + fired when in fact it was inhibited instead. Separate out the inhibited status + so that the correct data appears in the log. + + Signed-off-by: Keith Packard + +commit 38db8202a4d6ab90305768410f1a37106cc95794 +Author: Keith Packard +Date: Fri Aug 7 20:20:59 2020 -0700 + + micropeak: Add support for MicroPeak v2.0 + + MicroPeak v2.0 sends a 'unique id' with the log data; capture that and + included it in the file name. + + MicroPeak v2.0 can be directly connected to the host using the µP I/O + board. Handle that case by sending the 'l' command which will cause + the device to dump the log. + + Signed-off-by: Keith Packard + +commit 0743e7213729df629aea90b3a5dc904fe397b5cb +Author: Keith Packard +Date: Fri Aug 7 20:19:28 2020 -0700 + + micropeak: Fix top-level window building + + The menu wasn't actually working, and the application would randomly + start at the wrong size or crash. + + Signed-off-by: Keith Packard + +commit 7dd23ac750226746f340df64107dab84cd7ea113 +Author: Keith Packard +Date: Fri Aug 7 20:18:10 2020 -0700 + + micropeak: Check for empty data when fetching log + + Don't pop up the graph window and don't save data from an erased + device. + + Signed-off-by: Keith Packard + +commit 838d359ed8676f056fe487dad3dfbec34bd65009 +Author: Keith Packard +Date: Fri Aug 7 20:16:55 2020 -0700 + + altos/mpusb-v3.0: Make this build again + + It's not built by default and the requirements in the Makefile have + changed. + + Signed-off-by: Keith Packard + +commit 52eaf4a2480ac0fd367978e423e2f252949f978b +Author: Keith Packard +Date: Fri Aug 7 20:15:32 2020 -0700 + + altos/micropeak-v2.0: Functionally complete. + + Get flight mode working correctly. + Offer log dumping from serial link. + + Signed-off-by: Keith Packard + +commit 999b3598019c75d77af6ab40c1942a7d57a2ec3c +Author: Keith Packard +Date: Fri Aug 7 20:13:50 2020 -0700 + + altos: Add MicroPeak v2.0 support to ao_log_micro + + Support 4-byte sample count (required for stm32l0 flash storage + limitations). + + Mix in log ID on-the-fly so that erased flash parts still report + device type. + + Signed-off-by: Keith Packard + +commit 476fd2f2c23da427b6b2a68f7d285767a924041e +Author: Keith Packard +Date: Fri Aug 7 20:12:22 2020 -0700 + + altos/stm32l0: Big update in functionality + + Fix baud rate setting in LPUART + Add code to turn everything off. + + Signed-off-by: Keith Packard + +commit 7b1f4177d42e5e951a7db4289c847d355a785c2a +Author: Keith Packard +Date: Thu Aug 6 11:05:03 2020 -0700 + + altos: Remove support for !HAS_TASK_QUEUE + + This uses a bit more memory, but the amount can be controlled by + setting the size of the sleep hash table, which makes this fit on even + the smaller devices like the early EasyMini boards. + + Signed-off-by: Keith Packard + +commit a6baf04bae3fe6a6b3da2f456419732ffeb4d056 +Author: Keith Packard +Date: Fri Aug 7 18:17:07 2020 -0700 + + altos: Remove ao_led_toggle API from general code + + The generic implementation would need to record LED status as it + cannot be read back from the device on most hardware. Just get rid of + it and let attiny keep its implementation (which does work). + + Signed-off-by: Keith Packard + +commit 0385d7d68c51e05f5b555749ccc20e3c7c202370 +Author: Keith Packard +Date: Fri Aug 7 18:15:47 2020 -0700 + + ao-tools: Add TeleGPS log parsing to ao-eeprom + + Signed-off-by: Keith Packard + +commit 9df66f7589b663899e2c729b884eed4b64e5d4da +Author: Keith Packard +Date: Thu Aug 6 10:44:49 2020 -0700 + + altos: add noreturn attribute to ao_panic + + Signed-off-by: Keith Packard + +commit 33ea5b3658377cea325db285a3e457724f660384 +Author: Keith Packard +Date: Wed Aug 5 22:32:14 2020 -0700 + + altos/stm32l0: Add LPUART driver + + This is a simpler UART which micropeak has connected to the LED and + we'll use for transmitting the log on power up + + Signed-off-by: Keith Packard + +commit 980d54134bedb64d506c0702f09b4d5277000848 +Author: Keith Packard +Date: Wed Aug 5 17:17:47 2020 -0700 + + altos/stm32l0: Provide ao_spi_speed inline as per new clocking API + + Signed-off-by: Keith Packard + +commit 2cd7ecf437bec322e6a201992d0404f31207bd68 +Author: Keith Packard +Date: Tue Jun 23 16:22:21 2020 -0700 + + altos/micropeak-v2.0: Finish hardware bring-up + + All of the hardware is working: + + * serial + * SPI + * ms56067 + * ADC + * flash + * clocking + * timer + + Now we just need an application + + Signed-off-by: Keith Packard + +commit 845b51d09a6a6f257aebb6db202b12ee1fa9ed7e +Author: Keith Packard +Date: Tue Jun 23 16:21:57 2020 -0700 + + altos/stm32l0: Add adc and flash drivers + + Signed-off-by: Keith Packard + +commit d2b750a04bbaf428a38fd95891a7ce1cc7d3d2f3 +Author: Keith Packard +Date: Tue Jun 23 16:21:26 2020 -0700 + + altos/stm32l0: Remove some unused code in ao_timer.c + + Signed-off-by: Keith Packard + +commit 9dea51ca2174d86d5ab4a8a27179519b34869a36 +Author: Keith Packard +Date: Tue Jun 23 16:20:56 2020 -0700 + + altos/stm32l0: Remove some unused code in USART driver + + Signed-off-by: Keith Packard + +commit db7bf095dfa75858eb12328f104051ea1686e1d5 +Author: Keith Packard +Date: Tue Jun 23 16:20:26 2020 -0700 + + altos/stm32l0: Get exti working + + Signed-off-by: Keith Packard + +commit e58d08a93818b3d60746f0f17b34e96fbf8ba0e3 +Author: Keith Packard +Date: Tue Jun 23 16:19:47 2020 -0700 + + altos/stm32l0: Get SPI driver working + + This isn't using DMA, but it seems to work now. + + Signed-off-by: Keith Packard + +commit b0c4df25a0c419eeb53e0e241489c0bd6bee04ef +Author: Keith Packard +Date: Tue Jun 23 16:19:11 2020 -0700 + + altos/stm32l0: Some device addrs were wrong + + Signed-off-by: Keith Packard + +commit 3df505b02fb7d4ba2d40351e658931b02425b74f +Author: Keith Packard +Date: Tue Jun 23 16:18:27 2020 -0700 + + altos/stm32l0: More DMA fixes + + This code still doesn't work, but it should be closer' + + Signed-off-by: Keith Packard + +commit 1e1a84e9ea21ef6037a2127098499e294d293fa8 +Author: Keith Packard +Date: Tue Jun 23 16:17:03 2020 -0700 + + altos: Micropeak v2.0 doesn't have a flash loader anymore + + The current version doesn't have USB, so the existing flash loader + protocol won't work anyways. + + Signed-off-by: Keith Packard + +commit 0375e9840ea1bcc486b56ccb3aaace57875312a7 +Author: Keith Packard +Date: Tue Jun 23 16:16:28 2020 -0700 + + altos/ao_storage: Allow apps to #define storage parameters + + This avoids placing them in RAM. + + Signed-off-by: Keith Packard + +commit 45b00da14ea814cf8f14dcb2cfaccaddd0fbb38d +Author: Keith Packard +Date: Tue Jun 23 16:15:28 2020 -0700 + + altos/ao_storage: allow erased byte value to be set by application + + External flash is usually 0xff for erased bytes, but other memory may + use different values + + Signed-off-by: Keith Packard + +commit 6b4da0492c6d9066c8a118fba9b8ffca02fa84ba +Author: Keith Packard +Date: Tue Jun 23 16:15:14 2020 -0700 + + remove ao_delay_until from ao.h + +commit 48bc180211f226b0406aae28a85d5e5ee77455a2 +Author: Keith Packard +Date: Mon Jun 22 17:42:03 2020 -0700 + + altos: Add ao_delay_until to ao_notask + + Used on micropeak + + Signed-off-by: Keith Packard + +commit b4a31f4bba8edee32d4f41780bd62bcfa064f20a +Author: Keith Packard +Date: Mon Jun 22 17:41:11 2020 -0700 + + altos: Move empty ao_mutex_get/put to ao_notask.h + + Make it work on any no-task project. + + Signed-off-by: Keith Packard + +commit 7cd8e0aca8ea42a5ff077971e439b0816608b324 +Author: Keith Packard +Date: Sat Jun 20 15:15:35 2020 -0700 + + altos: Declare ao_delay_until API in ao.h + + This uses AO_TICK_TYPE which isn't defined until we get to ao.h + + Signed-off-by: Keith Packard + +commit eea198932b8f12d4729f6138a40489d954d6f93a +Author: Keith Packard +Date: Sat Jun 20 15:14:26 2020 -0700 + + altos: Switch micropeak v2.0 to stm32l0 + + The stm32f042 takes too much power for micropeak. Try the stm32l0 + instead. + + Signed-off-by: Keith Packard + +commit d907b0fe40d31995848e5b207009ba230da2e36e +Author: Keith Packard +Date: Sat Jun 20 15:13:09 2020 -0700 + + altos: Add initial stm32l0 support + + A low-power cortex M0 chip for MicroPeak v2.0 + + Signed-off-by: Keith Packard + +commit b8a9273162b7016afc29f4c98fc3b66324d4c85b +Author: Keith Packard +Date: Sat Jun 20 15:00:28 2020 -0700 + + altos: Fix a bunch of time variables to be AO_TICK_TYPE + + The default tick type is now 32 bits, so all of these + variables were mis-typed at 16 bits. + + Signed-off-by: Keith Packard + +commit 304dbcbff72c6fa66c71224ecf98ec55447ffff7 +Author: Keith Packard +Date: Fri Aug 7 20:08:34 2020 -0700 + + altos/stm: Fix stack validation code + + This is not included by default, and broke at some point. + + Signed-off-by: Keith Packard + +commit ff3a2de3223f5cf3fd87f40cd9961e2c2890a867 +Author: Bdale Garbee +Date: Mon Aug 3 12:43:22 2020 -0600 + + doc: EasyMotor and EasyTimer have the same mounting geometry as EasyMini + +commit 21da942560863ed191953e1af2fbca66bcc29fb8 +Author: Keith Packard +Date: Sun Aug 2 17:29:44 2020 -0700 + + altos/stmf0, stm32f0: Call ao_boot_chain to start application + + This used to be done inside ao_boot_check_chain or ao_boot_check_pin, + but it made more sense to have it done in _start instead. stm and lpc + were adjusted, but stmf0 and stm32f4 were missed. + + This caused boards using this process to wedge in the boot loader. + + Signed-off-by: Keith Packard + +commit 6b5e5899d174466552a34a4d8574f0439776240d +Author: Keith Packard +Date: Sun Aug 2 13:31:58 2020 -0700 + + altosui: Re-set pad orientation labels after product name is set + + We don't know what product is being configured until after we query + the configuration, which means we need to re-set the orientation label + once that has been fetched. + + Signed-off-by: Keith Packard + +commit 341157c7415fcf879696c9d8167722a0c5ff264c +Author: Keith Packard +Date: Wed Jul 29 10:53:39 2020 -0700 + + altos: Use new ao_spi_speed inline to set SPI speeds using spec'd frequencies + + Instead of hand-adjusting SPI speeds for each driver and product based + on processor supported rates, create an inline function that takes the + maximum frequency supported by the device and maps that to a value + supported by the SoC. This ensures that we don't accidentally drive devices + faster than they want (as could happen with AO_SPI_SPEED_FAST), but do go + as fast as possible in every configuration. Using an inline function means + the value is computed at compile time. + + Signed-off-by: Keith Packard + +commit 202166275ba5220db54f63dcd9366e9115d09c0d +Author: Keith Packard +Date: Tue Jul 28 23:44:33 2020 -0700 + + altos: Support flash parts > 8MB + + The number of sectors (64kB) units in the connected flash + part can be larger than 255, so switch from 8-bits to 32-bits for + holding this value. + + Signed-off-by: Keith Packard + +commit c56bcc315ac29d001e62859b61ede890a8b7c64f +Author: Keith Packard +Date: Tue Jul 28 23:43:04 2020 -0700 + + altos: Protect shared storage_data with mutex + + As storage_data is shared between all threads, protect it + with a mutex to avoid collisions. + + Signed-off-by: Keith Packard + +commit 8a24d37e40210b1fb5cdab944c3a6d9ae4e144d7 +Author: Keith Packard +Date: Tue Jul 28 23:40:36 2020 -0700 + + altos/stm: Increase MISO DMA priority to very high + + We're still losing incoming bytes in full duplex mode. + + Signed-off-by: Keith Packard + +commit 3058ecdeafdee959b1103965f3df4ffcd59683e4 +Merge: 0a53faa8 8ec51d69 +Author: Bdale Garbee +Date: Wed Jul 22 15:23:02 2020 -0600 + + Merge branch 'master' of ssh://git.gag.com/scm/git/fw/altos + +commit 0a53faa8173565b1277d1a35c60022de567c2dce +Author: Bdale Garbee +Date: Wed Jul 22 15:22:21 2020 -0600 + + ao-bringup: ensure TeleMega turnon scripts are using the right test versions + +commit 8ec51d698921d07c394e6e0e48ac5d587f70ece8 +Author: Keith Packard +Date: Wed Jul 22 09:04:30 2020 -0700 + + altos: Add 'booster' mode for dual-deploy igniters + + Booster mode triggers the 'main' channel at first motor burnout + allowing the use of a simple flight computer in the booster while + providing both a separation charge and an apogee event for recovery. + + Signed-off-by: Keith Packard + +commit d0c0dec140b8fa847704c9a22a39d254445188b9 +Author: Keith Packard +Date: Wed Jul 22 08:57:05 2020 -0700 + + altos: Use state transitions to directly drive igniters + + Instead of a separate igniter API, have the igniter code monitor + flight state changes to trigger igniter events. This simplifes the + code while allowing further changes in the igniter code. + + Signed-off-by: Keith Packard + +commit 6ff8e55581ca85b9cc892806a2481d57a65e8bae +Author: Keith Packard +Date: Wed Jul 22 08:56:10 2020 -0700 + + Releasing: save .map files too + + These are useful to debug issues with linker scripts or library problems + + Signed-off-by: Keith Packard + +commit 4c5942fb082811f136322ec26de615cdb7e17580 +Author: Keith Packard +Date: Thu Jul 16 10:23:34 2020 -0700 + + Add support for TLS if needed + + Define USE_TLS if you want TLS support from altos. + + Signed-off-by: Keith Packard + +commit 8066ce73d96f85efe7f5e51b1576b5fd0ff9565e +Author: Keith Packard +Date: Thu Jul 16 09:29:52 2020 -0700 + + altosui: Spurious ; in altos-windows.nsi.in kept out TM v3.0 ihx + + Looks like a semicolon got stuck in this file, which commented out the + TeleMetrum v3.0 firmware from being included in the windows build + + Signed-off-by: Keith Packard + +commit bfe338d11965d2d1715bdd81d92ef32f1b5ff9fa +Author: Bdale Garbee +Date: Thu Jul 2 20:21:19 2020 -0600 + + releasing 1.9.4 + commit 8359fcc23a93a37ee3aee4c5d2ef183f18ea3f27 Merge: b95d6674 9b62f683 Author: Bdale Garbee diff --git a/Releasing b/Releasing index 223a14d3..e9ceb408 100644 --- a/Releasing +++ b/Releasing @@ -101,40 +101,40 @@ These are Bdale's notes on how to do a release. - store a stable copy of ARM binaries for production use - cp src/chaoskey-v1.0/{*.elf,*.ihx,*.bin} \ - src/easymega-v1.0/{*.elf,*.ihx} \ - src/easymega-v2.0/{*.elf,*.ihx} \ - src/easymini-v1.0/{*.elf,*.ihx} \ - src/easymini-v2.0/{*.elf,*.ihx} \ - src/easytimer-v1/{*.elf,*.ihx} \ - src/telebt-v3.0/{*.elf,*.ihx} \ - src/telebt-v4.0/{*.elf,*.ihx} \ - src/teledongle-v3.0/{*.elf,*.ihx} \ - src/telegps-v1.0/{*.elf,*.ihx} \ - src/telegps-v2.0/{*.elf,*.ihx} \ - src/telemega-v[1-4].0/{*.elf,*.ihx} \ - src/telemetrum-v2.0/{*.elf,*.ihx} \ - src/telemetrum-v3.0/{*.elf,*.ihx} \ - src/telemini-v3.0/{*.elf,*.ihx} \ - src/telelco-v2.0/{*.elf,*.ihx} \ - src/telefireeight-v1.0/{*.elf,*.ihx} \ - src/telefireeight-v2.0/{*.elf,*.ihx} \ + cp src/chaoskey-v1.0/{*.elf,*.ihx,*.bin,*.map} \ + src/easymega-v1.0/{*.elf,*.ihx,*.map} \ + src/easymega-v2.0/{*.elf,*.ihx,*.map} \ + src/easymini-v1.0/{*.elf,*.ihx,*.map} \ + src/easymini-v2.0/{*.elf,*.ihx,*.map} \ + src/easytimer-v1/{*.elf,*.ihx,*.map} \ + src/telebt-v3.0/{*.elf,*.ihx,*.map} \ + src/telebt-v4.0/{*.elf,*.ihx,*.map} \ + src/teledongle-v3.0/{*.elf,*.ihx,*.map} \ + src/telegps-v1.0/{*.elf,*.ihx,*.map} \ + src/telegps-v2.0/{*.elf,*.ihx,*.map} \ + src/telemega-v[1-4].0/{*.elf,*.ihx,*.map} \ + src/telemetrum-v2.0/{*.elf,*.ihx,*.map} \ + src/telemetrum-v3.0/{*.elf,*.ihx,*.map} \ + src/telemini-v3.0/{*.elf,*.ihx,*.map} \ + src/telelco-v2.0/{*.elf,*.ihx,*.map} \ + src/telefireeight-v1.0/{*.elf,*.ihx,*.map} \ + src/telefireeight-v2.0/{*.elf,*.ihx,*.map} \ ~/altusmetrumllc/Binaries/ - cp src/chaoskey-v1.0/flash-loader/{*.elf,*.bin} \ + cp src/chaoskey-v1.0/flash-loader/{*.elf,*.bin,*.map} \ src/easymega-v1.0/flash-loader/*.elf \ src/easymega-v2.0/flash-loader/*.elf \ src/easymini-v1.0/flash-loader/*.elf \ - src/easymini-v2.0/flash-loader/{*.elf,*.bin} \ - src/easytimer-v1/flash-loader/{*.elf,*.bin} \ + src/easymini-v2.0/flash-loader/{*.elf,*.bin,*.map} \ + src/easytimer-v1/flash-loader/{*.elf,*.bin,*.map} \ src/telebt-v3.0/flash-loader/*.elf \ - src/telebt-v4.0/flash-loader/{*.elf,*.bin} \ + src/telebt-v4.0/flash-loader/{*.elf,*.bin,*.map} \ src/teledongle-v3.0/flash-loader/*.elf \ src/telegps-v1.0/flash-loader/*.elf \ - src/telegps-v2.0/flash-loader/{*.elf,*.bin} \ + src/telegps-v2.0/flash-loader/{*.elf,*.bin,*.map} \ src/telemega-v[1-4].0/flash-loader/*.elf \ src/telemetrum-v2.0/flash-loader/*.elf \ src/telemetrum-v3.0/flash-loader/*.elf \ - src/telemini-v3.0/flash-loader/{*.elf,*.bin} \ + src/telemini-v3.0/flash-loader/{*.elf,*.bin,*.map} \ src/telelco-v2.0/flash-loader/*.elf \ src/telefireeight-v1.0/flash-loader/*.elf \ src/telefireeight-v2.0/flash-loader/*.elf \ diff --git a/altosdroid/Makefile.am b/altosdroid/Makefile.am index 7fb16404..f9f69662 100644 --- a/altosdroid/Makefile.am +++ b/altosdroid/Makefile.am @@ -3,8 +3,10 @@ REL_APK=app/build/outputs/apk/release/app-release.apk if ANDROID all_target=$(DBG_APK) +all_target += bin/AltosDroid-debug.apk if ANDROID_RELEASE all_target+=$(REL_APK) +all_target += bin/AltosDroid-release.apk endif else all_target= @@ -53,6 +55,14 @@ SRC=$(JAVA_SRC) $(DRAWABLES) $(RES) all: $(all_target) +bin/AltosDroid-debug.apk: $(DBG_APK) + mkdir -p bin + cp $^ $@ + +bin/AltosDroid-release.apk: $(REL_APK) + mkdir -p bin + cp $^ $@ + .NOTPARALLEL: $(ALTOSLIB): $(ALTOSLIB_SRCDIR)/$(ALTOSLIB_JAR) diff --git a/altoslib/AltosConfigData.java b/altoslib/AltosConfigData.java index 5d58566e..83f3ca07 100644 --- a/altoslib/AltosConfigData.java +++ b/altoslib/AltosConfigData.java @@ -796,33 +796,28 @@ public class AltosConfigData { has_setting, radio_calibration); /* When remote, reset the dongle frequency at the same time */ - if (remote) { - link.flush_output(); + if (remote && frequency != link.frequency) { link.stop_remote(); link.set_radio_frequency(frequency); - link.flush_output(); link.start_remote(); } } if (telemetry_rate != AltosLib.MISSING) { link.printf("c T %d\n", telemetry_rate); - if (remote) { - link.flush_output(); + if (remote && telemetry_rate != link.telemetry_rate) { link.stop_remote(); link.set_telemetry_rate(telemetry_rate); - link.flush_output(); link.start_remote(); } } if (callsign != null) { link.printf("c c %s\n", callsign); - if (remote) { - link.flush_output(); + if (remote && !callsign.equals(link.callsign)) { + System.out.printf("changing link callsign from %s to %s\n", link.callsign, callsign); link.stop_remote(); link.set_callsign(callsign); - link.flush_output(); link.start_remote(); } } @@ -882,7 +877,7 @@ public class AltosConfigData { /* UI doesn't support accel cal */ link.printf("c w\n"); - link.flush_output(); + read_link(link, "Saved"); } public AltosConfigData(AltosLink link) throws InterruptedException, TimeoutException { diff --git a/altoslib/AltosHexfile.java b/altoslib/AltosHexfile.java index 14f660a0..71882600 100644 --- a/altoslib/AltosHexfile.java +++ b/altoslib/AltosHexfile.java @@ -287,6 +287,8 @@ public class AltosHexfile { return null; } + private static final int look_around[] = { 0, -2, 2, -4, 4 }; + private long find_usb_descriptors() { AltosHexsym usb_descriptors = lookup_symbol("ao_usb_descriptors"); long a; @@ -294,24 +296,22 @@ public class AltosHexfile { if (usb_descriptors == null) return -1; - try { - /* The address of this has moved depending on - * padding in the linker script. Look forward - * and backwards two bytes to see if we can find it - */ - a = usb_descriptors.address; - - if (get_u8(a) == 0x12 && get_u8(a+1) == AO_USB_DESC_DEVICE) - return a; - else if (get_u8(a+1) == 0x12 && get_u8(a+3) == AO_USB_DESC_DEVICE) - return a + 2; - else if (get_u8(a-2) == 0x12 && get_u8(a-1) == AO_USB_DESC_DEVICE) - return a - 2; + /* The address of this has moved depending on padding + * in the linker script and romconfig symbols. Look + * forward and backwards two and four bytes to see if + * we can find it + */ + a = usb_descriptors.address; - return -1; - } catch (ArrayIndexOutOfBoundsException ae) { - return -1; + for (int look : look_around) { + try { + if (get_u8(a + look) == 0x12 && get_u8(a + look + 1) == AO_USB_DESC_DEVICE) + return a; + } catch (ArrayIndexOutOfBoundsException ae) { + continue; + } } + return -1; } public AltosUsbId find_usb_id() { diff --git a/altoslib/AltosIdleFetch.java b/altoslib/AltosIdleFetch.java index ca3e33eb..1ac075e3 100644 --- a/altoslib/AltosIdleFetch.java +++ b/altoslib/AltosIdleFetch.java @@ -227,7 +227,7 @@ public class AltosIdleFetch implements AltosDataProvider { try { boolean matched = false; /* Fetch config data from remote */ - AltosConfigData config_data = new AltosConfigData(link); + AltosConfigData config_data = link.config_data(); listener.set_state(AltosLib.ao_flight_stateless); for (AltosIdler idler : idlers) { if (idler.matches(config_data)) { diff --git a/altoslib/AltosLink.java b/altoslib/AltosLink.java index 9946b835..b713b3dc 100644 --- a/altoslib/AltosLink.java +++ b/altoslib/AltosLink.java @@ -539,6 +539,7 @@ public abstract class AltosLink implements Runnable { if (debug) System.out.printf("stop remote\n"); try { + flush_output(); flush_input(); } finally { printf ("~\n"); diff --git a/altoslib/AltosPreferences.java b/altoslib/AltosPreferences.java index 00b4c4b3..2fda9621 100644 --- a/altoslib/AltosPreferences.java +++ b/altoslib/AltosPreferences.java @@ -72,8 +72,8 @@ public class AltosPreferences { /* Launcher channel preference name */ public final static String launcherChannelPreference = "LAUNCHER-CHANNEL"; - /* Default logdir is ~/TeleMetrum */ - public final static String logdirName = "TeleMetrum"; + /* Default logdir is ~/AltusMetrum */ + public final static String logdirName = "AltusMetrum"; /* Log directory */ public static File logdir; diff --git a/altoslib/AltosRomconfig.java b/altoslib/AltosRomconfig.java index d868b9aa..67094658 100644 --- a/altoslib/AltosRomconfig.java +++ b/altoslib/AltosRomconfig.java @@ -28,6 +28,7 @@ public class AltosRomconfig implements AltosUnitInfoListener { public int check; public int serial_number; public int radio_calibration; + public int address_offset; public AltosUsbId usb_id; public String usb_product; @@ -46,9 +47,9 @@ public class AltosRomconfig implements AltosUnitInfoListener { return (int) (find_address(hexfile, name, len) - hexfile.address); } - static int get_int(AltosHexfile hexfile, String name, int len) throws AltosNoSymbol { + static private int get_int(AltosHexfile hexfile, String name, int len, int adjust) throws AltosNoSymbol { byte[] bytes = hexfile.data; - int start = (int) find_offset(hexfile, name, len); + int start = (int) find_offset(hexfile, name, len) + adjust; int v = 0; int o = 0; @@ -142,33 +143,46 @@ public class AltosRomconfig implements AltosUnitInfoListener { } } + static final int adjust_rom[] = { 0, -4, 4 }; + public AltosRomconfig(AltosHexfile hexfile) { try { - version = get_int(hexfile, ao_romconfig_version, 2); - check = get_int(hexfile, ao_romconfig_check, 2); - if (check == (~version & 0xffff)) { - switch (version) { - case 2: - case 1: - serial_number = get_int(hexfile, ao_serial_number, 2); - try { - radio_calibration = get_int(hexfile, ao_radio_cal, 4); - } catch (AltosNoSymbol missing) { - radio_calibration = 0; - } - - valid = true; - - /* XXX TeleBT v4.0 units originally shipped without RF calibration programmed. Go fetch - * the correct value from the web site - */ - if (serial_number == 2584 || - (3686 <= serial_number && serial_number <= 3938 && radio_calibration == 5695485)) - { - fetch_radio_cal(); + for (int adjust : adjust_rom) { + try { + version = get_int(hexfile, ao_romconfig_version, 2, adjust); + check = get_int(hexfile, ao_romconfig_check, 2, adjust); + if (check == (~version & 0xffff)) { + System.out.printf("adjust %d version %x check %x success\n", adjust, version, check); + switch (version) { + case 2: + case 1: + serial_number = get_int(hexfile, ao_serial_number, 2, adjust); + try { + radio_calibration = get_int(hexfile, ao_radio_cal, 4, adjust); + } catch (AltosNoSymbol missing) { + radio_calibration = 0; + } + + valid = true; + + /* XXX TeleBT v4.0 units originally shipped without RF calibration programmed. Go fetch + * the correct value from the web site + */ + if (serial_number == 2584 || + (3686 <= serial_number && serial_number <= 3938 && radio_calibration == 5695485)) + { + fetch_radio_cal(); + } + + break; + } + break; + } else { + System.out.printf("adjust %d version %x check %x fail\n", adjust, version, check); } - - break; + } catch (ArrayIndexOutOfBoundsException aie) { + System.out.printf("adjust %d out of bounds\n", adjust); + continue; } } usb_id = hexfile.find_usb_id(); diff --git a/altosui/AltosConfigFCUI.java b/altosui/AltosConfigFCUI.java index 8df3c022..278d3fea 100644 --- a/altosui/AltosConfigFCUI.java +++ b/altosui/AltosConfigFCUI.java @@ -97,6 +97,8 @@ public class AltosConfigFCUI ActionListener listener; + static final String title = "Configure Flight Computer"; + static String[] main_deploy_values_m = { "100", "150", "200", "250", "300", "350", "400", "450", "500" @@ -119,6 +121,7 @@ public class AltosConfigFCUI "Dual Deploy", "Redundant Apogee", "Redundant Main", + "Separation & Apogee", }; static String[] aprs_interval_values = { @@ -310,6 +313,22 @@ public class AltosConfigFCUI } } + void set_pad_orientation_values() { + String [] new_values; + if (has_radio()) + new_values = pad_orientation_values_radio; + else + new_values = pad_orientation_values_no_radio; + if (new_values != pad_orientation_values) { + int id = pad_orientation_value.getSelectedIndex(); + pad_orientation_value.removeAllItems(); + pad_orientation_values = new_values; + for (int i = 0; i < new_values.length; i++) + pad_orientation_value.addItem(pad_orientation_values[i]); + pad_orientation_value.setSelectedIndex(id); + } + } + void set_accel_tool_tips() { if (accel_plus_value.isVisible()) { accel_plus_value.setToolTipText("Pad acceleration value in flight orientation"); @@ -329,7 +348,7 @@ public class AltosConfigFCUI /* Build the UI using a grid bag */ public AltosConfigFCUI(JFrame in_owner, boolean remote) { - super (in_owner, "Configure Flight Computer", false); + super (in_owner, title, false); owner = in_owner; GridBagConstraints c; @@ -338,7 +357,8 @@ public class AltosConfigFCUI Insets il = new Insets(4,4,4,4); Insets ir = new Insets(4,4,4,4); - pane = getContentPane(); + pane = getScrollablePane(); + pane.setLayout(new GridBagLayout()); /* Product */ @@ -787,10 +807,7 @@ public class AltosConfigFCUI c.anchor = GridBagConstraints.LINE_START; c.insets = ir; c.ipady = 5; - if (has_radio()) - pad_orientation_values = pad_orientation_values_radio; - else - pad_orientation_values = pad_orientation_values_no_radio; + pad_orientation_values = pad_orientation_values_no_radio; pad_orientation_value = new JComboBox(pad_orientation_values); pad_orientation_value.setEditable(false); @@ -1030,11 +1047,13 @@ public class AltosConfigFCUI public void set_dirty() { dirty = true; + setTitle(title + " (modified)"); save.setEnabled(true); } public void set_clean() { dirty = false; + setTitle(title); save.setEnabled(false); } @@ -1062,13 +1081,13 @@ public class AltosConfigFCUI if (cmd.equals("Close") || cmd.equals("Reboot")) if (!check_dirty(cmd)) return; + if (cmd.equals("Save")) + save.setEnabled(false); listener.actionPerformed(e); if (cmd.equals("Close") || cmd.equals("Reboot")) { setVisible(false); dispose(); } - if (cmd.equals("Save") || cmd.equals("Reset")) - set_clean(); } /* ItemListener interface method */ @@ -1101,6 +1120,7 @@ public class AltosConfigFCUI set_pad_orientation_tool_tip(); set_accel_tool_tips(); set_flight_log_max_tool_tip(); + set_pad_orientation_values(); } public void set_version(String version) { diff --git a/altosui/AltosConfigPyroUI.java b/altosui/AltosConfigPyroUI.java index 309bb8ee..2b01cee8 100644 --- a/altosui/AltosConfigPyroUI.java +++ b/altosui/AltosConfigPyroUI.java @@ -386,7 +386,7 @@ public class AltosConfigPyroUI GridBagConstraints c; - pane = getContentPane(); + pane = getScrollablePane(); pane.setLayout(new GridBagLayout()); int nrow = 0; diff --git a/altosui/AltosConfigTDUI.java b/altosui/AltosConfigTDUI.java index 0fdf4449..b2e8e803 100644 --- a/altosui/AltosConfigTDUI.java +++ b/altosui/AltosConfigTDUI.java @@ -82,7 +82,7 @@ public class AltosConfigTDUI Insets il = new Insets(4,4,4,4); Insets ir = new Insets(4,4,4,4); - pane = getContentPane(); + pane = getScrollablePane(); pane.setLayout(new GridBagLayout()); /* Product */ diff --git a/altosui/AltosFlightUI.java b/altosui/AltosFlightUI.java index 608042a5..a2d0c364 100644 --- a/altosui/AltosFlightUI.java +++ b/altosui/AltosFlightUI.java @@ -186,7 +186,7 @@ public class AltosFlightUI extends AltosUIFrame implements AltosFlightDisplay { voice = in_voice; reader = in_reader; - bag = getContentPane(); + bag = getScrollablePane(); bag.setLayout(new GridBagLayout()); setTitle(String.format("AltOS %s", reader.name)); diff --git a/altosui/AltosIdleMonitorUI.java b/altosui/AltosIdleMonitorUI.java index 26bc06e4..50994bb2 100644 --- a/altosui/AltosIdleMonitorUI.java +++ b/altosui/AltosIdleMonitorUI.java @@ -226,7 +226,7 @@ public class AltosIdleMonitorUI extends AltosUIFrame implements AltosFlightDispl /* We let the user set the freq/callsign, so don't bother with the cancel dialog */ link.set_cancel_enable(false); - bag = getContentPane(); + bag = getScrollablePane(); bag.setLayout(new GridBagLayout()); setTitle(String.format("AltOS %s", device.toShortString())); diff --git a/altosui/AltosIgniteUI.java b/altosui/AltosIgniteUI.java index 0d848ab8..8256722a 100644 --- a/altosui/AltosIgniteUI.java +++ b/altosui/AltosIgniteUI.java @@ -65,7 +65,7 @@ public class AltosIgniteUI } Igniter(AltosIgniteUI ui, String label, String name, int y) { - Container pane = getContentPane(); + Container pane = getScrollablePane(); GridBagConstraints c = new GridBagConstraints(); Insets i = new Insets(4,4,4,4); @@ -388,7 +388,7 @@ public class AltosIgniteUI private void make_ui() { group = new ButtonGroup(); - Container pane = getContentPane(); + Container pane = getScrollablePane(); GridBagConstraints c = new GridBagConstraints(); Insets i = new Insets(4,4,4,4); diff --git a/altosui/AltosLaunchUI.java b/altosui/AltosLaunchUI.java index 875b786e..6615063b 100644 --- a/altosui/AltosLaunchUI.java +++ b/altosui/AltosLaunchUI.java @@ -393,7 +393,7 @@ public class AltosLaunchUI if (!open()) return; - Container pane = getContentPane(); + Container pane = getScrollablePane(); GridBagConstraints c = new GridBagConstraints(); Insets i = new Insets(4,4,4,4); @@ -510,4 +510,4 @@ public class AltosLaunchUI setVisible(true); } -} \ No newline at end of file +} diff --git a/altosui/AltosUI.app/Contents/MacOS/JavaApplicationStub b/altosui/AltosUI.app/Contents/MacOS/JavaApplicationStub index 16966918..145a260b 100755 --- a/altosui/AltosUI.app/Contents/MacOS/JavaApplicationStub +++ b/altosui/AltosUI.app/Contents/MacOS/JavaApplicationStub @@ -1,4 +1,16 @@ #!/bin/bash +# +# Fix fonts. I don't know why the getting the +# basename of the app set to . matters, but it does +# +case "$0" in + /*) + cd `dirname "$0"` + ./`basename "$0"` "$@" + exit $? + ;; +esac +export FREETYPE_PROPERTIES=truetype:interpreter-version=35 ################################################################################## # # # universalJavaApplicationStub # diff --git a/altosui/Instdrv/NSIS/Includes/java.nsh b/altosui/Instdrv/NSIS/Includes/java.nsh index 8e0e208a..c7ec9ca9 100644 --- a/altosui/Instdrv/NSIS/Includes/java.nsh +++ b/altosui/Instdrv/NSIS/Includes/java.nsh @@ -150,7 +150,7 @@ var quit var skip Function GetJRE - ${OpenURL} "java.com" + ${OpenURL} "adoptopenjdk.net" MessageBox MB_OK "Click OK to continue after completing the Java Install." FunctionEnd diff --git a/altosui/Makefile.am b/altosui/Makefile.am index b172b022..6d4ed1bc 100644 --- a/altosui/Makefile.am +++ b/altosui/Makefile.am @@ -183,7 +183,7 @@ LINUX_FILES=$(FAT_FILES) $(LINUX_LIBS) $(FIRMWARE) $(DOC) $(desktop_file).in $(L LINUX_EXTRA=altosui-fat MACOSX_INFO_PLIST=Info.plist -MACOSX_INSTALL=install-macosx +MACOSX_INSTALL=install-macosx ask-pass MACOSX_FILES=$(FAT_FILES) libaltos.dylib $(MACOSX_INFO_PLIST) $(DOC) ReadMe-Mac.rtf $(MACOSX_ICONS) $(MACOSX_INSTALL) MACOSX_EXTRA=$(FIRMWARE) diff --git a/altosui/altos-windows.nsi.in b/altosui/altos-windows.nsi.in index fa803c5f..6d487672 100644 --- a/altosui/altos-windows.nsi.in +++ b/altosui/altos-windows.nsi.in @@ -121,7 +121,7 @@ Section "Firmware" SetOutPath $INSTDIR File "../src/telemetrum-v2.0/telemetrum-v2.0-${VERSION}.ihx" -; File "../src/telemetrum-v3.0/telemetrum-v3.0-${VERSION}.ihx" + File "../src/telemetrum-v3.0/telemetrum-v3.0-${VERSION}.ihx" File "../src/telemini-v3.0/telemini-v3.0-${VERSION}.ihx" File "../src/telegps-v1.0/telegps-v1.0-${VERSION}.ihx" File "../src/telegps-v2.0/telegps-v2.0-${VERSION}.ihx" diff --git a/altosui/ask-pass b/altosui/ask-pass new file mode 100755 index 00000000..605ccb7c --- /dev/null +++ b/altosui/ask-pass @@ -0,0 +1,2 @@ +#!/bin/bash +osascript -e 'display dialog "Password:" with hidden answer default answer "" with title "Password for '$USER'"' -e 'text returned of result' diff --git a/altosui/install-macosx b/altosui/install-macosx index aebfd527..8f0067e5 100755 --- a/altosui/install-macosx +++ b/altosui/install-macosx @@ -1,9 +1,47 @@ -#!/bin/sh +#!/bin/bash + +JVM=/Library/Java/JavaVirtualMachines dir=`dirname "$0"` + +case `id -u` in + 0) + ;; + *) + SUDO_ASKPASS="${dir}/ask-pass" sudo -A "$0" "$@" + exit 0 + ;; +esac + +# Check for java +if ls "$JVM" | grep -q adopt; then + echo "Adopt OpenJDK already present" +else + open https://adoptopenjdk.net/ + osascript -e 'display dialog "Install Java from https://adoptopenjdk.net then click Continue" buttons {"Continue"} default button 1 with title "Install Java"' >/dev/null +fi + cd "$dir" -mkdir -p ~/Applications/AltOS -find ~/Applications/AltOS -type d -print0 | xargs -0 chmod +w -cp -f -a * ~/Applications/AltOS -cd ~/Applications/AltOS -chmod +w * -xattr -c * +LIBRARY=/Library/AltusMetrum +APPLICATIONS=/Applications +INSTALLED= +for file in *; do + echo 'Installing' "$file" + case "$file" in + *.app) + mkdir -p "${APPLICATIONS}" + if [ -d "${APPLICATIONS}/${file}" ]; then + rm -rf "${APPLICATIONS}/${file}" + fi + cp -a "$file" "${APPLICATIONS}/${file}" + chmod -R +w "${APPLICATIONS}/${file}" + xattr -rc "${APPLICATIONS}/${file}" + APP=`basename "$file" .app` + INSTALLED="${INSTALLED} ${APP}" + ;; + *) + mkdir -p "${LIBRARY}" + cp -a "$file" "${LIBRARY}" + ;; + esac +done +osascript -e 'display dialog "Installation of'"${INSTALLED}"' complete" with title "Installation Complete" buttons {"OK"} default button 1' >/dev/null diff --git a/altosuilib/AltosBTManage.java b/altosuilib/AltosBTManage.java index 1726190d..37e820b6 100644 --- a/altosuilib/AltosBTManage.java +++ b/altosuilib/AltosBTManage.java @@ -219,7 +219,7 @@ public class AltosBTManage extends AltosUIDialog implements ActionListener, Iter found_devices = new LinkedBlockingQueue(); - Container pane = getContentPane(); + Container pane = getScrollablePane(); pane.setLayout(new GridBagLayout()); GridBagConstraints c = new GridBagConstraints(); diff --git a/altosuilib/AltosConfigFreqUI.java b/altosuilib/AltosConfigFreqUI.java index d24480b3..49fe6b40 100644 --- a/altosuilib/AltosConfigFreqUI.java +++ b/altosuilib/AltosConfigFreqUI.java @@ -67,7 +67,7 @@ class AltosEditFreqUI extends AltosUIDialog implements ActionListener { got_ok = false; frame = in_frame; - Container pane = getContentPane(); + Container pane = getScrollablePane(); pane.setLayout(new GridBagLayout()); GridBagConstraints c = new GridBagConstraints(); @@ -302,7 +302,7 @@ public class AltosConfigFreqUI extends AltosUIDialog implements ActionListener { frequencies = new FrequencyList(in_frequencies); - Container pane = getContentPane(); + Container pane = getScrollablePane(); pane.setLayout(new GridBagLayout()); GridBagConstraints c = new GridBagConstraints(); diff --git a/altosuilib/AltosEepromMonitorUI.java b/altosuilib/AltosEepromMonitorUI.java index 7da9786c..90ce58ac 100644 --- a/altosuilib/AltosEepromMonitorUI.java +++ b/altosuilib/AltosEepromMonitorUI.java @@ -56,7 +56,7 @@ public class AltosEepromMonitorUI extends AltosUIDialog implements AltosEepromMo Insets il = new Insets(4,4,4,4); Insets ir = new Insets(4,4,4,4); - pane = getContentPane(); + pane = getScrollablePane(); pane.setLayout(new GridBagLayout()); c = new GridBagConstraints(); diff --git a/altosuilib/AltosFlashUI.java b/altosuilib/AltosFlashUI.java index fd84f921..6b78aea7 100644 --- a/altosuilib/AltosFlashUI.java +++ b/altosuilib/AltosFlashUI.java @@ -131,7 +131,7 @@ public class AltosFlashUI Insets il = new Insets(4,4,4,4); Insets ir = new Insets(4,4,4,4); - pane = getContentPane(); + pane = getScrollablePane(); pane.setLayout(new GridBagLayout()); c = new GridBagConstraints(); @@ -208,9 +208,18 @@ public class AltosFlashUI public AltosHexfileFilter(String usb_product) { int l; + int dash; /* Trim off any trailing variants (1.0a vs 1.0) */ - for (l = usb_product.length(); l > 0; l--) { + for (dash = usb_product.length(); dash > 0; dash--) { + char c = usb_product.charAt(dash-1); + if (c == '-') + break; + } + if (dash == 0) + dash = usb_product.length(); + + for (l = usb_product.length(); l > dash; l--) { char c = usb_product.charAt(l-1); if (c < 'a' || 'z' < c) break; @@ -637,7 +646,7 @@ public class AltosFlashUI super(in_owner, "Open Flash Target Device", true); owner = in_owner; - Container pane = getContentPane(); + Container pane = getScrollablePane(); GridBagConstraints c = new GridBagConstraints(); Insets i = new Insets(4,4,4,4); diff --git a/altosuilib/AltosRomconfigUI.java b/altosuilib/AltosRomconfigUI.java index a25c39c4..44d3a9f8 100644 --- a/altosuilib/AltosRomconfigUI.java +++ b/altosuilib/AltosRomconfigUI.java @@ -51,7 +51,7 @@ public class AltosRomconfigUI Insets il = new Insets(4,4,4,4); Insets ir = new Insets(4,4,4,4); - pane = getContentPane(); + pane = getScrollablePane(); pane.setLayout(new GridBagLayout()); int y = 0; @@ -74,7 +74,10 @@ public class AltosRomconfigUI c.weightx = 1; c.anchor = GridBagConstraints.LINE_START; c.insets = ir; - product_value = new JLabel(config.usb_product); + String product = "unknown"; + if (config != null) + product = config.usb_product; + product_value = new JLabel(product); pane.add(product_value, c); y++; diff --git a/altosuilib/AltosScanUI.java b/altosuilib/AltosScanUI.java index a09142e5..4ec858fa 100644 --- a/altosuilib/AltosScanUI.java +++ b/altosuilib/AltosScanUI.java @@ -470,7 +470,7 @@ public class AltosScanUI if (!open()) return; - Container pane = getContentPane(); + Container pane = getScrollablePane(); GridBagConstraints c = new GridBagConstraints(); Insets i = new Insets(4,4,4,4); diff --git a/altosuilib/AltosUIAccelCal.java b/altosuilib/AltosUIAccelCal.java index 7ca8ea82..94d80193 100644 --- a/altosuilib/AltosUIAccelCal.java +++ b/altosuilib/AltosUIAccelCal.java @@ -164,7 +164,7 @@ public class AltosUIAccelCal this.link = link; this.config_values = config_values; - pane = getContentPane(); + pane = getScrollablePane(); pane.setLayout(new GridBagLayout()); GridBagConstraints c = new GridBagConstraints(); diff --git a/altosuilib/AltosUIConfigure.java b/altosuilib/AltosUIConfigure.java index 8ee89dd4..09e7daaa 100644 --- a/altosuilib/AltosUIConfigure.java +++ b/altosuilib/AltosUIConfigure.java @@ -260,7 +260,7 @@ public class AltosUIConfigure super(in_owner, name, false); owner = in_owner; - pane = getContentPane(); + pane = getScrollablePane(); pane.setLayout(new GridBagLayout()); row = 0; diff --git a/altosuilib/AltosUIDialog.java b/altosuilib/AltosUIDialog.java index 34bd50d8..be883a14 100644 --- a/altosuilib/AltosUIDialog.java +++ b/altosuilib/AltosUIDialog.java @@ -30,6 +30,30 @@ class AltosUIDialogListener extends WindowAdapter { public class AltosUIDialog extends JDialog implements AltosUIListener { + private Container scrollPane; + + public Container getScrollablePane() { + if (scrollPane == null) { + Container content = super.getContentPane(); + /* Create a container to hold the dialog contents */ + scrollPane = new Container(); + + /* Make an opaque box to use the right color */ + Box box = new Box(BoxLayout.X_AXIS); + box.add(scrollPane); + box.setOpaque(true); + + /* Create a scrollpane to hold the box */ + JScrollPane scroll = new JScrollPane(); + JViewport view = scroll.getViewport(); + view.add(box); + + /* Add the scroll pane to the top level */ + content.add(scroll); + } + return (Container) scrollPane; + } + public void ui_changed(String look_and_feel) { SwingUtilities.updateComponentTreeUI(this); this.pack(); diff --git a/altosuilib/AltosUIFrame.java b/altosuilib/AltosUIFrame.java index 71e16e1d..f701ce7a 100644 --- a/altosuilib/AltosUIFrame.java +++ b/altosuilib/AltosUIFrame.java @@ -41,6 +41,30 @@ public class AltosUIFrame extends JFrame implements AltosUIListener, AltosPositi this.pack(); } + private Container scrollPane; + + public Container getScrollablePane() { + if (scrollPane == null) { + Container content = super.getContentPane(); + /* Create a container to hold the dialog contents */ + scrollPane = new Container(); + + /* Make an opaque box to use the right color */ + Box box = new Box(BoxLayout.X_AXIS); + box.add(scrollPane); + box.setOpaque(true); + + /* Create a scrollpane to hold the box */ + JScrollPane scroll = new JScrollPane(); + JViewport view = scroll.getViewport(); + view.add(box); + + /* Add the scroll pane to the top level */ + content.add(scroll); + } + return (Container) scrollPane; + } + static String[] altos_icon_names = { "/altusmetrum-altosui-16.png", "/altusmetrum-altosui-32.png", diff --git a/altosuilib/AltosUIMapPreload.java b/altosuilib/AltosUIMapPreload.java index 31c8ed1b..9ba27355 100644 --- a/altosuilib/AltosUIMapPreload.java +++ b/altosuilib/AltosUIMapPreload.java @@ -336,7 +336,7 @@ public class AltosUIMapPreload extends AltosUIFrame implements ActionListener, I public AltosUIMapPreload(AltosUIFrame in_owner) { owner = in_owner; - Container pane = getContentPane(); + Container pane = getScrollablePane(); GridBagConstraints c = new GridBagConstraints(); Insets i = new Insets(4,4,4,4); diff --git a/altosuilib/AltosUIPreferences.java b/altosuilib/AltosUIPreferences.java index 7e3178d8..c40903ce 100644 --- a/altosuilib/AltosUIPreferences.java +++ b/altosuilib/AltosUIPreferences.java @@ -129,18 +129,23 @@ public class AltosUIPreferences extends AltosPreferences { backend.putInt(fontSizePreference, font_size); flush_preferences(); AltosUILib.set_fonts(font_size); - for (AltosFontListener l : font_listeners) + for (AltosFontListener l : font_listeners) { + System.out.printf("notifying %s of font size change\n", l); l.font_size_changed(font_size); + } + System.out.printf("all fonts changed\n"); } } public static void register_font_listener(AltosFontListener l) { + System.out.printf("register font listener\n"); synchronized (backend) { font_listeners.add(l); } } public static void unregister_font_listener(AltosFontListener l) { + System.out.printf("unregister font listener\n"); synchronized (backend) { font_listeners.remove(l); } diff --git a/altosuilib/AltosUSBDevice.java b/altosuilib/AltosUSBDevice.java index 50ec4c03..585bd774 100644 --- a/altosuilib/AltosUSBDevice.java +++ b/altosuilib/AltosUSBDevice.java @@ -26,7 +26,7 @@ public class AltosUSBDevice extends altos_device implements AltosDevice { public String toString() { String name = getName(); - if (name == null) + if (name == null || "".equals(name)) name = "Altus Metrum"; return String.format("%-20.20s %4d %s", name, getSerial(), getPath()); @@ -34,7 +34,7 @@ public class AltosUSBDevice extends altos_device implements AltosDevice { public String toShortString() { String name = getName(); - if (name == null) + if (name == null || "".equals(name)) name = "Altus Metrum"; return String.format("%s %d %s", name, getSerial(), getPath()); diff --git a/ao-bringup/turnon_telebt b/ao-bringup/turnon_telebt index 3e9fddaa..af72bab8 100755 --- a/ao-bringup/turnon_telebt +++ b/ao-bringup/turnon_telebt @@ -66,12 +66,8 @@ esac CALFILE=cal-$SERIAL.txt -echo 'E 0' > $dev - ../ao-tools/ao-cal-freq/ao-cal-freq --nosave --output=$CALFILE --tty=$dev -# echo 'E 1' > $dev - CAL_VALUE=`cat $CALFILE` echo $SERIAL","$CAL_VALUE >> cal_values echo "Reflashing with calibration: $CAL_VALUE" diff --git a/ao-bringup/turnon_telemega_v1.0 b/ao-bringup/turnon_telemega_v1.0 index 7b95bf20..a8fb8c86 100755 --- a/ao-bringup/turnon_telemega_v1.0 +++ b/ao-bringup/turnon_telemega_v1.0 @@ -58,6 +58,6 @@ SERIAL=$SERIAL ./cal-freq $dev echo 'E 1' > $dev -./test-telemega +./test-telemega-v1.0 exit $? diff --git a/ao-bringup/turnon_telemega_v3.0 b/ao-bringup/turnon_telemega_v3.0 index 1fce345a..272a69d7 100755 --- a/ao-bringup/turnon_telemega_v3.0 +++ b/ao-bringup/turnon_telemega_v3.0 @@ -76,6 +76,6 @@ done echo 'E 1' > $dev -./test-telemega +./test-telemega-v3.0 exit $? diff --git a/ao-tools/ao-eeprom/ao-eeprom.c b/ao-tools/ao-eeprom/ao-eeprom.c index 2f076242..90055d78 100644 --- a/ao-tools/ao-eeprom/ao-eeprom.c +++ b/ao-tools/ao-eeprom/ao-eeprom.c @@ -636,7 +636,43 @@ main (int argc, char **argv) break; case AO_LOG_FORMAT_TELEGPS: log_gps = (struct ao_log_gps *) &eeprom->data[pos]; - (void) log_gps; + switch (log_gps->type) { + case AO_LOG_GPS_TIME: + printf(" lat %10.7f ° lon %10.7f ° alt %8d m", + log_gps->u.gps.latitude / 10000000.0, + log_gps->u.gps.longitude/ 10000000.0, + (int32_t) (log_gps->u.gps.altitude_low | + (log_gps->u.gps.altitude_high << 16))); + printf(" time %02d:%02d:%02d %04d-%02d-%02d flags %02x", + log_gps->u.gps.hour, + log_gps->u.gps.minute, + log_gps->u.gps.second, + log_gps->u.gps.year + 2000, + log_gps->u.gps.month, + log_gps->u.gps.day, + log_gps->u.gps.flags); + printf(" course %3d ground_speed %5u climb_rate %6d pdop %3d hdop %3d vdop %3d mode %3d", + log_gps->u.gps.course, + log_gps->u.gps.ground_speed, + log_gps->u.gps.climb_rate, + log_gps->u.gps.pdop, + log_gps->u.gps.hdop, + log_gps->u.gps.vdop, + log_gps->u.gps.mode); + break; + case AO_LOG_GPS_SAT: + printf(" channels %2d", + log_gps->u.gps_sat.channels); + for (i = 0; i < 12; i++) { + printf(" svid %3d c_n %2d", + log_gps->u.gps_sat.sats[i].svid, + log_gps->u.gps_sat.sats[i].c_n); + } + break; + default: + printf (" unknown"); + break; + } break; case AO_LOG_FORMAT_DETHERM: break; diff --git a/configure.ac b/configure.ac index 8a037767..bd3d51cd 100644 --- a/configure.ac +++ b/configure.ac @@ -18,13 +18,13 @@ dnl dnl Process this file with autoconf to create configure. AC_PREREQ(2.57) -AC_INIT([altos], 1.9.4) +AC_INIT([altos], 1.9.5) ANDROID_VERSION=27 AC_CONFIG_SRCDIR([src/kernel/ao.h]) AM_INIT_AUTOMAKE([foreign dist-bzip2]) AM_MAINTAINER_MODE -RELEASE_DATE=2020-07-02 +RELEASE_DATE=2020-09-29 AC_SUBST(RELEASE_DATE) DOC_DATE=`LC_ALL=C date -d $RELEASE_DATE +'%d %b %Y'` diff --git a/doc/Makefile.am b/doc/Makefile.am index e56e2a55..165317e2 100644 --- a/doc/Makefile.am +++ b/doc/Makefile.am @@ -17,6 +17,7 @@ FAKETIME=TZ=UTC faketime -f '$(RELEASE_DATE) 00:00:00 i0' endif RELNOTES_INC=\ + release-notes-1.9.5.inc \ release-notes-1.9.4.inc \ release-notes-1.9.3.inc \ release-notes-1.9.2.inc \ diff --git a/doc/RELNOTES b/doc/RELNOTES index 066283c3..7541b844 100644 --- a/doc/RELNOTES +++ b/doc/RELNOTES @@ -1,6 +1,6 @@ Creating documentation for a new release of AltOS -* Write release notes in release-notes-${version}.inc. Add to Makefile +* Write release notes in release-notes-${version}.inc. * Make sure that doc/altusmetrum.txt has the right copyright year diff --git a/doc/config-device.inc b/doc/config-device.inc index 15f9129e..a533ca82 100644 --- a/doc/config-device.inc +++ b/doc/config-device.inc @@ -171,6 +171,10 @@ ifdef::altusmetrum[] is fired first, followed after a two second delay by the 'main' channel. + Separation & Apogee:: + This fires the 'main' channel when the first motor + burns out and fires the 'apogee' charge at apogee. + ifdef::telemetrum,telemega,easymega,easytimer[] ==== Pad Orientation diff --git a/doc/easymini-outline.txt b/doc/easymini-outline.txt index c4b1baa5..eac1c4af 100644 --- a/doc/easymini-outline.txt +++ b/doc/easymini-outline.txt @@ -1,10 +1,10 @@ :notitle: :doctype: article -== EasyMini Outline and Hole Pattern +== EasyMini/EasyMotor/EasyTimer Outline and Hole Pattern This image, when printed, provides a precise template for the - mounting holes in EasyMini. EasyMini has overall dimensions - of 0.800 x 1.500 inches, and the mounting holes are sized for - use with 4-40 or M3 screws. + mounting holes in EasyMini, EasyMotor, and EasyTimer. Each of + these products has overall dimensions of 0.800 x 1.500 inches, + and the mounting holes are sized for use with 4-40 or M3 screws. image::easymini.svg[align="center"] diff --git a/doc/easymini-release-notes.inc b/doc/easymini-release-notes.inc index 990ee69f..66544c15 100644 --- a/doc/easymini-release-notes.inc +++ b/doc/easymini-release-notes.inc @@ -1,5 +1,9 @@ [appendix] == Release Notes + :leveloffset: 2 + include::release-notes-1.9.5.adoc[] + + <<<< :leveloffset: 2 include::release-notes-1.9.4.adoc[] diff --git a/doc/release-notes-1.9.5.inc b/doc/release-notes-1.9.5.inc new file mode 100644 index 00000000..220caaac --- /dev/null +++ b/doc/release-notes-1.9.5.inc @@ -0,0 +1,45 @@ += Release Notes for Version 1.9.5 +include::release-head.adoc[] +:doctype: article + + Version 1.9.5 + + == AltOS + + * Add Booster mode for all dual-deploy altimeters. Select + "Separation & Apogee" mode in AltosUI to fire the 'main' + channel at first motor burnout and the 'apogee' channel at + apogee. + + * Improve reliability of stm32l firmware under heavy + load. This was found using Monitor Idle on TeleMega with all + flash slots full of data which would occasionally lock up. + + * Fix orientation label in AltosUI for devices with + radios. This makes the orientation say 'Antenna up' and + 'Antenna Down' for TeleMetrum and TeleMega again. + + * Fix log data for pyro channels which were inhibited (often + because of a tilt limit). They used to report 'fired' as + soon as they were inhibited, which was misleading. Now they + never report as having been fired. + + * Allow Igniter Test to fire each igniter more than once. + + == AltosUI + + * Improve performance of Monitor Idle mode by sending less data for each + update. + + * Improve Mac OS X install scripts so that they work on + Catalina. This involves sending the user to get Java from + the AdoptOpenJDK project which provides a version that works + with Java applications. + + * Make larger dialogs scrollable for use on smaller screens. + + * Fix troubles re-flashing EasyMega boards running older + firmware. + + * Add TeleMetrum v3.0 firmware to the Windows + AltosUI packages. diff --git a/doc/release-notes.inc b/doc/release-notes.inc index 160128b2..917753f4 100644 --- a/doc/release-notes.inc +++ b/doc/release-notes.inc @@ -1,5 +1,9 @@ [appendix] == Release Notes + :leveloffset: 2 + include::release-notes-1.9.5.adoc[] + + <<<< :leveloffset: 2 include::release-notes-1.9.4.adoc[] diff --git a/doc/telegps-release-notes.inc b/doc/telegps-release-notes.inc index 8b315ccb..30e8f73b 100644 --- a/doc/telegps-release-notes.inc +++ b/doc/telegps-release-notes.inc @@ -1,15 +1,17 @@ [appendix] == Release Notes :leveloffset: 2 - include::release-notes-1.9.4.adoc[] + include::release-notes-1.9.5.adoc[] <<<< + :leveloffset: 2 + include::release-notes-1.9.4.adoc[] + <<<< :leveloffset: 2 include::release-notes-1.9.3.adoc[] <<<< - :leveloffset: 2 include::release-notes-1.9.1.adoc[] diff --git a/doc/telelaunch-configuration.inc b/doc/telelaunch-configuration.inc index f5199cc4..0317613c 100644 --- a/doc/telelaunch-configuration.inc +++ b/doc/telelaunch-configuration.inc @@ -59,9 +59,13 @@ memory. For example, the default 435.750 MHz would be configured using - c f 435750 + + c F 435750 c w + Note that the 'f' parameter is a frequency calibration value + that you really, really, really don't want to change. So, + please be careful to make sure you use capital 'F', not lower + case 'f' when changing the operating frequency! === Callsign diff --git a/doc/updating-firmware.inc b/doc/updating-firmware.inc index 1999a9c7..b9216a22 100644 --- a/doc/updating-firmware.inc +++ b/doc/updating-firmware.inc @@ -84,7 +84,7 @@ Connect pin 6 and pin 1 of the companion connector. Pin 1 can be identified by the square pad - around it, and then the pins could sequentially across + around it, and then the pins count sequentially across the board. Be very careful to *not* short pin 8 to anything as that is connected directly to the battery. Pin 7 carries 3.3V and the board will crash @@ -97,7 +97,7 @@ Connect pin 6 and pin 1 of the companion connector. Pin 1 can be identified by the square pad - around it, and then the pins could sequentially across + around it, and then the pins count sequentially across the board. Be very careful to *not* short pin 8 to anything as that is connected directly to the battery. Pin 7 carries 3.3V and the board will crash @@ -111,7 +111,7 @@ Connect pin 5 and pin 1 of the debug connector, which is the six holes next to the beeper. Pin 1 can be identified by the square pad around it, and then the - pins could sequentially across the board, making Pin 5 + pins count sequentially across the board, making Pin 5 the one on the other end of the row. endif::easytimer[] @@ -120,7 +120,7 @@ Connect pin 6 and pin 1 of the companion connector. Pin 1 can be identified by the square pad - around it, and then the pins could sequentially across + around it, and then the pins count sequentially across the board. Be very careful to *not* short pin 8 to anything as that is connected directly to the battery. Pin 7 carries 3.3V and the board will crash @@ -134,7 +134,7 @@ Connect pin 6 and pin 1 of the debug connector, which is the six holes next to the beeper. Pin 1 can be identified by the square pad around it, and then the - pins could sequentially across the board, making Pin 6 + pins count sequentially across the board, making Pin 6 the one on the other end of the row. endif::easymini[] diff --git a/libaltos/Makefile-standalone b/libaltos/Makefile-standalone index 1430aacb..77c7cca5 100644 --- a/libaltos/Makefile-standalone +++ b/libaltos/Makefile-standalone @@ -33,12 +33,12 @@ OS_SRCS=libaltos_posix.c libaltos_darwin.c # -iwithsysroot /System/Library/Frameworks/IOKit.framework/Headers \ # -iwithsysroot /System/Library/Frameworks/CoreFoundation.framework/Headers -XCODE=/Applications/Xcode-beta.app -SDK=$(XCODE)/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.11.sdk +XCODE=/Applications/Xcode.app +SDK=$(XCODE)/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.15.sdk MINVERSION=10.5 OS_LIB_CFLAGS=\ - -DDARWIN -DPOSIX_TTY -arch i386 -arch x86_64 -isysroot $(SDK) \ + -DDARWIN -DPOSIX_TTY -arch x86_64 -isysroot $(SDK) \ -mmacosx-version-min=10.5 \ -iwithsysroot /System/Library/Frameworks/JavaVM.framework/Headers \ -iwithsysroot /System/Library/Frameworks/IOKit.framework/Headers \ diff --git a/libaltos/libaltos.dylib b/libaltos/libaltos.dylib index c18493ea..0d5b9c46 100755 Binary files a/libaltos/libaltos.dylib and b/libaltos/libaltos.dylib differ diff --git a/libaltos/libaltos_darwin.c b/libaltos/libaltos_darwin.c index c6b6355f..794c0215 100644 --- a/libaltos/libaltos_darwin.c +++ b/libaltos/libaltos_darwin.c @@ -192,7 +192,8 @@ altos_list_next(struct altos_list *list, struct altos_device *device) if (get_number (usb_device, CFSTR(kUSBVendorID), &device->vendor) && get_number (usb_device, CFSTR(kUSBProductID), &device->product) && get_string (object, CFSTR(kIOCalloutDeviceKey), device->path, sizeof (device->path)) && - get_string (usb_device, CFSTR(kUSBProductString), device->name, sizeof (device->name)) && + (get_string (usb_device, CFSTR("kUSBProductString"), device->name, sizeof (device->name)) || + get_string (usb_device, CFSTR(kUSBProductString), device->name, sizeof (device->name))) && get_string (usb_device, CFSTR(kUSBSerialNumberString), serial_string, sizeof (serial_string))) { device->serial = atoi(serial_string); IOObjectRelease(object); diff --git a/libaltos/libaltos_windows.c b/libaltos/libaltos_windows.c index 03c2958f..162c85ba 100644 --- a/libaltos/libaltos_windows.c +++ b/libaltos/libaltos_windows.c @@ -131,6 +131,15 @@ altos_ftdi_list_start(void) return list; } +static struct { + char *windows; + char *real; +} name_map[] = { + { .windows = "AltusMetrum28", .real = "EasyMega" }, + { .windows = "AltusMetrum2c", .real = "EasyMotor" }, + { 0, 0 }, +}; + PUBLIC int altos_list_next(struct altos_list *list, struct altos_device *device) { @@ -148,6 +157,7 @@ altos_list_next(struct altos_list *list, struct altos_device *device) DWORD friendlyname_len; char instanceid[1024]; DWORD instanceid_len; + int i; dev_info_data.cbSize = sizeof (SP_DEVINFO_DATA); while(SetupDiEnumDeviceInfo(list->dev_info, list->index, @@ -230,6 +240,16 @@ altos_list_next(struct altos_list *list, struct altos_device *device) altos_set_last_windows_error(); continue; } + for (i = 0; name_map[i].windows; i++) + if (!strcmp(name_map[i].windows, friendlyname)) { + strcpy(friendlyname, name_map[i].real); + break; + } + + char *space = strchr(friendlyname, ' '); + if (space) + *space = '\0'; + device->vendor = vid; device->product = pid; device->serial = serial; diff --git a/micropeak/Makefile.am b/micropeak/Makefile.am index 23ec077e..816dd4b3 100644 --- a/micropeak/Makefile.am +++ b/micropeak/Makefile.am @@ -137,7 +137,7 @@ MACOSX_DRIVERS=$(MACOSX_DRIVER_1) $(MACOSX_DRIVER_0) MACOSX_INFO_PLIST=Info.plist MACOSX_README=ReadMe-Mac.rtf -MACOSX_INSTALL=../altosui/install-macosx +MACOSX_INSTALL=../altosui/install-macosx ../altosui/ask-pass MACOSX_FILES=$(FAT_FILES) libaltos.dylib $(MACOSX_INFO_PLIST) $(MACOSX_DRIVERS) $(MACOSX_README) $(DOC) $(MACOSX_ICONS) $(MACOSX_INSTALL) $(MACOSX_DRIVER_0): diff --git a/micropeak/MicroData.java b/micropeak/MicroData.java index 4a795dff..359ccd7a 100644 --- a/micropeak/MicroData.java +++ b/micropeak/MicroData.java @@ -34,8 +34,10 @@ public class MicroData { private double time_step; private ArrayList bytes; + public int nsamples; public int log_id; String name; + String unique_id; public static final int LOG_ID_MICROPEAK = 0; public static final int LOG_ID_MICROKITE = 1; @@ -134,6 +136,21 @@ public class MicroData { return v; } + private String get_line(InputStream f) throws IOException, FileEndedException, NonHexcharException { + int c; + StringBuffer line = new StringBuffer(); + + do { + c = f.read(); + } while (Character.isWhitespace(c)); + + do { + line.append((char) c); + c = f.read(); + } while (!Character.isWhitespace(c)); + return new String(line); + } + private int swap16(int i) { return ((i << 8) & 0xff00) | ((i >> 8) & 0xff); } @@ -277,10 +294,14 @@ public class MicroData { file_crc = 0xffff; ground_pressure = get_32(f); min_pressure = get_32(f); - int nsamples = get_16(f); + nsamples = get_16(f); log_id = nsamples >> 12; nsamples &= 0xfff; + if (log_id == LOG_ID_MICROPEAK2) { + int nsamples_high = get_16(f); + nsamples |= (nsamples_high << 12); + } cal_data.set_ground_pressure(ground_pressure); @@ -328,6 +349,15 @@ public class MicroData { flight_series.set_pressure(cur); } + int current_crc = swap16(~file_crc & 0xffff); + int crc = get_16(f); + + crc_valid = crc == current_crc; + + if (log_id == LOG_ID_MICROPEAK2) { + unique_id = get_line(f); + } + flight_series.finish(); /* Build states */ @@ -335,8 +365,10 @@ public class MicroData { flight_series.set_time(0); flight_series.set_state(AltosLib.ao_flight_boost); - flight_series.set_time(flight_series.speed_series.max().time); - flight_series.set_state(AltosLib.ao_flight_coast); + if (flight_series.speed_series != null && flight_series.speed_series.max() != null) { + flight_series.set_time(flight_series.speed_series.max().time); + flight_series.set_state(AltosLib.ao_flight_coast); + } flight_series.set_time(flight_series.height_series.max().time); flight_series.set_state(AltosLib.ao_flight_drogue); @@ -351,10 +383,6 @@ public class MicroData { flight_stats = new AltosFlightStats(flight_series); - int current_crc = swap16(~file_crc & 0xffff); - int crc = get_16(f); - - crc_valid = crc == current_crc; } catch (FileEndedException fe) { throw new IOException("File Ended Unexpectedly"); diff --git a/micropeak/MicroDownload.java b/micropeak/MicroDownload.java index 1ede2d9a..7e3d1e59 100644 --- a/micropeak/MicroDownload.java +++ b/micropeak/MicroDownload.java @@ -64,21 +64,27 @@ public class MicroDownload extends AltosUIDialog implements Runnable, ActionList } private void done_internal() { - setVisible(false); - dispose(); - if (data != null && data.crc_valid) { - status_value.setText("Received MicroPeak Data"); - owner = owner.SetData(data); - MicroSave save = new MicroSave(owner, data); - if (save.runDialog()) - owner.SetName(data.name); + if (data.nsamples == 0) { + JOptionPane.showMessageDialog(owner, + "No Flight Data Present", + "Empty Log", + JOptionPane.WARNING_MESSAGE); + } else { + status_value.setText("Received MicroPeak Data"); + owner = owner.SetData(data); + MicroSave save = new MicroSave(owner, data); + if (save.runDialog()) + owner.SetName(data.name); + } } else { JOptionPane.showMessageDialog(owner, "Download Failed", "Flight data corrupted", JOptionPane.ERROR_MESSAGE); } + setVisible(false); + dispose(); } public void drain_queue() { @@ -152,6 +158,7 @@ public class MicroDownload extends AltosUIDialog implements Runnable, ActionList } catch (MicroData.NonHexcharException nhe) { } } + write_thread.join(); } catch (FileNotFoundException fe) { } catch (IOException ioe) { } catch (InterruptedException ie) { @@ -162,6 +169,25 @@ public class MicroDownload extends AltosUIDialog implements Runnable, ActionList } Thread serial_thread; + Thread write_thread; + + public class SerialWriter implements Runnable { + MicroSerial serial; + + public void run () { + try { + Thread.sleep(100); + serial.write('l'); + serial.write('\n'); + serial.flush(); + } catch (InterruptedException ie) { + } + } + + public SerialWriter(MicroSerial serial) { + this.serial = serial; + } + } public void start() { try { @@ -172,6 +198,10 @@ public class MicroDownload extends AltosUIDialog implements Runnable, ActionList } serial_thread = new Thread(this); serial_thread.start(); + + SerialWriter writer = new SerialWriter(serial); + write_thread = new Thread(writer); + write_thread.start(); } public void actionPerformed(ActionEvent ae) { @@ -194,7 +224,7 @@ public class MicroDownload extends AltosUIDialog implements Runnable, ActionList this.owner = owner; this.device = device; - pane = getContentPane(); + pane = getScrollablePane(); pane.setLayout(new GridBagLayout()); c = new GridBagConstraints(); diff --git a/micropeak/MicroFile.java b/micropeak/MicroFile.java index cea41c41..f75cd1c3 100644 --- a/micropeak/MicroFile.java +++ b/micropeak/MicroFile.java @@ -25,22 +25,29 @@ import org.altusmetrum.altosuilib_14.*; public class MicroFile { - public static File make(File directory, int year, int month, int day) { + public static File make(MicroData data, File directory, int year, int month, int day) { + String unique = ""; + if (data != null && data.unique_id != null) + unique = String.format("-%s", data.unique_id); for (int sequence = 1;; sequence++) { - String s = String.format("%04d-%02d-%02d-flight-%03d.mpd", - year, month, day, sequence); + String s = String.format("%04d-%02d-%02d%s-flight-%03d.mpd", + year, month, day, unique, sequence); File file = new File(directory, s); if (!file.exists()) return file; } } - public static File make(File directory) { + public static File make(MicroData data, File directory) { Calendar cal = Calendar.getInstance(); - return make(directory, cal.get(Calendar.YEAR), cal.get(Calendar.MONTH) + 1, cal.get(Calendar.DAY_OF_MONTH)); + return make(data, directory, cal.get(Calendar.YEAR), cal.get(Calendar.MONTH) + 1, cal.get(Calendar.DAY_OF_MONTH)); + } + + public static File make(MicroData data) { + return make(data, AltosUIPreferences.logdir()); } public static File make() { - return make(AltosUIPreferences.logdir()); + return make(null); } -} \ No newline at end of file +} diff --git a/micropeak/MicroPeak.app/Contents/MacOS/JavaApplicationStub b/micropeak/MicroPeak.app/Contents/MacOS/JavaApplicationStub index 16966918..145a260b 100755 --- a/micropeak/MicroPeak.app/Contents/MacOS/JavaApplicationStub +++ b/micropeak/MicroPeak.app/Contents/MacOS/JavaApplicationStub @@ -1,4 +1,16 @@ #!/bin/bash +# +# Fix fonts. I don't know why the getting the +# basename of the app set to . matters, but it does +# +case "$0" in + /*) + cd `dirname "$0"` + ./`basename "$0"` "$@" + exit $? + ;; +esac +export FREETYPE_PROPERTIES=truetype:interpreter-version=35 ################################################################################## # # # universalJavaApplicationStub # diff --git a/micropeak/MicroPeak.java b/micropeak/MicroPeak.java index eb08c552..7d3e20d8 100644 --- a/micropeak/MicroPeak.java +++ b/micropeak/MicroPeak.java @@ -37,8 +37,30 @@ public class MicroPeak extends MicroFrame implements ActionListener, ItemListene MicroData data; Container container; JTabbedPane pane; + JMenuBar menu_bar; static int number_of_windows; + /* File menu */ + final static String open_command = "open"; + final static String save_command = "save"; + final static String export_command = "export"; + final static String preferences_command = "preferences"; + final static String close_command = "close"; + final static String exit_command = "exit"; + + static final String[][] file_menu_entries = new String[][] { + { "Open", open_command }, + { "Save a Copy", save_command }, + { "Export Data", export_command }, + { "Preferences", preferences_command }, + { "Close", close_command }, + { "Exit", exit_command }, + }; + + /* Download menu */ + final static String download_command = "download"; + final static String download_label = "Download"; + MicroPeak SetData(MicroData data) { MicroPeak mp = this; if (this.data != null) { @@ -174,20 +196,20 @@ public class MicroPeak extends MicroFrame implements ActionListener, ItemListene } public void actionPerformed(ActionEvent ev) { - if ("Exit".equals(ev.getActionCommand())) - System.exit(0); - else if ("Close".equals(ev.getActionCommand())) - Close(); - else if ("Open".equals(ev.getActionCommand())) + if (open_command.equals(ev.getActionCommand())) SelectFile(); - else if ("Download".equals(ev.getActionCommand())) - DownloadData(); - else if ("Export".equals(ev.getActionCommand())) + else if (save_command.equals(ev.getActionCommand())) + Save(); + else if (export_command.equals(ev.getActionCommand())) Export(); - else if ("Preferences".equals(ev.getActionCommand())) + else if (preferences_command.equals(ev.getActionCommand())) Preferences(); - else if ("Save a Copy".equals(ev.getActionCommand())) - Save(); + else if (close_command.equals(ev.getActionCommand())) + Close(); + else if (exit_command.equals(ev.getActionCommand())) + System.exit(0); + else if (download_command.equals(ev.getActionCommand())) + DownloadData(); } public void itemStateChanged(ItemEvent e) { @@ -225,6 +247,29 @@ public class MicroPeak extends MicroFrame implements ActionListener, ItemListene return 1.0; } + private void add_menu(JMenu menu, String label, String action) { + JMenuItem item = new JMenuItem(label); + menu.add(item); + item.addActionListener(this); + item.setActionCommand(action); + } + + + private JMenu make_menu(String label, String[][] items) { + JMenu menu = new JMenu(label); + for (int i = 0; i < items.length; i++) { + if (MAC_OS_X) { + if (items[i][1].equals("exit")) + continue; + if (items[i][1].equals("preferences")) + continue; + } + add_menu(menu, items[i][0], items[i][1]); + } + menu_bar.add(menu); + return menu; + } + public MicroPeak() { ++number_of_windows; @@ -238,43 +283,15 @@ public class MicroPeak extends MicroFrame implements ActionListener, ItemListene setTitle("MicroPeak"); - JMenuBar menuBar = new JMenuBar(); - setJMenuBar(menuBar); - - JMenu fileMenu = new JMenu("File"); - menuBar.add(fileMenu); - - JMenuItem openAction = new JMenuItem("Open"); - fileMenu.add(openAction); - openAction.addActionListener(this); - - JMenuItem downloadAction = new JMenuItem("Download"); - fileMenu.add(downloadAction); - downloadAction.addActionListener(this); - - JMenuItem saveAction = new JMenuItem("Save a Copy"); - fileMenu.add(saveAction); - saveAction.addActionListener(this); - - JMenuItem exportAction = new JMenuItem("Export"); - fileMenu.add(exportAction); - exportAction.addActionListener(this); - - JMenuItem preferencesAction = new JMenuItem("Preferences"); - fileMenu.add(preferencesAction); - preferencesAction.addActionListener(this); - - JMenuItem closeAction = new JMenuItem("Close"); - fileMenu.add(closeAction); - closeAction.addActionListener(this); + menu_bar = new JMenuBar(); + setJMenuBar(menu_bar); - JMenuItem exitAction = new JMenuItem("Exit"); - fileMenu.add(exitAction); - exitAction.addActionListener(this); + JMenu file_menu = make_menu("File", file_menu_entries); - JButton downloadButton = new JButton ("Download"); - downloadButton.addActionListener(this); - menuBar.add(downloadButton); + JButton download_button = new JButton (download_label); + download_button.setActionCommand(download_command); + download_button.addActionListener(this); + menu_bar.add(download_button); setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE); addWindowListener(new WindowAdapter() { @@ -303,12 +320,7 @@ public class MicroPeak extends MicroFrame implements ActionListener, ItemListene container.validate(); doLayout(); validate(); - Insets i = getInsets(); - Dimension ps = pane.getPreferredSize(); - ps.width += i.left + i.right; - ps.height += i.top + i.bottom; -// setPreferredSize(ps); - setSize(ps); + pack(); setVisible(true); } diff --git a/micropeak/MicroSave.java b/micropeak/MicroSave.java index b45cd834..f6e2ed2a 100644 --- a/micropeak/MicroSave.java +++ b/micropeak/MicroSave.java @@ -72,7 +72,7 @@ public class MicroSave extends JFileChooser { JOptionPane.YES_NO_OPTION); if (r != JOptionPane.YES_OPTION) continue; - + if (!file.canWrite()) { JOptionPane.showMessageDialog(frame, String.format("\"%s\" is not writable", @@ -104,6 +104,6 @@ public class MicroSave extends JFileChooser { setFileFilter(new FileNameExtensionFilter("MicroPeak data file", "mpd")); setCurrentDirectory(AltosUIPreferences.last_logdir()); - setSelectedFile(MicroFile.make()); + setSelectedFile(MicroFile.make(data)); } } diff --git a/micropeak/MicroSerial.java b/micropeak/MicroSerial.java index 57fb30db..c6882428 100644 --- a/micropeak/MicroSerial.java +++ b/micropeak/MicroSerial.java @@ -28,6 +28,8 @@ public class MicroSerial extends InputStream { private MicroSerialLog log; public int read() { + if (file == null) + return -1; int c = libaltos.altos_getchar(file, 0); if (Thread.interrupted()) return -1; @@ -40,6 +42,14 @@ public class MicroSerial extends InputStream { return c; } + public void write(char c) { + libaltos.altos_putchar(file, c); + } + + public void flush() { + libaltos.altos_flush(file); + } + public void close() { if (file != null) { libaltos.altos_close(file); diff --git a/src/Makefile b/src/Makefile index 7d683d8c..3443ec8a 100644 --- a/src/Makefile +++ b/src/Makefile @@ -49,7 +49,7 @@ ARMM0DIRS=\ chaoskey-v1.0 chaoskey-v1.0/flash-loader \ telemini-v3.0 telemini-v3.0/flash-loader \ easymini-v2.0 easymini-v2.0/flash-loader \ - micropeak-v2.0 micropeak-v2.0/flash-loader + micropeak-v2.0 AVRDIRS=\ micropeak microkite microsplash diff --git a/src/attiny/ao_arch.h b/src/attiny/ao_arch.h index 5550eb44..1a2bd34b 100644 --- a/src/attiny/ao_arch.h +++ b/src/attiny/ao_arch.h @@ -73,11 +73,8 @@ #define ao_arch_block_interrupts() cli() #define ao_arch_release_interrupts() sei() -#define ao_mutex_get(m) -#define ao_mutex_put(m) - void -ao_delay_until(uint16_t target); +ao_delay_until(AO_TICK_TYPE target); /* We can't hit 100 Hz, but we can hit 125 */ #define AO_HERTZ 125 diff --git a/src/attiny/ao_arch_funcs.h b/src/attiny/ao_arch_funcs.h index 69b259d9..e51f456b 100644 --- a/src/attiny/ao_arch_funcs.h +++ b/src/attiny/ao_arch_funcs.h @@ -121,3 +121,5 @@ extern void ao_report_altitude(void); void ao_delay_us(uint16_t us); +void +ao_led_toggle(uint8_t colors); diff --git a/src/attiny/ao_clock.c b/src/attiny/ao_clock.c index 2ac0500b..06695850 100644 --- a/src/attiny/ao_clock.c +++ b/src/attiny/ao_clock.c @@ -31,7 +31,7 @@ ISR(TIMER1_COMPA_vect) AO_TICK_TYPE ao_time(void) { - uint16_t r; + AO_TICK_TYPE r; cli(); r = ao_tick_count; @@ -127,7 +127,7 @@ void ao_delay_us(uint16_t us) } void -ao_delay_until(uint16_t target) +ao_delay_until(AO_TICK_TYPE target) { cli(); ao_wakeup_count = target; @@ -137,7 +137,7 @@ ao_delay_until(uint16_t target) } void -ao_delay(uint16_t ticks) +ao_delay(AO_TICK_TYPE ticks) { ao_delay_until(ao_time() + ticks); } diff --git a/src/avr/ao_arch.h b/src/avr/ao_arch.h index d3454f91..a8fa8583 100644 --- a/src/avr/ao_arch.h +++ b/src/avr/ao_arch.h @@ -78,9 +78,8 @@ extern uint8_t ao_cpu_sleep_disable; #define ao_arch_task_globals uint8_t ao_cpu_sleep_disable; -#define ao_arch_init_stack(task, start) \ +#define ao_arch_init_stack(task, sp, start) \ do { \ - uint8_t *sp = task->stack8 + AO_STACK_SIZE - 1; \ uint16_t a = (uint16_t) start; \ int i; \ \ diff --git a/src/cortexelf-v1/ao_pins.h b/src/cortexelf-v1/ao_pins.h index c2bbf2d2..2a94d968 100644 --- a/src/cortexelf-v1/ao_pins.h +++ b/src/cortexelf-v1/ao_pins.h @@ -19,7 +19,6 @@ #ifndef _AO_PINS_H_ #define _AO_PINS_H_ -#define HAS_TASK_QUEUE 1 /* 8MHz High speed external crystal */ #define AO_HSE 8000000 diff --git a/src/drivers/ao_adxl375.c b/src/drivers/ao_adxl375.c index dca2213b..c7cf78af 100644 --- a/src/drivers/ao_adxl375.c +++ b/src/drivers/ao_adxl375.c @@ -26,6 +26,8 @@ #define PRINTD(l,...) #endif +#define AO_ADXL375_SPI_SPEED ao_spi_speed(5000000) + struct ao_adxl375_sample ao_adxl375_current; static void diff --git a/src/drivers/ao_bmx160.c b/src/drivers/ao_bmx160.c index c3922b60..427a081b 100644 --- a/src/drivers/ao_bmx160.c +++ b/src/drivers/ao_bmx160.c @@ -24,7 +24,9 @@ static uint8_t ao_bmx160_configured; static struct ao_bmm150_trim ao_bmm150_trim; -#define ao_bmx160_spi_get() ao_spi_get(AO_BMX160_SPI_BUS, AO_SPI_SPEED_8MHz) +#define AO_BMX160_SPI_SPEED ao_spi_speed(10000000) + +#define ao_bmx160_spi_get() ao_spi_get(AO_BMX160_SPI_BUS, AO_BMX160_SPI_SPEED) #define ao_bmx160_spi_put() ao_spi_put(AO_BMX160_SPI_BUS) #define ao_bmx160_spi_start() ao_spi_set_cs(AO_BMX160_SPI_CS_PORT, \ diff --git a/src/drivers/ao_cc1120.c b/src/drivers/ao_cc1120.c index b1a13778..1ebc0ea2 100644 --- a/src/drivers/ao_cc1120.c +++ b/src/drivers/ao_cc1120.c @@ -42,8 +42,10 @@ extern const uint32_t ao_radio_cal; #define FOSC 32000000 -#define ao_radio_try_select(task_id) ao_spi_try_get_mask(AO_CC1120_SPI_CS_PORT,(1 << AO_CC1120_SPI_CS_PIN),AO_CC1120_SPI_BUS,AO_SPI_SPEED_4MHz, task_id) -#define ao_radio_select() ao_spi_get_mask(AO_CC1120_SPI_CS_PORT,(1 << AO_CC1120_SPI_CS_PIN),AO_CC1120_SPI_BUS,AO_SPI_SPEED_4MHz) +#define AO_CC1120_SPI_SPEED ao_spi_speed(6100000) /* 6.1MHz max with 32MHz osc */ + +#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_CC1120_SPI_SPEED, 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_CC1120_SPI_SPEED) #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_start_bytes() ao_spi_start_bytes(AO_CC1120_SPI_BUS) #define ao_radio_spi_stop_bytes() ao_spi_stop_bytes(AO_CC1120_SPI_BUS) diff --git a/src/drivers/ao_cc115l.c b/src/drivers/ao_cc115l.c index 2b5fd3fd..dc8e9ff3 100644 --- a/src/drivers/ao_cc115l.c +++ b/src/drivers/ao_cc115l.c @@ -39,6 +39,8 @@ static uint8_t ao_radio_abort; /* radio operation should abort */ #define FOSC 26000000 +#define AO_CC115L_SPI_SPEED ao_spi_speed(6500000) /* for back-to-back access */ + #define ao_radio_select() ao_spi_get_mask(AO_CC115L_SPI_CS_PORT,(1 << AO_CC115L_SPI_CS_PIN),AO_CC115L_SPI_BUS,AO_CC115L_SPI_SPEED) #define ao_radio_deselect() ao_spi_put_mask(AO_CC115L_SPI_CS_PORT,(1 << AO_CC115L_SPI_CS_PIN),AO_CC115L_SPI_BUS) #define ao_radio_spi_send(d,l) ao_spi_send((d), (l), AO_CC115L_SPI_BUS) diff --git a/src/drivers/ao_cc1200.c b/src/drivers/ao_cc1200.c index 105e0d50..3ccf121f 100644 --- a/src/drivers/ao_cc1200.c +++ b/src/drivers/ao_cc1200.c @@ -51,9 +51,7 @@ extern const uint32_t ao_radio_cal; #define FOSC 40000000 #endif -#ifndef AO_CC1200_SPI_SPEED -#error AO_CC1200_SPI_SPEED undefined -#endif +#define AO_CC1200_SPI_SPEED ao_spi_speed(7700000) /* 7.7MHz max for extended memory reads */ #define ao_radio_select() ao_spi_get_mask(AO_CC1200_SPI_CS_PORT,(1 << AO_CC1200_SPI_CS_PIN),AO_CC1200_SPI_BUS,AO_CC1200_SPI_SPEED) #define ao_radio_deselect() ao_spi_put_mask(AO_CC1200_SPI_CS_PORT,(1 << AO_CC1200_SPI_CS_PIN),AO_CC1200_SPI_BUS) diff --git a/src/drivers/ao_companion.c b/src/drivers/ao_companion.c index d6fbb6b7..093356a5 100644 --- a/src/drivers/ao_companion.c +++ b/src/drivers/ao_companion.c @@ -28,11 +28,13 @@ #error HAS_COMPANION not set in ao_companion.c #endif +#define AO_COMPANION_SPI_SPEED ao_spi_speed(200000) + #define COMPANION_SELECT() do { \ ao_spi_get_bit(AO_COMPANION_CS_PORT, \ AO_COMPANION_CS_PIN, \ AO_COMPANION_SPI_BUS, \ - AO_SPI_SPEED_200kHz); \ + AO_COMPANION_SPI_SPEED); \ } while (0) #define COMPANION_DESELECT() do { \ diff --git a/src/drivers/ao_led.c b/src/drivers/ao_led.c index 899bee74..b32034e7 100644 --- a/src/drivers/ao_led.c +++ b/src/drivers/ao_led.c @@ -147,15 +147,6 @@ ao_led_set(AO_LED_TYPE colors) ao_gpio_set(ao_leds[i].port, ao_leds[i].pin, (colors >> i) & 1); } -void -ao_led_toggle(AO_LED_TYPE colors) -{ - AO_LED_TYPE i; - for (i = 0; i < N_LED; i++) - if (colors & (1 << i)) - ao_gpio_set(ao_leds[i].port, ao_leds[i].pin, ~ao_gpio_get(ao_leds[i].port, ao_leds[i].pin)); -} - void ao_led_for(AO_LED_TYPE colors, AO_TICK_TYPE ticks) { diff --git a/src/drivers/ao_m25.c b/src/drivers/ao_m25.c index ca0615e7..2e4cbedf 100644 --- a/src/drivers/ao_m25.c +++ b/src/drivers/ao_m25.c @@ -82,11 +82,11 @@ uint16_t ao_storage_unit; */ #if M25_MAX_CHIPS > 1 -static uint8_t ao_m25_size[M25_MAX_CHIPS]; /* number of sectors in each chip */ +static uint32_t ao_m25_size[M25_MAX_CHIPS]; /* number of sectors in each chip */ static ao_port_t ao_m25_pin[M25_MAX_CHIPS]; /* chip select pin for each chip */ static uint8_t ao_m25_numchips; /* number of chips detected */ #endif -static uint8_t ao_m25_total; /* total sectors available */ +static uint32_t ao_m25_total; /* total sectors available */ static ao_port_t ao_m25_wip; /* write in progress */ static uint8_t ao_m25_mutex; @@ -101,12 +101,14 @@ static uint8_t ao_m25_mutex; static uint8_t ao_m25_instruction[4]; -#define M25_SELECT(cs) ao_spi_get_mask(AO_M25_SPI_CS_PORT,cs,AO_M25_SPI_BUS, AO_SPI_SPEED_FAST) +#define AO_M25_SPI_SPEED ao_spi_speed(10000000) /* this seems like a reasonable minimum speed to require */ + +#define M25_SELECT(cs) ao_spi_get_mask(AO_M25_SPI_CS_PORT,cs,AO_M25_SPI_BUS,AO_M25_SPI_SPEED) #define M25_DESELECT(cs) ao_spi_put_mask(AO_M25_SPI_CS_PORT,cs,AO_M25_SPI_BUS) #define M25_BLOCK_SHIFT 16 #define M25_BLOCK 65536L -#define M25_POS_TO_SECTOR(pos) ((uint8_t) ((pos) >> M25_BLOCK_SHIFT)) +#define M25_POS_TO_SECTOR(pos) ((uint32_t) ((pos) >> M25_BLOCK_SHIFT)) #define M25_SECTOR_TO_POS(sector) (((uint32_t) (sector)) << M25_BLOCK_SHIFT) /* @@ -146,7 +148,7 @@ ao_m25_write_enable(ao_port_t cs) /* * Returns the number of 64kB sectors */ -static uint8_t +static uint32_t ao_m25_read_capacity(ao_port_t cs) { uint8_t capacity; @@ -172,7 +174,7 @@ ao_m25_set_address(uint32_t pos) { ao_port_t mask; #if M25_MAX_CHIPS > 1 - uint8_t size; + uint32_t size; uint8_t chip; for (chip = 0; chip < ao_m25_numchips; chip++) { @@ -204,7 +206,8 @@ static uint8_t ao_m25_scan(void) { #if M25_MAX_CHIPS > 1 - uint8_t pin, size; + uint8_t pin; + uint32_t size; #endif if (ao_m25_total) @@ -344,12 +347,12 @@ ao_storage_device_info(void) ao_mutex_put(&ao_m25_mutex); #if M25_MAX_CHIPS > 1 - printf ("Detected chips %d size %d\n", ao_m25_numchips, ao_m25_total); + printf ("Detected chips %d size %ld\n", ao_m25_numchips, ao_m25_total); for (chip = 0; chip < ao_m25_numchips; chip++) printf ("Flash chip %d select %02x size %d\n", chip, ao_m25_pin[chip], ao_m25_size[chip]); #else - printf ("Detected chips 1 size %d\n", ao_m25_total); + printf ("Detected chips 1 size %ld\n", ao_m25_total); #endif #if M25_DEBUG diff --git a/src/drivers/ao_mma655x.c b/src/drivers/ao_mma655x.c index 4c24e98b..7736a0f8 100644 --- a/src/drivers/ao_mma655x.c +++ b/src/drivers/ao_mma655x.c @@ -30,12 +30,14 @@ #define PRINTD(l,...) #endif +#define AO_MMA655X_SPI_SPEED ao_spi_speed(8333333) /* 120ns clock period */ + static void ao_mma655x_start(void) { ao_spi_get_bit(AO_MMA655X_CS_PORT, AO_MMA655X_CS_PIN, AO_MMA655X_SPI_INDEX, - AO_SPI_SPEED_FAST); + AO_MMA655X_SPI_SPEED); } static void diff --git a/src/drivers/ao_mpu6000.c b/src/drivers/ao_mpu6000.c index c894239e..7c9d6b6b 100644 --- a/src/drivers/ao_mpu6000.c +++ b/src/drivers/ao_mpu6000.c @@ -32,7 +32,9 @@ static uint8_t ao_mpu6000_configured; #if AO_MPU6000_SPI -#define ao_mpu6000_spi_get() ao_spi_get(AO_MPU6000_SPI_BUS, AO_SPI_SPEED_1MHz) +#define AO_MPU6000_SPI_SPEED ao_spi_speed(1000000) /* 1Mhz for all register access */ + +#define ao_mpu6000_spi_get() ao_spi_get(AO_MPU6000_SPI_BUS, AO_MPU6000_SPI_SPEED) #define ao_mpu6000_spi_put() ao_spi_put(AO_MPU6000_SPI_BUS) #define ao_mpu6000_spi_start() ao_spi_set_cs(AO_MPU6000_SPI_CS_PORT, \ @@ -383,7 +385,7 @@ ao_mpu6000_init(void) */ ao_cur_task = &ao_mpu6000_task; - ao_spi_get(AO_MPU6000_SPI_BUS, AO_SPI_SPEED_1MHz); + ao_mpu6000_spi_get(); ao_cur_task = NULL; #endif diff --git a/src/drivers/ao_mpu9250.c b/src/drivers/ao_mpu9250.c index 0597a81c..09b65bfa 100644 --- a/src/drivers/ao_mpu9250.c +++ b/src/drivers/ao_mpu9250.c @@ -35,7 +35,7 @@ static uint8_t ao_mpu9250_configured; #if AO_MPU9250_SPI #ifndef AO_MPU9250_SPI_SPEED -#define AO_MPU9250_SPI_SPEED AO_SPI_SPEED_1MHz +#define AO_MPU9250_SPI_SPEED ao_spi_speed(1000000) /* 1MHz max SCLK */ #endif #define ao_mpu9250_spi_get() ao_spi_get(AO_MPU9250_SPI_BUS, AO_MPU9250_SPI_SPEED) diff --git a/src/drivers/ao_ms5607.c b/src/drivers/ao_ms5607.c index 1ebba3e9..c5e733a4 100644 --- a/src/drivers/ao_ms5607.c +++ b/src/drivers/ao_ms5607.c @@ -25,9 +25,7 @@ struct ao_ms5607_prom ao_ms5607_prom; static uint8_t ms5607_configured; -#ifndef AO_MS5607_SPI_SPEED -#define AO_MS5607_SPI_SPEED AO_SPI_SPEED_FAST -#endif +#define AO_MS5607_SPI_SPEED ao_spi_speed(20000000) static void ao_ms5607_start(void) { diff --git a/src/drivers/ao_rn4678.c b/src/drivers/ao_rn4678.c index 4d13decc..3983dc94 100644 --- a/src/drivers/ao_rn4678.c +++ b/src/drivers/ao_rn4678.c @@ -350,11 +350,10 @@ ao_bt_panic(int where) { int i; for (;;) { - for (i = 0; i < 50; i++) { - ao_led_toggle(AO_BT_LED); + for (i = 0; i < 25; i++) { + ao_led_for(AO_BT_LED, AO_MS_TO_TICKS(10)); ao_delay(AO_MS_TO_TICKS(10)); } - ao_led_off(AO_BT_LED); ao_delay(AO_MS_TO_TICKS(500)); for (i = 0; i < where; i++) { ao_led_for(AO_BT_LED, AO_MS_TO_TICKS(200)); @@ -548,7 +547,10 @@ ao_rn_factory(void) v = 1-v; ao_delay(AO_MS_TO_TICKS(50)); ao_gpio_set(AO_RN_P3_1_PORT, AO_RN_P3_1_PIN, v); - ao_led_toggle(AO_BT_LED); + if (v) + ao_led_on(AO_BT_LED); + else + ao_led_off(AO_BT_LED); } /* And let P3_1 float again */ diff --git a/src/easymega-v1.0/ao_pins.h b/src/easymega-v1.0/ao_pins.h index bfa777c6..d16843d6 100644 --- a/src/easymega-v1.0/ao_pins.h +++ b/src/easymega-v1.0/ao_pins.h @@ -19,7 +19,6 @@ #ifndef _AO_PINS_H_ #define _AO_PINS_H_ -#define HAS_TASK_QUEUE 1 /* 8MHz High speed external crystal */ #define AO_HSE 8000000 diff --git a/src/easymega-v2.0/ao_pins.h b/src/easymega-v2.0/ao_pins.h index 399654f0..a3d04da5 100644 --- a/src/easymega-v2.0/ao_pins.h +++ b/src/easymega-v2.0/ao_pins.h @@ -19,7 +19,6 @@ #ifndef _AO_PINS_H_ #define _AO_PINS_H_ -#define HAS_TASK_QUEUE 1 /* 16MHz High speed external crystal */ #define AO_HSE 16000000 @@ -324,7 +323,6 @@ struct ao_adc { #define AO_ADXL375_SPI_INDEX (AO_SPI_1_PB3_PB4_PB5 | AO_SPI_MODE_3) #define AO_ADXL375_CS_PORT (&stm_gpioc) #define AO_ADXL375_CS_PIN 12 -#define AO_ADXL375_SPI_SPEED AO_SPI_SPEED_4MHz #define AO_ADXL375_INT1_PORT (&stm_gpiob) #define AO_ADXL375_INT1_PIN 8 diff --git a/src/easymega-v3.0/ao_pins.h b/src/easymega-v3.0/ao_pins.h index fa810fda..863909d5 100644 --- a/src/easymega-v3.0/ao_pins.h +++ b/src/easymega-v3.0/ao_pins.h @@ -19,7 +19,6 @@ #ifndef _AO_PINS_H_ #define _AO_PINS_H_ -#define HAS_TASK_QUEUE 1 /* 16MHz High speed external crystal */ #define AO_HSE 16000000 @@ -324,7 +323,6 @@ struct ao_adc { #define AO_ADXL375_SPI_INDEX (AO_SPI_1_PB3_PB4_PB5 | AO_SPI_MODE_3) #define AO_ADXL375_CS_PORT (&stm_gpioc) #define AO_ADXL375_CS_PIN 12 -#define AO_ADXL375_SPI_SPEED AO_SPI_SPEED_4MHz #define AO_ADXL375_INT1_PORT (&stm_gpiob) #define AO_ADXL375_INT1_PIN 8 diff --git a/src/easymini-v1.0/ao_pins.h b/src/easymini-v1.0/ao_pins.h index 201b913e..ef8cba2d 100644 --- a/src/easymini-v1.0/ao_pins.h +++ b/src/easymini-v1.0/ao_pins.h @@ -19,7 +19,9 @@ #define HAS_BEEP 1 #define HAS_BATTERY_REPORT 1 -#define AO_STACK_SIZE 376 +#define AO_STACK_SIZE 360 +#define SLEEP_HASH_SIZE 3 +#define AO_NUM_TASKS 6 #define IS_FLASH_LOADER 0 @@ -93,6 +95,7 @@ #define USE_INTERNAL_FLASH 0 #define HAS_IGNITE 1 #define HAS_IGNITE_REPORT 1 +#define SLEEP_HASH_SIZE 3 #define AO_DATA_RING 16 diff --git a/src/easymini-v2.0/ao_pins.h b/src/easymini-v2.0/ao_pins.h index 38d46310..ba5749e9 100644 --- a/src/easymini-v2.0/ao_pins.h +++ b/src/easymini-v2.0/ao_pins.h @@ -93,7 +93,6 @@ #define AO_MS5607_MISO_PIN 6 #define AO_MS5607_MISO_MASK (1 << AO_MS5607_MISO_PIN) #define AO_MS5607_SPI_INDEX AO_SPI_1_PA5_PA6_PA7 -#define AO_MS5607_SPI_SPEED AO_SPI_SPEED_12MHz #define AO_DATA_RING 64 diff --git a/src/easytimer-v1/ao_pins.h b/src/easytimer-v1/ao_pins.h index 3ceb49f3..1169a283 100644 --- a/src/easytimer-v1/ao_pins.h +++ b/src/easytimer-v1/ao_pins.h @@ -19,7 +19,6 @@ #ifndef _AO_PINS_H_ #define _AO_PINS_H_ -#define HAS_TASK_QUEUE 1 /* 16MHz High speed external crystal */ #define AO_HSE 16000000 diff --git a/src/fox1ihu/ao_pins.h b/src/fox1ihu/ao_pins.h index b5dd7283..34fdefe6 100644 --- a/src/fox1ihu/ao_pins.h +++ b/src/fox1ihu/ao_pins.h @@ -18,7 +18,6 @@ #ifndef _AO_PINS_H_ #define _AO_PINS_H_ -#define HAS_TASK_QUEUE 1 /* 8MHz High speed external crystal */ #define AO_HSE 8000000 diff --git a/src/kernel/ao.h b/src/kernel/ao.h index fb7af24d..5df4903c 100644 --- a/src/kernel/ao.h +++ b/src/kernel/ao.h @@ -42,6 +42,11 @@ extern char ao_getchar(void); typedef AO_PORT_TYPE ao_port_t; +#ifndef AO_TICK_TYPE +#define AO_TICK_TYPE uint32_t +#define AO_TICK_SIGNED int32_t +#endif + #if HAS_TASK #include #else @@ -81,7 +86,7 @@ typedef AO_PORT_TYPE ao_port_t; /* Stop the operating system, beeping and blinking the reason */ void -ao_panic(uint8_t reason); +ao_panic(uint8_t reason) __attribute__((noreturn)); /* * ao_romconfig.c @@ -100,11 +105,6 @@ extern AO_ROMCONFIG_SYMBOL uint32_t ao_radio_cal; * ao_timer.c */ -#ifndef AO_TICK_TYPE -#define AO_TICK_TYPE uint32_t -#define AO_TICK_SIGNED int32_t -#endif - extern volatile AO_TICK_TYPE ao_tick_count; /* Our timer runs at 100Hz */ @@ -124,7 +124,7 @@ ao_time_ns(void); /* Suspend the current task until ticks time has passed */ void -ao_delay(uint16_t ticks); +ao_delay(AO_TICK_TYPE ticks); /* Set the ADC interval */ void @@ -749,9 +749,6 @@ enum ao_igniter { ao_igniter_main = 1 }; -void -ao_ignite(enum ao_igniter igniter); - enum ao_igniter_status { ao_igniter_unknown, /* unknown status (ambiguous voltage) */ ao_igniter_ready, /* continuity detected */ diff --git a/src/kernel/ao_beep.h b/src/kernel/ao_beep.h index fdc150f1..8c5d5343 100644 --- a/src/kernel/ao_beep.h +++ b/src/kernel/ao_beep.h @@ -85,7 +85,7 @@ ao_beep(uint8_t beep); /* Turn on the beeper for the specified time */ void -ao_beep_for(uint8_t beep, uint16_t ticks); +ao_beep_for(uint8_t beep, AO_TICK_TYPE ticks); /* Initialize the beeper */ void diff --git a/src/kernel/ao_config.c b/src/kernel/ao_config.c index 217b0ab1..24eb79d9 100644 --- a/src/kernel/ao_config.c +++ b/src/kernel/ao_config.c @@ -1039,7 +1039,7 @@ const struct ao_config_var ao_config_vars[] = { ao_config_log_set, ao_config_log_show }, #endif #if HAS_IGNITE - { "i <0 dual, 1 apogee, 2 main>\0Igniter mode", + { "i <0 dual, 1 apogee, 2 main, 3 booster>\0Igniter mode", ao_config_ignite_mode_set, ao_config_ignite_mode_show }, #endif #if HAS_AES diff --git a/src/kernel/ao_config.h b/src/kernel/ao_config.h index 87509dff..3cfd0d07 100644 --- a/src/kernel/ao_config.h +++ b/src/kernel/ao_config.h @@ -139,6 +139,7 @@ extern uint32_t ao_send_radio_setting; #define AO_IGNITE_MODE_DUAL 0 #define AO_IGNITE_MODE_APOGEE 1 #define AO_IGNITE_MODE_MAIN 2 +#define AO_IGNITE_MODE_BOOSTER 3 #define AO_RADIO_ENABLE_CORE 1 #define AO_RADIO_DISABLE_TELEMETRY 2 diff --git a/src/kernel/ao_flight.c b/src/kernel/ao_flight.c index c5069158..2142546c 100644 --- a/src/kernel/ao_flight.c +++ b/src/kernel/ao_flight.c @@ -222,6 +222,8 @@ ao_flight(void) ) { ao_flight_state = ao_flight_boost; + ao_wakeup(&ao_flight_state); + ao_launch_tick = ao_boost_tick = ao_sample_tick; /* start logging data */ @@ -242,8 +244,6 @@ ao_flight(void) ao_gps_new = AO_GPS_NEW_DATA | AO_GPS_NEW_TRACKING; ao_wakeup(&ao_gps_new); #endif - - ao_wakeup(&ao_flight_state); } break; case ao_flight_boost: @@ -278,8 +278,8 @@ ao_flight(void) #else ao_flight_state = ao_flight_coast; #endif - ++ao_motor_number; ao_wakeup(&ao_flight_state); + ++ao_motor_number; } break; #if HAS_ACCEL && HAS_BARO @@ -327,11 +327,9 @@ ao_flight(void) #endif ) { -#if HAS_IGNITE - /* ignite the drogue charge */ - ao_ignite(ao_igniter_drogue); -#endif - + /* enter drogue state */ + ao_flight_state = ao_flight_drogue; + ao_wakeup(&ao_flight_state); #if HAS_TELEMETRY /* slow down the telemetry system */ ao_telemetry_set_interval(AO_TELEMETRY_INTERVAL_RECOVER); @@ -339,10 +337,6 @@ ao_flight(void) /* Turn the RDF beacon back on */ ao_rdf_set(1); #endif - - /* and enter drogue state */ - ao_flight_state = ao_flight_drogue; - ao_wakeup(&ao_flight_state); } else #else /* not HAS_BARO */ @@ -362,12 +356,11 @@ ao_flight(void) ao_interval_max_accel_through - ao_interval_min_accel_through <= ao_data_accel_to_sample(MAX_QUIET_ACCEL)) { ao_flight_state = ao_flight_landed; + ao_wakeup(&ao_flight_state); #if HAS_ADC /* turn off the ADC capture */ ao_timer_set_adc_interval(0); #endif - - ao_wakeup(&ao_flight_state); } /* Reset interval values */ @@ -410,9 +403,8 @@ ao_flight(void) */ if (ao_height <= ao_config.main_deploy) { -#if HAS_IGNITE - ao_ignite(ao_igniter_main); -#endif + ao_flight_state = ao_flight_main; + ao_wakeup(&ao_flight_state); /* * Start recording min/max height @@ -423,9 +415,6 @@ ao_flight(void) ao_interval_end = ao_sample_tick + AO_INTERVAL_TICKS; ao_interval_min_height = ao_interval_max_height = ao_avg_height; - - ao_flight_state = ao_flight_main; - ao_wakeup(&ao_flight_state); } break; @@ -445,13 +434,11 @@ ao_flight(void) if (ao_interval_max_height - ao_interval_min_height <= AO_M_TO_HEIGHT(4)) { ao_flight_state = ao_flight_landed; - + ao_wakeup(&ao_flight_state); #if HAS_ADC /* turn off the ADC capture */ ao_timer_set_adc_interval(0); #endif - - ao_wakeup(&ao_flight_state); } ao_interval_min_height = ao_interval_max_height = ao_avg_height; ao_interval_end = ao_sample_tick + AO_INTERVAL_TICKS; diff --git a/src/kernel/ao_ignite.c b/src/kernel/ao_ignite.c index 71c99a61..e4e4843e 100644 --- a/src/kernel/ao_ignite.c +++ b/src/kernel/ao_ignite.c @@ -25,15 +25,6 @@ #if HAS_IGNITE struct ao_ignition ao_ignition[2]; -void -ao_ignite(enum ao_igniter igniter) -{ - ao_arch_block_interrupts(); - ao_ignition[igniter].request = 1; - ao_wakeup(&ao_ignition); - ao_arch_release_interrupts(); -} - #ifndef AO_SENSE_DROGUE #define AO_SENSE_DROGUE(p) ((p)->adc.sense_d) #define AO_SENSE_MAIN(p) ((p)->adc.sense_m) @@ -86,9 +77,9 @@ ao_igniter_status(enum ao_igniter igniter) static void ao_igniter_fire(enum ao_igniter igniter) { - ao_ignition[igniter].firing = 1; - switch(ao_config.ignite_mode) { - case AO_IGNITE_MODE_DUAL: + if (!ao_ignition[igniter].fired) { + ao_ignition[igniter].firing = 1; + ao_ignition[igniter].fired = 1; switch (igniter) { case ao_igniter_drogue: AO_IGNITER_SET_DROGUE(1); @@ -101,58 +92,47 @@ ao_igniter_fire(enum ao_igniter igniter) AO_IGNITER_SET_MAIN(0); break; } - break; - case AO_IGNITE_MODE_APOGEE: - switch (igniter) { - case ao_igniter_drogue: - AO_IGNITER_SET_DROGUE(1); - ao_delay(AO_IGNITER_FIRE_TIME); - AO_IGNITER_SET_DROGUE(0); - ao_delay(AO_IGNITER_CHARGE_TIME); - AO_IGNITER_SET_MAIN(1); - ao_delay(AO_IGNITER_FIRE_TIME); - AO_IGNITER_SET_MAIN(0); - break; - default: - break; - } - break; - case AO_IGNITE_MODE_MAIN: - switch (igniter) { - case ao_igniter_main: - AO_IGNITER_SET_DROGUE(1); - ao_delay(AO_IGNITER_FIRE_TIME); - AO_IGNITER_SET_DROGUE(0); - ao_delay(AO_IGNITER_CHARGE_TIME); - AO_IGNITER_SET_MAIN(1); - ao_delay(AO_IGNITER_FIRE_TIME); - AO_IGNITER_SET_MAIN(0); - break; - default: - break; - } - break; + ao_ignition[igniter].firing = 0; + ao_delay(AO_IGNITER_CHARGE_TIME); } - ao_ignition[igniter].firing = 0; } static void ao_igniter(void) { - enum ao_igniter igniter; - ao_config_get(); for (;;) { - ao_sleep(&ao_ignition); - for (igniter = ao_igniter_drogue; igniter <= ao_igniter_main; igniter++) { - if (ao_ignition[igniter].request && !ao_ignition[igniter].fired) { - if (igniter == ao_igniter_drogue && ao_config.apogee_delay) - ao_delay(AO_SEC_TO_TICKS(ao_config.apogee_delay)); - - ao_igniter_fire(igniter); - ao_delay(AO_IGNITER_CHARGE_TIME); - ao_ignition[igniter].fired = 1; + /* Wait for flight state change */ + ao_sleep(&ao_flight_state); + + /* Fire any igniters that are supposed to be triggered + * in this new state + */ + switch(ao_config.ignite_mode) { + case AO_IGNITE_MODE_DUAL: + if (ao_flight_drogue <= ao_flight_state && ao_flight_state < ao_flight_landed) + ao_igniter_fire(ao_igniter_drogue); + if (ao_flight_main <= ao_flight_state && ao_flight_state < ao_flight_landed) + ao_igniter_fire(ao_igniter_main); + break; + case AO_IGNITE_MODE_APOGEE: + if (ao_flight_drogue <= ao_flight_state && ao_flight_state < ao_flight_landed) { + ao_igniter_fire(ao_igniter_drogue); + ao_igniter_fire(ao_igniter_main); } + break; + case AO_IGNITE_MODE_MAIN: + if (ao_flight_main <= ao_flight_state && ao_flight_state < ao_flight_landed) { + ao_igniter_fire(ao_igniter_drogue); + ao_igniter_fire(ao_igniter_main); + } + break; + case AO_IGNITE_MODE_BOOSTER: + if (ao_flight_fast <= ao_flight_state && ao_flight_state < ao_flight_landed) + ao_igniter_fire(ao_igniter_main); + if (ao_flight_drogue <= ao_flight_state && ao_flight_state < ao_flight_landed) + ao_igniter_fire(ao_igniter_drogue); + break; } } } @@ -168,10 +148,12 @@ ao_ignite_manual(void) ao_cmd_white(); #if HAS_IGNITE if (ao_cmd_lex_c == 'm' && ao_match_word("main")) { + ao_ignition[ao_igniter_main].fired = 0; ao_igniter_fire(ao_igniter_main); return; } if (ao_cmd_lex_c == 'd' && ao_match_word("drogue")) { + ao_ignition[ao_igniter_drogue].fired = 0; ao_igniter_fire(ao_igniter_drogue); return; } diff --git a/src/kernel/ao_led.h b/src/kernel/ao_led.h index b770381f..60c2d41f 100644 --- a/src/kernel/ao_led.h +++ b/src/kernel/ao_led.h @@ -45,10 +45,6 @@ ao_led_set(AO_LED_TYPE colors); void ao_led_set_mask(AO_LED_TYPE colors, AO_LED_TYPE mask); -/* Toggle the specified LEDs */ -void -ao_led_toggle(AO_LED_TYPE colors); - /* Turn on the specified LEDs for the indicated interval */ void ao_led_for(AO_LED_TYPE colors, AO_TICK_TYPE ticks); diff --git a/src/kernel/ao_log_micro.c b/src/kernel/ao_log_micro.c index d6f9c5a8..1cb03715 100644 --- a/src/kernel/ao_log_micro.c +++ b/src/kernel/ao_log_micro.c @@ -19,26 +19,24 @@ #include #include #include -#ifndef ao_async_byte +#ifndef LOG_MICRO_ASYNC +#define LOG_MICRO_ASYNC 1 +#endif +#if LOG_MICRO_ASYNC #include #else #include #endif #include -static uint16_t ao_log_offset = STARTING_LOG_OFFSET; +static N_SAMPLES_TYPE ao_log_offset = STARTING_LOG_OFFSET; -#define AO_LOG_ID_SHIFT 12 -#define AO_LOG_ID_MASK ((1 << AO_LOG_ID_SHIFT) - 1) void ao_log_micro_save(void) { - uint16_t n_samples = (ao_log_offset - STARTING_LOG_OFFSET) / sizeof (uint16_t); + N_SAMPLES_TYPE n_samples = (ao_log_offset - STARTING_LOG_OFFSET) / sizeof (uint16_t); -#if AO_LOG_ID - n_samples |= AO_LOG_ID << AO_LOG_ID_SHIFT; -#endif ao_eeprom_write(PA_GROUND_OFFSET, &pa_ground, sizeof (pa_ground)); ao_eeprom_write(PA_MIN_OFFSET, &pa_min, sizeof (pa_min)); ao_eeprom_write(N_SAMPLES_OFFSET, &n_samples, sizeof (n_samples)); @@ -88,24 +86,26 @@ ao_log_hex_nibble(uint8_t b) ao_async_byte('a' - 10 + b); } -static void +void ao_log_hex(uint8_t b) { ao_log_hex_nibble(b>>4); ao_log_hex_nibble(b&0xf); } -static void +void ao_log_newline(void) { ao_async_byte('\r'); ao_async_byte('\n'); } +#define MAX_N_SAMPLES ((MAX_LOG_OFFSET - STARTING_LOG_OFFSET) / 2) + void ao_log_micro_dump(void) { - uint16_t n_samples; + N_SAMPLES_TYPE n_samples; uint16_t nbytes; uint8_t byte; uint16_t b; @@ -113,12 +113,24 @@ ao_log_micro_dump(void) ao_eeprom_read(N_SAMPLES_OFFSET, &n_samples, sizeof (n_samples)); - if (n_samples == 0xffff) + if (n_samples == (N_SAMPLES_TYPE) (~0)) n_samples = 0; + nbytes = STARTING_LOG_OFFSET + sizeof (uint16_t) * n_samples; + + /* + * Rewrite n_samples so that it includes the log ID value with + * 32-bit n_samples split into two chunks + */ + if (sizeof (n_samples) > 2) { + N_SAMPLES_TYPE n_samples_low; + N_SAMPLES_TYPE n_samples_high; + n_samples_low = n_samples & ((1 << AO_LOG_ID_SHIFT) - 1); + n_samples_high = (n_samples - n_samples_low) << AO_LOG_ID_WIDTH; + n_samples = n_samples_low | n_samples_high; + } #if AO_LOG_ID - n_samples &= AO_LOG_ID_MASK; + n_samples |= AO_LOG_ID << AO_LOG_ID_SHIFT; #endif - nbytes = STARTING_LOG_OFFSET + sizeof (uint16_t) * n_samples; ao_async_start(); ao_async_byte('M'); ao_async_byte('P'); @@ -126,6 +138,11 @@ ao_log_micro_dump(void) if ((b & 0xf) == 0) ao_log_newline(); ao_eeprom_read(b, &byte, 1); +#if AO_LOG_ID + if (N_SAMPLES_OFFSET <= b && b < (N_SAMPLES_OFFSET + sizeof(n_samples))) { + byte = n_samples >> ((b - N_SAMPLES_OFFSET) << 3); + } +#endif ao_log_hex(byte); crc = ao_log_micro_crc(crc, byte); } diff --git a/src/kernel/ao_log_micro.h b/src/kernel/ao_log_micro.h index f0243028..f4870c71 100644 --- a/src/kernel/ao_log_micro.h +++ b/src/kernel/ao_log_micro.h @@ -19,14 +19,28 @@ #ifndef _AO_LOG_MICRO_H_ #define _AO_LOG_MICRO_H_ +#ifndef N_SAMPLES_TYPE +#define N_SAMPLES_TYPE uint16_t +#endif + #define PA_GROUND_OFFSET 0 #define PA_MIN_OFFSET 4 #define N_SAMPLES_OFFSET 8 -#define STARTING_LOG_OFFSET 10 +#define STARTING_LOG_OFFSET (N_SAMPLES_OFFSET + sizeof (N_SAMPLES_TYPE)) #ifndef MAX_LOG_OFFSET #define MAX_LOG_OFFSET 512 #endif +#define AO_LOG_ID_SHIFT 12 +#define AO_LOG_ID_WIDTH 4 +#define AO_LOG_ID_MASK (((1 << AO_LOG_ID_WIDTH) - 1) << AO_LOG_ID_SHIFT); + +void +ao_log_hex(uint8_t b); + +void +ao_log_newline(void); + void ao_log_micro_save(void); diff --git a/src/kernel/ao_notask.c b/src/kernel/ao_notask.c index a5bdc8a7..8c5743fd 100644 --- a/src/kernel/ao_notask.c +++ b/src/kernel/ao_notask.c @@ -41,17 +41,20 @@ ao_sleep(void *wchan) #if HAS_AO_DELAY void -ao_delay(uint16_t ticks) +ao_delay_until(AO_TICK_TYPE target) { - AO_TICK_TYPE target; - - if (!ticks) - ticks = 1; - target = ao_tick_count + ticks; - do { - ao_sleep(&ao_time); - } while ((int16_t) (target - ao_tick_count) > 0); + ao_arch_block_interrupts(); + while ((int16_t) (target - ao_tick_count) > 0) + ao_sleep((void *) &ao_tick_count); + ao_arch_release_interrupts(); } + +void +ao_delay(AO_TICK_TYPE ticks) +{ + ao_delay_until(ao_time() + ticks); +} + #endif void diff --git a/src/kernel/ao_notask.h b/src/kernel/ao_notask.h index ce622b63..f698a4ee 100644 --- a/src/kernel/ao_notask.h +++ b/src/kernel/ao_notask.h @@ -19,10 +19,16 @@ #ifndef _AO_NOTASK_H_ #define _AO_NOTASK_H_ +void +ao_delay_until(AO_TICK_TYPE target); + uint8_t ao_sleep(void *wchan); void ao_wakeup(void *wchan); +static inline void ao_mutex_get(uint8_t *m) {(void) m;} +static inline void ao_mutex_put(uint8_t *m) {(void) m;} + #endif /* _AO_NOTASK_H_ */ diff --git a/src/kernel/ao_pyro.c b/src/kernel/ao_pyro.c index 30d1518f..80e1980e 100644 --- a/src/kernel/ao_pyro.c +++ b/src/kernel/ao_pyro.c @@ -69,6 +69,7 @@ ao_pyro_print_status(void) #endif uint16_t ao_pyro_fired; +uint16_t ao_pyro_inhibited; #ifndef PYRO_DBG #define PYRO_DBG 0 @@ -274,9 +275,9 @@ ao_pyro_check(void) for (p = 0; p < AO_PYRO_NUM; p++) { pyro = &ao_config.pyro[p]; - /* Ignore igniters which have already fired + /* Ignore igniters which have already fired or inhibited */ - if (ao_pyro_fired & (1 << p)) + if ((ao_pyro_fired|ao_pyro_inhibited) & (1 << p)) continue; /* Ignore disabled igniters @@ -308,10 +309,10 @@ ao_pyro_check(void) /* Check to make sure the required conditions * remain valid. If not, inhibit the channel - * by setting the fired bit + * by setting the inhibited bit */ if (!ao_pyro_ready(pyro)) { - ao_pyro_fired |= (1 << p); + ao_pyro_inhibited |= (1 << p); continue; } diff --git a/src/kernel/ao_storage.c b/src/kernel/ao_storage.c index ca5fcb46..213ec2d6 100644 --- a/src/kernel/ao_storage.c +++ b/src/kernel/ao_storage.c @@ -22,6 +22,7 @@ #define AO_STORAGE_DATA_SIZE 128 static uint8_t storage_data[AO_STORAGE_DATA_SIZE]; +static uint8_t storage_mutex; uint8_t ao_storage_read(ao_pos_t pos, void *v_buf, uint16_t len) @@ -85,28 +86,41 @@ ao_storage_write(ao_pos_t pos, void *v_buf, uint16_t len) return 1; } +#ifndef AO_STORAGE_ERASED_BYTE +#define AO_STORAGE_ERASED_BYTE 0xff +#endif + uint8_t ao_storage_is_erased(uint32_t pos) { uint32_t read_pos; uint32_t read_len; uint32_t i; + uint8_t ret = 1; + ao_storage_setup(); + ao_mutex_get(&storage_mutex); read_pos = pos; read_len = ao_storage_block; while (read_len) { uint32_t this_time = AO_STORAGE_DATA_SIZE; if (this_time > read_len) this_time = read_len; - if (!ao_storage_read(read_pos, storage_data, this_time)) - return 0; + if (!ao_storage_read(read_pos, storage_data, this_time)) { + ret = 0; + goto done; + } for (i = 0; i < this_time; i++) - if (storage_data[i] != 0xff) - return 0; + if (storage_data[i] != AO_STORAGE_ERASED_BYTE) { + ret = 0; + goto done; + } read_pos += this_time; read_len -= this_time; } - return 1; +done: + ao_mutex_put(&storage_mutex); + return ret; } uint8_t @@ -144,25 +158,29 @@ static void ao_storage_dump(void) { uint32_t block; - uint8_t i, j; + uint8_t i, j, k; block = ao_cmd_hex(); if (ao_cmd_status != ao_cmd_success) return; - for (i = 0; ; i += 8) { + ao_mutex_get(&storage_mutex); + for (i = 0; ; i += AO_STORAGE_DATA_SIZE) { if (ao_storage_read((block << 8) + i, storage_data, - 8)) { - ao_cmd_put16((uint16_t) i); - for (j = 0; j < 8; j++) { - putchar(' '); - ao_cmd_put8(storage_data[j]); + AO_STORAGE_DATA_SIZE)) { + for (k = 0; k < AO_STORAGE_DATA_SIZE; k += 8) { + ao_cmd_put16((uint16_t) i + k); + for (j = 0; j < 8; j++) { + putchar(' '); + ao_cmd_put8(storage_data[k + j]); + } + putchar ('\n'); } - putchar ('\n'); } - if (i == 248) + if (i == 256 - AO_STORAGE_DATA_SIZE) break; } + ao_mutex_put(&storage_mutex); } #if HAS_STORAGE_DEBUG diff --git a/src/kernel/ao_storage.h b/src/kernel/ao_storage.h index 1c5867e0..026074b5 100644 --- a/src/kernel/ao_storage.h +++ b/src/kernel/ao_storage.h @@ -31,10 +31,14 @@ typedef ao_storage_pos_t ao_pos_t; /* Total bytes of available storage */ +#ifndef ao_storage_total extern ao_pos_t ao_storage_total; +#endif /* Block size - device is erased in these units. At least 256 bytes */ +#ifndef ao_storage_block extern ao_pos_t ao_storage_block; +#endif #ifndef USE_STORAGE_CONFIG #define USE_STORAGE_CONFIG 1 @@ -50,7 +54,9 @@ extern ao_pos_t ao_storage_config; #endif /* Storage unit size - device reads and writes must be within blocks of this size. Usually 256 bytes. */ +#ifndef ao_storage_unit extern uint16_t ao_storage_unit; +#endif /* Initialize above values. Can only be called once the OS is running */ void diff --git a/src/kernel/ao_task.c b/src/kernel/ao_task.c index 0bc85d40..dd278bde 100644 --- a/src/kernel/ao_task.c +++ b/src/kernel/ao_task.c @@ -24,19 +24,14 @@ #if HAS_STACK_GUARD #include #endif +#include #define DEBUG 0 -#define AO_NO_TASK_INDEX 0xff - struct ao_task * ao_tasks[AO_NUM_TASKS]; uint8_t ao_num_tasks; struct ao_task *ao_cur_task; -#if !HAS_TASK_QUEUE -static uint8_t ao_cur_task_index; -#endif - #ifdef ao_arch_task_globals ao_arch_task_globals #endif @@ -61,16 +56,16 @@ static inline void ao_check_stack(void) { #define ao_task_irq_check() #endif -#if HAS_TASK_QUEUE - +#ifndef SLEEP_HASH_SIZE #define SLEEP_HASH_SIZE 17 +#endif static struct ao_list run_queue; static struct ao_list alarm_queue; static struct ao_list ao_sleep_queue[SLEEP_HASH_SIZE]; static void -ao_task_to_run_queue(struct ao_task *task) +_ao_task_to_run_queue(struct ao_task *task) { ao_task_irq_check(); ao_list_del(&task->queue); @@ -84,7 +79,7 @@ ao_task_sleep_queue(void *wchan) } static void -ao_task_to_sleep_queue(struct ao_task *task, void *wchan) +_ao_task_to_sleep_queue(struct ao_task *task, void *wchan) { ao_task_irq_check(); ao_list_del(&task->queue); @@ -125,10 +120,10 @@ ao_task_validate_alarm_queue(void) #define ao_task_validate_alarm_queue() #endif -uint16_t ao_task_alarm_tick; +AO_TICK_TYPE ao_task_alarm_tick; static void -ao_task_to_alarm_queue(struct ao_task *task) +_ao_task_to_alarm_queue(struct ao_task *task) { struct ao_task *alarm; ao_task_irq_check(); @@ -146,7 +141,7 @@ ao_task_to_alarm_queue(struct ao_task *task) } static void -ao_task_from_alarm_queue(struct ao_task *task) +_ao_task_from_alarm_queue(struct ao_task *task) { ao_task_irq_check(); ao_list_del(&task->alarm_queue); @@ -173,17 +168,17 @@ ao_task_exit_queue(struct ao_task *task) } void -ao_task_check_alarm(uint16_t tick) +ao_task_alarm(AO_TICK_TYPE tick) { struct ao_task *alarm, *next; 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) + if ((AO_TICK_SIGNED) (tick - alarm->alarm) < 0) break; alarm->alarm = 0; - ao_task_from_alarm_queue(alarm); - ao_task_to_run_queue(alarm); + _ao_task_from_alarm_queue(alarm); + _ao_task_to_run_queue(alarm); }); } @@ -287,7 +282,20 @@ ao_task_validate(void) } #endif /* DEBUG */ -#endif /* HAS_TASK_QUEUE */ +static inline void * +ao_stack_top(struct ao_task *task) +{ + uint8_t *top = &task->stack8[AO_STACK_SIZE]; + + /* Subtract off the TLS space, but keep the resulting + * stack 8-byte aligned + */ +#if USE_TLS + return top - ((_tls_size() + 7) & ~3); +#else + return top; +#endif +} void ao_add_task(struct ao_task * task, void (*task_func)(void), const char *name) @@ -310,12 +318,14 @@ ao_add_task(struct ao_task * task, void (*task_func)(void), const char *name) * Construct a stack frame so that it will 'return' * to the start of the task */ - ao_arch_init_stack(task, task_func); - ao_arch_critical( -#if HAS_TASK_QUEUE - ao_task_init_queue(task); - ao_task_to_run_queue(task); + uint32_t *sp = ao_stack_top(task); +#if USE_TLS + _init_tls(sp); #endif + ao_arch_init_stack(task, sp, task_func); + ao_task_init_queue(task); + ao_arch_critical( + _ao_task_to_run_queue(task); ao_tasks[ao_num_tasks] = task; ao_num_tasks++; ); @@ -323,38 +333,25 @@ ao_add_task(struct ao_task * task, void (*task_func)(void), const char *name) uint8_t ao_task_minimize_latency; -/* Task switching function. This must not use any stack variables */ +/* Task switching function. */ void -ao_yield(void) ao_arch_naked_define +ao_yield(void) { - ao_arch_save_regs(); - -#if HAS_TASK_QUEUE - if (ao_cur_task == NULL) - ao_cur_task = ao_tasks[ao_num_tasks-1]; -#else - if (ao_cur_task_index == AO_NO_TASK_INDEX) - ao_cur_task_index = ao_num_tasks-1; -#endif - else + if (ao_cur_task) { #if HAS_SAMPLE_PROFILE - uint16_t tick = ao_sample_profile_timer_value(); - uint16_t run = tick - ao_cur_task->start; + AO_TICK_TYPE tick = ao_sample_profile_timer_value(); + AO_TICK_TYPE run = tick - ao_cur_task->start; if (run > ao_cur_task->max_run) ao_cur_task->max_run = run; ++ao_cur_task->yields; #endif + ao_arch_save_regs(); ao_arch_save_stack(); } ao_arch_isr_stack(); -#if !HAS_TASK_QUEUE - if (ao_task_minimize_latency) - ao_arch_release_interrupts(); - else -#endif - ao_arch_block_interrupts(); + ao_arch_block_interrupts(); #if AO_CHECK_STACK in_yield = 1; @@ -362,12 +359,11 @@ ao_yield(void) ao_arch_naked_define /* Find a task to run. If there isn't any runnable task, * this loop will run forever, which is just fine */ -#if HAS_TASK_QUEUE /* If the current task is running, move it to the * end of the queue to allow other tasks a chance */ - if (ao_cur_task->wchan == NULL) - ao_task_to_run_queue(ao_cur_task); + if (ao_cur_task && ao_cur_task->wchan == NULL) + _ao_task_to_run_queue(ao_cur_task); for (;;) { ao_arch_memory_barrier(); if (!ao_list_is_empty(&run_queue)) @@ -380,31 +376,6 @@ ao_yield(void) ao_arch_naked_define ao_arch_wait_interrupt(); } ao_cur_task = ao_list_first_entry(&run_queue, struct ao_task, queue); -#else - { - uint8_t ao_last_task_index = ao_cur_task_index; - for (;;) { - ++ao_cur_task_index; - if (ao_cur_task_index == ao_num_tasks) - ao_cur_task_index = 0; - - ao_cur_task = ao_tasks[ao_cur_task_index]; - - /* Check for ready task */ - if (ao_cur_task->wchan == NULL) - break; - - /* Check if the alarm is set for a time which has passed */ - if (ao_cur_task->alarm && - (int16_t) (ao_time() - ao_cur_task->alarm) >= 0) - break; - - /* Wait for interrupts when there's nothing ready */ - if (ao_cur_task_index == ao_last_task_index && !ao_task_minimize_latency) - ao_arch_wait_interrupt(); - } - } -#endif #if HAS_SAMPLE_PROFILE ao_cur_task->start = ao_sample_profile_timer_value(); #endif @@ -413,6 +384,9 @@ ao_yield(void) ao_arch_naked_define #endif #if AO_CHECK_STACK in_yield = 0; +#endif +#if USE_TLS + _set_tls(ao_stack_top(ao_cur_task)); #endif ao_arch_restore_stack(); } @@ -420,15 +394,10 @@ ao_yield(void) ao_arch_naked_define uint8_t ao_sleep(void *wchan) { -#if HAS_TASK_QUEUE - uint32_t flags; - flags = ao_arch_irqsave(); -#endif - ao_cur_task->wchan = wchan; -#if HAS_TASK_QUEUE - ao_task_to_sleep_queue(ao_cur_task, wchan); - ao_arch_irqrestore(flags); -#endif + ao_arch_critical( + ao_cur_task->wchan = wchan; + _ao_task_to_sleep_queue(ao_cur_task, wchan); + ); ao_yield(); if (ao_cur_task->wchan) { ao_cur_task->wchan = NULL; @@ -442,7 +411,6 @@ void ao_wakeup(void *wchan) { ao_validate_cur_stack(); -#if HAS_TASK_QUEUE struct ao_task *sleep, *next; struct ao_list *sleep_queue; uint32_t flags; @@ -454,52 +422,33 @@ ao_wakeup(void *wchan) ao_list_for_each_entry_safe(sleep, next, sleep_queue, struct ao_task, queue) { if (sleep->wchan == wchan) { sleep->wchan = NULL; - ao_task_to_run_queue(sleep); + _ao_task_to_run_queue(sleep); } } ao_arch_irqrestore(flags); -#else - { - uint8_t i; - for (i = 0; i < ao_num_tasks; i++) - if (ao_tasks[i]->wchan == wchan) - ao_tasks[i]->wchan = NULL; - } -#endif ao_check_stack(); } uint8_t -ao_sleep_for(void *wchan, uint16_t timeout) +ao_sleep_for(void *wchan, AO_TICK_TYPE timeout) { uint8_t ret; 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 - */ - if (!(ao_cur_task->alarm = ao_time() + timeout + 1)) - ao_cur_task->alarm = 1; -#if HAS_TASK_QUEUE - ao_task_to_alarm_queue(ao_cur_task); - ao_arch_irqrestore(flags); -#endif + ao_arch_critical( + /* 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 + */ + if (!(ao_cur_task->alarm = ao_time() + timeout + 1)) + ao_cur_task->alarm = 1; + _ao_task_to_alarm_queue(ao_cur_task); + ); } ret = ao_sleep(wchan); if (timeout) { -#if HAS_TASK_QUEUE - uint32_t flags; - - flags = ao_arch_irqsave(); -#endif - ao_cur_task->alarm = 0; -#if HAS_TASK_QUEUE - ao_task_from_alarm_queue(ao_cur_task); - ao_arch_irqrestore(flags); -#endif + ao_arch_critical( + ao_cur_task->alarm = 0; + _ao_task_from_alarm_queue(ao_cur_task); + ); } return ret; } @@ -507,7 +456,7 @@ ao_sleep_for(void *wchan, uint16_t timeout) static uint8_t ao_forever; void -ao_delay(uint16_t ticks) +ao_delay(AO_TICK_TYPE ticks) { if (!ticks) ticks = 1; @@ -519,21 +468,17 @@ ao_exit(void) { uint8_t i; ao_arch_block_interrupts(); - ao_num_tasks--; -#if HAS_TASK_QUEUE for (i = 0; i < ao_num_tasks; i++) if (ao_tasks[i] == ao_cur_task) break; ao_task_exit_queue(ao_cur_task); -#else - i = ao_cur_task_index; - ao_cur_task_index = AO_NO_TASK_INDEX; -#endif + /* Remove task from list */ + ao_num_tasks--; for (; i < ao_num_tasks; i++) ao_tasks[i] = ao_tasks[i+1]; ao_cur_task = NULL; ao_yield(); - /* we'll never get back here */ + __builtin_unreachable(); } #if HAS_TASK_INFO @@ -542,7 +487,7 @@ ao_task_info(void) { uint8_t i; struct ao_task *task; - uint16_t now = ao_time(); + AO_TICK_TYPE now = ao_time(); for (i = 0; i < ao_num_tasks; i++) { task = ao_tasks[i]; @@ -552,7 +497,7 @@ ao_task_info(void) task->alarm ? (int16_t) (task->alarm - now) : 9999, task->name); } -#if HAS_TASK_QUEUE && DEBUG +#if DEBUG ao_task_validate(); #endif } @@ -561,9 +506,6 @@ ao_task_info(void) void ao_start_scheduler(void) { -#if !HAS_TASK_QUEUE - ao_cur_task_index = AO_NO_TASK_INDEX; -#endif ao_cur_task = NULL; #if HAS_ARCH_START_SCHEDULER ao_arch_start_scheduler(); diff --git a/src/kernel/ao_task.h b/src/kernel/ao_task.h index 03b62969..beb4da30 100644 --- a/src/kernel/ao_task.h +++ b/src/kernel/ao_task.h @@ -18,9 +18,8 @@ #ifndef _AO_TASK_H_ #define _AO_TASK_H_ -#if HAS_TASK_QUEUE + #include -#endif #ifndef HAS_TASK_INFO #define HAS_TASK_INFO 1 @@ -38,7 +37,7 @@ /* An AltOS task */ struct ao_task { void *wchan; /* current wait channel (NULL if running) */ - uint16_t alarm; /* abort ao_sleep time */ + AO_TICK_TYPE alarm; /* abort ao_sleep time */ uint16_t task_id; /* unique id */ /* Saved stack pointer */ union { @@ -46,10 +45,8 @@ struct ao_task { uint8_t *sp8; }; const char *name; /* task name */ -#if HAS_TASK_QUEUE struct ao_list queue; struct ao_list alarm_queue; -#endif /* Provide both 32-bit and 8-bit stacks */ union { uint32_t stack32[AO_STACK_SIZE>>2]; @@ -67,8 +64,6 @@ struct ao_task { #define AO_NUM_TASKS 16 /* maximum number of tasks */ #endif -#define AO_NO_TASK 0 /* no task id */ - extern struct ao_task * ao_tasks[AO_NUM_TASKS]; extern uint8_t ao_num_tasks; extern struct ao_task *ao_cur_task; @@ -96,7 +91,7 @@ ao_sleep(void *wchan); * 1 on alarm */ uint8_t -ao_sleep_for(void *wchan, uint16_t timeout); +ao_sleep_for(void *wchan, AO_TICK_TYPE timeout); /* Wake all tasks sleeping on wchan */ void @@ -105,7 +100,7 @@ ao_wakeup(void *wchan); #if 0 /* set an alarm to go off in 'delay' ticks */ void -ao_alarm(uint16_t delay); +ao_alarm(AO_TICK_TYPE delay); /* Clear any pending alarm */ void @@ -120,16 +115,24 @@ ao_yield(void) ao_arch_naked_declare; void ao_add_task(struct ao_task * task, void (*start)(void), const char *name); -#if HAS_TASK_QUEUE /* Called on timer interrupt to check alarms */ -extern uint16_t ao_task_alarm_tick; +extern AO_TICK_TYPE ao_task_alarm_tick; +extern volatile AO_TICK_TYPE ao_tick_count; + void -ao_task_check_alarm(uint16_t tick); +ao_task_alarm(AO_TICK_TYPE tick); + +static inline void +ao_task_check_alarm(void) { +#if HAS_TASK + if ((AO_TICK_SIGNED) (ao_tick_count - ao_task_alarm_tick) >= 0) + ao_task_alarm(ao_tick_count); #endif +} /* Terminate the current task */ void -ao_exit(void); +ao_exit(void) __attribute__ ((noreturn)); /* Dump task info to console */ void @@ -139,11 +142,7 @@ ao_task_info(void); void ao_start_scheduler(void) __attribute__((noreturn)); -#if HAS_TASK_QUEUE void ao_task_init(void); -#else -#define ao_task_init() -#endif #endif diff --git a/src/lpc/ao_arch.h b/src/lpc/ao_arch.h index c638aa22..eedac777 100644 --- a/src/lpc/ao_arch.h +++ b/src/lpc/ao_arch.h @@ -103,18 +103,28 @@ ao_serial_init(void); /* SPI definitions */ -#define AO_SPI_SPEED_12MHz 4 -#define AO_SPI_SPEED_8MHz 6 -#define AO_SPI_SPEED_6MHz 8 -#define AO_SPI_SPEED_4MHz 12 -#define AO_SPI_SPEED_2MHz 24 -#define AO_SPI_SPEED_1MHz 48 -#define AO_SPI_SPEED_500kHz 96 -#define AO_SPI_SPEED_250kHz 192 -#define AO_SPI_SPEED_125kHz 384 -#define AO_SPI_SPEED_62500Hz 768 - -#define AO_SPI_SPEED_FAST AO_SPI_SPEED_12MHz +#define _AO_SPI_SPEED_12MHz 4 +#define _AO_SPI_SPEED_8MHz 6 +#define _AO_SPI_SPEED_6MHz 8 +#define _AO_SPI_SPEED_4MHz 12 +#define _AO_SPI_SPEED_2MHz 24 +#define _AO_SPI_SPEED_1MHz 48 +#define _AO_SPI_SPEED_500kHz 96 +#define _AO_SPI_SPEED_250kHz 192 +#define _AO_SPI_SPEED_125kHz 384 +#define _AO_SPI_SPEED_62500Hz 768 + +static inline uint32_t +ao_spi_speed(uint32_t hz) +{ + if (hz >= 4000000) return _AO_SPI_SPEED_4MHz; + if (hz >= 2000000) return _AO_SPI_SPEED_2MHz; + if (hz >= 1000000) return _AO_SPI_SPEED_1MHz; + if (hz >= 500000) return _AO_SPI_SPEED_500kHz; + if (hz >= 250000) return _AO_SPI_SPEED_250kHz; + if (hz >= 125000) return _AO_SPI_SPEED_125kHz; + return _AO_SPI_SPEED_62500Hz; +} #define AO_BOOT_APPLICATION_BASE ((uint32_t *) 0x00001000) #define AO_BOOT_APPLICATION_BOUND ((uint32_t *) (0x00000000 + 32 * 1024)) diff --git a/src/lpc/ao_arch_funcs.h b/src/lpc/ao_arch_funcs.h index 1368f7e5..e0280e76 100644 --- a/src/lpc/ao_arch_funcs.h +++ b/src/lpc/ao_arch_funcs.h @@ -107,9 +107,8 @@ ao_arch_memory_barrier(void) { #if HAS_TASK static inline void -ao_arch_init_stack(struct ao_task *task, void *start) +ao_arch_init_stack(struct ao_task *task, uint32_t *sp, void *start) { - uint32_t *sp = &task->stack32[AO_STACK_SIZE >> 2]; uint32_t a = (uint32_t) start; int i; diff --git a/src/lpc/ao_beep_lpc.c b/src/lpc/ao_beep_lpc.c index eab86ee6..ab06ef48 100644 --- a/src/lpc/ao_beep_lpc.c +++ b/src/lpc/ao_beep_lpc.c @@ -59,7 +59,7 @@ ao_beep(uint8_t beep) } void -ao_beep_for(uint8_t beep, uint16_t ticks) +ao_beep_for(uint8_t beep, AO_TICK_TYPE ticks) { ao_beep(beep); ao_delay(ticks); diff --git a/src/lpc/ao_led_lpc.c b/src/lpc/ao_led_lpc.c index 46bf0495..3747df97 100644 --- a/src/lpc/ao_led_lpc.c +++ b/src/lpc/ao_led_lpc.c @@ -42,12 +42,6 @@ ao_led_set(AO_PORT_TYPE colors) ao_led_on(on); } -void -ao_led_toggle(AO_PORT_TYPE colors) -{ - lpc_gpio.pin[LED_PORT] ^= colors; -} - void ao_led_for(AO_PORT_TYPE colors, AO_TICK_TYPE ticks) { diff --git a/src/lpc/ao_timer_lpc.c b/src/lpc/ao_timer_lpc.c index 62b16318..a334ee0d 100644 --- a/src/lpc/ao_timer_lpc.c +++ b/src/lpc/ao_timer_lpc.c @@ -17,6 +17,7 @@ */ #include +#include #define AO_SYSTICK (AO_LPC_SYSCLK / 2) @@ -53,10 +54,7 @@ void lpc_systick_isr(void) { if (lpc_systick.csr & (1 << LPC_SYSTICK_CSR_COUNTFLAG)) { ++ao_tick_count; -#if HAS_TASK_QUEUE - if (ao_task_alarm_tick && (int16_t) (ao_tick_count - ao_task_alarm_tick) >= 0) - ao_task_check_alarm((uint16_t) ao_tick_count); -#endif + ao_task_check_alarm(); #if AO_DATA_ALL if (++ao_data_count == ao_data_interval) { ao_data_count = 0; diff --git a/src/micropeak-v2.0/Makefile b/src/micropeak-v2.0/Makefile index 5949ec09..a662e49b 100644 --- a/src/micropeak-v2.0/Makefile +++ b/src/micropeak-v2.0/Makefile @@ -3,7 +3,7 @@ # # -include ../stmf0/Makefile.defs +include ../stm32l0/Makefile.defs PUBLISH_DIR=$(HOME)/altusmetrumllc/Binaries PUBLISH_HEX=$(PUBLISH_DIR)/$(HEX) @@ -14,35 +14,6 @@ MICRO_SRC=\ ao_microflight.c \ ao_microkalman.c -ALTOS_SRC = \ - ao_micropeak.c \ - ao_spi_stm.c \ - ao_dma_stm.c \ - ao_led_stmf0.c \ - ao_timer.c \ - ao_ms5607.c \ - ao_exti_stm.c \ - ao_convert_pa.c \ - ao_romconfig.c \ - ao_product.c \ - ao_panic.c \ - ao_stdio.c \ - ao_serial_stm.c \ - ao_usb_stm.c \ - ao_mutex.c \ - ao_interrupt.c \ - ao_cmd.c \ - ao_config.c \ - ao_task.c \ - ao_data.c \ - ao_boot_chain.c \ - ao_microflight.c \ - ao_report_micro.c \ - ao_storage_stm.c \ - ao_storage.c \ - ao_log_micro.c \ - ao_microkalman.c - INC=\ ao.h \ ao_pins.h \ @@ -52,15 +23,40 @@ INC=\ ao_ms5607.h \ ao_log_micro.h \ ao_micropeak.h \ + ao_lpuart.h \ altitude-pa.h \ ao_product.h \ - stm32f0.h + stm32l0.h + +ALTOS_SRC = \ + ao_interrupt.c \ + ao_panic.c \ + ao_micro.c \ + ao_report_micro.c \ + ao_stdio.c \ + ao_notask.c \ + ao_serial_stm.c \ + ao_lpuart_stm.c \ + ao_timer.c \ + ao_spi_stm32l0.c \ + ao_adc_stm32l0.c \ + ao_ms5607.c \ + ao_exti_stm.c \ + ao_convert_pa.c \ + ao_led.c \ + ao_cmd.c \ + ao_product.c \ + ao_romconfig.c \ + ao_flash_stm32l0.c \ + ao_microflight.c \ + ao_log_micro.c \ + ao_microkalman.c IDPRODUCT=0x14 PRODUCT=MicroPeak-v2.0 PRODUCT_DEF=-DMICROPEAK -CFLAGS = $(PRODUCT_DEF) $(STMF0_CFLAGS) +CFLAGS = $(PRODUCT_DEF) $(STML0_CFLAGS) -Wl,--gc-sections -ffunction-sections -fdata-sections PROGNAME=micropeak-v2.0 PROG=$(PROGNAME)-$(VERSION).elf @@ -71,7 +67,7 @@ OBJ=$(SRC:.c=.o) all: $(PROG) $(HEX) -LDFLAGS=-nostartfiles $(CFLAGS) -L$(TOPDIR)/stmf0 -Tmicropeak.ld -n +LDFLAGS=-nostartfiles $(CFLAGS) -L$(TOPDIR)/stm32l0 -Taltos.ld -n $(PROG): Makefile $(OBJ) micropeak.ld $(call quiet,CC) $(LDFLAGS) -o $(PROG) $(OBJ) $(LIBS) -Wl,-Map=$(PROGNAME)-$(VERSION).map diff --git a/src/micropeak-v2.0/ao_micro.c b/src/micropeak-v2.0/ao_micro.c new file mode 100644 index 00000000..5a21d658 --- /dev/null +++ b/src/micropeak-v2.0/ao_micro.c @@ -0,0 +1,224 @@ +/* + * Copyright © 2020 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include +#include +#include +#include +#include +#include + +uint32_t pa; +alt_t ground_alt, max_alt; +alt_t ao_max_height; + +static void +ao_msi_init(void) +{ + uint32_t icscr = stm_rcc.icscr; + + /* Set MSI clock to desired range */ + icscr &= ~(STM_RCC_ICSCR_MSIRANGE_MASK << STM_RCC_ICSCR_MSIRANGE); + icscr |= (AO_MSI_RANGE << STM_RCC_ICSCR_MSIRANGE); + stm_rcc.icscr = icscr; + + /* Set vcore to 1.2V */ + uint32_t cr = stm_pwr.cr; + cr &= ~(STM_PWR_CR_VOS_MASK << STM_PWR_CR_VOS); + cr |= (STM_PWR_CR_VOS_1_2 << STM_PWR_CR_VOS); + stm_pwr.cr = cr; +} + +void +ao_pa_get(void) +{ + static struct ao_ms5607_value value; + + ao_ms5607_sample(&ao_ms5607_current); + ao_ms5607_convert(&ao_ms5607_current, &value); + pa = value.pres; +} + +static void +ao_compute_height(void) +{ + ground_alt = ao_pa_to_altitude(pa_ground); + max_alt = ao_pa_to_altitude(pa_min); + ao_max_height = max_alt - ground_alt; +} + +static void +ao_pips(void) +{ + uint8_t i; + for (i = 0; i < 5; i++) { + ao_led_on(AO_LED_REPORT); + ao_delay(AO_MS_TO_TICKS(80)); + ao_led_off(AO_LED_REPORT); + ao_delay(AO_MS_TO_TICKS(80)); + } + ao_delay(AO_MS_TO_TICKS(200)); +} + +static void +power_down(void) +{ + ao_timer_stop(); + for(;;) { + /* + * Table 40, entering standby mode + * + * SLEEPDEEP = 1 in M0 SCR + * PDDS = 1 + * WUF = 0 + */ + stm_rcc.apb2enr |= (1 << STM_RCC_APB2ENR_SYSCFGEN); + stm_rcc.apb1enr |= (1 << STM_RCC_APB1ENR_PWREN); + stm_scb.scr |= ((1 << STM_SCB_SCR_SLEEPDEEP) | + (1 << STM_SCB_SCR_SLEEPONEXIT)); + stm_pwr.cr |= (1 << STM_PWR_CR_PDDS); + stm_pwr.csr &= ~(1 << STM_PWR_CSR_WUF); + ao_arch_wait_interrupt(); + } +} + +static bool log_stdout; + +static void +log_micro_dump(void) +{ + int i; + if (!log_stdout) { + ao_led_off(AO_LED_REPORT); + ao_lpuart1_enable(); + } + ao_log_micro_dump(); + for (i = 0; i < 4; i++) + ao_async_byte(stm_device_id.lot_num_0_3[i]); + for (i = 0; i < 3; i++) + ao_async_byte(stm_device_id.lot_num_4_6[i]); + ao_async_byte('-'); + ao_log_hex(stm_device_id.waf_num); + ao_async_byte('-'); + for (i = 0; i < 4; i++) + ao_log_hex(stm_device_id.unique_id[i]); + ao_log_newline(); + if (!log_stdout) + ao_lpuart1_disable(); +} + +static void +log_erase(void) +{ + uint32_t pos; + + for (pos = 0; pos < ao_storage_total; pos += STM_FLASH_PAGE_SIZE) + { + if (!ao_storage_device_is_erased(pos)) + ao_storage_device_erase(pos); + } +} + +static void +flight_mode(void) +{ + /* Give the person a second to get their finger out of the way */ + ao_delay(AO_MS_TO_TICKS(1000)); + + ao_log_micro_restore(); + ao_compute_height(); + ao_report_altitude(); + ao_pips(); + log_micro_dump(); +#if BOOST_DELAY + ao_delay(BOOST_DELAY); +#endif + log_erase(); + ao_microflight(); + ao_log_micro_save(); + ao_compute_height(); + ao_report_altitude(); + power_down(); +} + +void ao_async_byte(char c) +{ + if (log_stdout) + putchar(c); + else + ao_lpuart1_putchar(c); +} + +static void +log_micro_dump_uart(void) +{ + log_stdout = true; + log_micro_dump(); + log_stdout = false; +} + +static void +log_erase_cmd(void) +{ + ao_cmd_white(); + if (!ao_match_word("DoIt")) + return; + log_erase(); +} + +const struct ao_cmds ao_micro_cmds[] = { + { log_micro_dump_uart, "l\0Dump log" }, + { flight_mode, "F\0Flight mode" }, + { power_down, "S\0Standby" }, + { log_erase_cmd, "z \0Erase. is doit with D&I" }, + {} +}; + +static void +cmd_mode(void) +{ + ao_serial_init(); + ao_cmd_init(); + ao_cmd_register(ao_micro_cmds); + ao_cmd(); +} + +int +main(void) +{ + ao_msi_init(); + ao_led_init(); + ao_timer_init(); + ao_spi_init(); + ao_ms5607_init(); + ao_ms5607_setup(); + + /* Check the power supply voltage; it'll be 3.3V if + * the I/O board is connected + */ + uint16_t vref = ao_adc_read_vref(); + + uint32_t vdda = 3 * stm_vrefint_cal.vrefint_cal * 1000 / vref; + + /* Power supply > 3.25V means we're on USB power */ + if (vdda > 3250) { + cmd_mode(); + } else { + flight_mode(); + } +} diff --git a/src/micropeak-v2.0/ao_micropeak.c b/src/micropeak-v2.0/ao_micropeak.c index a4de4854..c6c1e221 100644 --- a/src/micropeak-v2.0/ao_micropeak.c +++ b/src/micropeak-v2.0/ao_micropeak.c @@ -56,7 +56,7 @@ ao_pips(void) } void -ao_delay_until(uint16_t target) { +ao_delay_until(AO_TICK_TYPE target) { int16_t delay = target - ao_time(); if (delay > 0) { ao_sleep_for(ao_delay_until, delay); @@ -145,10 +145,10 @@ ao_battery_fini(void) stm_rcc.apb2enr &= ~(1 << STM_RCC_APB2ENR_ADCEN); } -static uint16_t +static AO_TICK_TYPE ao_battery_voltage(void) { - uint16_t vrefint; + AO_TICK_TYPE vrefint; ao_battery_init(); @@ -212,7 +212,7 @@ ao_show_bat(void) uint8_t ao_log_present(void) { - uint16_t n_samples; + AO_TICK_TYPE n_samples; ao_eeprom_read(N_SAMPLES_OFFSET, &n_samples, sizeof (n_samples)); diff --git a/src/micropeak-v2.0/ao_pins.h b/src/micropeak-v2.0/ao_pins.h index d3bd2281..951083bd 100644 --- a/src/micropeak-v2.0/ao_pins.h +++ b/src/micropeak-v2.0/ao_pins.h @@ -20,12 +20,14 @@ extern uint8_t ao_on_battery; -#define AO_SYSCLK (ao_on_battery ? STM_HSI_FREQ : 48000000) +#define HAS_TASK 0 -#define LED_PORT_ENABLE STM_RCC_AHBENR_IOPAEN -#define LED_PORT (&stm_gpioa) -#define LED_PIN_ORANGE 2 -#define AO_LED_ORANGE (1 << LED_PIN_ORANGE) +#define AO_SYSCLK STM_MSI_FREQ_524288 +#define AO_MSI_RANGE STM_RCC_ICSCR_MSIRANGE_524288 + +#define LED_0_PORT (&stm_gpioa) +#define LED_0_PIN 1 +#define AO_LED_ORANGE (1 << 0) #define AO_LED_REPORT AO_LED_ORANGE #define AO_LED_PANIC AO_LED_ORANGE @@ -33,32 +35,28 @@ extern uint8_t ao_on_battery; #define AO_POWER_MANAGEMENT 0 -/* 48MHz clock based on USB */ -#define AO_HSI48 1 -/* Need HSI running to flash */ -#define AO_NEED_HSI 1 - -/* HCLK = 12MHz usb / 2MHz battery */ -#define AO_AHB_PRESCALER (ao_on_battery ? 16 : 1) -#define AO_RCC_CFGR_HPRE_DIV (ao_on_battery ? STM_RCC_CFGR_HPRE_DIV_16 : STM_RCC_CFGR_HPRE_DIV_1) +/* HCLK = MSI (2.097MHz) */ +#define AO_AHB_PRESCALER (1) +#define AO_RCC_CFGR_HPRE_DIV (STM_RCC_CFGR_HPRE_DIV_1) -/* APB = 12MHz usb / 2MHz battery */ -#define AO_APB_PRESCALER (ao_on_battery ? 2 : 1) -#define AO_RCC_CFGR_PPRE_DIV (ao_on_battery ? STM_RCC_CFGR_PPRE_DIV_2 : STM_RCC_CFGR_PPRE_DIV_1) - -#define HAS_USB 1 -#define AO_PA11_PA12_RMP 1 +/* APB = MSI */ +#define AO_APB1_PRESCALER (1) +#define AO_APB2_PRESCALER (1) +#define AO_RCC_CFGR_PPRE_DIV (STM_RCC_CFGR_PPRE_DIV_1) #define PACKET_HAS_SLAVE 0 #define HAS_SERIAL_1 0 #define HAS_SERIAL_2 1 -#define USE_SERIAL_2_STDIN 0 +#define USE_SERIAL_2_STDIN 1 #define USE_SERIAL_2_FLOW 0 #define USE_SERIAL_2_SW_FLOW 0 -#define SERIAL_2_PA2_PA3 1 -#define SERIAL_2_PA14_PA15 0 -#define USE_SERIAL2_FLOW 0 -#define USE_SERIAL2_SW_FLOW 0 +#define SERIAL_2_PA9_PA10 1 + +#define HAS_LPUART_1 1 +#define LPUART_1_PA0_PA1 1 +#define USE_LPUART_1_STDIN 0 +#define USE_LPUART_1_FLOW 0 +#define USE_LPUART_1_SW_FLOW 0 #define IS_FLASH_LOADER 0 @@ -109,9 +107,8 @@ typedef int32_t alt_t; #define AO_ALT_VALUE(x) ((x) * (alt_t) 10) -#define AO_DATA_RING 32 - #define HAS_ADC 0 +#define HAS_AO_DELAY 1 static inline void ao_power_off(void) __attribute((noreturn)); @@ -124,24 +121,16 @@ ao_power_off(void) { extern alt_t ao_max_height; -void ao_delay_until(uint16_t target); - -#define ao_async_stop() do { \ - ao_serial2_drain(); \ - stm_moder_set(&stm_gpioa, 2, STM_MODER_OUTPUT); \ - ao_serial_shutdown(); \ - } while (0) +#define ao_async_stop() +#define ao_async_start() -#define ao_async_start() do { \ - ao_serial_init(); \ - stm_moder_set(&stm_gpioa, 2, STM_MODER_ALTERNATE); \ - ao_delay(AO_MS_TO_TICKS(100)); \ - } while (0) +#define LOG_MICRO_ASYNC 0 -#define ao_async_byte(b) ao_serial2_putchar((char) (b)) +void ao_async_byte(char c); -#define ao_eeprom_read(pos, ptr, size) ao_storage_read(pos, ptr, size) -#define ao_eeprom_write(pos, ptr, size) ao_storage_write(pos, ptr, size) +#define ao_eeprom_read(pos, ptr, size) ao_storage_device_read(pos, ptr, size) +#define ao_eeprom_write(pos, ptr, size) ao_storage_device_write(pos, ptr, size) +#define N_SAMPLES_TYPE uint32_t #define MAX_LOG_OFFSET ao_storage_total #define ao_storage_log_max ao_storage_total @@ -151,4 +140,6 @@ extern uint32_t __flash_end__[]; #define AO_BOOT_APPLICATION_BOUND ((uint32_t *) __flash__) #define USE_STORAGE_CONFIG 0 +#define HAS_STORAGE_DEBUG 1 + #endif /* _AO_PINS_H_ */ diff --git a/src/micropeak-v2.0/micropeak.ld b/src/micropeak-v2.0/micropeak.ld index b4e06a87..93536c48 100644 --- a/src/micropeak-v2.0/micropeak.ld +++ b/src/micropeak-v2.0/micropeak.ld @@ -16,13 +16,12 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -__flash = 0x08001000; -__flash_size = 22K; +__flash = 0x08000000; +__flash_size = 10K; __flash__ = __flash + __flash_size; __flash_end__ = __flash__ + 6K; __ram = 0x20000000; -__ram_size = 6K; +__ram_size = 2K; __stack_size = 512; -INCLUDE registers.ld INCLUDE picolibc.ld diff --git a/src/mpusb-v3.0/Makefile b/src/mpusb-v3.0/Makefile index c09eedcf..63ab4859 100644 --- a/src/mpusb-v3.0/Makefile +++ b/src/mpusb-v3.0/Makefile @@ -49,11 +49,8 @@ OBJ=$(SRC:.c=.o) all: $(PROG) $(HEX) -$(PROG): Makefile $(OBJ) altos.ld - $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(OBJ) $(LIBS) - -ao_product.h: ao-make-product.5c ../Version - $(call quiet,NICKLE,$<) $< -m altusmetrum.org -i $(IDPRODUCT) -p $(PRODUCT) -v $(VERSION) > $@ +$(PROG): Makefile $(OBJ) + $(call quiet,CC) $(LDFLAGS) -o $(PROG) $(OBJ) $(LIBS) $(OBJ): $(INC) diff --git a/src/mpusb-v3.0/ao_pins.h b/src/mpusb-v3.0/ao_pins.h index 3e79aad3..54ff374c 100644 --- a/src/mpusb-v3.0/ao_pins.h +++ b/src/mpusb-v3.0/ao_pins.h @@ -20,7 +20,6 @@ #ifndef _AO_PINS_H_ #define _AO_PINS_H_ -#define HAS_TASK_QUEUE 1 #define IS_FLASH_LOADER 0 diff --git a/src/product/ao_flash_pins.h b/src/product/ao_flash_pins.h index 019b5425..cf6299ca 100644 --- a/src/product/ao_flash_pins.h +++ b/src/product/ao_flash_pins.h @@ -21,8 +21,6 @@ /* Common definitions for the USB flash loader */ -#define HAS_TASK_QUEUE 0 - #define HAS_USB 1 #define USE_USB_STDIO 0 #define HAS_USB_DISABLE 0 diff --git a/src/product/ao_flash_task.c b/src/product/ao_flash_task.c index a680ca18..bbd5675a 100644 --- a/src/product/ao_flash_task.c +++ b/src/product/ao_flash_task.c @@ -26,6 +26,7 @@ void ao_panic(uint8_t reason) { (void) reason; + for (;;); } void diff --git a/src/stm-flash/ao_pins.h b/src/stm-flash/ao_pins.h index 853b6841..268cf2f2 100644 --- a/src/stm-flash/ao_pins.h +++ b/src/stm-flash/ao_pins.h @@ -19,7 +19,6 @@ #ifndef _AO_PINS_H_ #define _AO_PINS_H_ -#define HAS_TASK_QUEUE 0 /* Bridge SB17 on the board and use the MCO from the other chip */ #define AO_HSE 8000000 diff --git a/src/stm-vga/ao_pins.h b/src/stm-vga/ao_pins.h index 8503c4fd..93264031 100644 --- a/src/stm-vga/ao_pins.h +++ b/src/stm-vga/ao_pins.h @@ -71,7 +71,6 @@ #define HAS_USB 1 #define HAS_BEEP 0 #define PACKET_HAS_SLAVE 0 -#define HAS_TASK_QUEUE 1 #define CONSOLE_STDIN 1 diff --git a/src/stm/ao_arch_funcs.h b/src/stm/ao_arch_funcs.h index ad46ef32..083f7a2b 100644 --- a/src/stm/ao_arch_funcs.h +++ b/src/stm/ao_arch_funcs.h @@ -24,20 +24,26 @@ /* PCLK is set to 16MHz (HCLK 32MHz, APB prescaler 2) */ -#define AO_SPI_SPEED_8MHz STM_SPI_CR1_BR_PCLK_2 -#define AO_SPI_SPEED_4MHz STM_SPI_CR1_BR_PCLK_4 -#define AO_SPI_SPEED_2MHz STM_SPI_CR1_BR_PCLK_8 -#define AO_SPI_SPEED_1MHz STM_SPI_CR1_BR_PCLK_16 -#define AO_SPI_SPEED_500kHz STM_SPI_CR1_BR_PCLK_32 -#define AO_SPI_SPEED_250kHz STM_SPI_CR1_BR_PCLK_64 -#define AO_SPI_SPEED_125kHz STM_SPI_CR1_BR_PCLK_128 -#define AO_SPI_SPEED_62500Hz STM_SPI_CR1_BR_PCLK_256 +//#define AO_SPI_SPEED_8MHz STM_SPI_CR1_BR_PCLK_2 /* too fast to use safely */ +#define _AO_SPI_SPEED_4MHz STM_SPI_CR1_BR_PCLK_4 +#define _AO_SPI_SPEED_2MHz STM_SPI_CR1_BR_PCLK_8 +#define _AO_SPI_SPEED_1MHz STM_SPI_CR1_BR_PCLK_16 +#define _AO_SPI_SPEED_500kHz STM_SPI_CR1_BR_PCLK_32 +#define _AO_SPI_SPEED_250kHz STM_SPI_CR1_BR_PCLK_64 +#define _AO_SPI_SPEED_125kHz STM_SPI_CR1_BR_PCLK_128 +#define _AO_SPI_SPEED_62500Hz STM_SPI_CR1_BR_PCLK_256 -#define AO_SPI_SPEED_FAST AO_SPI_SPEED_8MHz - -/* Companion bus wants something no faster than 200kHz */ - -#define AO_SPI_SPEED_200kHz AO_SPI_SPEED_125kHz +static inline uint32_t +ao_spi_speed(uint32_t hz) +{ + if (hz >= 4000000) return _AO_SPI_SPEED_4MHz; + if (hz >= 2000000) return _AO_SPI_SPEED_2MHz; + if (hz >= 1000000) return _AO_SPI_SPEED_1MHz; + if (hz >= 500000) return _AO_SPI_SPEED_500kHz; + if (hz >= 250000) return _AO_SPI_SPEED_250kHz; + if (hz >= 125000) return _AO_SPI_SPEED_125kHz; + return _AO_SPI_SPEED_62500Hz; +} #define AO_SPI_CPOL_BIT 4 #define AO_SPI_CPHA_BIT 5 @@ -151,8 +157,6 @@ ao_spi_recv(void *block, uint16_t len, uint8_t spi_index); void ao_spi_duplex(const void *out, void *in, uint16_t len, uint8_t spi_index); -extern uint16_t ao_spi_speed[STM_NUM_SPI]; - void ao_spi_init(void); @@ -473,9 +477,8 @@ ao_arch_irq_check(void) { #if HAS_TASK static inline void -ao_arch_init_stack(struct ao_task *task, void *start) +ao_arch_init_stack(struct ao_task *task, uint32_t *sp, void *start) { - uint32_t *sp = &task->stack32[AO_STACK_SIZE>>2]; uint32_t a = (uint32_t) start; int i; @@ -559,8 +562,8 @@ ao_validate_cur_stack(void) asm("mrs %0,psp" : "=&r" (psp)); if (ao_cur_task && - psp <= ao_cur_task->stack && - psp >= ao_cur_task->stack - 256) + (psp <= ao_cur_task->stack8 || + psp >= ao_cur_task->stack8 + AO_STACK_SIZE)) ao_panic(AO_PANIC_STACK); } #endif diff --git a/src/stm/ao_beep_stm.c b/src/stm/ao_beep_stm.c index 2bcd6849..12d2b0b6 100644 --- a/src/stm/ao_beep_stm.c +++ b/src/stm/ao_beep_stm.c @@ -148,7 +148,7 @@ ao_beep(uint8_t beep) } void -ao_beep_for(uint8_t beep, uint16_t ticks) +ao_beep_for(uint8_t beep, AO_TICK_TYPE ticks) { ao_beep(beep); ao_delay(ticks); diff --git a/src/stm/ao_led_stm.c b/src/stm/ao_led_stm.c index ed4ec161..7f40eaca 100644 --- a/src/stm/ao_led_stm.c +++ b/src/stm/ao_led_stm.c @@ -68,24 +68,6 @@ ao_led_set(AO_LED_TYPE colors) ao_led_on(on); } -void -ao_led_toggle(AO_LED_TYPE colors) -{ -#ifdef LED_PORT - LED_PORT->odr ^= (colors & LEDS_AVAILABLE); -#else -#ifdef LED_PORT_0 - LED_PORT_0->odr ^= ((colors & LEDS_AVAILABLE) & LED_PORT_0_MASK) << LED_PORT_0_SHIFT; -#endif -#ifdef LED_PORT_1 - LED_PORT_1->odr ^= ((colors & LEDS_AVAILABLE) & LED_PORT_1_MASK) << LED_PORT_1_SHIFT; -#endif -#ifdef LED_PORT_2 - LED_PORT_2->odr ^= ((colors & LEDS_AVAILABLE) & LED_PORT_2_MASK) << LED_PORT_2_SHIFT; -#endif -#endif -} - void ao_led_for(AO_LED_TYPE colors, AO_TICK_TYPE ticks) { diff --git a/src/stm/ao_spi_stm.c b/src/stm/ao_spi_stm.c index 1a04a289..0215f03e 100644 --- a/src/stm/ao_spi_stm.c +++ b/src/stm/ao_spi_stm.c @@ -116,7 +116,7 @@ ao_spi_set_dma_miso(uint8_t id, void *data, uint16_t len, uint32_t minc) data, len, (0 << STM_DMA_CCR_MEM2MEM) | - (STM_DMA_CCR_PL_HIGH << STM_DMA_CCR_PL) | + (STM_DMA_CCR_PL_VERY_HIGH << STM_DMA_CCR_PL) | (STM_DMA_CCR_MSIZE_8 << STM_DMA_CCR_MSIZE) | (STM_DMA_CCR_PSIZE_8 << STM_DMA_CCR_PSIZE) | (minc << STM_DMA_CCR_MINC) | diff --git a/src/stm/ao_timer.c b/src/stm/ao_timer.c index d00deffa..0d81b5de 100644 --- a/src/stm/ao_timer.c +++ b/src/stm/ao_timer.c @@ -67,10 +67,7 @@ void stm_systick_isr(void) #if HAS_TICK ++ao_tick_count; #endif -#if HAS_TASK_QUEUE - if (ao_task_alarm_tick && (int16_t) (ao_tick_count - ao_task_alarm_tick) >= 0) - ao_task_check_alarm((uint16_t) ao_tick_count); -#endif + ao_task_check_alarm(); #if AO_DATA_ALL if (++ao_data_count == ao_data_interval) { ao_data_count = 0; diff --git a/src/stm32f4/ao_arch.h b/src/stm32f4/ao_arch.h index 7dd4c80d..6d75f188 100644 --- a/src/stm32f4/ao_arch.h +++ b/src/stm32f4/ao_arch.h @@ -22,10 +22,6 @@ #define AO_STACK_SIZE 2048 #endif -#ifndef HAS_TASK_QUEUE -#define HAS_TASK_QUEUE 1 -#endif - #define AO_STACK_ALIGNMENT __attribute__ ((aligned(8))) #define AO_PORT_TYPE uint16_t diff --git a/src/stm32f4/ao_arch_funcs.h b/src/stm32f4/ao_arch_funcs.h index 6fa65497..74f4021b 100644 --- a/src/stm32f4/ao_arch_funcs.h +++ b/src/stm32f4/ao_arch_funcs.h @@ -82,9 +82,8 @@ ao_arch_irq_check(void) { #if HAS_TASK static inline void -ao_arch_init_stack(struct ao_task *task, void *start) +ao_arch_init_stack(struct ao_task *task, uint32_t *sp, void *start) { - uint32_t *sp = &task->stack32[AO_STACK_SIZE>>2]; uint32_t a = (uint32_t) start; int i; diff --git a/src/stm32f4/ao_interrupt.c b/src/stm32f4/ao_interrupt.c index 24f56abc..20577b14 100644 --- a/src/stm32f4/ao_interrupt.c +++ b/src/stm32f4/ao_interrupt.c @@ -45,8 +45,11 @@ void start(void) #ifdef AO_BOOT_CHAIN if (ao_boot_check_chain()) { #ifdef AO_BOOT_PIN - ao_boot_check_pin(); + if (ao_boot_check_pin()) #endif + { + ao_boot_chain(AO_BOOT_APPLICATION_BASE); + } } #endif /* Enable FPU */ diff --git a/src/stm32f4/ao_timer.c b/src/stm32f4/ao_timer.c index fb83db00..999b587f 100644 --- a/src/stm32f4/ao_timer.c +++ b/src/stm32f4/ao_timer.c @@ -47,10 +47,7 @@ void stm_systick_isr(void) #if HAS_TICK ++ao_tick_count; #endif -#if HAS_TASK_QUEUE - if (ao_task_alarm_tick && (int16_t) (ao_tick_count - ao_task_alarm_tick) >= 0) - ao_task_check_alarm((uint16_t) ao_tick_count); -#endif + ao_task_check_alarm(); #if AO_DATA_ALL if (++ao_data_count == ao_data_interval) { ao_data_count = 0; diff --git a/src/stm32l0/Makefile-flash.defs b/src/stm32l0/Makefile-flash.defs new file mode 100644 index 00000000..08a4b177 --- /dev/null +++ b/src/stm32l0/Makefile-flash.defs @@ -0,0 +1,58 @@ +include $(TOPDIR)/stm/Makefile-stm.defs + +INC = \ + ao.h \ + ao_arch.h \ + ao_arch_funcs.h \ + ao_flash_pins.h \ + ao_flash_stm_pins.h \ + ao_flash_task.h \ + ao_pins.h \ + ao_product.h \ + Makefile + +# +# Common AltOS sources +# +SRC = \ + ao_interrupt.c \ + ao_romconfig.c \ + ao_boot_chain.c \ + ao_boot_pin.c \ + ao_product.c \ + ao_notask.c \ + ao_timer.c \ + ao_usb_stm.c \ + ao_flash_stm.c \ + ao_flash_task.c \ + ao_flash_loader_stm.c + +OBJ=$(SRC:.c=.o) + +PRODUCT=AltosFlash +PRODUCT_DEF=-DALTOS_FLASH +IDPRODUCT=0x000a + +CFLAGS = $(PRODUCT_DEF) $(STM_CFLAGS) + +LDFLAGS=$(CFLAGS) -L$(TOPDIR)/stm -Wl,-Taltos-loader.ld -n + +PROGNAME=altos-flash +PROG=$(HARDWARE)-$(PROGNAME)-$(VERSION).elf + +$(PROG): Makefile $(OBJ) altos-loader.ld + $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(OBJ) $(LIBS) + +$(OBJ): $(INC) + +all: $(PROG) + +distclean: clean + +clean: + rm -f *.o $(HARDWARE)-$(PROGNAME)-*.elf + rm -f ao_product.h + +install: + +uninstall: diff --git a/src/stm32l0/Makefile-stm32l0.defs b/src/stm32l0/Makefile-stm32l0.defs new file mode 100644 index 00000000..1eab283a --- /dev/null +++ b/src/stm32l0/Makefile-stm32l0.defs @@ -0,0 +1,16 @@ +ifndef TOPDIR +TOPDIR=.. +endif + +# Disable floating-point support in printf to save space + +PICOLIBC_PRINTF_CFLAGS = -DPICOLIBC_INTEGER_PRINTF_SCANF + +include $(TOPDIR)/Makefile.defs + +vpath % $(TOPDIR)/stm32l0:$(AO_VPATH) + +CC=$(ARM_CC) + +STML0_CFLAGS=-mlittle-endian -mcpu=cortex-m0 -mthumb \ + -I$(TOPDIR)/stm32l0 $(AO_CFLAGS) $(PICOLIBC_CFLAGS) diff --git a/src/stm32l0/Makefile.defs b/src/stm32l0/Makefile.defs new file mode 100644 index 00000000..911d8dc9 --- /dev/null +++ b/src/stm32l0/Makefile.defs @@ -0,0 +1,7 @@ +ifndef TOPDIR +TOPDIR=.. +endif + +include $(TOPDIR)/stm32l0/Makefile-stm32l0.defs + +LDFLAGS=$(CFLAGS) -L$(TOPDIR)/stm32l0 -Taltos.ld diff --git a/src/stm32l0/altos.ld b/src/stm32l0/altos.ld new file mode 100644 index 00000000..5c9688e3 --- /dev/null +++ b/src/stm32l0/altos.ld @@ -0,0 +1,31 @@ +/* + * Copyright © 2012 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +__flash = 0x08000000; +__flash_size = 12k; +__storage = __flash + __flash_size; +__storage_size = 16k - __flash_size; +__ram = 0x20000000; +__ram_size = 2k; +__stack_size = 512; + +PROVIDE(__storage = __storage); +PROVIDE(__storage_size = __storage_size); + +INCLUDE picolibc.ld +INCLUDE stm32l0.ld diff --git a/src/stm32l0/ao_adc_stm32l0.c b/src/stm32l0/ao_adc_stm32l0.c new file mode 100644 index 00000000..a7af0a08 --- /dev/null +++ b/src/stm32l0/ao_adc_stm32l0.c @@ -0,0 +1,111 @@ +/* + * Copyright © 2020 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include +#include + +void +ao_adc_init(void) +{ + stm_rcc.apb2enr |= (1 << STM_RCC_APB2ENR_ADCEN); + + /* Configure */ + stm_adc.cfgr1 = ((0 << STM_ADC_CFGR1_AWDCH) | /* analog watchdog channel 0 */ + (0 << STM_ADC_CFGR1_AWDEN) | /* Disable analog watchdog */ + (0 << STM_ADC_CFGR1_AWDSGL) | /* analog watchdog on all channels */ + (0 << STM_ADC_CFGR1_DISCEN) | /* Not discontinuous mode. All channels converted with one trigger */ + (0 << STM_ADC_CFGR1_AUTOOFF) | /* Leave ADC running */ + (1 << STM_ADC_CFGR1_WAIT) | /* Wait for data to be read before next conversion */ + (0 << STM_ADC_CFGR1_CONT) | /* only one set of conversions per trigger */ + (1 << STM_ADC_CFGR1_OVRMOD) | /* overwrite on overrun */ + (STM_ADC_CFGR1_EXTEN_DISABLE << STM_ADC_CFGR1_EXTEN) | /* SW trigger */ + (0 << STM_ADC_CFGR1_ALIGN) | /* Align to LSB */ + (STM_ADC_CFGR1_RES_12 << STM_ADC_CFGR1_RES) | /* 12 bit resolution */ + (STM_ADC_CFGR1_SCANDIR_UP << STM_ADC_CFGR1_SCANDIR) | /* scan 0 .. n */ + (STM_ADC_CFGR1_DMACFG_ONESHOT << STM_ADC_CFGR1_DMACFG) | /* one set of conversions then stop */ + (0 << STM_ADC_CFGR1_DMAEN)); /* disable DMA */ + + /* Set the clock */ + stm_adc.cfgr2 = STM_ADC_CFGR2_CKMODE_PCLK_2 << STM_ADC_CFGR2_CKMODE; + + /* Shortest sample time */ + stm_adc.smpr = STM_ADC_SMPR_SMP_71_5 << STM_ADC_SMPR_SMP; + +#define AO_ADC_LFMEN (AO_SYSCLK < 3500000) + + stm_adc.ccr = ((AO_ADC_LFMEN << STM_ADC_CCR_LFMEN) | + (0 << STM_ADC_CCR_VLCDEN) | + (0 << STM_ADC_CCR_TSEN) | + (0 << STM_ADC_CCR_VREFEN)); + + /* Calibrate. This also enables the ADC vreg */ + stm_adc.cr |= (1 << STM_ADC_CR_ADCAL); + while ((stm_adc.cr & (1 << STM_ADC_CR_ADCAL)) != 0) + ; + + /* Enable */ + stm_adc.isr = (1 << STM_ADC_ISR_ADRDY); /* Clear ADRDY bit */ + stm_adc.cr |= (1 << STM_ADC_CR_ADEN); + while ((stm_adc.isr & (1 << STM_ADC_ISR_ADRDY)) == 0) + ; +} + +static void +ao_adc_shutdown(void) +{ + /* Disable ADC */ + stm_adc.cr |= (1 << STM_ADC_CR_ADDIS); + while ((stm_adc.cr & (1 << STM_ADC_CR_ADEN)) != 0) + ; + + /* Clear ADRDY bit */ + stm_adc.isr = (1 << STM_ADC_ISR_ADRDY); + + /* Disable ADC vreg */ + stm_adc.cr &= ~(1 << STM_ADC_CR_ADVREGEN); + + /* Disable ADC clocks */ + stm_rcc.apb2enr &= ~(1 << STM_RCC_APB2ENR_ADCEN); +} + +uint16_t +ao_adc_read_vref(void) +{ + uint16_t value; + + ao_adc_init(); + + /* Turn on voltage reference */ + stm_adc.ccr |= (1 << STM_ADC_CCR_VREFEN); + + /* Select VREF */ + stm_adc.chselr = (1 << STM_ADC_CHSEL_VREF); + + /* Start conversion */ + stm_adc.cr |= (1 << STM_ADC_CR_ADSTART); + + /* Wait for conversion complete */ + while ((stm_adc.isr & (1 << STM_ADC_ISR_EOC)) == 0) + ; + + /* Fetch result */ + value = stm_adc.dr; + + ao_adc_shutdown(); + return value; +} diff --git a/src/stm32l0/ao_adc_stm32l0.h b/src/stm32l0/ao_adc_stm32l0.h new file mode 100644 index 00000000..8dd4c478 --- /dev/null +++ b/src/stm32l0/ao_adc_stm32l0.h @@ -0,0 +1,22 @@ +/* + * Copyright © 2020 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#pragma once + +uint16_t +ao_adc_read_vref(void); diff --git a/src/stm32l0/ao_arch.h b/src/stm32l0/ao_arch.h new file mode 100644 index 00000000..542d2eec --- /dev/null +++ b/src/stm32l0/ao_arch.h @@ -0,0 +1,128 @@ +/* + * Copyright © 2012 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#ifndef _AO_ARCH_H_ +#define _AO_ARCH_H_ + +#include +#include + +/* + * STM32L0 definitions and code fragments for AltOS + */ + +#ifndef AO_STACK_SIZE +#define AO_STACK_SIZE 256 +#endif + +#define HAS_USB 0 + +#define AO_PORT_TYPE uint16_t + +/* Various definitions to make GCC look more like SDCC */ + +#define ao_arch_naked_declare __attribute__((naked)) +#define ao_arch_naked_define +#define __interrupt(n) +#define __at(n) + +#define ao_arch_reboot() \ + (stm_scb.aircr = ((STM_SCB_AIRCR_VECTKEY_KEY << STM_SCB_AIRCR_VECTKEY) | \ + (1 << STM_SCB_AIRCR_SYSRESETREQ))) + +#define ao_arch_nop() asm("nop") + +#define ao_arch_interrupt(n) /* nothing */ + +/* + * ao_romconfig.c + */ + +#define AO_ROMCONFIG_SYMBOL __attribute__((section(".romconfig"))) const + +#ifndef AO_SYSCLK +#if AO_HSE +#define AO_PLLSRC AO_HSE +#else +#define AO_PLLSRC STM_HSI_FREQ +#endif + +#define AO_PLLVCO (AO_PLLSRC * AO_PLLMUL) +#define AO_SYSCLK (AO_PLLVCO / AO_PLLDIV) +#endif + +#define AO_HCLK (AO_SYSCLK / AO_AHB_PRESCALER) +#define AO_FCLK AO_HCLK +#define AO_PCLK1 (AO_HCLK / AO_APB1_PRESCALER) +#define AO_PCLK2 (AO_HCLK / AO_APB2_PRESCALER) +#define AO_SYSTICK (AO_HCLK / 8) + +#if AO_APB1_PRESCALER == 1 +#define AO_TIM23467_CLK AO_PCLK1 +#else +#define AO_TIM23467_CLK (2 * AO_PCLK1) +#endif + +#if AO_APB2_PRESCALER == 1 +#define AO_TIM91011_CLK AO_PCLK2 +#else +#define AO_TIM91011_CLK (2 * AO_PCLK2) +#endif + +/* The stm32l implements only 4 bits of the priority fields */ + +#if AO_NONMASK_INTERRUPT +#define AO_STM_NVIC_NONMASK_PRIORITY 0x00 + +/* Set the basepri register to this value to mask all + * non-maskable priorities + */ +#define AO_STM_NVIC_BASEPRI_MASK 0x10 +#endif + +#define AO_STM_NVIC_HIGH_PRIORITY 0x40 +#define AO_STM_NVIC_MED_PRIORITY 0x80 +#define AO_STM_NVIC_LOW_PRIORITY 0xC0 +#define AO_STM_NVIC_CLOCK_PRIORITY 0xf0 + +void ao_lcd_stm_init(void); + +void ao_lcd_font_init(void); + +void ao_lcd_font_string(char *s); + +extern const uint32_t ao_radio_cal; + +void +ao_adc_init(void); + +/* ADC maximum reported value */ +#define AO_ADC_MAX 4095 + +#define HAS_BOOT_LOADER 0 + +#ifndef AO_LED_TYPE +#define AO_LED_TYPE uint16_t +#endif + +void +ao_timer_stop(void); + +#endif /* _AO_ARCH_H_ */ + + diff --git a/src/stm32l0/ao_arch_funcs.h b/src/stm32l0/ao_arch_funcs.h new file mode 100644 index 00000000..297bd66c --- /dev/null +++ b/src/stm32l0/ao_arch_funcs.h @@ -0,0 +1,599 @@ +/* + * Copyright © 2012 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#ifndef _AO_ARCH_FUNCS_H_ +#define _AO_ARCH_FUNCS_H_ + +/* ao_spi_stm.c + */ + +/* PCLK is set to 16MHz (HCLK 32MHz, APB prescaler 2) */ + +#define _AO_SPI_SPEED_8MHz STM_SPI_CR1_BR_PCLK_2 +#define _AO_SPI_SPEED_4MHz STM_SPI_CR1_BR_PCLK_4 +#define _AO_SPI_SPEED_2MHz STM_SPI_CR1_BR_PCLK_8 +#define _AO_SPI_SPEED_1MHz STM_SPI_CR1_BR_PCLK_16 +#define _AO_SPI_SPEED_500kHz STM_SPI_CR1_BR_PCLK_32 +#define _AO_SPI_SPEED_250kHz STM_SPI_CR1_BR_PCLK_64 +#define _AO_SPI_SPEED_125kHz STM_SPI_CR1_BR_PCLK_128 +#define _AO_SPI_SPEED_62500Hz STM_SPI_CR1_BR_PCLK_256 + +/* Companion bus wants something no faster than 200kHz */ + +static inline uint32_t +ao_spi_speed(uint32_t hz) +{ + if (hz >= 4000000) return _AO_SPI_SPEED_4MHz; + if (hz >= 2000000) return _AO_SPI_SPEED_2MHz; + if (hz >= 1000000) return _AO_SPI_SPEED_1MHz; + if (hz >= 500000) return _AO_SPI_SPEED_500kHz; + if (hz >= 250000) return _AO_SPI_SPEED_250kHz; + if (hz >= 125000) return _AO_SPI_SPEED_125kHz; + return _AO_SPI_SPEED_62500Hz; +} + +#define AO_SPI_CPOL_BIT 4 +#define AO_SPI_CPHA_BIT 5 + +#define AO_SPI_CONFIG_1 0x00 +#define AO_SPI_1_CONFIG_PA5_PA6_PA7 AO_SPI_CONFIG_1 + +#define AO_SPI_CONFIG_2 0x04 +#define AO_SPI_1_CONFIG_PA12_PA13_PA14 AO_SPI_CONFIG_2 +#define AO_SPI_2_CONFIG_PD1_PD3_PD4 AO_SPI_CONFIG_2 + +#define AO_SPI_CONFIG_3 0x08 +#define AO_SPI_1_CONFIG_PB3_PB4_PB5 AO_SPI_CONFIG_3 + +#define AO_SPI_CONFIG_NONE 0x0c + +#define AO_SPI_INDEX_MASK 0x01 +#define AO_SPI_CONFIG_MASK 0x0c + +#define AO_SPI_1_PA5_PA6_PA7 (STM_SPI_INDEX(1) | AO_SPI_1_CONFIG_PA5_PA6_PA7) +#define AO_SPI_1_PA12_PA13_PA14 (STM_SPI_INDEX(1) | AO_SPI_1_CONFIG_PA12_PA13_PA14) +#define AO_SPI_1_PB3_PB4_PB5 (STM_SPI_INDEX(1) | AO_SPI_1_CONFIG_PB3_PB4_PB5) + +#define AO_SPI_2_PB13_PB14_PB15 (STM_SPI_INDEX(2) | AO_SPI_2_CONFIG_PB13_PB14_PB15) +#define AO_SPI_2_PD1_PD3_PD4 (STM_SPI_INDEX(2) | AO_SPI_2_CONFIG_PD1_PD3_PD4) + +#define AO_SPI_INDEX(id) ((id) & AO_SPI_INDEX_MASK) +#define AO_SPI_CONFIG(id) ((id) & AO_SPI_CONFIG_MASK) +#define AO_SPI_PIN_CONFIG(id) ((id) & (AO_SPI_INDEX_MASK | AO_SPI_CONFIG_MASK)) +#define AO_SPI_CPOL(id) ((uint32_t) (((id) >> AO_SPI_CPOL_BIT) & 1)) +#define AO_SPI_CPHA(id) ((uint32_t) (((id) >> AO_SPI_CPHA_BIT) & 1)) + +#define AO_SPI_MAKE_MODE(pol,pha) (((pol) << AO_SPI_CPOL_BIT) | ((pha) << AO_SPI_CPHA_BIT)) +#define AO_SPI_MODE_0 AO_SPI_MAKE_MODE(0,0) +#define AO_SPI_MODE_1 AO_SPI_MAKE_MODE(0,1) +#define AO_SPI_MODE_2 AO_SPI_MAKE_MODE(1,0) +#define AO_SPI_MODE_3 AO_SPI_MAKE_MODE(1,1) + +uint8_t +ao_spi_try_get(uint8_t spi_index, uint32_t speed, uint8_t task_id); + +void +ao_spi_get(uint8_t spi_index, uint32_t speed); + +void +ao_spi_put(uint8_t spi_index); + +void +ao_spi_send(const void *block, uint16_t len, uint8_t spi_index); + +void +ao_spi_send_fixed(uint8_t value, uint16_t len, uint8_t spi_index); + +void +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) +{ + struct stm_spi *stm_spi = &stm_spi1; + (void) spi_index; + + 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; +} + +static inline uint8_t +ao_spi_recv_byte(uint8_t spi_index) +{ + struct stm_spi *stm_spi = &stm_spi1; + (void) spi_index; + + 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 +ao_spi_recv(void *block, uint16_t len, uint8_t spi_index); + +void +ao_spi_duplex(const void *out, void *in, uint16_t len, uint8_t spi_index); + +void +ao_spi_init(void); + +#define ao_spi_set_cs(reg,mask) ((reg)->bsrr = ((uint32_t) (mask)) << 16) +#define ao_spi_clr_cs(reg,mask) ((reg)->bsrr = (mask)) + +#define ao_spi_get_mask(reg,mask,bus, speed) do { \ + ao_spi_get(bus, speed); \ + ao_spi_set_cs(reg,mask); \ + } while (0) + +static inline uint8_t +ao_spi_try_get_mask(struct stm_gpio *reg, uint16_t mask, uint8_t bus, uint32_t speed, uint8_t task_id) +{ + if (!ao_spi_try_get(bus, speed, task_id)) + return 0; + ao_spi_set_cs(reg, mask); + return 1; +} + +#define ao_spi_put_mask(reg,mask,bus) do { \ + ao_spi_clr_cs(reg,mask); \ + ao_spi_put(bus); \ + } while (0) + +#define ao_spi_get_bit(reg,bit,bus,speed) ao_spi_get_mask(reg,(1< + +void +ao_debug_out(char c); + +#if HAS_SERIAL_1 +extern struct ao_stm_usart ao_stm_usart1; +#endif + +#if HAS_SERIAL_2 +extern struct ao_stm_usart ao_stm_usart2; +#endif + +#if HAS_SERIAL_3 +extern struct ao_stm_usart ao_stm_usart3; +#endif + +#define ARM_PUSH32(stack, val) (*(--(stack)) = (val)) + +typedef uint32_t ao_arch_irq_t; + +static inline void +ao_arch_block_interrupts(void) { +#ifdef AO_NONMASK_INTERRUPTS + asm("msr basepri,%0" : : "r" (AO_STM_NVIC_BASEPRI_MASK)); +#else + asm("cpsid i"); +#endif +} + +static inline void +ao_arch_release_interrupts(void) { +#ifdef AO_NONMASK_INTERRUPTS + asm("msr basepri,%0" : : "r" (0x0)); +#else + asm("cpsie i"); +#endif +} + +static inline uint32_t +ao_arch_irqsave(void) { + uint32_t val; +#ifdef AO_NONMASK_INTERRUPTS + asm("mrs %0,basepri" : "=r" (val)); +#else + asm("mrs %0,primask" : "=r" (val)); +#endif + ao_arch_block_interrupts(); + return val; +} + +static inline void +ao_arch_irqrestore(uint32_t basepri) { +#ifdef AO_NONMASK_INTERRUPTS + asm("msr basepri,%0" : : "r" (basepri)); +#else + asm("msr primask,%0" : : "r" (basepri)); +#endif +} + +static inline void +ao_arch_memory_barrier(void) { + asm volatile("" ::: "memory"); +} + +static inline void +ao_arch_irq_check(void) { +#ifdef AO_NONMASK_INTERRUPTS + uint32_t basepri; + asm("mrs %0,basepri" : "=r" (basepri)); + if (basepri == 0) + ao_panic(AO_PANIC_IRQ); +#else + uint32_t primask; + asm("mrs %0,primask" : "=r" (primask)); + if ((primask & 1) == 0) + ao_panic(AO_PANIC_IRQ); +#endif +} + +#if HAS_TASK +static inline void +ao_arch_init_stack(struct ao_task *task, void *start) +{ + uint32_t *sp = &task->stack32[AO_STACK_SIZE >> 2]; + uint32_t a = (uint32_t) start; + int i; + + /* Return address (goes into LR) */ + ARM_PUSH32(sp, a); + + /* Clear register values r0-r7 */ + i = 8; + while (i--) + ARM_PUSH32(sp, 0); + + /* APSR */ + ARM_PUSH32(sp, 0); + + /* PRIMASK with interrupts enabled */ + ARM_PUSH32(sp, 0); + + task->sp32 = sp; +} + +static inline void ao_arch_save_regs(void) { + /* Save general registers */ + asm("push {r0-r7,lr}\n"); + + /* Save APSR */ + asm("mrs r0,apsr"); + asm("push {r0}"); + + /* Save PRIMASK */ + asm("mrs r0,primask"); + asm("push {r0}"); +} + +static inline void ao_arch_save_stack(void) { + uint32_t *sp; + asm("mov %0,sp" : "=&r" (sp) ); + ao_cur_task->sp32 = (sp); +} + +static inline void ao_arch_restore_stack(void) { + /* Switch stacks */ + asm("mov sp, %0" : : "r" (ao_cur_task->sp32) ); + + /* Restore PRIMASK */ + asm("pop {r0}"); + asm("msr primask,r0"); + + /* Restore APSR */ + asm("pop {r0}"); + asm("msr apsr_nczvq,r0"); + + /* Restore general registers */ + asm("pop {r0-r7,pc}\n"); +} + +#ifndef HAS_SAMPLE_PROFILE +#define HAS_SAMPLE_PROFILE 0 +#endif + +#if DEBUG +#define HAS_ARCH_VALIDATE_CUR_STACK 1 + +static inline void +ao_validate_cur_stack(void) +{ + uint8_t *psp; + + asm("mrs %0,psp" : "=&r" (psp)); + if (ao_cur_task && + psp <= ao_cur_task->stack && + psp >= ao_cur_task->stack - 256) + ao_panic(AO_PANIC_STACK); +} +#endif + +#if !HAS_SAMPLE_PROFILE +#define HAS_ARCH_START_SCHEDULER 1 + +static inline void ao_arch_start_scheduler(void) { + uint32_t sp; + uint32_t control; + + asm("mrs %0,msp" : "=&r" (sp)); + asm("msr psp,%0" : : "r" (sp)); + asm("mrs %0,control" : "=r" (control)); + control |= (1 << 1); + asm("msr control,%0" : : "r" (control)); + asm("isb"); +} +#endif + +#define ao_arch_isr_stack() + +#endif + +static inline void +ao_arch_wait_interrupt(void) { +#ifdef AO_NONMASK_INTERRUPTS + asm( + "dsb\n" /* Serialize data */ + "isb\n" /* Serialize instructions */ + "cpsid i\n" /* Block all interrupts */ + "msr basepri,%0\n" /* Allow all interrupts through basepri */ + "wfi\n" /* Wait for an interrupt */ + "cpsie i\n" /* Allow all interrupts */ + "msr basepri,%1\n" /* Block interrupts through basepri */ + : : "r" (0), "r" (AO_STM_NVIC_BASEPRI_MASK)); +#else + asm("\twfi\n"); + ao_arch_release_interrupts(); + ao_arch_block_interrupts(); +#endif +} + +#define ao_arch_critical(b) do { \ + uint32_t __mask = ao_arch_irqsave(); \ + do { b } while (0); \ + ao_arch_irqrestore(__mask); \ + } while (0) + +void start(void); + +bool +ao_storage_device_is_erased(uint32_t pos); + +#endif /* _AO_ARCH_FUNCS_H_ */ diff --git a/src/stm32l0/ao_dma_stm32l0.c b/src/stm32l0/ao_dma_stm32l0.c new file mode 100644 index 00000000..d32844c3 --- /dev/null +++ b/src/stm32l0/ao_dma_stm32l0.c @@ -0,0 +1,204 @@ +/* + * Copyright © 2012 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include "ao.h" + +#define NUM_DMA 7 + +struct ao_dma_config { + void (*isr)(int index); +}; + +uint8_t ao_dma_done[NUM_DMA]; + +static struct ao_dma_config ao_dma_config[NUM_DMA]; +static uint8_t ao_dma_allocated[NUM_DMA]; +static uint8_t ao_dma_mutex[NUM_DMA]; +static uint8_t ao_dma_active; + +#ifndef LEAVE_DMA_ON +static uint8_t ao_dma_active; +#endif + +#define ch_mask(id) (STM_DMA_ISR_MASK << STM_DMA_ISR(id)) + +static void +ao_dma_isr(uint8_t low_index, uint8_t high_index, uint32_t mask) { + /* Get channel interrupt bits */ + uint32_t isr = stm_dma1.isr & mask; + uint8_t index; + + /* Ack them */ + stm_dma1.ifcr = isr; + for (index = low_index; index <= high_index; index++) { + if (isr & ch_mask(index)) { + if (ao_dma_config[index].isr) + (*ao_dma_config[index].isr)(index); + else { + ao_dma_done[index] = 1; + ao_wakeup(&ao_dma_done[index]); + } + } + } +} + +void stm_dma1_channel1_isr(void) { + ao_dma_isr(STM_DMA_INDEX(1), + STM_DMA_INDEX(1), + ch_mask(STM_DMA_INDEX(1))); +} + +void stm_dma1_channel3_2_isr(void) { + ao_dma_isr(STM_DMA_INDEX(2), + STM_DMA_INDEX(3), + ch_mask(STM_DMA_INDEX(2)) | + ch_mask(STM_DMA_INDEX(3))); +} + +void stm_dma1_channel7_4_isr(void) { + ao_dma_isr(STM_DMA_INDEX(4), STM_DMA_INDEX(7), + ch_mask(STM_DMA_INDEX(4)) | + ch_mask(STM_DMA_INDEX(5)) | + ch_mask(STM_DMA_INDEX(6)) | + ch_mask(STM_DMA_INDEX(7))); +} + +void +ao_dma_set_transfer(uint8_t index, + volatile void *peripheral, + void *memory, + uint16_t count, + uint32_t ccr) +{ + if (ao_dma_allocated[index]) { + if (ao_dma_mutex[index]) + ao_panic(AO_PANIC_DMA); + ao_dma_mutex[index] = 0xff; + } else + ao_mutex_get(&ao_dma_mutex[index]); +#ifndef LEAVE_DMA_ON + ao_arch_critical( + if (ao_dma_active++ == 0) + stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_DMA1EN); + ); +#endif + stm_dma1.channel[index].ccr = ccr | (1 << STM_DMA_CCR_TCIE); + stm_dma1.channel[index].cndtr = count; + stm_dma1.channel[index].cpar = peripheral; + stm_dma1.channel[index].cmar = memory; + ao_dma_config[index].isr = NULL; +} + +void +ao_dma_set_isr(uint8_t index, void (*isr)(int)) +{ + ao_dma_config[index].isr = isr; +} + +void +ao_dma_start(uint8_t index) +{ + ao_dma_done[index] = 0; + stm_dma1.channel[index].ccr |= (1 << STM_DMA_CCR_EN); +} + +void +ao_dma_done_transfer(uint8_t index) +{ + stm_dma1.channel[index].ccr &= ~(1 << STM_DMA_CCR_EN); +#ifndef LEAVE_DMA_ON + ao_arch_critical( + if (--ao_dma_active == 0) + stm_rcc.ahbenr &= ~(1 << STM_RCC_AHBENR_DMA1EN); + ); +#endif + if (ao_dma_allocated[index]) + ao_dma_mutex[index] = 0; + else + ao_mutex_put(&ao_dma_mutex[index]); +} + +void +ao_dma_alloc(uint8_t index, uint8_t cselr) +{ + if (ao_dma_allocated[index]) + ao_panic(AO_PANIC_DMA); + ao_dma_allocated[index] = 1; + + int shift = (index << 2); + uint32_t mask = ~(0xf << shift); + stm_dma1.cselr = (stm_dma1.cselr & mask) | (cselr << shift); +} + +#if DEBUG +void +ao_dma_dump_cmd(void) +{ + int i; + +#ifndef LEAVE_DMA_ON + ao_arch_critical( + if (ao_dma_active++ == 0) + stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_DMA1EN); + ); +#endif + printf ("isr %08x ifcr%08x\n", stm_dma1.isr, stm_dma1.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_dma1.channel[i].ccr, + stm_dma1.channel[i].cndtr, + stm_dma1.channel[i].cpar, + stm_dma1.channel[i].cmar, + ao_dma_config[i].isr); +#ifndef LEAVE_DMA_ON + ao_arch_critical( + if (--ao_dma_active == 0) + stm_rcc.ahbenr &= ~(1 << STM_RCC_AHBENR_DMA1EN); + ); +#endif +} + +static const struct ao_cmds ao_dma_cmds[] = { + { ao_dma_dump_cmd, "D\0Dump DMA status" }, + { 0, NULL } +}; +#endif + +void +ao_dma_init(void) +{ + int index; + +#ifdef LEAVE_DMA_ON + stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_DMA1EN); +#endif + for (index = 0; index < STM_NUM_DMA; index++) { + stm_nvic_set_enable(STM_ISR_DMA1_CHANNEL1_POS + index); + stm_nvic_set_priority(STM_ISR_DMA1_CHANNEL1_POS + index, + AO_STM_NVIC_MED_PRIORITY); + ao_dma_allocated[index] = 0; + ao_dma_mutex[index] = 0; + } +#if DEBUG + ao_cmd_register(&ao_dma_cmds[0]); +#endif +} diff --git a/src/stm32l0/ao_exti.h b/src/stm32l0/ao_exti.h new file mode 100644 index 00000000..1d19a48f --- /dev/null +++ b/src/stm32l0/ao_exti.h @@ -0,0 +1,50 @@ +/* + * Copyright © 2012 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#ifndef _AO_EXTI_H_ +#define _AO_EXTI_H_ + +#define AO_EXTI_MODE_RISING 1 +#define AO_EXTI_MODE_FALLING 2 +#define AO_EXTI_MODE_PULL_NONE 0 +#define AO_EXTI_MODE_PULL_UP 4 +#define AO_EXTI_MODE_PULL_DOWN 8 +#define AO_EXTI_PRIORITY_LOW 16 +#define AO_EXTI_PRIORITY_MED 0 +#define AO_EXTI_PRIORITY_HIGH 32 +#define AO_EXTI_PIN_NOCONFIGURE 64 + +void +ao_exti_setup(struct stm_gpio *gpio, uint8_t pin, uint8_t mode, void (*callback)(void)); + +void +ao_exti_set_mode(struct stm_gpio *gpio, uint8_t pin, uint8_t mode); + +void +ao_exti_set_callback(struct stm_gpio *gpio, uint8_t pin, void (*callback)(void)); + +void +ao_exti_enable(struct stm_gpio *gpio, uint8_t pin); + +void +ao_exti_disable(struct stm_gpio *gpio, uint8_t pin); + +void +ao_exti_init(void); + +#endif /* _AO_EXTI_H_ */ diff --git a/src/stm32l0/ao_exti_stm.c b/src/stm32l0/ao_exti_stm.c new file mode 100644 index 00000000..d808d1e9 --- /dev/null +++ b/src/stm32l0/ao_exti_stm.c @@ -0,0 +1,152 @@ +/* + * Copyright © 2012 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include +#include + +static void (*ao_exti_callback[16])(void); + +uint32_t ao_last_exti; + +static void ao_exti_range_isr(uint8_t first, uint8_t last, uint16_t mask) { + uint16_t pending = (ao_last_exti = stm_exti.pr) & mask; + uint8_t pin; + static uint16_t last_mask; + static uint8_t last_pin; + + if (pending == last_mask) { + stm_exti.pr = last_mask; + (*ao_exti_callback[last_pin])(); + return; + } + stm_exti.pr = pending; + for (pin = first; pin <= last; pin++) + if ((pending & ((uint32_t) 1 << pin)) && ao_exti_callback[pin]) { + last_mask = (1 << pin); + last_pin = pin; + (*ao_exti_callback[pin])(); + } +} + +void stm_exti1_0_isr(void) { ao_exti_range_isr(0, 1, 0x3); } +void stm_exti3_2_isr(void) { ao_exti_range_isr(2, 3, 0xc); } +void stm_exti15_4_isr(void) { ao_exti_range_isr(4, 15, 0xfff0); } + +void +ao_exti_setup (struct stm_gpio *gpio, uint8_t pin, uint8_t mode, void (*callback)(void)) { + uint32_t mask = 1 << pin; + uint8_t irq; + uint8_t prio; + + ao_exti_callback[pin] = callback; + + /* configure gpio to interrupt routing */ + stm_exticr_set(gpio, pin); + +#if 0 + if (!(mode & AO_EXTI_PIN_NOCONFIGURE)) { + uint32_t pupdr; + /* configure pin as input, setting selected pull-up/down mode */ + stm_moder_set(gpio, pin, STM_MODER_INPUT); + switch (mode & (AO_EXTI_MODE_PULL_UP|AO_EXTI_MODE_PULL_DOWN)) { + case 0: + default: + pupdr = STM_PUPDR_NONE; + break; + case AO_EXTI_MODE_PULL_UP: + pupdr = STM_PUPDR_PULL_UP; + break; + case AO_EXTI_MODE_PULL_DOWN: + pupdr = STM_PUPDR_PULL_DOWN; + break; + } + stm_pupdr_set(gpio, pin, pupdr); + } +#endif + + /* Set interrupt mask and rising/falling mode */ + stm_exti.imr &= ~mask; + if (mode & AO_EXTI_MODE_RISING) + stm_exti.rtsr |= mask; + else + stm_exti.rtsr &= ~mask; + if (mode & AO_EXTI_MODE_FALLING) + stm_exti.ftsr |= mask; + else + stm_exti.ftsr &= ~mask; + + if (pin <= 1) + irq = STM_ISR_EXTI1_0_POS; + else if (2 <= pin && pin <= 3) + irq = STM_ISR_EXTI3_2_POS; + else + irq = STM_ISR_EXTI15_4_POS; + + /* Set priority */ + prio = AO_STM_NVIC_MED_PRIORITY; + if (mode & AO_EXTI_PRIORITY_LOW) + prio = AO_STM_NVIC_LOW_PRIORITY; + else if (mode & AO_EXTI_PRIORITY_HIGH) + prio = AO_STM_NVIC_HIGH_PRIORITY; + + stm_nvic_set_priority(irq, prio); + stm_nvic_set_enable(irq); +} + +void +ao_exti_set_mode(struct stm_gpio *gpio, uint8_t pin, uint8_t mode) { + (void) gpio; + + uint32_t mask = 1 << pin; + + if (mode & AO_EXTI_MODE_RISING) + stm_exti.rtsr |= mask; + else + stm_exti.rtsr &= ~mask; + if (mode & AO_EXTI_MODE_FALLING) + stm_exti.ftsr |= mask; + else + stm_exti.ftsr &= ~mask; +} + +void +ao_exti_set_callback(struct stm_gpio *gpio, uint8_t pin, void (*callback)(void)) { + (void) gpio; + ao_exti_callback[pin] = callback; +} + +void +ao_exti_enable(struct stm_gpio *gpio, uint8_t pin) { + uint32_t mask = (1 << pin); + (void) gpio; + stm_exti.pr = mask; + stm_exti.imr |= mask; +} + +void +ao_exti_disable(struct stm_gpio *gpio, uint8_t pin) { + uint32_t mask = (1 << pin); + (void) gpio; + stm_exti.imr &= ~mask; + stm_exti.pr = mask; +} + +void +ao_exti_init(void) +{ +} diff --git a/src/stm32l0/ao_flash.h b/src/stm32l0/ao_flash.h new file mode 100644 index 00000000..274d6fed --- /dev/null +++ b/src/stm32l0/ao_flash.h @@ -0,0 +1,28 @@ +/* + * Copyright © 2020 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#ifndef _AO_FLASH_H_ +#define _AO_FLASH_H_ + +void +ao_flash_erase_page(uint32_t *page); + +void +ao_flash_page(uint32_t *page, uint32_t *src); + +#endif /* _AO_FLASH_H_ */ diff --git a/src/stm32l0/ao_flash_stm32l0.c b/src/stm32l0/ao_flash_stm32l0.c new file mode 100644 index 00000000..ba327442 --- /dev/null +++ b/src/stm32l0/ao_flash_stm32l0.c @@ -0,0 +1,226 @@ +/* + * Copyright © 2020 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include +#include + +static uint8_t +ao_flash_pecr_is_locked(void) +{ + return (stm_flash.pecr & (1 << STM_FLASH_PECR_PE_LOCK)) != 0; +} + +static uint8_t +ao_flash_pgr_is_locked(void) +{ + return (stm_flash.pecr & (1 << STM_FLASH_PECR_PRG_LOCK)) != 0; +} + +static void +ao_flash_pecr_unlock(void) +{ + if (!ao_flash_pecr_is_locked()) + return; + + /* Unlock Data EEPROM and FLASH_PECR register */ + stm_flash.pekeyr = STM_FLASH_PEKEYR_PEKEY1; + stm_flash.pekeyr = STM_FLASH_PEKEYR_PEKEY2; + if (ao_flash_pecr_is_locked()) + ao_panic(AO_PANIC_FLASH); +} + +static void +ao_flash_pgr_unlock(void) +{ + if (!ao_flash_pgr_is_locked()) + return; + + /* Unlock program memory */ + stm_flash.prgkeyr = STM_FLASH_PRGKEYR_PRGKEY1; + stm_flash.prgkeyr = STM_FLASH_PRGKEYR_PRGKEY2; + if (ao_flash_pgr_is_locked()) + ao_panic(AO_PANIC_FLASH); +} + +static void +ao_flash_lock(void) +{ + stm_flash.pecr |= (1 << STM_FLASH_PECR_OPT_LOCK) | (1 << STM_FLASH_PECR_PRG_LOCK) | (1 << STM_FLASH_PECR_PE_LOCK); +} + +static void +ao_flash_wait_bsy(void) +{ + while (stm_flash.sr & (1 << STM_FLASH_SR_BSY)) + ; +} + +static void __attribute__ ((section(".sdata2.flash"), noinline)) +_ao_flash_erase_page(uint32_t *page) +{ + stm_flash.pecr |= (1 << STM_FLASH_PECR_ERASE) | (1 << STM_FLASH_PECR_PROG); + + *page = 0x00000000; + + ao_flash_wait_bsy(); +} + +void +ao_flash_erase_page(uint32_t *page) +{ + ao_arch_block_interrupts(); + ao_flash_pecr_unlock(); + ao_flash_pgr_unlock(); + + _ao_flash_erase_page(page); + + ao_flash_lock(); + ao_arch_release_interrupts(); +} + +#if 0 +static void __attribute__ ((section(".sdata2.flash"), noinline)) +_ao_flash_half_page(uint32_t *dst, uint32_t *src) +{ + uint8_t i; + + stm_flash.pecr |= (1 << STM_FLASH_PECR_FPRG); + stm_flash.pecr |= (1 << STM_FLASH_PECR_PROG); + + ao_flash_wait_bsy(); + + for (i = 0; i < 32; i++) { + *dst++ = *src++; + } + + while (stm_flash.sr & (1 << STM_FLASH_SR_BSY)) + ; +} + +void +ao_flash_page(uint32_t *page, uint32_t *src) +{ + uint8_t h; + + ao_flash_erase_page(page); + + ao_arch_block_interrupts(); + ao_flash_pecr_unlock(); + ao_flash_pgr_unlock(); + for (h = 0; h < 2; h++) { + _ao_flash_half_page(page, src); + page += 32; + src += 32; + } + ao_flash_lock(); + ao_arch_release_interrupts(); +} +#endif + +static ao_pos_t write_pos; +static uint8_t write_pending; +static union { + uint32_t u32; + uint8_t u8[4]; +} write_buf; + +void +ao_storage_flush(void) +{ + if (write_pending) { + ao_flash_pecr_unlock(); + ao_flash_pgr_unlock(); + __storage[write_pos] = write_buf.u32; + ao_flash_lock(); + write_pending = 0; + } +} + +/* Read data within a storage unit */ +uint8_t +ao_storage_device_read(ao_pos_t pos, void *buf, uint16_t len) +{ + memcpy(buf, ((uint8_t *) __storage) + pos, len); + return 1; +} + +static void +flash_write_select(ao_pos_t pos) +{ + /* Flush any pending writes to another word */ + if (write_pending) { + if (pos == write_pos) + return; + __storage[write_pos] = write_buf.u32; + write_pending = 0; + } + write_pos = pos; +} + +/* Write data within a storage unit */ +uint8_t +ao_storage_device_write(ao_pos_t pos, void *buf, uint16_t len) +{ + uint8_t *b8 = buf; + + ao_flash_pecr_unlock(); + ao_flash_pgr_unlock(); + while (len) { + ao_pos_t this_pos = pos >> 2; + + flash_write_select(this_pos); + + /* Update write buffer with new contents */ + int this_word = 4 - (pos & 3); + if (this_word > len) + this_word = len; + memcpy(&write_buf.u8[pos & 3], b8, this_word); + pos += this_word; + len -= this_word; + b8 += this_word; + + /* If we filled the buffer, flush it out */ + if ((pos & 3) == 0) { + __storage[write_pos] = write_buf.u32; + } else { + write_pending = 1; + } + } + ao_flash_lock(); + return 1; +} + +bool +ao_storage_device_is_erased(uint32_t pos) +{ + uint8_t *m = ((uint8_t *) __storage) + pos; + uint32_t i; + + for (i = 0; i < STM_FLASH_PAGE_SIZE; i++) + if (*m++ != AO_STORAGE_ERASED_BYTE) + return false; + return true; +} + +/* Erase device from pos through pos + ao_storage_block */ +uint8_t +ao_storage_device_erase(uint32_t pos) +{ + ao_flash_erase_page(__storage + (pos >> 2)); + return 1; +} diff --git a/src/stm32l0/ao_interrupt.c b/src/stm32l0/ao_interrupt.c new file mode 100644 index 00000000..47effe5f --- /dev/null +++ b/src/stm32l0/ao_interrupt.c @@ -0,0 +1,153 @@ +/* + * Copyright © 2012 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include +#include +#include + +/* Interrupt functions */ + +void stm_halt_isr(void) +{ + ao_panic(AO_PANIC_CRASH); +} + +void stm_ignore_isr(void) +{ +} + +void _start(void); + +#define STRINGIFY(x) #x + +#define isr(name) \ + void __attribute__ ((weak)) stm_ ## name ## _isr(void); \ + _Pragma(STRINGIFY(weak stm_ ## name ## _isr = stm_ignore_isr)) + +#define isr_halt(name) \ + void __attribute__ ((weak)) stm_ ## name ## _isr(void); \ + _Pragma(STRINGIFY(weak stm_ ## name ## _isr = stm_halt_isr)) + +isr(nmi) +isr_halt(hardfault) +isr_halt(memmanage) +isr_halt(busfault) +isr_halt(usagefault) +isr(svc) +isr(debugmon) +isr(pendsv) +isr(systick) +isr(wwdg) +isr(pvd) +isr(rtc) +isr(flash) +isr(rcc_crs) +isr(exti1_0) +isr(exti3_2) +isr(exti15_4) +isr(dma1_channel1) +isr(dma1_channel3_2) +isr(dma1_channel7_4) +isr(adc_comp) +isr(lptim1) +isr(usart4_usart5) +isr(tim2) +isr(tim3) +isr(tim4) +isr(tim6) +isr(tim7) +isr(tim21) +isr(i2c3) +isr(tim22) +isr(i2c1) +isr(i2c2) +isr(spi1) +isr(spi2) +isr(usart1) +isr(usart2) +isr(usart3) +isr(lpuart1_aes) + +#define i(addr,name) [(addr)/4] = stm_ ## name ## _isr + +extern char __stack[]; +void _start(void) __attribute__((__noreturn__)); +void main(void) __attribute__((__noreturn__)); + +__attribute__ ((section(".init"))) +const void *const __interrupt_vector[] = { + [0] = &__stack, + [1] = _start, + i(0x08, nmi), + i(0x0c, hardfault), + i(0x2c, svc), + i(0x38, pendsv), + i(0x3c, systick), + i(0x40, wwdg), + i(0x44, pvd), + i(0x48, rtc), + i(0x4c, flash), + i(0x50, rcc_crs), + i(0x54, exti1_0), + i(0x58, exti3_2), + i(0x5c, exti15_4), + i(0x64, dma1_channel1), + i(0x68, dma1_channel3_2), + i(0x6c, dma1_channel7_4), + i(0x70, adc_comp), + i(0x74, lptim1), + i(0x78, usart4_usart5), + i(0x7c, tim2), + i(0x80, tim3), + i(0x84, tim6), + i(0x88, tim7), + i(0x90, tim21), + i(0x94, i2c3), + i(0x98, tim22), + i(0x9c, i2c1), + i(0xa0, i2c2), + i(0xa4, spi1), + i(0xa8, spi2), + i(0xac, usart1), + i(0xb0, usart2), + i(0xb4, lpuart1_aes), +}; + +extern char __data_source[]; +extern char __data_start[]; +extern char __data_size[]; +extern char __bss_start[]; +extern char __bss_size[]; + +void _start(void) +{ +#ifdef AO_BOOT_CHAIN + if (ao_boot_check_chain()) { +#ifdef AO_BOOT_PIN + if (ao_boot_check_pin()) +#endif + { + ao_boot_chain(AO_BOOT_APPLICATION_BASE); + } + } +#endif + memcpy(__data_start, __data_source, (uintptr_t) __data_size); + memset(__bss_start, '\0', (uintptr_t) __bss_size); + + main(); +} diff --git a/src/stm32l0/ao_lpuart.h b/src/stm32l0/ao_lpuart.h new file mode 100644 index 00000000..567eda7e --- /dev/null +++ b/src/stm32l0/ao_lpuart.h @@ -0,0 +1,34 @@ +/* + * Copyright © 2020 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + */ + +char +ao_lpuart1_getchar(void); + +void +ao_lpuart1_putchar(char c); + +int +_ao_lpuart1_pollchar(void); + +void +ao_lpuart1_drain(void); + +void +ao_lpuart1_set_speed(uint8_t speed); + +void +ao_lpuart1_enable(void); + +void +ao_lpuart1_disable(void); diff --git a/src/stm32l0/ao_lpuart_stm.c b/src/stm32l0/ao_lpuart_stm.c new file mode 100644 index 00000000..c4a23f5b --- /dev/null +++ b/src/stm32l0/ao_lpuart_stm.c @@ -0,0 +1,375 @@ +/* + * Copyright © 2020 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + */ + +#include +#include +#include + +struct ao_stm_lpuart { + struct ao_fifo rx_fifo; + struct ao_fifo tx_fifo; + struct stm_lpuart *reg; + uint8_t tx_running; + uint8_t draining; +#if HAS_SERIAL_SW_FLOW + /* RTS - 0 if we have FIFO space, 1 if not + * CTS - 0 if we can send, 0 if not + */ + struct stm_gpio *gpio_rts; + struct stm_gpio *gpio_cts; + uint8_t pin_rts; + uint8_t pin_cts; + uint8_t rts; +#endif +}; + +static int +_ao_lpuart_tx_start(struct ao_stm_lpuart *lpuart) +{ + if (!ao_fifo_empty(lpuart->tx_fifo)) { +#if HAS_LPUART_SW_FLOW + if (lpuart->gpio_cts && ao_gpio_get(lpuart->gpio_cts, lpuart->pin_cts) == 1) { + ao_exti_enable(lpuart->gpio_cts, lpuart->pin_cts); + return 0; + } +#endif + if (lpuart->reg->isr & (1 << STM_LPUART_ISR_TXE)) + { + lpuart->tx_running = 1; + lpuart->reg->cr1 |= (1 << STM_LPUART_CR1_TXEIE) | (1 << STM_LPUART_CR1_TCIE); + ao_fifo_remove(lpuart->tx_fifo, lpuart->reg->tdr); + ao_wakeup(&lpuart->tx_fifo); + return 1; + } + } + return 0; +} + +#if HAS_LPUART_SW_FLOW +static void +_ao_lpuart_cts(struct ao_stm_lpuart *lpuart) +{ + if (_ao_lpuart_tx_start(lpuart)) + ao_exti_disable(lpuart->gpio_cts, lpuart->pin_cts); +} +#endif + +static void +_ao_lpuart_rx(struct ao_stm_lpuart *lpuart, int is_stdin) +{ + if (lpuart->reg->isr & (1 << STM_LPUART_ISR_RXNE)) { + lpuart->reg->icr = (1 << STM_LPUART_ICR_ORECF); + if (!ao_fifo_full(lpuart->rx_fifo)) { + ao_fifo_insert(lpuart->rx_fifo, lpuart->reg->rdr); + ao_wakeup(&lpuart->rx_fifo); + if (is_stdin) + ao_wakeup(&ao_stdin_ready); +#if HAS_LPUART_SW_FLOW + /* If the fifo is nearly full, turn off RTS and wait + * for it to drain a bunch + */ + if (lpuart->gpio_rts && ao_fifo_mostly(lpuart->rx_fifo)) { + ao_gpio_set(lpuart->gpio_rts, lpuart->pin_rts, 1); + lpuart->rts = 0; + } +#endif + } else { + lpuart->reg->cr1 &= ~(1 << STM_LPUART_CR1_RXNEIE); + } + } +} + +static void +ao_lpuart_isr(struct ao_stm_lpuart *lpuart, int is_stdin) +{ + _ao_lpuart_rx(lpuart, is_stdin); + + if (!_ao_lpuart_tx_start(lpuart)) + lpuart->reg->cr1 &= ~(1<< STM_LPUART_CR1_TXEIE); + + if (lpuart->reg->isr & (1 << STM_LPUART_ISR_TC)) { + lpuart->tx_running = 0; + lpuart->reg->cr1 &= ~(1 << STM_LPUART_CR1_TCIE); + if (lpuart->draining) { + lpuart->draining = 0; + ao_wakeup(&lpuart->tx_fifo); + } + } +} + +static int +_ao_lpuart_pollchar(struct ao_stm_lpuart *lpuart) +{ + int c; + + if (ao_fifo_empty(lpuart->rx_fifo)) + c = AO_READ_AGAIN; + else { + uint8_t u; + ao_fifo_remove(lpuart->rx_fifo,u); + if ((lpuart->reg->cr1 & (1 << STM_LPUART_CR1_RXNEIE)) == 0) { + if (ao_fifo_barely(lpuart->rx_fifo)) + lpuart->reg->cr1 |= (1 << STM_LPUART_CR1_RXNEIE); + } +#if HAS_LPUART_SW_FLOW + /* If we've cleared RTS, check if there's space now and turn it back on */ + if (lpuart->gpio_rts && lpuart->rts == 0 && ao_fifo_barely(lpuart->rx_fifo)) { + ao_gpio_set(lpuart->gpio_rts, lpuart->pin_rts, 0); + lpuart->rts = 1; + } +#endif + c = u; + } + return c; +} + +static char +ao_lpuart_getchar(struct ao_stm_lpuart *lpuart) +{ + int c; + ao_arch_block_interrupts(); + while ((c = _ao_lpuart_pollchar(lpuart)) == AO_READ_AGAIN) + ao_sleep(&lpuart->rx_fifo); + ao_arch_release_interrupts(); + return (char) c; +} + +#if 0 +static inline uint8_t +_ao_lpuart_sleep_for(struct ao_stm_lpuart *lpuart, uint16_t timeout) +{ + return ao_sleep_for(&lpuart->rx_fifo, timeout); +} +#endif + +static void +ao_lpuart_putchar(struct ao_stm_lpuart *lpuart, char c) +{ + ao_arch_block_interrupts(); + while (ao_fifo_full(lpuart->tx_fifo)) + ao_sleep(&lpuart->tx_fifo); + ao_fifo_insert(lpuart->tx_fifo, c); + _ao_lpuart_tx_start(lpuart); + ao_arch_release_interrupts(); +} + +static void +ao_lpuart_drain(struct ao_stm_lpuart *lpuart) +{ + ao_arch_block_interrupts(); + while (!ao_fifo_empty(lpuart->tx_fifo) || lpuart->tx_running) { + lpuart->draining = 1; + ao_sleep(&lpuart->tx_fifo); + } + ao_arch_release_interrupts(); +} + +extern const uint32_t ao_usart_speeds[]; + +static void +ao_lpuart_set_speed(struct ao_stm_lpuart *lpuart, uint8_t speed) +{ + if (speed > AO_SERIAL_SPEED_115200) + return; + lpuart->reg->brr = 256 * AO_PCLK1 / ao_usart_speeds[speed]; +} + +static void +ao_lpuart_enable(struct ao_stm_lpuart *lpuart, int hw_flow) +{ + lpuart->reg->cr1 = ((0 << STM_LPUART_CR1_M1) | + (0 << STM_LPUART_CR1_DEAT) | + (0 << STM_LPUART_CR1_DEDT) | + (0 << STM_LPUART_CR1_CMIE) | + (0 << STM_LPUART_CR1_MME) | + (0 << STM_LPUART_CR1_M0) | + (0 << STM_LPUART_CR1_WAKE) | + (0 << STM_LPUART_CR1_PCE) | + (0 << STM_LPUART_CR1_PS) | + (0 << STM_LPUART_CR1_PEIE) | + (0 << STM_LPUART_CR1_TXEIE) | + (0 << STM_LPUART_CR1_TCIE) | + (1 << STM_LPUART_CR1_RXNEIE) | + (0 << STM_LPUART_CR1_IDLEIE) | + (1 << STM_LPUART_CR1_TE) | + (1 << STM_LPUART_CR1_RE) | + (0 << STM_LPUART_CR1_UESM) | + (0 << STM_LPUART_CR1_UE)); + + lpuart->reg->cr2 = ((0 << STM_LPUART_CR2_ADD) | + (0 << STM_LPUART_CR2_MSBFIRST) | + (0 << STM_LPUART_CR2_DATAINV) | + (0 << STM_LPUART_CR2_TXINV) | + (0 << STM_LPUART_CR2_RXINV) | + (0 << STM_LPUART_CR2_SWAP) | + (0 << STM_LPUART_CR2_STOP) | + (0 << STM_LPUART_CR2_ADDM7)); + + uint32_t cr3 = ((0 << STM_LPUART_CR3_UCESM) | + (0 << STM_LPUART_CR3_WUFIE) | + (0 << STM_LPUART_CR3_WUS) | + (0 << STM_LPUART_CR3_DEP) | + (0 << STM_LPUART_CR3_DEM) | + (0 << STM_LPUART_CR3_DDRE) | + (0 << STM_LPUART_CR3_OVRDIS) | + (0 << STM_LPUART_CR3_CTSIE) | + (0 << STM_LPUART_CR3_CTSE) | + (0 << STM_LPUART_CR3_RTSE) | + (0 << STM_LPUART_CR3_DMAT) | + (0 << STM_LPUART_CR3_DMAR) | + (0 << STM_LPUART_CR3_HDSEL) | + (0 << STM_LPUART_CR3_EIE)); + + if (hw_flow) + cr3 |= ((1 << STM_LPUART_CR3_CTSE) | + (1 << STM_LPUART_CR3_RTSE)); + + lpuart->reg->cr3 = cr3; + + /* Pick a 9600 baud rate */ + ao_lpuart_set_speed(lpuart, AO_SERIAL_SPEED_9600); + + /* Enable the lpuart */ + lpuart->reg->cr1 |= (1 << STM_LPUART_CR1_UE); +} + +static void +ao_lpuart_disable(struct ao_stm_lpuart *lpuart) +{ + ao_lpuart_drain(lpuart); + lpuart->reg->cr1 = 0; +} + +#if HAS_LPUART_1 + +struct ao_stm_lpuart ao_stm_lpuart1; + +void stm_lpuart1_aes_isr(void) { + ao_lpuart_isr(&ao_stm_lpuart1, USE_LPUART_1_STDIN); +} + +char +ao_lpuart1_getchar(void) +{ + return ao_lpuart_getchar(&ao_stm_lpuart1); +} + +void +ao_lpuart1_putchar(char c) +{ + ao_lpuart_putchar(&ao_stm_lpuart1, c); +} + +int +_ao_lpuart1_pollchar(void) +{ + return _ao_lpuart_pollchar(&ao_stm_lpuart1); +} + +void +ao_lpuart1_drain(void) +{ + ao_lpuart_drain(&ao_stm_lpuart1); +} + +void +ao_lpuart1_set_speed(uint8_t speed) +{ + ao_lpuart_drain(&ao_stm_lpuart1); + ao_lpuart_set_speed(&ao_stm_lpuart1, speed); +} + +#endif /* HAS_LPUART_1 */ + +#if HAS_LPUART_SW_FLOW +static void +ao_lpuart_set_sw_rts_cts(struct ao_stm_lpuart *lpuart, + void (*isr)(void), + struct stm_gpio *port_rts, + int pin_rts, + struct stm_gpio *port_cts, + int pin_cts) +{ + /* Pull RTS low to note that there's space in the FIFO + */ + ao_enable_output(port_rts, pin_rts, 0); + lpuart->gpio_rts = port_rts; + lpuart->pin_rts = pin_rts; + lpuart->rts = 1; + + ao_exti_setup(port_cts, pin_cts, AO_EXTI_MODE_FALLING|AO_EXTI_PRIORITY_MED, isr); + lpuart->gpio_cts = port_cts; + lpuart->pin_cts = pin_cts; +} +#endif + +void +ao_lpuart1_enable(void) +{ + /* + * TX RX + * PA1 PA0 + * PA2 PA3 + * PA4 PA3 + * PA14 PA13 + * PB6 PB7 + */ + +#ifdef HAS_LPUART_1 + /* Clock source defaults to PCLK1, so just leave it */ + +# if LPUART_1_PA0_PA1 + ao_enable_port(&stm_gpioa); + stm_afr_set(&stm_gpioa, 0, STM_AFR_AF6); + stm_afr_set(&stm_gpioa, 1, STM_AFR_AF6); +# else +# error "No LPUART_1 port configuration specified" +# endif + /* Enable LPUART */ + stm_rcc.apb1enr |= (1 << STM_RCC_APB1ENR_LPUART1EN); + + ao_stm_lpuart1.reg = &stm_lpuart1; + ao_lpuart_enable(&ao_stm_lpuart1, USE_LPUART_1_FLOW && !USE_LPUART_1_SW_FLOW); + + stm_nvic_set_enable(STM_ISR_LPUART1_AES_POS); + stm_nvic_set_priority(STM_ISR_LPUART1_AES_POS, 4); +# if USE_LPUART_1_STDIN && !DELAY_LPUART_1_STDIN + ao_add_stdio(_ao_lpuart1_pollchar, + ao_lpuart1_putchar, + NULL); +# endif +#endif +} + +void +ao_lpuart1_disable(void) +{ + /* Stop LPUART */ + ao_lpuart_disable(&ao_stm_lpuart1); + + /* Disable interrupts */ + stm_nvic_clear_enable(STM_ISR_LPUART1_AES_POS); + + /* Remap pins to GPIO use */ +# if LPUART_1_PA0_PA1 + stm_moder_set(&stm_gpioa, 0, STM_MODER_INPUT); + stm_moder_set(&stm_gpioa, 1, STM_MODER_OUTPUT); +# else +# error "No LPUART_1 port configuration specified" +# endif + + /* Disable LPUART */ + stm_rcc.apb1enr &= ~(1 << STM_RCC_APB1ENR_LPUART1EN); +} + diff --git a/src/stm32l0/ao_pwm_stm.c b/src/stm32l0/ao_pwm_stm.c new file mode 100644 index 00000000..341f8887 --- /dev/null +++ b/src/stm32l0/ao_pwm_stm.c @@ -0,0 +1,191 @@ +/* + * Copyright © 2015 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include "ao.h" +#include "ao_pwm.h" + +static uint8_t pwm_running; + +static uint16_t pwm_value[NUM_PWM]; + +static void +ao_pwm_up(void) +{ + if (pwm_running++ == 0) { + struct stm_tim234 *tim = &AO_PWM_TIMER; + + tim->ccr1 = 0; + tim->ccr2 = 0; + tim->ccr3 = 0; + tim->ccr4 = 0; + tim->arr = PWM_MAX - 1; /* turn on the timer */ + tim->cr1 = ((STM_TIM234_CR1_CKD_1 << STM_TIM234_CR1_CKD) | + (0 << STM_TIM234_CR1_ARPE) | + (STM_TIM234_CR1_CMS_EDGE << STM_TIM234_CR1_CMS) | + (STM_TIM234_CR1_DIR_UP << STM_TIM234_CR1_DIR) | + (0 << STM_TIM234_CR1_OPM) | + (0 << STM_TIM234_CR1_URS) | + (0 << STM_TIM234_CR1_UDIS) | + (1 << STM_TIM234_CR1_CEN)); + + /* Set the timer running */ + tim->egr = (1 << STM_TIM234_EGR_UG); + } +} + +static void +ao_pwm_down(void) +{ + if (--pwm_running == 0) { + struct stm_tim234 *tim = &AO_PWM_TIMER; + + tim->arr = 0; + tim->cr1 = ((STM_TIM234_CR1_CKD_1 << STM_TIM234_CR1_CKD) | + (0 << STM_TIM234_CR1_ARPE) | + (STM_TIM234_CR1_CMS_EDGE << STM_TIM234_CR1_CMS) | + (STM_TIM234_CR1_DIR_UP << STM_TIM234_CR1_DIR) | + (0 << STM_TIM234_CR1_OPM) | + (0 << STM_TIM234_CR1_URS) | + (0 << STM_TIM234_CR1_UDIS) | + (0 << STM_TIM234_CR1_CEN)); + + /* Stop the timer */ + tim->egr = (1 << STM_TIM234_EGR_UG); + } +} + +void +ao_pwm_set(uint8_t pwm, uint16_t value) +{ + struct stm_tim234 *tim = &AO_PWM_TIMER; + + if (value > PWM_MAX) + value = PWM_MAX; + if (value != 0) { + if (pwm_value[pwm] == 0) + ao_pwm_up(); + } + switch (pwm) { + case 0: + tim->ccr1 = value; + break; + case 1: + tim->ccr2 = value; + break; + case 2: + tim->ccr3 = value; + break; + case 3: + tim->ccr4 = value; + break; + } + if (value == 0) { + if (pwm_value[pwm] != 0) + ao_pwm_down(); + } + pwm_value[pwm] = value; +} + +static void +ao_pwm_cmd(void) +{ + uint8_t ch; + uint16_t val; + + ch = ao_cmd_decimal(); + val = ao_cmd_decimal(); + if (ao_cmd_status != ao_cmd_success) + return; + + printf("Set channel %d to %d\n", ch, val); + ao_pwm_set(ch, val); +} + +static const struct ao_cmds ao_pwm_cmds[] = { + { ao_pwm_cmd, "P \0Set PWM ch to val" }, + { 0, NULL }, +}; + +void +ao_pwm_init(void) +{ + struct stm_tim234 *tim = &AO_PWM_TIMER; + + stm_rcc.apb1enr |= (1 << AO_PWM_TIMER_ENABLE); + + tim->cr1 = 0; + tim->psc = AO_PWM_TIMER_SCALE - 1; + tim->cnt = 0; + tim->ccer = ((1 << STM_TIM234_CCER_CC1E) | + (0 << STM_TIM234_CCER_CC1P) | + (1 << STM_TIM234_CCER_CC2E) | + (0 << STM_TIM234_CCER_CC2P) | + (1 << STM_TIM234_CCER_CC3E) | + (0 << STM_TIM234_CCER_CC3P) | + (1 << STM_TIM234_CCER_CC4E) | + (0 << STM_TIM234_CCER_CC4P)); + + tim->ccmr1 = ((0 << STM_TIM234_CCMR1_OC2CE) | + (STM_TIM234_CCMR1_OC2M_PWM_MODE_1 << STM_TIM234_CCMR1_OC2M) | + (0 << STM_TIM234_CCMR1_OC2PE) | + (0 << STM_TIM234_CCMR1_OC2FE) | + (STM_TIM234_CCMR1_CC2S_OUTPUT << STM_TIM234_CCMR1_CC2S) | + + (0 << STM_TIM234_CCMR1_OC1CE) | + (STM_TIM234_CCMR1_OC1M_PWM_MODE_1 << STM_TIM234_CCMR1_OC1M) | + (0 << STM_TIM234_CCMR1_OC1PE) | + (0 << STM_TIM234_CCMR1_OC1FE) | + (STM_TIM234_CCMR1_CC1S_OUTPUT << STM_TIM234_CCMR1_CC1S)); + + + tim->ccmr2 = ((0 << STM_TIM234_CCMR2_OC4CE) | + (STM_TIM234_CCMR2_OC4M_PWM_MODE_1 << STM_TIM234_CCMR2_OC4M) | + (0 << STM_TIM234_CCMR2_OC4PE) | + (0 << STM_TIM234_CCMR2_OC4FE) | + (STM_TIM234_CCMR2_CC4S_OUTPUT << STM_TIM234_CCMR2_CC4S) | + + (0 << STM_TIM234_CCMR2_OC3CE) | + (STM_TIM234_CCMR2_OC3M_PWM_MODE_1 << STM_TIM234_CCMR2_OC3M) | + (0 << STM_TIM234_CCMR2_OC3PE) | + (0 << STM_TIM234_CCMR2_OC3FE) | + (STM_TIM234_CCMR2_CC3S_OUTPUT << STM_TIM234_CCMR2_CC3S)); + tim->egr = 0; + + tim->sr = 0; + tim->dier = 0; + tim->smcr = 0; + tim->cr2 = ((0 << STM_TIM234_CR2_TI1S) | + (STM_TIM234_CR2_MMS_RESET<< STM_TIM234_CR2_MMS) | + (0 << STM_TIM234_CR2_CCDS)); + + stm_afr_set(AO_PWM_0_GPIO, AO_PWM_0_PIN, STM_AFR_AF2); + stm_ospeedr_set(AO_PWM_0_GPIO, AO_PWM_0_PIN, STM_OSPEEDR_40MHz); +#if NUM_PWM > 1 + stm_afr_set(AO_PWM_1_GPIO, AO_PWM_1_PIN, STM_AFR_AF2); + stm_ospeedr_set(AO_PWM_1_GPIO, AO_PWM_1_PIN, STM_OSPEEDR_40MHz); +#endif +#if NUM_PWM > 2 + stm_afr_set(AO_PWM_2_GPIO, AO_PWM_2_PIN, STM_AFR_AF2); + stm_ospeedr_set(AO_PWM_2_GPIO, AO_PWM_2_PIN, STM_OSPEEDR_40MHz); +#endif +#if NUM_PWM > 3 + stm_afr_set(AO_PWM_3_GPIO, AO_PWM_3_PIN, STM_AFR_AF2); + stm_ospeedr_set(AO_PWM_3_GPIO, AO_PWM_3_PIN, STM_OSPEEDR_40MHz); +#endif + ao_cmd_register(&ao_pwm_cmds[0]); +} diff --git a/src/stm32l0/ao_serial_stm.c b/src/stm32l0/ao_serial_stm.c new file mode 100644 index 00000000..ac745d97 --- /dev/null +++ b/src/stm32l0/ao_serial_stm.c @@ -0,0 +1,454 @@ +/* + * Copyright © 2020 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + */ + +#include +#include + +static int +_ao_usart_tx_start(struct ao_stm_usart *usart) +{ + if (!ao_fifo_empty(usart->tx_fifo)) { +#if HAS_SERIAL_SW_FLOW + if (usart->gpio_cts && ao_gpio_get(usart->gpio_cts, usart->pin_cts) == 1) { + ao_exti_enable(usart->gpio_cts, usart->pin_cts); + return 0; + } +#endif + if (usart->reg->isr & (1 << STM_USART_ISR_TXE)) + { + usart->tx_running = 1; + usart->reg->cr1 |= (1 << STM_USART_CR1_TXEIE) | (1 << STM_USART_CR1_TCIE); + ao_fifo_remove(usart->tx_fifo, usart->reg->tdr); + ao_wakeup(&usart->tx_fifo); + return 1; + } + } + return 0; +} + +#if HAS_SERIAL_SW_FLOW +static void +_ao_usart_cts(struct ao_stm_usart *usart) +{ + if (_ao_usart_tx_start(usart)) + ao_exti_disable(usart->gpio_cts, usart->pin_cts); +} +#endif + +static void +_ao_usart_rx(struct ao_stm_usart *usart, int is_stdin) +{ + if (usart->reg->isr & (1 << STM_USART_ISR_RXNE)) { + usart->reg->icr = (1 << STM_USART_ICR_ORECF); + if (!ao_fifo_full(usart->rx_fifo)) { + ao_fifo_insert(usart->rx_fifo, usart->reg->rdr); + ao_wakeup(&usart->rx_fifo); + if (is_stdin) + ao_wakeup(&ao_stdin_ready); +#if HAS_SERIAL_SW_FLOW + /* If the fifo is nearly full, turn off RTS and wait + * for it to drain a bunch + */ + if (usart->gpio_rts && ao_fifo_mostly(usart->rx_fifo)) { + ao_gpio_set(usart->gpio_rts, usart->pin_rts, 1); + usart->rts = 0; + } +#endif + } else { + usart->reg->cr1 &= ~(1 << STM_USART_CR1_RXNEIE); + } + } +} + +static void +ao_usart_isr(struct ao_stm_usart *usart, int is_stdin) +{ + _ao_usart_rx(usart, is_stdin); + + if (!_ao_usart_tx_start(usart)) + usart->reg->cr1 &= ~(1<< STM_USART_CR1_TXEIE); + + if (usart->reg->isr & (1 << STM_USART_ISR_TC)) { + usart->tx_running = 0; + usart->reg->cr1 &= ~(1 << STM_USART_CR1_TCIE); + if (usart->draining) { + usart->draining = 0; + ao_wakeup(&usart->tx_fifo); + } + } +} + +static int +_ao_usart_pollchar(struct ao_stm_usart *usart) +{ + int c; + + if (ao_fifo_empty(usart->rx_fifo)) + c = AO_READ_AGAIN; + else { + uint8_t u; + ao_fifo_remove(usart->rx_fifo,u); + if ((usart->reg->cr1 & (1 << STM_USART_CR1_RXNEIE)) == 0) { + if (ao_fifo_barely(usart->rx_fifo)) + usart->reg->cr1 |= (1 << STM_USART_CR1_RXNEIE); + } +#if HAS_SERIAL_SW_FLOW + /* If we've cleared RTS, check if there's space now and turn it back on */ + if (usart->gpio_rts && usart->rts == 0 && ao_fifo_barely(usart->rx_fifo)) { + ao_gpio_set(usart->gpio_rts, usart->pin_rts, 0); + usart->rts = 1; + } +#endif + c = u; + } + return c; +} + +static char +ao_usart_getchar(struct ao_stm_usart *usart) +{ + int c; + ao_arch_block_interrupts(); + while ((c = _ao_usart_pollchar(usart)) == AO_READ_AGAIN) + ao_sleep(&usart->rx_fifo); + ao_arch_release_interrupts(); + return (char) c; +} + +#if 0 +static inline uint8_t +_ao_usart_sleep_for(struct ao_stm_usart *usart, uint16_t timeout) +{ + return ao_sleep_for(&usart->rx_fifo, timeout); +} +#endif + +static void +ao_usart_putchar(struct ao_stm_usart *usart, char c) +{ + ao_arch_block_interrupts(); + while (ao_fifo_full(usart->tx_fifo)) + ao_sleep(&usart->tx_fifo); + ao_fifo_insert(usart->tx_fifo, c); + _ao_usart_tx_start(usart); + ao_arch_release_interrupts(); +} + +#if 0 +static void +ao_usart_drain(struct ao_stm_usart *usart) +{ + ao_arch_block_interrupts(); + while (!ao_fifo_empty(usart->tx_fifo) || usart->tx_running) { + usart->draining = 1; + ao_sleep(&usart->tx_fifo); + } + ao_arch_release_interrupts(); +} +#endif + +const uint32_t ao_usart_speeds[] = { + [AO_SERIAL_SPEED_4800] = 4800, + [AO_SERIAL_SPEED_9600] = 9600, + [AO_SERIAL_SPEED_19200] = 19200, + [AO_SERIAL_SPEED_57600] = 57600, + [AO_SERIAL_SPEED_115200] = 115200, +}; + +static void +ao_usart_set_speed(struct ao_stm_usart *usart, uint8_t speed) +{ + if (speed > AO_SERIAL_SPEED_115200) + return; + usart->reg->brr = AO_PCLK2 / ao_usart_speeds[speed]; +} + +static void +ao_usart_init(struct ao_stm_usart *usart, int hw_flow) +{ + usart->reg->cr1 = ((0 << STM_USART_CR1_M1) | + (0 << STM_USART_CR1_EOBIE) | + (0 << STM_USART_CR1_RTOIE) | + (0 << STM_USART_CR1_DEAT) | + (0 << STM_USART_CR1_DEDT) | + (0 << STM_USART_CR1_OVER8) | + (0 << STM_USART_CR1_CMIE) | + (0 << STM_USART_CR1_MME) | + (0 << STM_USART_CR1_M0) | + (0 << STM_USART_CR1_WAKE) | + (0 << STM_USART_CR1_PCE) | + (0 << STM_USART_CR1_PS) | + (0 << STM_USART_CR1_PEIE) | + (0 << STM_USART_CR1_TXEIE) | + (0 << STM_USART_CR1_TCIE) | + (1 << STM_USART_CR1_RXNEIE) | + (0 << STM_USART_CR1_IDLEIE) | + (1 << STM_USART_CR1_TE) | + (1 << STM_USART_CR1_RE) | + (0 << STM_USART_CR1_UESM) | + (0 << STM_USART_CR1_UE)); + + usart->reg->cr2 = ((0 << STM_USART_CR2_ADD) | + (0 << STM_USART_CR2_RTOEN) | + (0 << STM_USART_CR2_ABRMOD) | + (0 << STM_USART_CR2_ABREN) | + (0 << STM_USART_CR2_MSBFIRST) | + (0 << STM_USART_CR2_DATAINV) | + (0 << STM_USART_CR2_TXINV) | + (0 << STM_USART_CR2_RXINV) | + (0 << STM_USART_CR2_SWAP) | + (0 << STM_USART_CR2_LINEN) | + (0 << STM_USART_CR2_STOP) | + (0 << STM_USART_CR2_CLKEN) | + (0 << STM_USART_CR2_CPOL) | + (0 << STM_USART_CR2_CHPA) | + (0 << STM_USART_CR2_LBCL) | + (0 << STM_USART_CR2_LBDIE) | + (0 << STM_USART_CR2_LBDL) | + (0 << STM_USART_CR2_ADDM7)); + + uint32_t cr3 = ((0 << STM_USART_CR3_WUFIE) | + (0 << STM_USART_CR3_WUS) | + (0 << STM_USART_CR3_SCARCNT) | + (0 << STM_USART_CR3_DEP) | + (0 << STM_USART_CR3_DEM) | + (0 << STM_USART_CR3_DDRE) | + (0 << STM_USART_CR3_OVRDIS) | + (0 << STM_USART_CR3_ONEBIT) | + (0 << STM_USART_CR3_CTIIE) | + (0 << STM_USART_CR3_CTSE) | + (0 << STM_USART_CR3_RTSE) | + (0 << STM_USART_CR3_DMAT) | + (0 << STM_USART_CR3_DMAR) | + (0 << STM_USART_CR3_SCEN) | + (0 << STM_USART_CR3_NACK) | + (0 << STM_USART_CR3_HDSEL) | + (0 << STM_USART_CR3_IRLP) | + (0 << STM_USART_CR3_IREN) | + (0 << STM_USART_CR3_EIE)); + + if (hw_flow) + cr3 |= ((1 << STM_USART_CR3_CTSE) | + (1 << STM_USART_CR3_RTSE)); + + usart->reg->cr3 = cr3; + + /* Pick a 9600 baud rate */ + ao_usart_set_speed(usart, AO_SERIAL_SPEED_9600); + + /* Enable the usart */ + usart->reg->cr1 |= (1 << STM_USART_CR1_UE); +} + +#if HAS_SERIAL_1 + +struct ao_stm_usart ao_stm_usart1; + +void stm_usart1_isr(void) { ao_usart_isr(&ao_stm_usart1, USE_SERIAL_1_STDIN); } + +char +ao_serial1_getchar(void) +{ + return ao_usart_getchar(&ao_stm_usart1); +} + +void +ao_serial1_putchar(char c) +{ + ao_usart_putchar(&ao_stm_usart1, c); +} + +int +_ao_serial1_pollchar(void) +{ + return _ao_usart_pollchar(&ao_stm_usart1); +} + +#if 0 +uint8_t +_ao_serial1_sleep_for(uint16_t timeout) +{ + return _ao_usart_sleep_for(&ao_stm_usart1, timeout); +} +#endif + +#if 0 +void +ao_serial1_drain(void) +{ + ao_usart_drain(&ao_stm_usart1); +} + +void +ao_serial1_set_speed(uint8_t speed) +{ + ao_usart_drain(&ao_stm_usart1); + ao_usart_set_speed(&ao_stm_usart1, speed); +} +#endif +#endif /* HAS_SERIAL_1 */ + +#if HAS_SERIAL_2 + +struct ao_stm_usart ao_stm_usart2; + +void stm_usart2_isr(void) { ao_usart_isr(&ao_stm_usart2, USE_SERIAL_2_STDIN); } + +char +ao_serial2_getchar(void) +{ + return ao_usart_getchar(&ao_stm_usart2); +} + +void +ao_serial2_putchar(char c) +{ + ao_usart_putchar(&ao_stm_usart2, c); +} + +int +_ao_serial2_pollchar(void) +{ + return _ao_usart_pollchar(&ao_stm_usart2); +} + +#if 0 +uint8_t +_ao_serial2_sleep_for(uint16_t timeout) +{ + return _ao_usart_sleep_for(&ao_stm_usart2, timeout); +} + +void +ao_serial2_drain(void) +{ + ao_usart_drain(&ao_stm_usart2); +} + +void +ao_serial2_set_speed(uint8_t speed) +{ + ao_usart_drain(&ao_stm_usart2); + ao_usart_set_speed(&ao_stm_usart2, speed); +} +#endif + +#if USE_SERIAL_2_FLOW && USE_SERIAL_2_SW_FLOW +void +ao_serial2_cts(void) +{ + _ao_usart_cts(&ao_stm_usart2); +} +#endif + +#endif /* HAS_SERIAL_2 */ + +#if HAS_SERIAL_SW_FLOW +static void +ao_serial_set_sw_rts_cts(struct ao_stm_usart *usart, + void (*isr)(void), + struct stm_gpio *port_rts, + int pin_rts, + struct stm_gpio *port_cts, + int pin_cts) +{ + /* Pull RTS low to note that there's space in the FIFO + */ + ao_enable_output(port_rts, pin_rts, 0); + usart->gpio_rts = port_rts; + usart->pin_rts = pin_rts; + usart->rts = 1; + + ao_exti_setup(port_cts, pin_cts, AO_EXTI_MODE_FALLING|AO_EXTI_PRIORITY_MED, isr); + usart->gpio_cts = port_cts; + usart->pin_cts = pin_cts; +} +#endif + +#if 0 +void +ao_serial_shutdown(void) +{ +# if SERIAL_2_PA2_PA3 + stm_moder_set(&stm_gpioa, 2, STM_MODER_INPUT); + stm_moder_set(&stm_gpioa, 3, STM_MODER_INPUT); +# elif SERIAL_2_PA9_PA10 + stm_moder_set(&stm_gpioa, 9, STM_MODER_INPUT); + stm_moder_set(&stm_gpioa, 10, STM_MODER_INPUT); +# elif SERIAL_2_PA14_PA15 + stm_moder_set(&stm_gpioa, 14, STM_MODER_INPUT); + stm_moder_set(&stm_gpioa, 15, STM_MODER_INPUT); +# elif SERIAL_2_PB6_PB7 + stm_moder_set(&stm_gpiob, 6, STM_MODER_INPUT); + stm_moder_set(&stm_gpiob, 7, STM_MODER_INPUT); +#endif +#if HAS_SERIAL_1 + stm_rcc.apb2enr &= ~(1 << STM_RCC_APB2ENR_USART1EN); +#endif +#if HAS_SERIAL_2 + stm_nvic_set_disable(STM_ISR_USART2_POS); + stm_rcc.apb1enr &= ~(1 << STM_RCC_APB1ENR_USART2EN); +#endif +} +#endif + +void +ao_serial_init(void) +{ +#if HAS_SERIAL_1 +#endif + +#if HAS_SERIAL_2 + /* + * TX RX + * PA2 PA3 + * PA9 PA10 + * PA14 PA15 + * PB6 PB7 + */ + +# if SERIAL_2_PA2_PA3 + ao_enable_port(&stm_gpioa); + stm_afr_set(&stm_gpioa, 2, STM_AFR_AF4); + stm_afr_set(&stm_gpioa, 3, STM_AFR_AF4); +# elif SERIAL_2_PA9_PA10 + ao_enable_port(&stm_gpioa); + stm_afr_set(&stm_gpioa, 9, STM_AFR_AF4); + stm_afr_set(&stm_gpioa, 10, STM_AFR_AF4); +# elif SERIAL_2_PA14_PA15 + ao_enable_port(&stm_gpioa); + stm_afr_set(&stm_gpioa, 14, STM_AFR_AF4); + stm_afr_set(&stm_gpioa, 15, STM_AFR_AF4); +# elif SERIAL_2_PB6_PB7 + ao_enable_port(&stm_gpiob); + stm_afr_set(&stm_gpiob, 6, STM_AFR_AF0); + stm_afr_set(&stm_gpiob, 7, STM_AFR_AF0); +# else +# error "No SERIAL_2 port configuration specified" +# endif + /* Enable USART */ + stm_rcc.apb1enr |= (1 << STM_RCC_APB1ENR_USART2EN); + + ao_stm_usart2.reg = &stm_usart2; + ao_usart_init(&ao_stm_usart2, USE_SERIAL_2_FLOW && !USE_SERIAL_2_SW_FLOW); + + stm_nvic_set_enable(STM_ISR_USART2_POS); + stm_nvic_set_priority(STM_ISR_USART2_POS, 4); +# if USE_SERIAL_2_STDIN && !DELAY_SERIAL_2_STDIN + ao_add_stdio(_ao_serial2_pollchar, + ao_serial2_putchar, + NULL); +# endif +#endif +} diff --git a/src/stm32l0/ao_spi_stm32l0.c b/src/stm32l0/ao_spi_stm32l0.c new file mode 100644 index 00000000..b8831d5a --- /dev/null +++ b/src/stm32l0/ao_spi_stm32l0.c @@ -0,0 +1,498 @@ +/* + * Copyright © 2020 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include + +static uint8_t ao_spi_mutex; +static uint8_t ao_spi_pin_config; + +#define AO_DMA_SPI1_RX_INDEX STM_DMA_INDEX(2) +#define AO_DMA_SPI1_RX_CSELR STM_DMA_CSELR_C2S_SPI1_RX +#define AO_DMA_SPI1_TX_INDEX STM_DMA_INDEX(3) +#define AO_DMA_SPI1_TX_CSELR STM_DMA_CSELR_C3S_SPI1_TX + +#if 0 +static uint8_t spi_dev_null; + +static void +ao_spi_set_dma_mosi(uint8_t id, const void *data, uint16_t len, uint32_t minc) +{ + (void) id; + struct stm_spi *stm_spi = &stm_spi1; + + ao_dma_set_transfer(AO_DMA_SPI1_TX_INDEX, + &stm_spi->dr, + (void *) data, + len, + (0 << STM_DMA_CCR_MEM2MEM) | + (STM_DMA_CCR_PL_MEDIUM << STM_DMA_CCR_PL) | + (STM_DMA_CCR_MSIZE_8 << STM_DMA_CCR_MSIZE) | + (STM_DMA_CCR_PSIZE_8 << STM_DMA_CCR_PSIZE) | + (minc << STM_DMA_CCR_MINC) | + (0 << STM_DMA_CCR_PINC) | + (0 << STM_DMA_CCR_CIRC) | + (STM_DMA_CCR_DIR_MEM_TO_PER << STM_DMA_CCR_DIR)); +} + +static void +ao_spi_set_dma_miso(uint8_t id, void *data, uint16_t len, uint32_t minc) +{ + (void) id; + uint8_t miso_dma_index = STM_DMA_INDEX(2); + struct stm_spi *stm_spi = &stm_spi1; + + ao_dma_set_transfer(miso_dma_index, + &stm_spi->dr, + data, + len, + (0 << STM_DMA_CCR_MEM2MEM) | + (STM_DMA_CCR_PL_HIGH << STM_DMA_CCR_PL) | + (STM_DMA_CCR_MSIZE_8 << STM_DMA_CCR_MSIZE) | + (STM_DMA_CCR_PSIZE_8 << STM_DMA_CCR_PSIZE) | + (minc << STM_DMA_CCR_MINC) | + (0 << STM_DMA_CCR_PINC) | + (0 << STM_DMA_CCR_CIRC) | + (STM_DMA_CCR_DIR_PER_TO_MEM << STM_DMA_CCR_DIR)); +} + +static void +ao_spi_run(uint8_t id, uint8_t which, uint16_t len) +{ + (void) id; + uint8_t mosi_dma_index = STM_DMA_INDEX(3); + uint8_t miso_dma_index = STM_DMA_INDEX(2); + struct stm_spi *stm_spi = &stm_spi1; + + 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)); + + stm_spi->cr2 = 0; + + ao_dma_done_transfer(mosi_dma_index); + ao_dma_done_transfer(miso_dma_index); +} +#endif + +void +ao_spi_send(const void *block, uint16_t len, uint8_t spi_index) +{ + (void) spi_index; +#if 0 + /* Set up the transmit DMA to deliver data */ + ao_spi_set_dma_mosi(id, block, len, 1); + + /* Set up the receive DMA -- when this is done, we know the SPI unit + * is idle. Without this, we'd have to poll waiting for the BSY bit to + * be cleared + */ + ao_spi_set_dma_miso(id, &spi_dev_null, len, 0); + + ao_spi_run(id, 1, len); +#else + const uint8_t *bytes = block; + struct stm_spi *stm_spi = &stm_spi1; + + while (len--) { + while ((stm_spi->sr & (1 << STM_SPI_SR_TXE)) == 0); + stm_spi->dr = *bytes++; + while ((stm_spi->sr & (1 << STM_SPI_SR_RXNE)) == 0); + (void) stm_spi->dr; + } +#endif +} + +#if 0 +void +ao_spi_send_fixed(uint8_t value, uint16_t len, uint8_t spi_index) +{ + uint8_t id = AO_SPI_INDEX(spi_index); + + /* Set up the transmit DMA to deliver data */ + ao_spi_set_dma_mosi(id, &value, len, 0); + + /* Set up the receive DMA -- when this is done, we know the SPI unit + * is idle. Without this, we'd have to poll waiting for the BSY bit to + * be cleared + */ + ao_spi_set_dma_miso(id, &spi_dev_null, len, 0); + + ao_spi_run(id, 3, len); +} + +void +ao_spi_start_bytes(uint8_t spi_index) +{ + (void) spi_index; + struct stm_spi *stm_spi = &stm_spi1; + + stm_spi->cr2 = ((0 << STM_SPI_CR2_TXEIE) | + (0 << STM_SPI_CR2_RXNEIE) | + (0 << STM_SPI_CR2_ERRIE) | + (0 << STM_SPI_CR2_SSOE) | + (0 << STM_SPI_CR2_TXDMAEN) | + (0 << STM_SPI_CR2_RXDMAEN)); +} + +void +ao_spi_stop_bytes(uint8_t spi_index) +{ + (void) spi_index; + struct stm_spi *stm_spi = &stm_spi1; + + 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; + stm_spi->cr2 = 0; +} + +void +ao_spi_send_sync(const void *block, uint16_t len, uint8_t spi_index) +{ + (void) spi_index; + const uint8_t *b = block; + struct stm_spi *stm_spi = &stm_spi1; + + 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)); + 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; +} +#endif + +void +ao_spi_recv(void *block, uint16_t len, uint8_t spi_index) +{ + (void) spi_index; +#if 0 + + spi_dev_null = 0xff; + + /* Set up transmit DMA to make the SPI hardware actually run */ + ao_spi_set_dma_mosi(id, &spi_dev_null, len, 0); + + /* Set up the receive DMA to capture data */ + ao_spi_set_dma_miso(id, block, len, 1); + + ao_spi_run(id, 9, len); +#else + uint8_t *bytes = block; + struct stm_spi *stm_spi = &stm_spi1; + + while (len--) { + while ((stm_spi->sr & (1 << STM_SPI_SR_TXE)) == 0); + stm_spi->dr = 0xff; + while ((stm_spi->sr & (1 << STM_SPI_SR_RXNE)) == 0); + *bytes++ = stm_spi->dr; + } +#endif +} + +#if 0 +void +ao_spi_duplex(const void *out, void *in, uint16_t len, uint8_t spi_index) +{ + uint8_t id = AO_SPI_INDEX(spi_index); + + /* Set up transmit DMA to send data */ + ao_spi_set_dma_mosi(id, out, len, 1); + + /* Set up the receive DMA to capture data */ + ao_spi_set_dma_miso(id, in, len, 1); + + ao_spi_run(id, 11, len); +} +#endif + +static void +ao_spi_disable_pin_config(uint8_t spi_pin_config) +{ + /* Disable current config + */ + switch (spi_pin_config) { + 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_PA12_PA13_PA14: + stm_gpio_set(&stm_gpioa, 13, 1); + stm_moder_set(&stm_gpioa, 13, STM_MODER_OUTPUT); /* clk */ + stm_moder_set(&stm_gpioa, 12, STM_MODER_OUTPUT); /* mosi */ + stm_moder_set(&stm_gpioa, 14, STM_MODER_INPUT); /* miso */ + 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; + } +} + +static void +ao_spi_enable_pin_config(uint8_t spi_pin_config) +{ + /* Enable new config + */ + switch (spi_pin_config) { + case AO_SPI_1_PA5_PA6_PA7: + stm_afr_set(&stm_gpioa, 5, STM_AFR_AF0); + stm_afr_set(&stm_gpioa, 6, STM_AFR_AF0); + stm_afr_set(&stm_gpioa, 7, STM_AFR_AF0); + break; + case AO_SPI_1_PA12_PA13_PA14: + stm_afr_set(&stm_gpioe, 12, STM_AFR_AF0); /* yes, AF0 */ + stm_afr_set(&stm_gpioe, 13, STM_AFR_AF5); + stm_afr_set(&stm_gpioe, 14, STM_AFR_AF5); + break; + case AO_SPI_1_PB3_PB4_PB5: + stm_afr_set(&stm_gpiob, 3, STM_AFR_AF0); + stm_afr_set(&stm_gpiob, 4, STM_AFR_AF0); + stm_afr_set(&stm_gpiob, 5, STM_AFR_AF0); + break; + } +} + +static void +ao_spi_config(uint8_t spi_index, uint32_t speed) +{ + uint8_t spi_pin_config = AO_SPI_PIN_CONFIG(spi_index); + struct stm_spi *stm_spi = &stm_spi1; + + if (spi_pin_config != ao_spi_pin_config) { + + /* Disable old config + */ + ao_spi_disable_pin_config(ao_spi_pin_config); + + /* Enable new config + */ + ao_spi_enable_pin_config(spi_pin_config); + + /* Remember current config + */ + ao_spi_pin_config = spi_pin_config; + } + + /* Turn the SPI transceiver on and set the mode */ + 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) | + (AO_SPI_CPOL(spi_index) << STM_SPI_CR1_CPOL) | /* Format */ + (AO_SPI_CPHA(spi_index) << STM_SPI_CR1_CPHA)); +} + +#if HAS_TASK +uint8_t +ao_spi_try_get(uint8_t spi_index, uint32_t speed, uint8_t task_id) +{ + uint8_t id = AO_SPI_INDEX(spi_index); + + if (!ao_mutex_try(&ao_spi_mutex[id], task_id)) + return 0; + ao_spi_config(spi_index, speed); + return 1; +} +#endif + +void +ao_spi_get(uint8_t spi_index, uint32_t speed) +{ + (void) spi_index; + + ao_mutex_get(&ao_spi_mutex); + ao_spi_config(spi_index, speed); +} + +void +ao_spi_put(uint8_t spi_index) +{ + (void) spi_index; + struct stm_spi *stm_spi = &stm_spi1; + + stm_spi->cr1 = 0; + ao_mutex_put(&ao_spi_mutex); +} + +static void +ao_spi_channel_init(uint8_t spi_index) +{ + (void) spi_index; + struct stm_spi *stm_spi = &stm_spi1; + + ao_spi_disable_pin_config(AO_SPI_PIN_CONFIG(spi_index)); + + stm_spi->cr1 = 0; + 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) +{ +#if HAS_SPI_1 +# if SPI_1_PA5_PA6_PA7 + ao_enable_port(&stm_gpioa); + stm_ospeedr_set(&stm_gpioa, 5, SPI_1_OSPEEDR); + stm_ospeedr_set(&stm_gpioa, 6, SPI_1_OSPEEDR); + stm_ospeedr_set(&stm_gpioa, 7, SPI_1_OSPEEDR); +# endif +# if SPI_1_PB3_PB4_PB5 + ao_enable_port(&stm_gpiob); + stm_ospeedr_set(&stm_gpiob, 3, SPI_1_OSPEEDR); + stm_ospeedr_set(&stm_gpiob, 4, SPI_1_OSPEEDR); + stm_ospeedr_set(&stm_gpiob, 5, SPI_1_OSPEEDR); +# endif +# if SPI_1_PE13_PE14_PE15 + ao_enable_port(&stm_gpioe); + stm_ospeedr_set(&stm_gpioe, 13, SPI_1_OSPEEDR); + stm_ospeedr_set(&stm_gpioe, 14, SPI_1_OSPEEDR); + stm_ospeedr_set(&stm_gpioe, 15, SPI_1_OSPEEDR); +# endif + stm_rcc.apb2enr |= (1 << STM_RCC_APB2ENR_SPI1EN); + ao_spi_pin_config = AO_SPI_CONFIG_NONE; + ao_spi_channel_init(0); +#if 0 + ao_dma_alloc(AO_DMA_SPI1_RX_INDEX, AO_DMA_SPI1_RX_CSELR); + ao_dma_alloc(AO_DMA_SPI1_TX_INDEX, AO_DMA_SPI1_TX_CSELR); +#endif +#endif + +#if HAS_SPI_2 +# if SPI_2_PB13_PB14_PB15 + ao_enable_port(&stm_gpiob); + stm_ospeedr_set(&stm_gpiob, 13, SPI_2_OSPEEDR); + stm_ospeedr_set(&stm_gpiob, 14, SPI_2_OSPEEDR); + stm_ospeedr_set(&stm_gpiob, 15, SPI_2_OSPEEDR); +# define HAS_SPI_2_CONFIG 1 +# endif +# if SPI_2_PD1_PD3_PD4 + ao_enable_port(&stm_gpiod); + stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_GPIODEN); + stm_ospeedr_set(&stm_gpiod, 1, SPI_2_OSPEEDR); + stm_ospeedr_set(&stm_gpiod, 3, SPI_2_OSPEEDR); + stm_ospeedr_set(&stm_gpiod, 4, SPI_2_OSPEEDR); +# define HAS_SPI_2_CONFIG 1 +# endif +# ifndef HAS_SPI_2_CONFIG 1 + #error "no config for SPI2" +# endif + stm_rcc.apb1enr |= (1 << STM_RCC_APB1ENR_SPI2EN); + ao_spi_pin_config[1] = AO_SPI_CONFIG_NONE; + ao_spi_channel_init(1); + ao_dma_alloc(AO_DMA_SPI2_RX_INDEX, AO_DMA_SPI2_RX_CSELR); + ao_dma_alloc(AO_DMA_SPI2_TX_INDEX, AO_DMA_SPI2_TX_CSELR); +#endif +#if DEBUG + ao_cmd_register(&ao_spi_cmds[0]); +#endif +} diff --git a/src/stm32l0/ao_timer.c b/src/stm32l0/ao_timer.c new file mode 100644 index 00000000..89193333 --- /dev/null +++ b/src/stm32l0/ao_timer.c @@ -0,0 +1,107 @@ +/* + * Copyright © 2020 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include "ao.h" +#include +#if HAS_FAKE_FLIGHT +#include +#endif + +#ifndef HAS_TICK +#define HAS_TICK 1 +#endif + +#if HAS_TICK +volatile AO_TICK_TYPE ao_tick_count; + +AO_TICK_TYPE +ao_time(void) +{ + return ao_tick_count; +} + +#if 0 +uint64_t +ao_time_ns(void) +{ + AO_TICK_TYPE before, after; + uint32_t cvr; + + do { + before = ao_tick_count; + cvr = stm_systick.cvr; + after = ao_tick_count; + } while (before != after); + + return (uint64_t) after * (1000000000ULL / AO_HERTZ) + + (uint64_t) cvr * (1000000000ULL / AO_SYSTICK); +} +#endif + +#if AO_DATA_ALL +volatile uint8_t ao_data_interval = 1; +volatile uint8_t ao_data_count; +#endif + +void stm_systick_isr(void) +{ + if (stm_systick.csr & (1 << STM_SYSTICK_CSR_COUNTFLAG)) { + ++ao_tick_count; + ao_task_check_alarm(); +#if AO_DATA_ALL + if (++ao_data_count == ao_data_interval) { + ao_data_count = 0; +#if HAS_ADC +#if HAS_FAKE_FLIGHT + if (ao_fake_flight_active) + ao_fake_flight_poll(); + else +#endif + ao_adc_poll(); +#endif +#if (AO_DATA_ALL & ~(AO_DATA_ADC)) + ao_wakeup((void *) &ao_data_count); +#endif + } +#endif +#ifdef AO_TIMER_HOOK + AO_TIMER_HOOK; +#endif + } +} + +#define SYSTICK_RELOAD (AO_SYSTICK / 100 - 1) + +void +ao_timer_init(void) +{ + stm_systick.csr = 0; + stm_systick.rvr = SYSTICK_RELOAD; + stm_systick.cvr = 0; + stm_systick.csr = ((1 << STM_SYSTICK_CSR_ENABLE) | + (1 << STM_SYSTICK_CSR_TICKINT) | + (STM_SYSTICK_CSR_CLKSOURCE_HCLK_8 << STM_SYSTICK_CSR_CLKSOURCE)); +} + +void +ao_timer_stop(void) +{ + stm_systick.csr = 0; +} + +#endif diff --git a/src/stm32l0/stm32l0.h b/src/stm32l0/stm32l0.h new file mode 100644 index 00000000..90f070ce --- /dev/null +++ b/src/stm32l0/stm32l0.h @@ -0,0 +1,2145 @@ +/* + * Copyright © 2012 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#ifndef _STM32L0_H_ +#define _STM32L0_H_ + +#include + +typedef volatile uint32_t vuint32_t; +typedef volatile uint16_t vuint16_t; +typedef volatile void * vvoid_t; + +struct stm_gpio { + vuint32_t moder; + vuint32_t otyper; + vuint32_t ospeedr; + vuint32_t pupdr; + + vuint32_t idr; + vuint32_t odr; + vuint32_t bsrr; + vuint32_t lckr; + + vuint32_t afrl; + vuint32_t afrh; + vuint32_t brr; +}; + +#define STM_MODER_SHIFT(pin) ((pin) << 1) +#define STM_MODER_MASK 3 +#define STM_MODER_INPUT 0 +#define STM_MODER_OUTPUT 1 +#define STM_MODER_ALTERNATE 2 +#define STM_MODER_ANALOG 3 + +static inline void +stm_moder_set(struct stm_gpio *gpio, int pin, vuint32_t value) { + gpio->moder = ((gpio->moder & + ~(STM_MODER_MASK << STM_MODER_SHIFT(pin))) | + value << STM_MODER_SHIFT(pin)); +} + +static inline uint32_t +stm_spread_mask(uint16_t mask) { + uint32_t m = mask; + + /* 0000000000000000mmmmmmmmmmmmmmmm */ + m = (m & 0xff) | ((m & 0xff00) << 8); + /* 00000000mmmmmmmm00000000mmmmmmmm */ + m = (m & 0x000f000f) | ((m & 0x00f000f0) << 4); + /* 0000mmmm0000mmmm0000mmmm0000mmmm */ + m = (m & 0x03030303) | ((m & 0x0c0c0c0c) << 2); + /* 00mm00mm00mm00mm00mm00mm00mm00mm */ + m = (m & 0x11111111) | ((m & 0x22222222) << 2); + /* 0m0m0m0m0m0m0m0m0m0m0m0m0m0m0m0m */ + return m; +} + +static inline void +stm_moder_set_mask(struct stm_gpio *gpio, uint16_t mask, uint32_t value) { + uint32_t bits32 = stm_spread_mask(mask); + uint32_t mask32 = 3 * bits32; + uint32_t value32 = (value & 3) * bits32; + + gpio->moder = ((gpio->moder & ~mask32) | value32); +} + +static inline uint32_t +stm_moder_get(struct stm_gpio *gpio, int pin) { + return (gpio->moder >> STM_MODER_SHIFT(pin)) & STM_MODER_MASK; +} + +#define STM_OTYPER_SHIFT(pin) (pin) +#define STM_OTYPER_MASK 1 +#define STM_OTYPER_PUSH_PULL 0 +#define STM_OTYPER_OPEN_DRAIN 1 + +static inline void +stm_otyper_set(struct stm_gpio *gpio, int pin, vuint32_t value) { + gpio->otyper = ((gpio->otyper & + ~(STM_OTYPER_MASK << STM_OTYPER_SHIFT(pin))) | + value << STM_OTYPER_SHIFT(pin)); +} + +static inline uint32_t +stm_otyper_get(struct stm_gpio *gpio, int pin) { + return (gpio->otyper >> STM_OTYPER_SHIFT(pin)) & STM_OTYPER_MASK; +} + +#define STM_OSPEEDR_SHIFT(pin) ((pin) << 1) +#define STM_OSPEEDR_MASK 3 +#define STM_OSPEEDR_LOW 0 +#define STM_OSPEEDR_MEDIUM 1 +#define STM_OSPEEDR_HIGH 2 +#define STM_OSPEEDR_VERY_HIGH 3 + +static inline void +stm_ospeedr_set(struct stm_gpio *gpio, int pin, uint32_t value) { + gpio->ospeedr = ((gpio->ospeedr & + ~(STM_OSPEEDR_MASK << STM_OSPEEDR_SHIFT(pin))) | + value << STM_OSPEEDR_SHIFT(pin)); +} + +static inline void +stm_ospeedr_set_mask(struct stm_gpio *gpio, uint16_t mask, uint32_t value) { + uint32_t bits32 = stm_spread_mask(mask); + uint32_t mask32 = 3 * bits32; + uint32_t value32 = (value & 3) * bits32; + + gpio->ospeedr = ((gpio->ospeedr & ~mask32) | value32); +} + +static inline uint32_t +stm_ospeedr_get(struct stm_gpio *gpio, int pin) { + return (gpio->ospeedr >> STM_OSPEEDR_SHIFT(pin)) & STM_OSPEEDR_MASK; +} + +#define STM_PUPDR_SHIFT(pin) ((pin) << 1) +#define STM_PUPDR_MASK 3 +#define STM_PUPDR_NONE 0 +#define STM_PUPDR_PULL_UP 1 +#define STM_PUPDR_PULL_DOWN 2 +#define STM_PUPDR_RESERVED 3 + +static inline void +stm_pupdr_set(struct stm_gpio *gpio, int pin, uint32_t value) { + gpio->pupdr = ((gpio->pupdr & + ~(STM_PUPDR_MASK << STM_PUPDR_SHIFT(pin))) | + value << STM_PUPDR_SHIFT(pin)); +} + +static inline void +stm_pupdr_set_mask(struct stm_gpio *gpio, uint16_t mask, uint32_t value) { + uint32_t bits32 = stm_spread_mask(mask); + uint32_t mask32 = 3 * bits32; + uint32_t value32 = (value & 3) * bits32; + + gpio->pupdr = (gpio->pupdr & ~mask32) | value32; +} + +static inline uint32_t +stm_pupdr_get(struct stm_gpio *gpio, int pin) { + return (gpio->pupdr >> STM_PUPDR_SHIFT(pin)) & STM_PUPDR_MASK; +} + +#define STM_AFR_SHIFT(pin) ((pin) << 2) +#define STM_AFR_MASK 0xf +#define STM_AFR_AF0 0x0 +#define STM_AFR_AF1 0x1 +#define STM_AFR_AF2 0x2 +#define STM_AFR_AF3 0x3 +#define STM_AFR_AF4 0x4 +#define STM_AFR_AF5 0x5 +#define STM_AFR_AF6 0x6 +#define STM_AFR_AF7 0x7 +#define STM_AFR_AF8 0x8 +#define STM_AFR_AF9 0x9 +#define STM_AFR_AF10 0xa +#define STM_AFR_AF11 0xb +#define STM_AFR_AF12 0xc +#define STM_AFR_AF13 0xd +#define STM_AFR_AF14 0xe +#define STM_AFR_AF15 0xf + +static inline void +stm_afr_set(struct stm_gpio *gpio, int pin, uint32_t value) { + /* + * Set alternate pin mode too + */ + stm_moder_set(gpio, pin, STM_MODER_ALTERNATE); + if (pin < 8) + gpio->afrl = ((gpio->afrl & + ~(STM_AFR_MASK << STM_AFR_SHIFT(pin))) | + value << STM_AFR_SHIFT(pin)); + else { + pin -= 8; + gpio->afrh = ((gpio->afrh & + ~(STM_AFR_MASK << STM_AFR_SHIFT(pin))) | + value << STM_AFR_SHIFT(pin)); + } +} + +static inline uint32_t +stm_afr_get(struct stm_gpio *gpio, int pin) { + if (pin < 8) + return (gpio->afrl >> STM_AFR_SHIFT(pin)) & STM_AFR_MASK; + else { + pin -= 8; + return (gpio->afrh >> STM_AFR_SHIFT(pin)) & STM_AFR_MASK; + } +} + +static inline void +stm_gpio_set(struct stm_gpio *gpio, int pin, uint8_t value) { + /* Use the bit set/reset register to do this atomically */ + gpio->bsrr = value ? (1 << pin) : (1 << (pin + 16)); +} + +static inline void +stm_gpio_set_mask(struct stm_gpio *gpio, uint16_t bits, uint16_t mask) { + /* Use the bit set/reset register to do this atomically */ + gpio->bsrr = ((uint32_t) (~bits & mask) << 16) | ((uint32_t) (bits & mask)); +} + +static inline void +stm_gpio_set_bits(struct stm_gpio *gpio, uint16_t bits) { + gpio->bsrr = bits; +} + +static inline void +stm_gpio_clr_bits(struct stm_gpio *gpio, uint16_t bits) { + gpio->bsrr = ((uint32_t) bits) << 16; +} + +static inline uint8_t +stm_gpio_get(struct stm_gpio *gpio, int pin) { + return (gpio->idr >> pin) & 1; +} + +static inline uint16_t +stm_gpio_get_all(struct stm_gpio *gpio) { + return gpio->idr; +} + +/* + * We can't define these in registers.ld or our fancy + * ao_enable_gpio macro will expand into a huge pile of code + * as the compiler won't do correct constant folding and + * dead-code elimination + */ + +extern struct stm_gpio stm_gpioa; +extern struct stm_gpio stm_gpiob; +extern struct stm_gpio stm_gpioc; +extern struct stm_gpio stm_gpiod; +extern struct stm_gpio stm_gpioe; +extern struct stm_gpio stm_gpioh; + +#define stm_gpiob (*((struct stm_gpio *) 0x50000400)) +#define stm_gpioa (*((struct stm_gpio *) 0x50000000)) + +struct stm_usart { + vuint32_t cr1; /* control register 1 */ + vuint32_t cr2; /* control register 2 */ + vuint32_t cr3; /* control register 3 */ + vuint32_t brr; /* baud rate register */ + + vuint32_t gtpr; /* guard time and prescaler */ + vuint32_t rtor; /* receiver timeout register */ + vuint32_t rqr; /* request register */ + vuint32_t isr; /* interrupt and status register */ + + vuint32_t icr; /* interrupt flag clear register */ + vuint32_t rdr; /* receive data register */ + vuint32_t tdr; /* transmit data register */ +}; + +#define STM_USART_CR1_M1 28 +#define STM_USART_CR1_EOBIE 27 +#define STM_USART_CR1_RTOIE 26 +#define STM_USART_CR1_DEAT 21 +#define STM_USART_CR1_DEDT 16 +#define STM_USART_CR1_OVER8 15 +#define STM_USART_CR1_CMIE 14 +#define STM_USART_CR1_MME 13 +#define STM_USART_CR1_M0 12 +#define STM_USART_CR1_WAKE 11 +#define STM_USART_CR1_PCE 10 +#define STM_USART_CR1_PS 9 +#define STM_USART_CR1_PEIE 8 +#define STM_USART_CR1_TXEIE 7 +#define STM_USART_CR1_TCIE 6 +#define STM_USART_CR1_RXNEIE 5 +#define STM_USART_CR1_IDLEIE 4 +#define STM_USART_CR1_TE 3 +#define STM_USART_CR1_RE 2 +#define STM_USART_CR1_UESM 1 +#define STM_USART_CR1_UE 0 + +#define STM_USART_CR2_ADD 24 +#define STM_USART_CR2_RTOEN 23 +#define STM_USART_CR2_ABRMOD 21 +#define STM_USART_CR2_ABREN 20 +#define STM_USART_CR2_MSBFIRST 19 +#define STM_USART_CR2_DATAINV 18 +#define STM_USART_CR2_TXINV 17 +#define STM_USART_CR2_RXINV 16 +#define STM_USART_CR2_SWAP 15 +#define STM_USART_CR2_LINEN 14 +#define STM_USART_CR2_STOP 12 +#define STM_USART_CR2_CLKEN 11 +#define STM_USART_CR2_CPOL 10 +#define STM_USART_CR2_CHPA 9 +#define STM_USART_CR2_LBCL 8 +#define STM_USART_CR2_LBDIE 6 +#define STM_USART_CR2_LBDL 5 +#define STM_USART_CR2_ADDM7 4 + +#define STM_USART_CR3_WUFIE 22 +#define STM_USART_CR3_WUS 20 +#define STM_USART_CR3_SCARCNT 17 +#define STM_USART_CR3_DEP 15 +#define STM_USART_CR3_DEM 14 +#define STM_USART_CR3_DDRE 13 +#define STM_USART_CR3_OVRDIS 12 +#define STM_USART_CR3_ONEBIT 11 +#define STM_USART_CR3_CTIIE 10 +#define STM_USART_CR3_CTSE 9 +#define STM_USART_CR3_RTSE 8 +#define STM_USART_CR3_DMAT 7 +#define STM_USART_CR3_DMAR 6 +#define STM_USART_CR3_SCEN 5 +#define STM_USART_CR3_NACK 4 +#define STM_USART_CR3_HDSEL 3 +#define STM_USART_CR3_IRLP 2 +#define STM_USART_CR3_IREN 1 +#define STM_USART_CR3_EIE 0 + +#define STM_USART_GTPR_GT 8 +#define STM_USART_GTPR_PSC 0 + +#define STM_USART_RQR_TXFRQ 4 +#define STM_USART_RQR_RXFRQ 3 +#define STM_USART_RQR_MMRQ 2 +#define STM_USART_RQR_SBKRQ 1 +#define STM_USART_RQR_ABRRQ 0 + +#define STM_USART_ISR_REACK 22 +#define STM_USART_ISR_TEACK 21 +#define STM_USART_ISR_WUF 20 +#define STM_USART_ISR_RWU 19 +#define STM_USART_ISR_SBKF 18 +#define STM_USART_ISR_CMF 17 +#define STM_USART_ISR_BUSY 16 +#define STM_USART_ISR_ABRF 15 +#define STM_USART_ISR_ABRE 14 +#define STM_USART_ISR_EOBF 12 +#define STM_USART_ISR_RTOF 11 +#define STM_USART_ISR_CTS 10 +#define STM_USART_ISR_CTSIF 9 +#define STM_USART_ISR_LBDF 8 +#define STM_USART_ISR_TXE 7 +#define STM_USART_ISR_TC 6 +#define STM_USART_ISR_RXNE 5 +#define STM_USART_ISR_IDLE 4 +#define STM_USART_ISR_ORE 3 +#define STM_USART_ISR_NF 2 +#define STM_USART_ISR_FE 1 +#define STM_USART_ISR_PE 0 + +#define STM_USART_ICR_WUCF 20 +#define STM_USART_ICR_CMCF 17 +#define STM_USART_ICR_EOBCF 12 +#define STM_USART_ICR_RTOCF 11 +#define STM_USART_ICR_CTSCF 9 +#define STM_USART_ICR_LBDCF 8 +#define STM_USART_ICR_TCCF 6 +#define STM_USART_ICR_IDLECF 4 +#define STM_USART_ICR_ORECF 3 +#define STM_USART_ICR_NCF 2 +#define STM_USART_ICR_FECF 1 +#define STM_USART_ICR_PECF 0 + +extern struct stm_usart stm_usart1; +extern struct stm_usart stm_usart2; +#define stm_usart1 (*((struct stm_usart *) 0x40013800)) +#define stm_usart2 (*((struct stm_usart *) 0x40004400)) + +struct stm_lpuart { + vuint32_t cr1; + vuint32_t cr2; + vuint32_t cr3; + vuint32_t brr; + + uint32_t unused_10; + uint32_t unused_14; + vuint32_t rqr; + vuint32_t isr; + + vuint32_t icr; + vuint32_t rdr; + vuint32_t tdr; +}; +extern struct stm_lpuart stm_lpuart1; + +#define stm_lpuart1 (*((struct stm_lpuart *) 0x40004800)) + +#define STM_LPUART_CR1_M1 28 +#define STM_LPUART_CR1_DEAT 21 +#define STM_LPUART_CR1_DEDT 16 +#define STM_LPUART_CR1_CMIE 14 +#define STM_LPUART_CR1_MME 13 +#define STM_LPUART_CR1_M0 12 +#define STM_LPUART_CR1_WAKE 11 +#define STM_LPUART_CR1_PCE 10 +#define STM_LPUART_CR1_PS 9 +#define STM_LPUART_CR1_PEIE 8 +#define STM_LPUART_CR1_TXEIE 7 +#define STM_LPUART_CR1_TCIE 6 +#define STM_LPUART_CR1_RXNEIE 5 +#define STM_LPUART_CR1_IDLEIE 4 +#define STM_LPUART_CR1_TE 3 +#define STM_LPUART_CR1_RE 2 +#define STM_LPUART_CR1_UESM 1 +#define STM_LPUART_CR1_UE 0 + +#define STM_LPUART_CR2_ADD 24 +#define STM_LPUART_CR2_MSBFIRST 19 +#define STM_LPUART_CR2_DATAINV 18 +#define STM_LPUART_CR2_TXINV 17 +#define STM_LPUART_CR2_RXINV 16 +#define STM_LPUART_CR2_SWAP 15 +#define STM_LPUART_CR2_STOP 12 +#define STM_LPUART_CR2_ADDM7 4 + +#define STM_LPUART_CR3_UCESM 23 +#define STM_LPUART_CR3_WUFIE 22 +#define STM_LPUART_CR3_WUS 20 +#define STM_LPUART_CR3_DEP 15 +#define STM_LPUART_CR3_DEM 14 +#define STM_LPUART_CR3_DDRE 13 +#define STM_LPUART_CR3_OVRDIS 12 +#define STM_LPUART_CR3_CTSIE 10 +#define STM_LPUART_CR3_CTSE 9 +#define STM_LPUART_CR3_RTSE 8 +#define STM_LPUART_CR3_DMAT 7 +#define STM_LPUART_CR3_DMAR 6 +#define STM_LPUART_CR3_HDSEL 3 +#define STM_LPUART_CR3_EIE 0 + +#define STM_LPUART_RQR_RXFRQ 3 +#define STM_LPUART_RQR_MMRQ 2 +#define STM_LPUART_RQR_SBKRQ 1 + +#define STM_LPUART_ISR_REACK 22 +#define STM_LPUART_ISR_TEACK 21 +#define STM_LPUART_ISR_WUF 20 +#define STM_LPUART_ISR_RWU 19 +#define STM_LPUART_ISR_SBKF 18 +#define STM_LPUART_ISR_CMF 17 +#define STM_LPUART_ISR_BUSY 16 +#define STM_LPUART_ISR_CTS 10 +#define STM_LPUART_ISR_CTSIF 9 +#define STM_LPUART_ISR_TXE 7 +#define STM_LPUART_ISR_TC 6 +#define STM_LPUART_ISR_RXNE 5 +#define STM_LPUART_ISR_IDLE 4 +#define STM_LPUART_ISR_ORE 3 +#define STM_LPUART_ISR_NF 2 +#define STM_LPUART_ISR_FE 1 +#define STM_LPUART_ISR_PE 1 + +#define STM_LPUART_ICR_WUCF 20 +#define STM_LPUART_ICR_CMCF 17 +#define STM_LPUART_ICR_CTSCF 9 +#define STM_LPUART_ICR_TCCF 6 +#define STM_LPUART_ICR_IDLECF 4 +#define STM_LPUART_ICR_ORECF 3 +#define STM_LPUART_ICR_NCF 2 +#define STM_LPUART_ICR_FECF 1 +#define STM_LPUART_ICR_PECF 0 + +struct stm_tim { +}; + +extern struct stm_tim stm_tim9; + +struct stm_tim1011 { + vuint32_t cr1; + uint32_t unused_4; + vuint32_t smcr; + vuint32_t dier; + vuint32_t sr; + vuint32_t egr; + vuint32_t ccmr1; + uint32_t unused_1c; + vuint32_t ccer; + vuint32_t cnt; + vuint32_t psc; + vuint32_t arr; + uint32_t unused_30; + vuint32_t ccr1; + uint32_t unused_38; + uint32_t unused_3c; + uint32_t unused_40; + uint32_t unused_44; + uint32_t unused_48; + uint32_t unused_4c; + vuint32_t or; +}; + +extern struct stm_tim1011 stm_tim10; +extern struct stm_tim1011 stm_tim11; + +#define STM_TIM1011_CR1_CKD 8 +#define STM_TIM1011_CR1_CKD_1 0 +#define STM_TIM1011_CR1_CKD_2 1 +#define STM_TIM1011_CR1_CKD_4 2 +#define STM_TIM1011_CR1_CKD_MASK 3 +#define STM_TIM1011_CR1_ARPE 7 +#define STM_TIM1011_CR1_URS 2 +#define STM_TIM1011_CR1_UDIS 1 +#define STM_TIM1011_CR1_CEN 0 + +#define STM_TIM1011_SMCR_ETP 15 +#define STM_TIM1011_SMCR_ECE 14 +#define STM_TIM1011_SMCR_ETPS 12 +#define STM_TIM1011_SMCR_ETPS_OFF 0 +#define STM_TIM1011_SMCR_ETPS_2 1 +#define STM_TIM1011_SMCR_ETPS_4 2 +#define STM_TIM1011_SMCR_ETPS_8 3 +#define STM_TIM1011_SMCR_ETPS_MASK 3 +#define STM_TIM1011_SMCR_ETF 8 +#define STM_TIM1011_SMCR_ETF_NONE 0 +#define STM_TIM1011_SMCR_ETF_CK_INT_2 1 +#define STM_TIM1011_SMCR_ETF_CK_INT_4 2 +#define STM_TIM1011_SMCR_ETF_CK_INT_8 3 +#define STM_TIM1011_SMCR_ETF_DTS_2_6 4 +#define STM_TIM1011_SMCR_ETF_DTS_2_8 5 +#define STM_TIM1011_SMCR_ETF_DTS_4_6 6 +#define STM_TIM1011_SMCR_ETF_DTS_4_8 7 +#define STM_TIM1011_SMCR_ETF_DTS_8_6 8 +#define STM_TIM1011_SMCR_ETF_DTS_8_8 9 +#define STM_TIM1011_SMCR_ETF_DTS_16_5 10 +#define STM_TIM1011_SMCR_ETF_DTS_16_6 11 +#define STM_TIM1011_SMCR_ETF_DTS_16_8 12 +#define STM_TIM1011_SMCR_ETF_DTS_32_5 13 +#define STM_TIM1011_SMCR_ETF_DTS_32_6 14 +#define STM_TIM1011_SMCR_ETF_DTS_32_8 15 +#define STM_TIM1011_SMCR_ETF_MASK 15 + +#define STM_TIM1011_DIER_CC1E 1 +#define STM_TIM1011_DIER_UIE 0 + +#define STM_TIM1011_SR_CC1OF 9 +#define STM_TIM1011_SR_CC1IF 1 +#define STM_TIM1011_SR_UIF 0 + +#define STM_TIM1011_EGR_CC1G 1 +#define STM_TIM1011_EGR_UG 0 + +#define STM_TIM1011_CCMR1_OC1CE 7 +#define STM_TIM1011_CCMR1_OC1M 4 +#define STM_TIM1011_CCMR1_OC1M_FROZEN 0 +#define STM_TIM1011_CCMR1_OC1M_SET_1_ACTIVE_ON_MATCH 1 +#define STM_TIM1011_CCMR1_OC1M_SET_1_INACTIVE_ON_MATCH 2 +#define STM_TIM1011_CCMR1_OC1M_TOGGLE 3 +#define STM_TIM1011_CCMR1_OC1M_FORCE_INACTIVE 4 +#define STM_TIM1011_CCMR1_OC1M_FORCE_ACTIVE 5 +#define STM_TIM1011_CCMR1_OC1M_PWM_MODE_1 6 +#define STM_TIM1011_CCMR1_OC1M_PWM_MODE_2 7 +#define STM_TIM1011_CCMR1_OC1M_MASK 7 +#define STM_TIM1011_CCMR1_OC1PE 3 +#define STM_TIM1011_CCMR1_OC1FE 2 +#define STM_TIM1011_CCMR1_CC1S 0 +#define STM_TIM1011_CCMR1_CC1S_OUTPUT 0 +#define STM_TIM1011_CCMR1_CC1S_INPUT_TI1 1 +#define STM_TIM1011_CCMR1_CC1S_INPUT_TI2 2 +#define STM_TIM1011_CCMR1_CC1S_INPUT_TRC 3 +#define STM_TIM1011_CCMR1_CC1S_MASK 3 + +#define STM_TIM1011_CCMR1_IC1F_NONE 0 +#define STM_TIM1011_CCMR1_IC1F_CK_INT_2 1 +#define STM_TIM1011_CCMR1_IC1F_CK_INT_4 2 +#define STM_TIM1011_CCMR1_IC1F_CK_INT_8 3 +#define STM_TIM1011_CCMR1_IC1F_DTS_2_6 4 +#define STM_TIM1011_CCMR1_IC1F_DTS_2_8 5 +#define STM_TIM1011_CCMR1_IC1F_DTS_4_6 6 +#define STM_TIM1011_CCMR1_IC1F_DTS_4_8 7 +#define STM_TIM1011_CCMR1_IC1F_DTS_8_6 8 +#define STM_TIM1011_CCMR1_IC1F_DTS_8_8 9 +#define STM_TIM1011_CCMR1_IC1F_DTS_16_5 10 +#define STM_TIM1011_CCMR1_IC1F_DTS_16_6 11 +#define STM_TIM1011_CCMR1_IC1F_DTS_16_8 12 +#define STM_TIM1011_CCMR1_IC1F_DTS_32_5 13 +#define STM_TIM1011_CCMR1_IC1F_DTS_32_6 14 +#define STM_TIM1011_CCMR1_IC1F_DTS_32_8 15 +#define STM_TIM1011_CCMR1_IC1F_MASK 15 +#define STM_TIM1011_CCMR1_IC1PSC 2 +#define STM_TIM1011_CCMR1_IC1PSC_1 0 +#define STM_TIM1011_CCMR1_IC1PSC_2 1 +#define STM_TIM1011_CCMR1_IC1PSC_4 2 +#define STM_TIM1011_CCMR1_IC1PSC_8 3 +#define STM_TIM1011_CCMR1_IC1PSC_MASK 3 +#define STM_TIM1011_CCMR1_CC1S 0 + +#define STM_TIM1011_CCER_CC1NP 3 +#define STM_TIM1011_CCER_CC1P 1 +#define STM_TIM1011_CCER_CC1E 0 + +#define STM_TIM1011_OR_TI1_RMP_RI 3 +#define STM_TIM1011_ETR_RMP 2 +#define STM_TIM1011_TI1_RMP 0 +#define STM_TIM1011_TI1_RMP_GPIO 0 +#define STM_TIM1011_TI1_RMP_LSI 1 +#define STM_TIM1011_TI1_RMP_LSE 2 +#define STM_TIM1011_TI1_RMP_RTC 3 +#define STM_TIM1011_TI1_RMP_MASK 3 + +struct stm_rcc { + vuint32_t cr; + vuint32_t icscr; + uint32_t unused08; + vuint32_t cfgr; + + vuint32_t cier; + vuint32_t cifr; + vuint32_t cicr; + vuint32_t iopstr; + + vuint32_t ahbrstr; + vuint32_t apb2rstr; + vuint32_t apb1rstr; + vuint32_t iopenr; + + vuint32_t ahbenr; + vuint32_t apb2enr; + vuint32_t apb1enr; + vuint32_t iopsmen; + + vuint32_t ahbsmenr; + vuint32_t apb2smenr; + vuint32_t apb1smenr; + vuint32_t ccipr; + + vuint32_t csr; +}; + +extern struct stm_rcc stm_rcc; + +/* Nominal high speed internal oscillator frequency is 16MHz */ +#define STM_HSI_FREQ 16000000 +#define STM_MSI_FREQ_65536 65536 +#define STM_MSI_FREQ_131072 131072 +#define STM_MSI_FREQ_262144 262144 +#define STM_MSI_FREQ_524288 524288 +#define STM_MSI_FREQ_1048576 1048576 +#define STM_MSI_FREQ_2097152 2097152 +#define STM_MSI_FREQ_4194304 4194304 + +#define STM_RCC_CR_RTCPRE (29) +#define STM_RCC_CR_RTCPRE_HSE_DIV_2 0 +#define STM_RCC_CR_RTCPRE_HSE_DIV_4 1 +#define STM_RCC_CR_RTCPRE_HSE_DIV_8 2 +#define STM_RCC_CR_RTCPRE_HSE_DIV_16 3 +#define STM_RCC_CR_RTCPRE_HSE_MASK 3 + +#define STM_RCC_CR_CSSON (28) +#define STM_RCC_CR_PLLRDY (25) +#define STM_RCC_CR_PLLON (24) +#define STM_RCC_CR_HSEBYP (18) +#define STM_RCC_CR_HSERDY (17) +#define STM_RCC_CR_HSEON (16) +#define STM_RCC_CR_MSIRDY (9) +#define STM_RCC_CR_MSION (8) +#define STM_RCC_CR_HSIRDY (1) +#define STM_RCC_CR_HSION (0) + +#define STM_RCC_ICSCR_HSI16CAL 0 +#define STM_RCC_ICSCR_HSI16TRIM 8 +#define STM_RCC_ICSCR_MSIRANGE 13 +#define STM_RCC_ICSCR_MSIRANGE_65536 0 +#define STM_RCC_ICSCR_MSIRANGE_131072 +#define STM_RCC_ICSCR_MSIRANGE_262144 2 +#define STM_RCC_ICSCR_MSIRANGE_524288 3 +#define STM_RCC_ICSCR_MSIRANGE_1048576 4 +#define STM_RCC_ICSCR_MSIRANGE_2097152 5 +#define STM_RCC_ICSCR_MSIRANGE_4194304 6 +#define STM_RCC_ICSCR_MSIRANGE_MASK 0x7 +#define STM_RCC_ICSCR_MSICAL 16 +#define STM_RCC_ICSCR_MSITRIM 24 + +#define STM_RCC_CFGR_MCOPRE (28) +#define STM_RCC_CFGR_MCOPRE_DIV_1 0 +#define STM_RCC_CFGR_MCOPRE_DIV_2 1 +#define STM_RCC_CFGR_MCOPRE_DIV_4 2 +#define STM_RCC_CFGR_MCOPRE_DIV_8 3 +#define STM_RCC_CFGR_MCOPRE_DIV_16 4 +#define STM_RCC_CFGR_MCOPRE_MASK 7 + +#define STM_RCC_CFGR_MCOSEL (24) +#define STM_RCC_CFGR_MCOSEL_DISABLE 0 +#define STM_RCC_CFGR_MCOSEL_SYSCLK 1 +#define STM_RCC_CFGR_MCOSEL_HSI 2 +#define STM_RCC_CFGR_MCOSEL_MSI 3 +#define STM_RCC_CFGR_MCOSEL_HSE 4 +#define STM_RCC_CFGR_MCOSEL_PLL 5 +#define STM_RCC_CFGR_MCOSEL_LSI 6 +#define STM_RCC_CFGR_MCOSEL_LSE 7 +#define STM_RCC_CFGR_MCOSEL_MASK 7 + +#define STM_RCC_CFGR_PLLDIV (22) +#define STM_RCC_CFGR_PLLDIV_2 1 +#define STM_RCC_CFGR_PLLDIV_3 2 +#define STM_RCC_CFGR_PLLDIV_4 3 +#define STM_RCC_CFGR_PLLDIV_MASK 3 + +#define STM_RCC_CFGR_PLLMUL (18) +#define STM_RCC_CFGR_PLLMUL_3 0 +#define STM_RCC_CFGR_PLLMUL_4 1 +#define STM_RCC_CFGR_PLLMUL_6 2 +#define STM_RCC_CFGR_PLLMUL_8 3 +#define STM_RCC_CFGR_PLLMUL_12 4 +#define STM_RCC_CFGR_PLLMUL_16 5 +#define STM_RCC_CFGR_PLLMUL_24 6 +#define STM_RCC_CFGR_PLLMUL_32 7 +#define STM_RCC_CFGR_PLLMUL_48 8 +#define STM_RCC_CFGR_PLLMUL_MASK 0xf + +#define STM_RCC_CFGR_PLLSRC (16) + +#define STM_RCC_CFGR_PPRE2 (11) +#define STM_RCC_CFGR_PPRE2_DIV_1 0 +#define STM_RCC_CFGR_PPRE2_DIV_2 4 +#define STM_RCC_CFGR_PPRE2_DIV_4 5 +#define STM_RCC_CFGR_PPRE2_DIV_8 6 +#define STM_RCC_CFGR_PPRE2_DIV_16 7 +#define STM_RCC_CFGR_PPRE2_MASK 7 + +#define STM_RCC_CFGR_PPRE1 (8) +#define STM_RCC_CFGR_PPRE1_DIV_1 0 +#define STM_RCC_CFGR_PPRE1_DIV_2 4 +#define STM_RCC_CFGR_PPRE1_DIV_4 5 +#define STM_RCC_CFGR_PPRE1_DIV_8 6 +#define STM_RCC_CFGR_PPRE1_DIV_16 7 +#define STM_RCC_CFGR_PPRE1_MASK 7 + +#define STM_RCC_CFGR_HPRE (4) +#define STM_RCC_CFGR_HPRE_DIV_1 0 +#define STM_RCC_CFGR_HPRE_DIV_2 8 +#define STM_RCC_CFGR_HPRE_DIV_4 9 +#define STM_RCC_CFGR_HPRE_DIV_8 0xa +#define STM_RCC_CFGR_HPRE_DIV_16 0xb +#define STM_RCC_CFGR_HPRE_DIV_64 0xc +#define STM_RCC_CFGR_HPRE_DIV_128 0xd +#define STM_RCC_CFGR_HPRE_DIV_256 0xe +#define STM_RCC_CFGR_HPRE_DIV_512 0xf +#define STM_RCC_CFGR_HPRE_MASK 0xf + +#define STM_RCC_CFGR_SWS (2) +#define STM_RCC_CFGR_SWS_MSI 0 +#define STM_RCC_CFGR_SWS_HSI 1 +#define STM_RCC_CFGR_SWS_HSE 2 +#define STM_RCC_CFGR_SWS_PLL 3 +#define STM_RCC_CFGR_SWS_MASK 3 + +#define STM_RCC_CFGR_SW (0) +#define STM_RCC_CFGR_SW_MSI 0 +#define STM_RCC_CFGR_SW_HSI 1 +#define STM_RCC_CFGR_SW_HSE 2 +#define STM_RCC_CFGR_SW_PLL 3 +#define STM_RCC_CFGR_SW_MASK 3 + +#define STM_RCC_IOPENR_IOPAEN 0 +#define STM_RCC_IOPENR_IOPBEN 1 +#define STM_RCC_IOPENR_IOPCEN 2 +#define STM_RCC_IOPENR_IOPDEN 3 +#define STM_RCC_IOPENR_IOPEEN 4 +#define STM_RCC_IOPENR_IOPHEN 7 + +#define STM_RCC_AHBENR_DMA1EN 0 +#define STM_RCC_AHBENR_MIFEN 8 +#define STM_RCC_AHBENR_CRCEN 12 +#define STM_RCC_AHBENR_CRYPEN 24 + +#define STM_RCC_APB2ENR_DBGEN (22) +#define STM_RCC_APB2ENR_USART1EN (14) +#define STM_RCC_APB2ENR_SPI1EN (12) +#define STM_RCC_APB2ENR_ADCEN (9) +#define STM_RCC_APB2ENR_FWEN (7) +#define STM_RCC_APB2ENR_TIM22EN (5) +#define STM_RCC_APB2ENR_TIM21EN (2) +#define STM_RCC_APB2ENR_SYSCFGEN (0) + +#define STM_RCC_APB1ENR_LPTIM1EN 31 +#define STM_RCC_APB1ENR_I2C3EN 30 +#define STM_RCC_APB1ENR_PWREN 28 +#define STM_RCC_APB1ENR_I2C2EN 22 +#define STM_RCC_APB1ENR_I2C1EN 21 +#define STM_RCC_APB1ENR_USART5EN 20 +#define STM_RCC_APB1ENR_USART4EN 19 +#define STM_RCC_APB1ENR_LPUART1EN 18 +#define STM_RCC_APB1ENR_USART2EN 17 +#define STM_RCC_APB1ENR_SPI2EN 14 +#define STM_RCC_APB1ENR_WWDGEN 11 +#define STM_RCC_APB1ENR_TIM7EN 5 +#define STM_RCC_APB1ENR_TIM6EN 4 +#define STM_RCC_APB1ENR_TIM3EN 1 +#define STM_RCC_APB1ENR_TIM2EN 0 + +#define STM_RCC_CCIPR_LPTIM1SEL 18 +#define STM_RCC_CCIPR_I2C3SEL 16 +#define STM_RCC_CCIPR_I2C1SEL 12 +#define STM_RCC_CCIPR_LPUART1SEL 10 +#define STM_RCC_CCIPR_LPUART1SEL_APB 0 +#define STM_RCC_CCIPR_LPUART1SEL_SYSTEM 1 +#define STM_RCC_CCIPR_LPUART1SEL_HSI16 2 +#define STM_RCC_CCIPR_LPUART1SEL_LSE 3 +#define STM_RCC_CCIPR_USART2SEL 2 +#define STM_RCC_CCIPR_USART1SEL 0 + +#define STM_RCC_CSR_LPWRRSTF (31) +#define STM_RCC_CSR_WWDGRSTF (30) +#define STM_RCC_CSR_IWDGRSTF (29) +#define STM_RCC_CSR_SFTRSTF (28) +#define STM_RCC_CSR_PORRSTF (27) +#define STM_RCC_CSR_PINRSTF (26) +#define STM_RCC_CSR_OBLRSTF (25) +#define STM_RCC_CSR_RMVF (24) +#define STM_RCC_CSR_RTFRST (23) +#define STM_RCC_CSR_RTCEN (22) +#define STM_RCC_CSR_RTCSEL (16) + +#define STM_RCC_CSR_RTCSEL_NONE 0 +#define STM_RCC_CSR_RTCSEL_LSE 1 +#define STM_RCC_CSR_RTCSEL_LSI 2 +#define STM_RCC_CSR_RTCSEL_HSE 3 +#define STM_RCC_CSR_RTCSEL_MASK 3 + +#define STM_RCC_CSR_LSEBYP (10) +#define STM_RCC_CSR_LSERDY (9) +#define STM_RCC_CSR_LSEON (8) +#define STM_RCC_CSR_LSIRDY (1) +#define STM_RCC_CSR_LSION (0) + +struct stm_pwr { + vuint32_t cr; + vuint32_t csr; +}; + +extern struct stm_pwr stm_pwr; + + +#define STM_PWR_CR_LPDS 16 +#define STM_PWR_CR_LPRUN 14 +#define STM_PWR_CR_DS_EE_KOFF 13 +#define STM_PWR_CR_VOS 11 +#define STM_PWR_CR_VOS_1_8 1 +#define STM_PWR_CR_VOS_1_5 2 +#define STM_PWR_CR_VOS_1_2 3 +#define STM_PWR_CR_VOS_MASK 3 +#define STM_PWR_CR_FWU 10 +#define STM_PWR_CR_ULP 9 +#define STM_PWR_CR_DBP 8 +#define STM_PWR_CR_PLS 5 +#define STM_PWR_CR_PLS_1_9 0 +#define STM_PWR_CR_PLS_2_1 1 +#define STM_PWR_CR_PLS_2_3 2 +#define STM_PWR_CR_PLS_2_5 3 +#define STM_PWR_CR_PLS_2_7 4 +#define STM_PWR_CR_PLS_2_9 5 +#define STM_PWR_CR_PLS_3_1 6 +#define STM_PWR_CR_PLS_EXT 7 +#define STM_PWR_CR_PLS_MASK 7 +#define STM_PWR_CR_PVDE 4 +#define STM_PWR_CR_CSBF 3 +#define STM_PWR_CR_CWUF 2 +#define STM_PWR_CR_PDDS 1 +#define STM_PWR_CR_LPSDSR 0 + +#define STM_PWR_CSR_EWUP3 (10) +#define STM_PWR_CSR_EWUP2 (9) +#define STM_PWR_CSR_EWUP1 (8) +#define STM_PWR_CSR_REGLPF (5) +#define STM_PWR_CSR_VOSF (4) +#define STM_PWR_CSR_VREFINTRDYF (3) +#define STM_PWR_CSR_PVDO (2) +#define STM_PWR_CSR_SBF (1) +#define STM_PWR_CSR_WUF (0) + +struct stm_tim67 { + vuint32_t cr1; + vuint32_t cr2; + uint32_t _unused_08; + vuint32_t dier; + + vuint32_t sr; + vuint32_t egr; + uint32_t _unused_18; + uint32_t _unused_1c; + + uint32_t _unused_20; + vuint32_t cnt; + vuint32_t psc; + vuint32_t arr; +}; + +extern struct stm_tim67 stm_tim6; + +#define STM_TIM67_CR1_ARPE (7) +#define STM_TIM67_CR1_OPM (3) +#define STM_TIM67_CR1_URS (2) +#define STM_TIM67_CR1_UDIS (1) +#define STM_TIM67_CR1_CEN (0) + +#define STM_TIM67_CR2_MMS (4) +#define STM_TIM67_CR2_MMS_RESET 0 +#define STM_TIM67_CR2_MMS_ENABLE 1 +#define STM_TIM67_CR2_MMS_UPDATE 2 +#define STM_TIM67_CR2_MMS_MASK 7 + +#define STM_TIM67_DIER_UDE (8) +#define STM_TIM67_DIER_UIE (0) + +#define STM_TIM67_SR_UIF (0) + +#define STM_TIM67_EGR_UG (0) + +struct stm_lcd { + vuint32_t cr; + vuint32_t fcr; + vuint32_t sr; + vuint32_t clr; + uint32_t unused_0x10; + vuint32_t ram[8*2]; +}; + +extern struct stm_lcd stm_lcd; + +#define STM_LCD_CR_MUX_SEG (7) + +#define STM_LCD_CR_BIAS (5) +#define STM_LCD_CR_BIAS_1_4 0 +#define STM_LCD_CR_BIAS_1_2 1 +#define STM_LCD_CR_BIAS_1_3 2 +#define STM_LCD_CR_BIAS_MASK 3 + +#define STM_LCD_CR_DUTY (2) +#define STM_LCD_CR_DUTY_STATIC 0 +#define STM_LCD_CR_DUTY_1_2 1 +#define STM_LCD_CR_DUTY_1_3 2 +#define STM_LCD_CR_DUTY_1_4 3 +#define STM_LCD_CR_DUTY_1_8 4 +#define STM_LCD_CR_DUTY_MASK 7 + +#define STM_LCD_CR_VSEL (1) +#define STM_LCD_CR_LCDEN (0) + +#define STM_LCD_FCR_PS (22) +#define STM_LCD_FCR_PS_1 0x0 +#define STM_LCD_FCR_PS_2 0x1 +#define STM_LCD_FCR_PS_4 0x2 +#define STM_LCD_FCR_PS_8 0x3 +#define STM_LCD_FCR_PS_16 0x4 +#define STM_LCD_FCR_PS_32 0x5 +#define STM_LCD_FCR_PS_64 0x6 +#define STM_LCD_FCR_PS_128 0x7 +#define STM_LCD_FCR_PS_256 0x8 +#define STM_LCD_FCR_PS_512 0x9 +#define STM_LCD_FCR_PS_1024 0xa +#define STM_LCD_FCR_PS_2048 0xb +#define STM_LCD_FCR_PS_4096 0xc +#define STM_LCD_FCR_PS_8192 0xd +#define STM_LCD_FCR_PS_16384 0xe +#define STM_LCD_FCR_PS_32768 0xf +#define STM_LCD_FCR_PS_MASK 0xf + +#define STM_LCD_FCR_DIV (18) +#define STM_LCD_FCR_DIV_16 0x0 +#define STM_LCD_FCR_DIV_17 0x1 +#define STM_LCD_FCR_DIV_18 0x2 +#define STM_LCD_FCR_DIV_19 0x3 +#define STM_LCD_FCR_DIV_20 0x4 +#define STM_LCD_FCR_DIV_21 0x5 +#define STM_LCD_FCR_DIV_22 0x6 +#define STM_LCD_FCR_DIV_23 0x7 +#define STM_LCD_FCR_DIV_24 0x8 +#define STM_LCD_FCR_DIV_25 0x9 +#define STM_LCD_FCR_DIV_26 0xa +#define STM_LCD_FCR_DIV_27 0xb +#define STM_LCD_FCR_DIV_28 0xc +#define STM_LCD_FCR_DIV_29 0xd +#define STM_LCD_FCR_DIV_30 0xe +#define STM_LCD_FCR_DIV_31 0xf +#define STM_LCD_FCR_DIV_MASK 0xf + +#define STM_LCD_FCR_BLINK (16) +#define STM_LCD_FCR_BLINK_DISABLE 0 +#define STM_LCD_FCR_BLINK_SEG0_COM0 1 +#define STM_LCD_FCR_BLINK_SEG0_COMALL 2 +#define STM_LCD_FCR_BLINK_SEGALL_COMALL 3 +#define STM_LCD_FCR_BLINK_MASK 3 + +#define STM_LCD_FCR_BLINKF (13) +#define STM_LCD_FCR_BLINKF_8 0 +#define STM_LCD_FCR_BLINKF_16 1 +#define STM_LCD_FCR_BLINKF_32 2 +#define STM_LCD_FCR_BLINKF_64 3 +#define STM_LCD_FCR_BLINKF_128 4 +#define STM_LCD_FCR_BLINKF_256 5 +#define STM_LCD_FCR_BLINKF_512 6 +#define STM_LCD_FCR_BLINKF_1024 7 +#define STM_LCD_FCR_BLINKF_MASK 7 + +#define STM_LCD_FCR_CC (10) +#define STM_LCD_FCR_CC_MASK 7 + +#define STM_LCD_FCR_DEAD (7) +#define STM_LCD_FCR_DEAD_MASK 7 + +#define STM_LCD_FCR_PON (4) +#define STM_LCD_FCR_PON_MASK 7 + +#define STM_LCD_FCR_UDDIE (3) +#define STM_LCD_FCR_SOFIE (1) +#define STM_LCD_FCR_HD (0) + +#define STM_LCD_SR_FCRSF (5) +#define STM_LCD_SR_RDY (4) +#define STM_LCD_SR_UDD (3) +#define STM_LCD_SR_UDR (2) +#define STM_LCD_SR_SOF (1) +#define STM_LCD_SR_ENS (0) + +#define STM_LCD_CLR_UDDC (3) +#define STM_LCD_CLR_SOFC (1) + +/* The SYSTICK starts at 0xe000e010 */ + +struct stm_systick { + vuint32_t csr; + vuint32_t rvr; + vuint32_t cvr; + vuint32_t calib; +}; + +extern struct stm_systick stm_systick; + +#define STM_SYSTICK_CSR_ENABLE 0 +#define STM_SYSTICK_CSR_TICKINT 1 +#define STM_SYSTICK_CSR_CLKSOURCE 2 +#define STM_SYSTICK_CSR_CLKSOURCE_HCLK_8 0 +#define STM_SYSTICK_CSR_CLKSOURCE_HCLK 1 +#define STM_SYSTICK_CSR_COUNTFLAG 16 + +/* The NVIC starts at 0xe000e100, so add that to the offsets to find the absolute address */ + +struct stm_nvic { + vuint32_t iser; /* 0x000 0xe000e100 Set Enable Register */ + + uint8_t _unused020[0x080 - 0x004]; + + vuint32_t icer; /* 0x080 0xe000e180 Clear Enable Register */ + + uint8_t _unused0a0[0x100 - 0x084]; + + vuint32_t ispr; /* 0x100 0xe000e200 Set Pending Register */ + + uint8_t _unused120[0x180 - 0x104]; + + vuint32_t icpr; /* 0x180 0xe000e280 Clear Pending Register */ + + uint8_t _unused1a0[0x300 - 0x184]; + + vuint32_t ipr[8]; /* 0x300 0xe000e400 Priority Register */ +}; + +extern struct stm_nvic stm_nvic; + +#define IRQ_MASK(irq) (1 << (irq)) +#define IRQ_BOOL(v,irq) (((v) >> (irq)) & 1) + +static inline void +stm_nvic_set_enable(int irq) { + stm_nvic.iser = IRQ_MASK(irq); +} + +static inline void +stm_nvic_clear_enable(int irq) { + stm_nvic.icer = IRQ_MASK(irq); +} + +static inline int +stm_nvic_enabled(int irq) { + return IRQ_BOOL(stm_nvic.iser, irq); +} + +static inline void +stm_nvic_set_pending(int irq) { + stm_nvic.ispr = IRQ_MASK(irq); +} + +static inline void +stm_nvic_clear_pending(int irq) { + stm_nvic.icpr = IRQ_MASK(irq); +} + +static inline int +stm_nvic_pending(int irq) { + return IRQ_BOOL(stm_nvic.ispr, irq); +} + +#define IRQ_PRIO_REG(irq) ((irq) >> 2) +#define IRQ_PRIO_BIT(irq) (((irq) & 3) << 3) +#define IRQ_PRIO_MASK(irq) (0xff << IRQ_PRIO_BIT(irq)) + +static inline void +stm_nvic_set_priority(int irq, uint8_t prio) { + int n = IRQ_PRIO_REG(irq); + uint32_t v; + + v = stm_nvic.ipr[n]; + v &= ~IRQ_PRIO_MASK(irq); + v |= (prio) << IRQ_PRIO_BIT(irq); + stm_nvic.ipr[n] = v; +} + +static inline uint8_t +stm_nvic_get_priority(int irq) { + return (stm_nvic.ipr[IRQ_PRIO_REG(irq)] >> IRQ_PRIO_BIT(irq)) & IRQ_PRIO_MASK(0); +} + +struct stm_scb { + vuint32_t cpuid; + vuint32_t icsr; + vuint32_t vtor; + vuint32_t aircr; + + vuint32_t scr; + vuint32_t ccr; + vuint32_t shpr1; + vuint32_t shpr2; + + vuint32_t shpr3; + vuint32_t shcrs; + vuint32_t cfsr; + vuint32_t hfsr; + + uint32_t unused_30; + vuint32_t mmfar; + vuint32_t bfar; +}; + +extern struct stm_scb stm_scb; + +#define STM_SCB_AIRCR_VECTKEY 16 +#define STM_SCB_AIRCR_VECTKEY_KEY 0x05fa +#define STM_SCB_AIRCR_PRIGROUP 8 +#define STM_SCB_AIRCR_SYSRESETREQ 2 +#define STM_SCB_AIRCR_VECTCLRACTIVE 1 +#define STM_SCB_AIRCR_VECTRESET 0 + +#define STM_SCB_SCR_SVONPEND 4 +#define STM_SCB_SCR_SLEEPDEEP 2 +#define STM_SCB_SCR_SLEEPONEXIT 1 + +struct stm_mpu { + vuint32_t typer; + vuint32_t cr; + vuint32_t rnr; + vuint32_t rbar; + + vuint32_t rasr; + vuint32_t rbar_a1; + vuint32_t rasr_a1; + vuint32_t rbar_a2; + vuint32_t rasr_a2; + vuint32_t rbar_a3; + vuint32_t rasr_a3; +}; + +extern struct stm_mpu stm_mpu; + +#define STM_MPU_TYPER_IREGION 16 +#define STM_MPU_TYPER_IREGION_MASK 0xff +#define STM_MPU_TYPER_DREGION 8 +#define STM_MPU_TYPER_DREGION_MASK 0xff +#define STM_MPU_TYPER_SEPARATE 0 + +#define STM_MPU_CR_PRIVDEFENA 2 +#define STM_MPU_CR_HFNMIENA 1 +#define STM_MPU_CR_ENABLE 0 + +#define STM_MPU_RNR_REGION 0 +#define STM_MPU_RNR_REGION_MASK 0xff + +#define STM_MPU_RBAR_ADDR 5 +#define STM_MPU_RBAR_ADDR_MASK 0x7ffffff + +#define STM_MPU_RBAR_VALID 4 +#define STM_MPU_RBAR_REGION 0 +#define STM_MPU_RBAR_REGION_MASK 0xf + +#define STM_MPU_RASR_XN 28 +#define STM_MPU_RASR_AP 24 +#define STM_MPU_RASR_AP_NONE_NONE 0 +#define STM_MPU_RASR_AP_RW_NONE 1 +#define STM_MPU_RASR_AP_RW_RO 2 +#define STM_MPU_RASR_AP_RW_RW 3 +#define STM_MPU_RASR_AP_RO_NONE 5 +#define STM_MPU_RASR_AP_RO_RO 6 +#define STM_MPU_RASR_AP_MASK 7 +#define STM_MPU_RASR_TEX 19 +#define STM_MPU_RASR_TEX_MASK 7 +#define STM_MPU_RASR_S 18 +#define STM_MPU_RASR_C 17 +#define STM_MPU_RASR_B 16 +#define STM_MPU_RASR_SRD 8 +#define STM_MPU_RASR_SRD_MASK 0xff +#define STM_MPU_RASR_SIZE 1 +#define STM_MPU_RASR_SIZE_MASK 0x1f +#define STM_MPU_RASR_ENABLE 0 + +#define isr_decl(name) void stm_ ## name ## _isr(void) + +isr_decl(halt); +isr_decl(ignore); + +isr_decl(nmi); +isr_decl(hardfault); +isr_decl(usagefault); +isr_decl(svc); +isr_decl(debugmon); +isr_decl(pendsv); +isr_decl(systick); +isr_decl(wwdg); +isr_decl(pvd); +isr_decl(rtc); +isr_decl(flash); +isr_decl(rcc_crs); +isr_decl(exti1_0); +isr_decl(exti3_2); +isr_decl(exti15_4); +isr_decl(dma1_channel1); +isr_decl(dma1_channel3_2); +isr_decl(dma1_channel7_4); +isr_decl(adc_comp); +isr_decl(lptim1); +isr_decl(usart4_usart5); +isr_decl(tim2); +isr_decl(tim3); +isr_decl(tim4); +isr_decl(tim6); +isr_decl(tim7); +isr_decl(tim21); +isr_decl(i2c3); +isr_decl(tim22); +isr_decl(i2c1); +isr_decl(i2c2); +isr_decl(spi1); +isr_decl(spi2); +isr_decl(usart1); +isr_decl(usart2); +isr_decl(usart3); +isr_decl(lpuart1_aes); + +#undef isr_decl + +#define STM_ISR_WWDG_POS 0 +#define STM_ISR_PVD_POS 1 +#define STM_ISR_RTC_POS 2 +#define STM_ISR_FLASH_POS 3 +#define STM_ISR_RCC_CRS_POS 4 +#define STM_ISR_EXTI1_0_POS 5 +#define STM_ISR_EXTI3_2_POS 6 +#define STM_ISR_EXTI15_4_POS 7 +#define STM_ISR_DMA1_CHANNEL1_POS 9 +#define STM_ISR_DMA1_CHANNEL3_2_POS 10 +#define STM_ISR_DMA1_CHANNEL7_4_POS 11 +#define STM_ISR_ADC_COMP_POS 12 +#define STM_ISR_LPTIM1_POS 13 +#define STM_ISR_USART4_USART5_POS 14 +#define STM_ISR_TIM2_POS 15 +#define STM_ISR_TIM3_POS 16 +#define STM_ISR_TIM6_POS 17 +#define STM_ISR_TIM7_POS 18 +#define STM_ISR_TIM21_POS 20 +#define STM_ISR_I2C3_POS 21 +#define STM_ISR_TIM22_POS 22 +#define STM_ISR_I2C1_POS 23 +#define STM_ISR_I2C2_POS 24 +#define STM_ISR_SPI1_POS 25 +#define STM_ISR_SPI2_POS 26 +#define STM_ISR_USART1_POS 27 +#define STM_ISR_USART2_POS 28 +#define STM_ISR_LPUART1_AES_POS 29 + +struct stm_syscfg { + vuint32_t memrmp; + vuint32_t pmc; + vuint32_t exticr[4]; +}; + +extern struct stm_syscfg stm_syscfg; + +#define STM_SYSCFG_MEMRMP_MEM_MODE 0 +#define STM_SYSCFG_MEMRMP_MEM_MODE_MAIN_FLASH 0 +#define STM_SYSCFG_MEMRMP_MEM_MODE_SYSTEM_FLASH 1 +#define STM_SYSCFG_MEMRMP_MEM_MODE_SRAM 3 +#define STM_SYSCFG_MEMRMP_MEM_MODE_MASK 3 + +#define STM_SYSCFG_PMC_USB_PU 0 + +#define STM_SYSCFG_EXTICR_PA 0 +#define STM_SYSCFG_EXTICR_PB 1 +#define STM_SYSCFG_EXTICR_PC 2 +#define STM_SYSCFG_EXTICR_PD 3 +#define STM_SYSCFG_EXTICR_PE 4 +#define STM_SYSCFG_EXTICR_PH 5 + +static inline void +stm_exticr_set(struct stm_gpio *gpio, int pin) { + uint8_t reg = pin >> 2; + uint8_t shift = (pin & 3) << 2; + uint8_t val = 0; + + /* Enable SYSCFG */ + stm_rcc.apb2enr |= (1 << STM_RCC_APB2ENR_SYSCFGEN); + + if (gpio == &stm_gpioa) + val = STM_SYSCFG_EXTICR_PA; + else if (gpio == &stm_gpiob) + val = STM_SYSCFG_EXTICR_PB; + else if (gpio == &stm_gpioc) + val = STM_SYSCFG_EXTICR_PC; + else if (gpio == &stm_gpiod) + val = STM_SYSCFG_EXTICR_PD; + else if (gpio == &stm_gpioe) + val = STM_SYSCFG_EXTICR_PE; + + stm_syscfg.exticr[reg] = (stm_syscfg.exticr[reg] & ~(0xf << shift)) | val << shift; +} + +struct stm_dma_channel { + vuint32_t ccr; + vuint32_t cndtr; + vvoid_t cpar; + vvoid_t cmar; + vuint32_t reserved; +}; + +#define STM_NUM_DMA 7 + +struct stm_dma { + vuint32_t isr; + vuint32_t ifcr; + struct stm_dma_channel channel[STM_NUM_DMA]; + uint8_t unused94[0xa8 - 0x94]; + vuint32_t cselr; +}; + +extern struct stm_dma stm_dma1; +#define stm_dma1 (*(struct stm_dma *) 0x40020000) + +/* DMA channels go from 1 to 7, instead of 0 to 6 (sigh) + */ + +#define STM_DMA_INDEX(channel) ((channel) - 1) + +#define STM_DMA_ISR(index) ((index) << 2) +#define STM_DMA_ISR_MASK 0xf +#define STM_DMA_ISR_TEIF 3 +#define STM_DMA_ISR_HTIF 2 +#define STM_DMA_ISR_TCIF 1 +#define STM_DMA_ISR_GIF 0 + +#define STM_DMA_IFCR(index) ((index) << 2) +#define STM_DMA_IFCR_MASK 0xf +#define STM_DMA_IFCR_CTEIF 3 +#define STM_DMA_IFCR_CHTIF 2 +#define STM_DMA_IFCR_CTCIF 1 +#define STM_DMA_IFCR_CGIF 0 + +#define STM_DMA_CCR_MEM2MEM (14) + +#define STM_DMA_CCR_PL (12) +#define STM_DMA_CCR_PL_LOW (0) +#define STM_DMA_CCR_PL_MEDIUM (1) +#define STM_DMA_CCR_PL_HIGH (2) +#define STM_DMA_CCR_PL_VERY_HIGH (3) +#define STM_DMA_CCR_PL_MASK (3) + +#define STM_DMA_CCR_MSIZE (10) +#define STM_DMA_CCR_MSIZE_8 (0) +#define STM_DMA_CCR_MSIZE_16 (1) +#define STM_DMA_CCR_MSIZE_32 (2) +#define STM_DMA_CCR_MSIZE_MASK (3) + +#define STM_DMA_CCR_PSIZE (8) +#define STM_DMA_CCR_PSIZE_8 (0) +#define STM_DMA_CCR_PSIZE_16 (1) +#define STM_DMA_CCR_PSIZE_32 (2) +#define STM_DMA_CCR_PSIZE_MASK (3) + +#define STM_DMA_CCR_MINC (7) +#define STM_DMA_CCR_PINC (6) +#define STM_DMA_CCR_CIRC (5) +#define STM_DMA_CCR_DIR (4) +#define STM_DMA_CCR_DIR_PER_TO_MEM 0 +#define STM_DMA_CCR_DIR_MEM_TO_PER 1 +#define STM_DMA_CCR_TEIE (3) +#define STM_DMA_CCR_HTIE (2) +#define STM_DMA_CCR_TCIE (1) +#define STM_DMA_CCR_EN (0) + +#define STM_DMA_CSELR_C7S_SPI2_TX 0x2 +#define STM_DMA_CSELR_C7S_USART2_TX 0x4 +#define STM_DMA_CSELR_C7S_LPUART1_TX 0x5 +#define STM_DMA_CSELR_C7S_I2C1_RX 0x6 +#define STM_DMA_CSELR_C7S_TIM2_CH2_TIM2_CH4 0x8 +#define STM_DMA_CSELR_C7S_USART4_TX 0xc +#define STM_DMA_CSELR_C7S_USART5_TX 0xd + +#define STM_DMA_CSELR_C6S_SPI2_RX 0x2 +#define STM_DMA_CSELR_C6S_USART2_RX 0x4 +#define STM_DMA_CSELR_C6S_LPUART1_RX 0x5 +#define STM_DMA_CSELR_C6S_I2C1_TX 0x6 +#define STM_DMA_CSELR_C6S_TIM3_TRIG 0xa +#define STM_DMA_CSELR_C6S_USART4_RX 0xc +#define STM_DMA_CSELR_C6S_USART5_RX 0xd + +#define STM_DMA_CSELR_C5S_SPI2_TX 0x2 +#define STM_DMA_CSELR_C5S_USART1_RX 0x3 +#define STM_DMA_CSELR_C5S_USART2_RX 0x4 +#define STM_DMA_CSELR_C5S_I2C2_RX 0x7 +#define STM_DMA_CSELR_C5S_TIM2_CH1 0x8 +#define STM_DMA_CSELR_C5S_TIM3_CH1 0xa +#define STM_DMA_CSELR_C5S_AES_IN 0xb +#define STM_DMA_CSELR_C5S_I2C3_RX 0xe + +#define STM_DMA_CSELR_C4S_SPI2_RX 0x2 +#define STM_DMA_CSELR_C4S_USART1_TX 0x3 +#define STM_DMA_CSELR_C4S_USART2_TX 0x4 +#define STM_DMA_CSELR_C4S_I2C2_TX 0x7 +#define STM_DMA_CSELR_C4S_TIM2_CH4 0x8 +#define STM_DMA_CSELR_C4S_I2C3_TX 0xe +#define STM_DMA_CSELR_C4S_TIM7_UP 0xf + +#define STM_DMA_CSELR_C3S_SPI1_TX 0x1 +#define STM_DMA_CSELR_C3S_USART1_RX 0x3 +#define STM_DMA_CSELR_C3S_LPUART1_RX 0x5 +#define STM_DMA_CSELR_C3S_I2C1_RX 0x6 +#define STM_DMA_CSELR_C3S_TIM2_CH2 0x8 +#define STM_DMA_CSELR_C3S_TIM4_CH4_TIM4_UP 0xa +#define STM_DMA_CSELR_C3S_AES_OUT 0xb +#define STM_DMA_CSELR_C3S_USART4_TX 0xc +#define STM_DMA_CSELR_C3S_USART5_TX 0xd +#define STM_DMA_CSELR_C3S_I2C3_RX 0xe + +#define STM_DMA_CSELR_C2S_ADC 0x0 +#define STM_DMA_CSELR_C2S_SPI1_RX 0x1 +#define STM_DMA_CSELR_C2S_USART1_TX 0x3 +#define STM_DMA_CSELR_C2S_LPUART1_TX 0x5 +#define STM_DMA_CSELR_C2S_I2C1_TX 0x6 +#define STM_DMA_CSELR_C2S_TIM2_UP 0x8 +#define STM_DMA_CSELR_C2S_TIM6_UP 0x9 +#define STM_DMA_CSELR_C2S_TIM3_CH3 0xa +#define STM_DMA_CSELR_C2S_AES_OUT 0xb +#define STM_DMA_CSELR_C2S_USART4_RX 0xc +#define STM_DMA_CSELR_C2S_USART5_RX 0xd +#define STM_DMA_CSELR_C2S_I2C3_TX 0xe + +#define STM_DMA_CSELR_C1S_ADC 0x0 +#define STM_DMA_CSELR_C1S_TIM2_CH3 0x8 +#define STM_DMA_CSELR_C1S_AES_IN 0xb + +#define STM_NUM_SPI 1 + +struct stm_spi { + vuint32_t cr1; + vuint32_t cr2; + vuint32_t sr; + vuint32_t dr; + vuint32_t crcpr; + vuint32_t rxcrcr; + vuint32_t txcrcr; +}; + +extern struct stm_spi stm_spi1; +#define stm_spi1 (*(struct stm_spi *) 0x40013000) + +/* SPI channels go from 1 to 3, instead of 0 to 2 (sigh) + */ + +#define STM_SPI_INDEX(channel) ((channel) - 1) + +#define STM_SPI_CR1_BIDIMODE 15 +#define STM_SPI_CR1_BIDIOE 14 +#define STM_SPI_CR1_CRCEN 13 +#define STM_SPI_CR1_CRCNEXT 12 +#define STM_SPI_CR1_DFF 11 +#define STM_SPI_CR1_RXONLY 10 +#define STM_SPI_CR1_SSM 9 +#define STM_SPI_CR1_SSI 8 +#define STM_SPI_CR1_LSBFIRST 7 +#define STM_SPI_CR1_SPE 6 +#define STM_SPI_CR1_BR 3 +#define STM_SPI_CR1_BR_PCLK_2 0 +#define STM_SPI_CR1_BR_PCLK_4 1 +#define STM_SPI_CR1_BR_PCLK_8 2 +#define STM_SPI_CR1_BR_PCLK_16 3 +#define STM_SPI_CR1_BR_PCLK_32 4 +#define STM_SPI_CR1_BR_PCLK_64 5 +#define STM_SPI_CR1_BR_PCLK_128 6 +#define STM_SPI_CR1_BR_PCLK_256 7 +#define STM_SPI_CR1_BR_MASK 7 + +#define STM_SPI_CR1_MSTR 2 +#define STM_SPI_CR1_CPOL 1 +#define STM_SPI_CR1_CPHA 0 + +#define STM_SPI_CR2_TXEIE 7 +#define STM_SPI_CR2_RXNEIE 6 +#define STM_SPI_CR2_ERRIE 5 +#define STM_SPI_CR2_SSOE 2 +#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 + +struct stm_adc { + vuint32_t isr; + vuint32_t ier; + vuint32_t cr; + vuint32_t cfgr1; + + vuint32_t cfgr2; + vuint32_t smpr; + vuint32_t r_18; + vuint32_t r_1c; + + vuint32_t tr; + vuint32_t r_24; + vuint32_t chselr; + vuint32_t r_2c; + + vuint32_t r_30[4]; + + vuint32_t dr; + + uint8_t r_44[0xb4 - 0x44]; + + vuint32_t calfact; + + uint8_t r_b8[0x308 - 0xb8]; + vuint32_t ccr; +}; + +extern struct stm_adc stm_adc; +#define stm_adc (*(struct stm_adc *) 0x40012400) + +#define STM_ADC_ISR_AWD 7 +#define STM_ADC_ISR_OVR 4 +#define STM_ADC_ISR_EOSEQ 3 +#define STM_ADC_ISR_EOC 2 +#define STM_ADC_ISR_EOSMP 1 +#define STM_ADC_ISR_ADRDY 0 + +#define STM_ADC_IER_AWDIE 7 +#define STM_ADC_IER_OVRIE 4 +#define STM_ADC_IER_EOSEQIE 3 +#define STM_ADC_IER_EOCIE 2 +#define STM_ADC_IER_EOSMPIE 1 +#define STM_ADC_IER_ADRDYIE 0 + +#define STM_ADC_CR_ADCAL 31 +#define STM_ADC_CR_ADVREGEN 28 +#define STM_ADC_CR_ADSTP 4 +#define STM_ADC_CR_ADSTART 2 +#define STM_ADC_CR_ADDIS 1 +#define STM_ADC_CR_ADEN 0 + +#define STM_ADC_CFGR1_AWDCH 26 +#define STM_ADC_CFGR1_AWDEN 23 +#define STM_ADC_CFGR1_AWDSGL 22 +#define STM_ADC_CFGR1_DISCEN 16 +#define STM_ADC_CFGR1_AUTOOFF 15 +#define STM_ADC_CFGR1_WAIT 14 +#define STM_ADC_CFGR1_CONT 13 +#define STM_ADC_CFGR1_OVRMOD 12 +#define STM_ADC_CFGR1_EXTEN 10 +#define STM_ADC_CFGR1_EXTEN_DISABLE 0 +#define STM_ADC_CFGR1_EXTEN_RISING 1 +#define STM_ADC_CFGR1_EXTEN_FALLING 2 +#define STM_ADC_CFGR1_EXTEN_BOTH 3 +#define STM_ADC_CFGR1_EXTEN_MASK 3 + +#define STM_ADC_CFGR1_EXTSEL 6 +#define STM_ADC_CFGR1_ALIGN 5 +#define STM_ADC_CFGR1_RES 3 +#define STM_ADC_CFGR1_RES_12 0 +#define STM_ADC_CFGR1_RES_10 1 +#define STM_ADC_CFGR1_RES_8 2 +#define STM_ADC_CFGR1_RES_6 3 +#define STM_ADC_CFGR1_RES_MASK 3 +#define STM_ADC_CFGR1_SCANDIR 2 +#define STM_ADC_CFGR1_SCANDIR_UP 0 +#define STM_ADC_CFGR1_SCANDIR_DOWN 1 +#define STM_ADC_CFGR1_DMACFG 1 +#define STM_ADC_CFGR1_DMACFG_ONESHOT 0 +#define STM_ADC_CFGR1_DMACFG_CIRCULAR 1 +#define STM_ADC_CFGR1_DMAEN 0 + +#define STM_ADC_CFGR2_CKMODE 30 +#define STM_ADC_CFGR2_CKMODE_ADCCLK 0 +#define STM_ADC_CFGR2_CKMODE_PCLK_2 1 +#define STM_ADC_CFGR2_CKMODE_PCLK_4 2 +#define STM_ADC_CFGR2_CKMODE_PCLK 3 + +#define STM_ADC_SMPR_SMP 0 +#define STM_ADC_SMPR_SMP_1_5 0 +#define STM_ADC_SMPR_SMP_7_5 1 +#define STM_ADC_SMPR_SMP_13_5 2 +#define STM_ADC_SMPR_SMP_28_5 3 +#define STM_ADC_SMPR_SMP_41_5 4 +#define STM_ADC_SMPR_SMP_55_5 5 +#define STM_ADC_SMPR_SMP_71_5 6 +#define STM_ADC_SMPR_SMP_239_5 7 + +#define STM_ADC_TR_HT 16 +#define STM_ADC_TR_LT 0 + +#define STM_ADC_CCR_LFMEN 25 +#define STM_ADC_CCR_VLCDEN 24 +#define STM_ADC_CCR_TSEN 23 +#define STM_ADC_CCR_VREFEN 22 +#define STM_ADC_CCR_PRESC 18 + +#define STM_ADC_CHSEL_TEMP 18 +#define STM_ADC_CHSEL_VREF 17 +#define STM_ADC_CHSEL_VLCD 16 + +struct stm_cal { + uint16_t ts_cal_cold; /* 30°C */ + uint16_t vrefint_cal; + uint16_t unused_c0; + uint16_t ts_cal_hot; /* 110°C */ +}; + +extern struct stm_cal stm_cal; + +#define stm_temp_cal_cold 30 +#define stm_temp_cal_hot 110 + +struct stm_dbg_mcu { + uint32_t idcode; +}; + +extern struct stm_dbg_mcu stm_dbg_mcu; + +static inline uint16_t +stm_dev_id(void) { + return stm_dbg_mcu.idcode & 0xfff; +} + +struct stm_flash_size { + uint16_t f_size; +}; + +extern struct stm_flash_size stm_flash_size_reg; +#define stm_flash_size_reg (*((struct stm_flash_size *) 0x1ff8007c)) + +/* Returns flash size in bytes */ +extern uint32_t +stm_flash_size(void); + +struct stm_device_id { + char lot_num_4_6[3]; + uint8_t waf_num; + char lot_num_0_3[4]; + uint8_t unique_id[4]; +}; + +extern struct stm_device_id stm_device_id; +#define stm_device_id (*((struct stm_device_id *) 0x1ff80050)) + +#define STM_NUM_I2C 2 + +#define STM_I2C_INDEX(channel) ((channel) - 1) + +struct stm_i2c { + vuint32_t cr1; + vuint32_t cr2; + vuint32_t oar1; + vuint32_t oar2; + vuint32_t dr; + vuint32_t sr1; + vuint32_t sr2; + vuint32_t ccr; + vuint32_t trise; +}; + +extern struct stm_i2c stm_i2c1, stm_i2c2; + +#define STM_I2C_CR1_SWRST 15 +#define STM_I2C_CR1_ALERT 13 +#define STM_I2C_CR1_PEC 12 +#define STM_I2C_CR1_POS 11 +#define STM_I2C_CR1_ACK 10 +#define STM_I2C_CR1_STOP 9 +#define STM_I2C_CR1_START 8 +#define STM_I2C_CR1_NOSTRETCH 7 +#define STM_I2C_CR1_ENGC 6 +#define STM_I2C_CR1_ENPEC 5 +#define STM_I2C_CR1_ENARP 4 +#define STM_I2C_CR1_SMBTYPE 3 +#define STM_I2C_CR1_SMBUS 1 +#define STM_I2C_CR1_PE 0 + +#define STM_I2C_CR2_LAST 12 +#define STM_I2C_CR2_DMAEN 11 +#define STM_I2C_CR2_ITBUFEN 10 +#define STM_I2C_CR2_ITEVTEN 9 +#define STM_I2C_CR2_ITERREN 8 +#define STM_I2C_CR2_FREQ 0 +#define STM_I2C_CR2_FREQ_2_MHZ 2 +#define STM_I2C_CR2_FREQ_4_MHZ 4 +#define STM_I2C_CR2_FREQ_8_MHZ 8 +#define STM_I2C_CR2_FREQ_16_MHZ 16 +#define STM_I2C_CR2_FREQ_24_MHZ 24 +#define STM_I2C_CR2_FREQ_32_MHZ 32 +#define STM_I2C_CR2_FREQ_MASK 0x3f + +#define STM_I2C_SR1_SMBALERT 15 +#define STM_I2C_SR1_TIMEOUT 14 +#define STM_I2C_SR1_PECERR 12 +#define STM_I2C_SR1_OVR 11 +#define STM_I2C_SR1_AF 10 +#define STM_I2C_SR1_ARLO 9 +#define STM_I2C_SR1_BERR 8 +#define STM_I2C_SR1_TXE 7 +#define STM_I2C_SR1_RXNE 6 +#define STM_I2C_SR1_STOPF 4 +#define STM_I2C_SR1_ADD10 3 +#define STM_I2C_SR1_BTF 2 +#define STM_I2C_SR1_ADDR 1 +#define STM_I2C_SR1_SB 0 + +#define STM_I2C_SR2_PEC 8 +#define STM_I2C_SR2_PEC_MASK 0xff00 +#define STM_I2C_SR2_DUALF 7 +#define STM_I2C_SR2_SMBHOST 6 +#define STM_I2C_SR2_SMBDEFAULT 5 +#define STM_I2C_SR2_GENCALL 4 +#define STM_I2C_SR2_TRA 2 +#define STM_I2C_SR2_BUSY 1 +#define STM_I2C_SR2_MSL 0 + +#define STM_I2C_CCR_FS 15 +#define STM_I2C_CCR_DUTY 14 +#define STM_I2C_CCR_CCR 0 +#define STM_I2C_CCR_MASK 0x7ff + +struct stm_tim234 { + vuint32_t cr1; + vuint32_t cr2; + vuint32_t smcr; + vuint32_t dier; + + vuint32_t sr; + vuint32_t egr; + vuint32_t ccmr1; + vuint32_t ccmr2; + + vuint32_t ccer; + vuint32_t cnt; + vuint32_t psc; + vuint32_t arr; + + uint32_t reserved_30; + vuint32_t ccr1; + vuint32_t ccr2; + vuint32_t ccr3; + + vuint32_t ccr4; + uint32_t reserved_44; + vuint32_t dcr; + vuint32_t dmar; + + uint32_t reserved_50; +}; + +extern struct stm_tim234 stm_tim2, stm_tim3, stm_tim4; + +#define STM_TIM234_CR1_CKD 8 +#define STM_TIM234_CR1_CKD_1 0 +#define STM_TIM234_CR1_CKD_2 1 +#define STM_TIM234_CR1_CKD_4 2 +#define STM_TIM234_CR1_CKD_MASK 3 +#define STM_TIM234_CR1_ARPE 7 +#define STM_TIM234_CR1_CMS 5 +#define STM_TIM234_CR1_CMS_EDGE 0 +#define STM_TIM234_CR1_CMS_CENTER_1 1 +#define STM_TIM234_CR1_CMS_CENTER_2 2 +#define STM_TIM234_CR1_CMS_CENTER_3 3 +#define STM_TIM234_CR1_CMS_MASK 3 +#define STM_TIM234_CR1_DIR 4 +#define STM_TIM234_CR1_DIR_UP 0 +#define STM_TIM234_CR1_DIR_DOWN 1 +#define STM_TIM234_CR1_OPM 3 +#define STM_TIM234_CR1_URS 2 +#define STM_TIM234_CR1_UDIS 1 +#define STM_TIM234_CR1_CEN 0 + +#define STM_TIM234_CR2_TI1S 7 +#define STM_TIM234_CR2_MMS 4 +#define STM_TIM234_CR2_MMS_RESET 0 +#define STM_TIM234_CR2_MMS_ENABLE 1 +#define STM_TIM234_CR2_MMS_UPDATE 2 +#define STM_TIM234_CR2_MMS_COMPARE_PULSE 3 +#define STM_TIM234_CR2_MMS_COMPARE_OC1REF 4 +#define STM_TIM234_CR2_MMS_COMPARE_OC2REF 5 +#define STM_TIM234_CR2_MMS_COMPARE_OC3REF 6 +#define STM_TIM234_CR2_MMS_COMPARE_OC4REF 7 +#define STM_TIM234_CR2_MMS_MASK 7 +#define STM_TIM234_CR2_CCDS 3 + +#define STM_TIM234_SMCR_ETP 15 +#define STM_TIM234_SMCR_ECE 14 +#define STM_TIM234_SMCR_ETPS 12 +#define STM_TIM234_SMCR_ETPS_OFF 0 +#define STM_TIM234_SMCR_ETPS_DIV_2 1 +#define STM_TIM234_SMCR_ETPS_DIV_4 2 +#define STM_TIM234_SMCR_ETPS_DIV_8 3 +#define STM_TIM234_SMCR_ETPS_MASK 3 +#define STM_TIM234_SMCR_ETF 8 +#define STM_TIM234_SMCR_ETF_NONE 0 +#define STM_TIM234_SMCR_ETF_INT_N_2 1 +#define STM_TIM234_SMCR_ETF_INT_N_4 2 +#define STM_TIM234_SMCR_ETF_INT_N_8 3 +#define STM_TIM234_SMCR_ETF_DTS_2_N_6 4 +#define STM_TIM234_SMCR_ETF_DTS_2_N_8 5 +#define STM_TIM234_SMCR_ETF_DTS_4_N_6 6 +#define STM_TIM234_SMCR_ETF_DTS_4_N_8 7 +#define STM_TIM234_SMCR_ETF_DTS_8_N_6 8 +#define STM_TIM234_SMCR_ETF_DTS_8_N_8 9 +#define STM_TIM234_SMCR_ETF_DTS_16_N_5 10 +#define STM_TIM234_SMCR_ETF_DTS_16_N_6 11 +#define STM_TIM234_SMCR_ETF_DTS_16_N_8 12 +#define STM_TIM234_SMCR_ETF_DTS_32_N_5 13 +#define STM_TIM234_SMCR_ETF_DTS_32_N_6 14 +#define STM_TIM234_SMCR_ETF_DTS_32_N_8 15 +#define STM_TIM234_SMCR_ETF_MASK 15 +#define STM_TIM234_SMCR_MSM 7 +#define STM_TIM234_SMCR_TS 4 +#define STM_TIM234_SMCR_TS_ITR0 0 +#define STM_TIM234_SMCR_TS_ITR1 1 +#define STM_TIM234_SMCR_TS_ITR2 2 +#define STM_TIM234_SMCR_TS_ITR3 3 +#define STM_TIM234_SMCR_TS_TI1F_ED 4 +#define STM_TIM234_SMCR_TS_TI1FP1 5 +#define STM_TIM234_SMCR_TS_TI2FP2 6 +#define STM_TIM234_SMCR_TS_ETRF 7 +#define STM_TIM234_SMCR_TS_MASK 7 +#define STM_TIM234_SMCR_OCCS 3 +#define STM_TIM234_SMCR_SMS 0 +#define STM_TIM234_SMCR_SMS_DISABLE 0 +#define STM_TIM234_SMCR_SMS_ENCODER_MODE_1 1 +#define STM_TIM234_SMCR_SMS_ENCODER_MODE_2 2 +#define STM_TIM234_SMCR_SMS_ENCODER_MODE_3 3 +#define STM_TIM234_SMCR_SMS_RESET_MODE 4 +#define STM_TIM234_SMCR_SMS_GATED_MODE 5 +#define STM_TIM234_SMCR_SMS_TRIGGER_MODE 6 +#define STM_TIM234_SMCR_SMS_EXTERNAL_CLOCK 7 +#define STM_TIM234_SMCR_SMS_MASK 7 + +#define STM_TIM234_DIER_TDE 14 +#define STM_TIM234_DIER_CC4DE 12 +#define STM_TIM234_DIER_CC3DE 11 +#define STM_TIM234_DIER_CC2DE 10 +#define STM_TIM234_DIER_CC1DE 9 +#define STM_TIM234_DIER_UDE 8 + +#define STM_TIM234_DIER_TIE 6 +#define STM_TIM234_DIER_CC4IE 4 +#define STM_TIM234_DIER_CC3IE 3 +#define STM_TIM234_DIER_CC2IE 2 +#define STM_TIM234_DIER_CC1IE 1 +#define STM_TIM234_DIER_UIE 0 + +#define STM_TIM234_SR_CC4OF 12 +#define STM_TIM234_SR_CC3OF 11 +#define STM_TIM234_SR_CC2OF 10 +#define STM_TIM234_SR_CC1OF 9 +#define STM_TIM234_SR_TIF 6 +#define STM_TIM234_SR_CC4IF 4 +#define STM_TIM234_SR_CC3IF 3 +#define STM_TIM234_SR_CC2IF 2 +#define STM_TIM234_SR_CC1IF 1 +#define STM_TIM234_SR_UIF 0 + +#define STM_TIM234_EGR_TG 6 +#define STM_TIM234_EGR_CC4G 4 +#define STM_TIM234_EGR_CC3G 3 +#define STM_TIM234_EGR_CC2G 2 +#define STM_TIM234_EGR_CC1G 1 +#define STM_TIM234_EGR_UG 0 + +#define STM_TIM234_CCMR1_OC2CE 15 +#define STM_TIM234_CCMR1_OC2M 12 +#define STM_TIM234_CCMR1_OC2M_FROZEN 0 +#define STM_TIM234_CCMR1_OC2M_SET_HIGH_ON_MATCH 1 +#define STM_TIM234_CCMR1_OC2M_SET_LOW_ON_MATCH 2 +#define STM_TIM234_CCMR1_OC2M_TOGGLE 3 +#define STM_TIM234_CCMR1_OC2M_FORCE_LOW 4 +#define STM_TIM234_CCMR1_OC2M_FORCE_HIGH 5 +#define STM_TIM234_CCMR1_OC2M_PWM_MODE_1 6 +#define STM_TIM234_CCMR1_OC2M_PWM_MODE_2 7 +#define STM_TIM234_CCMR1_OC2M_MASK 7 +#define STM_TIM234_CCMR1_OC2PE 11 +#define STM_TIM234_CCMR1_OC2FE 10 +#define STM_TIM234_CCMR1_CC2S 8 +#define STM_TIM234_CCMR1_CC2S_OUTPUT 0 +#define STM_TIM234_CCMR1_CC2S_INPUT_TI2 1 +#define STM_TIM234_CCMR1_CC2S_INPUT_TI1 2 +#define STM_TIM234_CCMR1_CC2S_INPUT_TRC 3 +#define STM_TIM234_CCMR1_CC2S_MASK 3 + +#define STM_TIM234_CCMR1_OC1CE 7 +#define STM_TIM234_CCMR1_OC1M 4 +#define STM_TIM234_CCMR1_OC1M_FROZEN 0 +#define STM_TIM234_CCMR1_OC1M_SET_HIGH_ON_MATCH 1 +#define STM_TIM234_CCMR1_OC1M_SET_LOW_ON_MATCH 2 +#define STM_TIM234_CCMR1_OC1M_TOGGLE 3 +#define STM_TIM234_CCMR1_OC1M_FORCE_LOW 4 +#define STM_TIM234_CCMR1_OC1M_FORCE_HIGH 5 +#define STM_TIM234_CCMR1_OC1M_PWM_MODE_1 6 +#define STM_TIM234_CCMR1_OC1M_PWM_MODE_2 7 +#define STM_TIM234_CCMR1_OC1M_MASK 7 +#define STM_TIM234_CCMR1_OC1PE 3 +#define STM_TIM234_CCMR1_OC1FE 2 +#define STM_TIM234_CCMR1_CC1S 0 +#define STM_TIM234_CCMR1_CC1S_OUTPUT 0 +#define STM_TIM234_CCMR1_CC1S_INPUT_TI1 1 +#define STM_TIM234_CCMR1_CC1S_INPUT_TI2 2 +#define STM_TIM234_CCMR1_CC1S_INPUT_TRC 3 +#define STM_TIM234_CCMR1_CC1S_MASK 3 + +#define STM_TIM234_CCMR1_IC2F 12 +#define STM_TIM234_CCMR1_IC2F_NONE 0 +#define STM_TIM234_CCMR1_IC2F_CK_INT_N_2 1 +#define STM_TIM234_CCMR1_IC2F_CK_INT_N_4 2 +#define STM_TIM234_CCMR1_IC2F_CK_INT_N_8 3 +#define STM_TIM234_CCMR1_IC2F_DTS_2_N_6 4 +#define STM_TIM234_CCMR1_IC2F_DTS_2_N_8 5 +#define STM_TIM234_CCMR1_IC2F_DTS_4_N_6 6 +#define STM_TIM234_CCMR1_IC2F_DTS_4_N_8 7 +#define STM_TIM234_CCMR1_IC2F_DTS_8_N_6 8 +#define STM_TIM234_CCMR1_IC2F_DTS_8_N_8 9 +#define STM_TIM234_CCMR1_IC2F_DTS_16_N_5 10 +#define STM_TIM234_CCMR1_IC2F_DTS_16_N_6 11 +#define STM_TIM234_CCMR1_IC2F_DTS_16_N_8 12 +#define STM_TIM234_CCMR1_IC2F_DTS_32_N_5 13 +#define STM_TIM234_CCMR1_IC2F_DTS_32_N_6 14 +#define STM_TIM234_CCMR1_IC2F_DTS_32_N_8 15 +#define STM_TIM234_CCMR1_IC2PSC 10 +#define STM_TIM234_CCMR1_IC2PSC_NONE 0 +#define STM_TIM234_CCMR1_IC2PSC_2 1 +#define STM_TIM234_CCMR1_IC2PSC_4 2 +#define STM_TIM234_CCMR1_IC2PSC_8 3 +#define STM_TIM234_CCMR1_IC1F 4 +#define STM_TIM234_CCMR1_IC1F_NONE 0 +#define STM_TIM234_CCMR1_IC1F_CK_INT_N_2 1 +#define STM_TIM234_CCMR1_IC1F_CK_INT_N_4 2 +#define STM_TIM234_CCMR1_IC1F_CK_INT_N_8 3 +#define STM_TIM234_CCMR1_IC1F_DTS_2_N_6 4 +#define STM_TIM234_CCMR1_IC1F_DTS_2_N_8 5 +#define STM_TIM234_CCMR1_IC1F_DTS_4_N_6 6 +#define STM_TIM234_CCMR1_IC1F_DTS_4_N_8 7 +#define STM_TIM234_CCMR1_IC1F_DTS_8_N_6 8 +#define STM_TIM234_CCMR1_IC1F_DTS_8_N_8 9 +#define STM_TIM234_CCMR1_IC1F_DTS_16_N_5 10 +#define STM_TIM234_CCMR1_IC1F_DTS_16_N_6 11 +#define STM_TIM234_CCMR1_IC1F_DTS_16_N_8 12 +#define STM_TIM234_CCMR1_IC1F_DTS_32_N_5 13 +#define STM_TIM234_CCMR1_IC1F_DTS_32_N_6 14 +#define STM_TIM234_CCMR1_IC1F_DTS_32_N_8 15 +#define STM_TIM234_CCMR1_IC1PSC 2 +#define STM_TIM234_CCMR1_IC1PSC_NONE 0 +#define STM_TIM234_CCMR1_IC1PSC_2 1 +#define STM_TIM234_CCMR1_IC1PSC_4 2 +#define STM_TIM234_CCMR1_IC1PSC_8 3 + +#define STM_TIM234_CCMR2_OC4CE 15 +#define STM_TIM234_CCMR2_OC4M 12 +#define STM_TIM234_CCMR2_OC4M_FROZEN 0 +#define STM_TIM234_CCMR2_OC4M_SET_HIGH_ON_MATCH 1 +#define STM_TIM234_CCMR2_OC4M_SET_LOW_ON_MATCH 2 +#define STM_TIM234_CCMR2_OC4M_TOGGLE 3 +#define STM_TIM234_CCMR2_OC4M_FORCE_LOW 4 +#define STM_TIM234_CCMR2_OC4M_FORCE_HIGH 5 +#define STM_TIM234_CCMR2_OC4M_PWM_MODE_1 6 +#define STM_TIM234_CCMR2_OC4M_PWM_MODE_2 7 +#define STM_TIM234_CCMR2_OC4M_MASK 7 +#define STM_TIM234_CCMR2_OC4PE 11 +#define STM_TIM234_CCMR2_OC4FE 10 +#define STM_TIM234_CCMR2_CC4S 8 +#define STM_TIM234_CCMR2_CC4S_OUTPUT 0 +#define STM_TIM234_CCMR2_CC4S_INPUT_TI4 1 +#define STM_TIM234_CCMR2_CC4S_INPUT_TI3 2 +#define STM_TIM234_CCMR2_CC4S_INPUT_TRC 3 +#define STM_TIM234_CCMR2_CC4S_MASK 3 + +#define STM_TIM234_CCMR2_OC3CE 7 +#define STM_TIM234_CCMR2_OC3M 4 +#define STM_TIM234_CCMR2_OC3M_FROZEN 0 +#define STM_TIM234_CCMR2_OC3M_SET_HIGH_ON_MATCH 1 +#define STM_TIM234_CCMR2_OC3M_SET_LOW_ON_MATCH 2 +#define STM_TIM234_CCMR2_OC3M_TOGGLE 3 +#define STM_TIM234_CCMR2_OC3M_FORCE_LOW 4 +#define STM_TIM234_CCMR2_OC3M_FORCE_HIGH 5 +#define STM_TIM234_CCMR2_OC3M_PWM_MODE_1 6 +#define STM_TIM234_CCMR2_OC3M_PWM_MODE_2 7 +#define STM_TIM234_CCMR2_OC3M_MASK 7 +#define STM_TIM234_CCMR2_OC3PE 3 +#define STM_TIM234_CCMR2_OC3FE 2 +#define STM_TIM234_CCMR2_CC3S 0 +#define STM_TIM234_CCMR2_CC3S_OUTPUT 0 +#define STM_TIM234_CCMR2_CC3S_INPUT_TI3 1 +#define STM_TIM234_CCMR2_CC3S_INPUT_TI4 2 +#define STM_TIM234_CCMR2_CC3S_INPUT_TRC 3 +#define STM_TIM234_CCMR2_CC3S_MASK 3 + +#define STM_TIM234_CCER_CC4NP 15 +#define STM_TIM234_CCER_CC4P 13 +#define STM_TIM234_CCER_CC4P_ACTIVE_HIGH 0 +#define STM_TIM234_CCER_CC4P_ACTIVE_LOW 1 +#define STM_TIM234_CCER_CC4E 12 +#define STM_TIM234_CCER_CC3NP 11 +#define STM_TIM234_CCER_CC3P 9 +#define STM_TIM234_CCER_CC3P_ACTIVE_HIGH 0 +#define STM_TIM234_CCER_CC3P_ACTIVE_LOW 1 +#define STM_TIM234_CCER_CC3E 8 +#define STM_TIM234_CCER_CC2NP 7 +#define STM_TIM234_CCER_CC2P 5 +#define STM_TIM234_CCER_CC2P_ACTIVE_HIGH 0 +#define STM_TIM234_CCER_CC2P_ACTIVE_LOW 1 +#define STM_TIM234_CCER_CC2E 4 +#define STM_TIM234_CCER_CC1NP 3 +#define STM_TIM234_CCER_CC1P 1 +#define STM_TIM234_CCER_CC1P_ACTIVE_HIGH 0 +#define STM_TIM234_CCER_CC1P_ACTIVE_LOW 1 +#define STM_TIM234_CCER_CC1E 0 + +struct stm_exti { + vuint32_t imr; + vuint32_t emr; + vuint32_t rtsr; + vuint32_t ftsr; + + vuint32_t swier; + vuint32_t pr; +}; + +extern struct stm_exti stm_exti; +#define stm_exti (*(struct stm_exti *) 0x40010400) + +struct stm_vrefint_cal { + vuint16_t vrefint_cal; +}; + +extern struct stm_vrefint_cal stm_vrefint_cal; +#define stm_vrefint_cal (*(struct stm_vrefint_cal *) 0x1ff80078) + +/* Flash interface */ + +struct stm_flash { + vuint32_t acr; + vuint32_t pecr; + vuint32_t pdkeyr; + vuint32_t pekeyr; + + vuint32_t prgkeyr; + vuint32_t optkeyr; + vuint32_t sr; + vuint32_t obr; + + vuint32_t wrpr; +}; + + +extern uint32_t __storage[], __storage_size[]; + +#define STM_FLASH_PAGE_SIZE 128 + +#define ao_storage_unit 128 +#define ao_storage_total ((uintptr_t) __storage_size) +#define ao_storage_block STM_FLASH_PAGE_SIZE +#define AO_STORAGE_ERASED_BYTE 0x00 + +extern struct stm_flash stm_flash; + +#define STM_FLASH_ACR_PRE_READ (6) +#define STM_FLASH_ACR_DISAB_BUF (5) +#define STM_FLASH_ACR_RUN_PD (4) +#define STM_FLASH_ACR_SLEEP_PD (3) +#define STM_FLASH_ACR_PRFEN (1) +#define STM_FLASH_ACR_LATENCY (0) + +#define STM_FLASH_PECR_NZDISABLE 23 +#define STM_FLASH_PECR_OBL_LAUNCH 18 +#define STM_FLASH_PECR_ERRIE 17 +#define STM_FLASH_PECR_EOPIE 16 +#define STM_FLASH_PECR_PARRALELLBANK 15 +#define STM_FLASH_PECR_FPRG 10 +#define STM_FLASH_PECR_ERASE 9 +#define STM_FLASH_PECR_FIX 8 +#define STM_FLASH_PECR_DATA 4 +#define STM_FLASH_PECR_PROG 3 +#define STM_FLASH_PECR_OPT_LOCK 2 +#define STM_FLASH_PECR_PRG_LOCK 1 +#define STM_FLASH_PECR_PE_LOCK 0 + +#define STM_FLASH_SR_OPTVERR 11 +#define STM_FLASH_SR_SIZERR 10 +#define STM_FLASH_SR_PGAERR 9 +#define STM_FLASH_SR_WRPERR 8 +#define STM_FLASH_SR_READY 3 +#define STM_FLASH_SR_ENDHV 2 +#define STM_FLASH_SR_EOP 1 +#define STM_FLASH_SR_BSY 0 + +#define STM_FLASH_OPTKEYR_OPTKEY1 0xFBEAD9C8 +#define STM_FLASH_OPTKEYR_OPTKEY2 0x24252627 + +#define STM_FLASH_PEKEYR_PEKEY1 0x89ABCDEF +#define STM_FLASH_PEKEYR_PEKEY2 0x02030405 + +#define STM_FLASH_PRGKEYR_PRGKEY1 0x8C9DAEBF +#define STM_FLASH_PRGKEYR_PRGKEY2 0x13141516 + +#endif /* _STM32L0_H_ */ diff --git a/src/stm32l0/stm32l0.ld b/src/stm32l0/stm32l0.ld new file mode 100644 index 00000000..e266e9a7 --- /dev/null +++ b/src/stm32l0/stm32l0.ld @@ -0,0 +1,58 @@ +/* IOPORT */ +stm_gpioh = 0x50001c00; +stm_gpioe = 0x50001000; +stm_gpiod = 0x50000c00; +stm_gpioc = 0x50000800; +stm_gpiob = 0x50000400; +stm_gpioa = 0x50000000; + +/* AHB */ +stm_aes = 0x40026000; +stm_crc = 0x40023000; +stm_flash = 0x40022000; +stm_rcc = 0x40021000; +stm_dma1 = 0x40020000; + +/* APB2 */ +stm_dbg = 0x40015800; +stm_usart1 = 0x40013800; +stm_spi1 = 0x40013000; +stm_adc = 0x40012400; +stm_firewall = 0x40011c00; +stm_tim22 = 0x40011400; +stm_tim21 = 0x40010800; +stm_exti = 0x40010400; +stm_syscfg = 0x40010000; +stm_comp = 0x40010000; + +/* APB1 */ +stm_lptim1 = 0x40007c00; +stm_i2c3 = 0x40007800; +stm_pwr = 0x40007000; +stm_i2c2 = 0x40005800; +stm_i2c1 = 0x40005400; +stm_usart5 = 0x40005000; +stm_usart4 = 0x40004c00; +stm_lpuart1 = 0x40004800; +stm_usart2 = 0x40004400; +stm_spi2 = 0x40003800; +stm_iwdg = 0x40003000; +stm_wwdg = 0x40002c00; +stm_rtc = 0x40002800; +stm_timer7 = 0x40001400; +stm_timer6 = 0x40001000; +stm_timer3 = 0x40000400; +stm_timer2 = 0x40000000; + +/* ARM */ +stm_systick = 0xe000e010; + +stm_nvic = 0xe000e100; + +stm_scb = 0xe000ed00; + +stm_mpu = 0xe000ed90; + +/* ID registers */ +stm_flash_size = 0x1ff8007c; +stm_device_id = 0x1ff80050; diff --git a/src/stmf0/ao_arch_funcs.h b/src/stmf0/ao_arch_funcs.h index 591ca8a0..defe2598 100644 --- a/src/stmf0/ao_arch_funcs.h +++ b/src/stmf0/ao_arch_funcs.h @@ -26,20 +26,27 @@ /* PCLK is set to 48MHz (HCLK 48MHz, HPRE 1, PPRE 1) */ -#define AO_SPI_SPEED_24MHz STM_SPI_CR1_BR_PCLK_2 -#define AO_SPI_SPEED_12MHz STM_SPI_CR1_BR_PCLK_4 -#define AO_SPI_SPEED_6MHz STM_SPI_CR1_BR_PCLK_8 -#define AO_SPI_SPEED_3MHz STM_SPI_CR1_BR_PCLK_16 -#define AO_SPI_SPEED_1500kHz STM_SPI_CR1_BR_PCLK_32 -#define AO_SPI_SPEED_750kHz STM_SPI_CR1_BR_PCLK_64 -#define AO_SPI_SPEED_375kHz STM_SPI_CR1_BR_PCLK_128 -#define AO_SPI_SPEED_187500Hz STM_SPI_CR1_BR_PCLK_256 +#define _AO_SPI_SPEED_24MHz STM_SPI_CR1_BR_PCLK_2 +#define _AO_SPI_SPEED_12MHz STM_SPI_CR1_BR_PCLK_4 +#define _AO_SPI_SPEED_6MHz STM_SPI_CR1_BR_PCLK_8 +#define _AO_SPI_SPEED_3MHz STM_SPI_CR1_BR_PCLK_16 +#define _AO_SPI_SPEED_1500kHz STM_SPI_CR1_BR_PCLK_32 +#define _AO_SPI_SPEED_750kHz STM_SPI_CR1_BR_PCLK_64 +#define _AO_SPI_SPEED_375kHz STM_SPI_CR1_BR_PCLK_128 +#define _AO_SPI_SPEED_187500Hz STM_SPI_CR1_BR_PCLK_256 -#define AO_SPI_SPEED_FAST AO_SPI_SPEED_24MHz - -/* Companion bus wants something no faster than 200kHz */ - -#define AO_SPI_SPEED_200kHz AO_SPI_SPEED_187500Hz +static inline uint32_t +ao_spi_speed(uint32_t hz) +{ + if (hz >=24000000) return _AO_SPI_SPEED_24MHz; + if (hz >=12000000) return _AO_SPI_SPEED_12MHz; + if (hz >= 6000000) return _AO_SPI_SPEED_6MHz; + if (hz >= 3000000) return _AO_SPI_SPEED_3MHz; + if (hz >= 1500000) return _AO_SPI_SPEED_1500kHz; + if (hz >= 750000) return _AO_SPI_SPEED_750kHz; + if (hz >= 375000) return _AO_SPI_SPEED_375kHz; + return _AO_SPI_SPEED_187500Hz; +} #define AO_SPI_CONFIG_1 0x00 #define AO_SPI_1_CONFIG_PA5_PA6_PA7 AO_SPI_CONFIG_1 @@ -141,8 +148,6 @@ ao_spi_recv(void *block, uint16_t len, uint8_t spi_index); void ao_spi_duplex(void *out, void *in, uint16_t len, uint8_t spi_index); -extern uint16_t ao_spi_speed[STM_NUM_SPI]; - void ao_spi_init(void); @@ -387,9 +392,8 @@ ao_arch_memory_barrier(void) { #if HAS_TASK static inline void -ao_arch_init_stack(struct ao_task *task, void *start) +ao_arch_init_stack(struct ao_task *task, uint32_t *sp, void *start) { - uint32_t *sp = &task->stack32[AO_STACK_SIZE >> 2]; uint32_t a = (uint32_t) start; int i; diff --git a/src/stmf0/ao_beep_stm.c b/src/stmf0/ao_beep_stm.c index 31af7f4a..39022da1 100644 --- a/src/stmf0/ao_beep_stm.c +++ b/src/stmf0/ao_beep_stm.c @@ -376,7 +376,7 @@ ao_beep(uint8_t beep) } void -ao_beep_for(uint8_t beep, uint16_t ticks) +ao_beep_for(uint8_t beep, AO_TICK_TYPE ticks) { ao_beep(beep); ao_delay(ticks); diff --git a/src/stmf0/ao_interrupt.c b/src/stmf0/ao_interrupt.c index 3d7dc7a8..3ef51dfa 100644 --- a/src/stmf0/ao_interrupt.c +++ b/src/stmf0/ao_interrupt.c @@ -186,8 +186,11 @@ void _start(void) #if AO_BOOT_CHAIN if (ao_boot_check_chain()) { #if AO_BOOT_PIN - ao_boot_check_pin(); + if (ao_boot_check_pin()) #endif + { + ao_boot_chain(AO_BOOT_APPLICATION_BASE); + } } #endif /* Turn on syscfg */ diff --git a/src/stmf0/ao_led_stmf0.c b/src/stmf0/ao_led_stmf0.c index 1564535e..63593aff 100644 --- a/src/stmf0/ao_led_stmf0.c +++ b/src/stmf0/ao_led_stmf0.c @@ -58,21 +58,6 @@ ao_led_set(AO_LED_TYPE colors) ao_led_on(on); } -void -ao_led_toggle(AO_LED_TYPE colors) -{ -#ifdef LED_PORT - LED_PORT->odr ^= (colors & LEDS_AVAILABLE); -#else -#ifdef LED_PORT_0 - LED_PORT_0->odr ^= ((colors & LEDS_AVAILABLE) & LED_PORT_0_MASK) << LED_PORT_0_SHIFT; -#endif -#ifdef LED_PORT_1 - LED_PORT_1->odr ^= ((colors & LEDS_AVAILABLE) & LED_PORT_1_MASK) << LED_PORT_1_SHIFT; -#endif -#endif -} - void ao_led_for(AO_LED_TYPE colors, AO_TICK_TYPE ticks) { diff --git a/src/stmf0/ao_timer.c b/src/stmf0/ao_timer.c index be333754..b0b6ec0a 100644 --- a/src/stmf0/ao_timer.c +++ b/src/stmf0/ao_timer.c @@ -60,10 +60,7 @@ void stm_systick_isr(void) { if (stm_systick.csr & (1 << STM_SYSTICK_CSR_COUNTFLAG)) { ++ao_tick_count; -#if HAS_TASK_QUEUE - if (ao_task_alarm_tick && (int16_t) (ao_tick_count - ao_task_alarm_tick) >= 0) - ao_task_check_alarm((uint16_t) ao_tick_count); -#endif + ao_task_check_alarm(); #if AO_DATA_ALL if (++ao_data_count == ao_data_interval) { ao_data_count = 0; diff --git a/src/teleballoon-v2.0/ao_pins.h b/src/teleballoon-v2.0/ao_pins.h index cb0ec838..6b006307 100644 --- a/src/teleballoon-v2.0/ao_pins.h +++ b/src/teleballoon-v2.0/ao_pins.h @@ -19,7 +19,6 @@ #ifndef _AO_PINS_H_ #define _AO_PINS_H_ -#define HAS_TASK_QUEUE 1 /* 8MHz High speed external crystal */ #define AO_HSE 8000000 diff --git a/src/telebt-v3.0/ao_pins.h b/src/telebt-v3.0/ao_pins.h index 62dddf2a..d71f2655 100644 --- a/src/telebt-v3.0/ao_pins.h +++ b/src/telebt-v3.0/ao_pins.h @@ -19,7 +19,6 @@ #ifndef _AO_PINS_H_ #define _AO_PINS_H_ -#define HAS_TASK_QUEUE 1 /* 8MHz High speed external crystal */ #define AO_HSE 8000000 @@ -198,7 +197,6 @@ struct ao_adc { #define AO_CC1200_SPI_CS_PIN 10 #define AO_CC1200_SPI_BUS AO_SPI_1_PA5_PA6_PA7 #define AO_CC1200_SPI stm_spi1 -#define AO_CC1200_SPI_SPEED AO_SPI_SPEED_FAST #define AO_CC1200_INT_PORT (&stm_gpiob) #define AO_CC1200_INT_PIN (11) diff --git a/src/telebt-v4.0/ao_pins.h b/src/telebt-v4.0/ao_pins.h index f3d70d1a..1b4efdd3 100644 --- a/src/telebt-v4.0/ao_pins.h +++ b/src/telebt-v4.0/ao_pins.h @@ -40,7 +40,6 @@ #define AO_PA11_PA12_RMP 0 #define IS_FLASH_LOADER 0 -#define HAS_TASK_QUEUE 1 /* * Serial ports @@ -272,7 +271,6 @@ struct ao_adc { #define AO_CC1200_SPI_CS_PIN 11 #define AO_CC1200_SPI_BUS AO_SPI_1_PA5_PA6_PA7 #define AO_CC1200_SPI stm_spi1 -#define AO_CC1200_SPI_SPEED AO_SPI_SPEED_6MHz #define AO_CC1200_INT_PORT (&stm_gpiob) #define AO_CC1200_INT_PIN (10) diff --git a/src/teledongle-v3.0/ao_pins.h b/src/teledongle-v3.0/ao_pins.h index be710aef..5641462a 100644 --- a/src/teledongle-v3.0/ao_pins.h +++ b/src/teledongle-v3.0/ao_pins.h @@ -23,7 +23,6 @@ #define AO_STACK_SIZE 320 -#define HAS_TASK_QUEUE 1 #define IS_FLASH_LOADER 0 @@ -96,7 +95,6 @@ #define AO_CC1200_SPI_CS_PIN 3 #define AO_CC1200_SPI_BUS 0 #define AO_CC1200_SPI 0 -#define AO_CC1200_SPI_SPEED AO_SPI_SPEED_8MHz #define AO_CC1200_INT_PORT 0 #define AO_CC1200_INT_PIN 2 diff --git a/src/telefireeight-v1.0/ao_pins.h b/src/telefireeight-v1.0/ao_pins.h index c15e06bf..b1952278 100644 --- a/src/telefireeight-v1.0/ao_pins.h +++ b/src/telefireeight-v1.0/ao_pins.h @@ -103,7 +103,6 @@ #define AO_CC1200_SPI_CS_PIN 11 #define AO_CC1200_SPI_BUS AO_SPI_1_PE13_PE14_PE15 #define AO_CC1200_SPI stm_spi1 -#define AO_CC1200_SPI_SPEED AO_SPI_SPEED_FAST #define AO_CC1200_INT_PORT (&stm_gpioe) #define AO_CC1200_INT_PIN (12) diff --git a/src/telefireeight-v2.0/ao_pins.h b/src/telefireeight-v2.0/ao_pins.h index 046514b4..a71eb441 100644 --- a/src/telefireeight-v2.0/ao_pins.h +++ b/src/telefireeight-v2.0/ao_pins.h @@ -88,7 +88,6 @@ #define AO_CC1200_SPI_CS_PIN 11 #define AO_CC1200_SPI_BUS AO_SPI_1_PE13_PE14_PE15 #define AO_CC1200_SPI stm_spi1 -#define AO_CC1200_SPI_SPEED AO_SPI_SPEED_FAST #define AO_CC1200_INT_PORT (&stm_gpioe) #define AO_CC1200_INT_PIN (12) diff --git a/src/telefireone-v1.0/ao_pins.h b/src/telefireone-v1.0/ao_pins.h index cd8eb658..9d43c2c2 100644 --- a/src/telefireone-v1.0/ao_pins.h +++ b/src/telefireone-v1.0/ao_pins.h @@ -123,7 +123,6 @@ #define AO_CC1200_SPI_CS_PIN 7 #define AO_CC1200_SPI_BUS AO_SPI_2_PB13_PB14_PB15 #define AO_CC1200_SPI stm_spi2 -#define AO_CC1200_SPI_SPEED AO_SPI_SPEED_FAST #define AO_CC1200_INT_PORT (&stm_gpiob) #define AO_CC1200_INT_PIN (11) diff --git a/src/telefireone-v2.0/ao_pins.h b/src/telefireone-v2.0/ao_pins.h index 8025ace6..3b76cccf 100644 --- a/src/telefireone-v2.0/ao_pins.h +++ b/src/telefireone-v2.0/ao_pins.h @@ -145,7 +145,6 @@ #define AO_CC1200_SPI_CS_PIN 3 #define AO_CC1200_SPI_BUS AO_SPI_2_PB13_PB14_PB15 #define AO_CC1200_SPI stm_spi2 -#define AO_CC1200_SPI_SPEED AO_SPI_SPEED_FAST #define AO_CC1200_INT_PORT (&stm_gpiob) #define AO_CC1200_INT_PIN (11) diff --git a/src/telefiretwo-v0.1/ao_pins.h b/src/telefiretwo-v0.1/ao_pins.h index dedd0fad..a3bc0a85 100644 --- a/src/telefiretwo-v0.1/ao_pins.h +++ b/src/telefiretwo-v0.1/ao_pins.h @@ -110,7 +110,6 @@ #define AO_CC1200_SPI_CS_PIN 7 #define AO_CC1200_SPI_BUS AO_SPI_2_PB13_PB14_PB15 #define AO_CC1200_SPI stm_spi2 -#define AO_CC1200_SPI_SPEED AO_SPI_SPEED_FAST #define AO_CC1200_INT_PORT (&stm_gpiob) #define AO_CC1200_INT_PIN (11) diff --git a/src/telefiretwo-v0.2/ao_pins.h b/src/telefiretwo-v0.2/ao_pins.h index 01faace2..e04c4fd7 100644 --- a/src/telefiretwo-v0.2/ao_pins.h +++ b/src/telefiretwo-v0.2/ao_pins.h @@ -111,7 +111,6 @@ #define AO_CC1200_SPI_CS_PIN 7 #define AO_CC1200_SPI_BUS AO_SPI_2_PB13_PB14_PB15 #define AO_CC1200_SPI stm_spi2 -#define AO_CC1200_SPI_SPEED AO_SPI_SPEED_FAST #define AO_CC1200_INT_PORT (&stm_gpiob) #define AO_CC1200_INT_PIN (11) diff --git a/src/telegps-v0.1/ao_pins.h b/src/telegps-v0.1/ao_pins.h index 5afc9498..ff04a044 100644 --- a/src/telegps-v0.1/ao_pins.h +++ b/src/telegps-v0.1/ao_pins.h @@ -19,7 +19,6 @@ #ifndef _AO_PINS_H_ #define _AO_PINS_H_ -#define HAS_TASK_QUEUE 1 /* 8MHz High speed external crystal */ #define AO_HSE 8000000 @@ -148,7 +147,6 @@ #define AO_CC115L_SPI_CS_PIN 12 #define AO_CC115L_SPI_BUS AO_SPI_2_PB13_PB14_PB15 #define AO_CC115L_SPI stm_spi2 -#define AO_CC115L_SPI_SPEED AO_SPI_SPEED_4MHz #define AO_CC115L_FIFO_INT_GPIO_IOCFG CC115L_IOCFG2 #define AO_CC115L_FIFO_INT_PORT (&stm_gpioa) diff --git a/src/telegps-v0.3/ao_pins.h b/src/telegps-v0.3/ao_pins.h index 873474bb..e22331d1 100644 --- a/src/telegps-v0.3/ao_pins.h +++ b/src/telegps-v0.3/ao_pins.h @@ -96,7 +96,6 @@ #define AO_CC115L_SPI_CS_PORT 0 #define AO_CC115L_SPI_CS_PIN 3 #define AO_CC115L_SPI_BUS 0 -#define AO_CC115L_SPI_SPEED AO_SPI_SPEED_6MHz #define AO_CC115L_FIFO_INT_GPIO_IOCFG CC115L_IOCFG2 #define AO_CC115L_FIFO_INT_PORT 0 diff --git a/src/telegps-v1.0/ao_pins.h b/src/telegps-v1.0/ao_pins.h index f3bdc0ac..fbc76739 100644 --- a/src/telegps-v1.0/ao_pins.h +++ b/src/telegps-v1.0/ao_pins.h @@ -98,7 +98,6 @@ #define AO_CC115L_SPI_CS_PORT 0 #define AO_CC115L_SPI_CS_PIN 3 #define AO_CC115L_SPI_BUS 0 -#define AO_CC115L_SPI_SPEED AO_SPI_SPEED_6MHz #define AO_CC115L_FIFO_INT_GPIO_IOCFG CC115L_IOCFG2 #define AO_CC115L_FIFO_INT_PORT 0 diff --git a/src/telegps-v2.0/ao_pins.h b/src/telegps-v2.0/ao_pins.h index a2e812fa..5c6aee0e 100644 --- a/src/telegps-v2.0/ao_pins.h +++ b/src/telegps-v2.0/ao_pins.h @@ -158,7 +158,6 @@ struct ao_adc { #define AO_CC1200_SPI_CS_PIN 1 #define AO_CC1200_SPI_BUS AO_SPI_1_PA5_PA6_PA7 #define AO_CC1200_SPI stm_spi1 -#define AO_CC1200_SPI_SPEED AO_SPI_SPEED_6MHz #define AO_CC1200_INT_PORT (&stm_gpioa) #define AO_CC1200_INT_PIN 4 diff --git a/src/telelco-v0.2-cc1200/ao_pins.h b/src/telelco-v0.2-cc1200/ao_pins.h index f3850ebd..b434e7cb 100644 --- a/src/telelco-v0.2-cc1200/ao_pins.h +++ b/src/telelco-v0.2-cc1200/ao_pins.h @@ -95,7 +95,6 @@ #define AO_CC1200_SPI_CS_PIN 0 #define AO_CC1200_SPI_BUS AO_SPI_2_PD1_PD3_PD4 #define AO_CC1200_SPI stm_spi2 -#define AO_CC1200_SPI_SPEED AO_SPI_SPEED_FAST #define AO_CC1200_INT_PORT (&stm_gpioc) #define AO_CC1200_INT_PIN (15) diff --git a/src/telelco-v0.3/ao_pins.h b/src/telelco-v0.3/ao_pins.h index c806268f..de89d746 100644 --- a/src/telelco-v0.3/ao_pins.h +++ b/src/telelco-v0.3/ao_pins.h @@ -95,7 +95,6 @@ #define AO_CC1200_SPI_CS_PIN 0 #define AO_CC1200_SPI_BUS AO_SPI_2_PD1_PD3_PD4 #define AO_CC1200_SPI stm_spi2 -#define AO_CC1200_SPI_SPEED AO_SPI_SPEED_FAST #define AO_CC1200_INT_PORT (&stm_gpioc) #define AO_CC1200_INT_PIN (15) diff --git a/src/telelco-v2.0/ao_pins.h b/src/telelco-v2.0/ao_pins.h index e0663314..bfbda423 100644 --- a/src/telelco-v2.0/ao_pins.h +++ b/src/telelco-v2.0/ao_pins.h @@ -93,7 +93,6 @@ #define AO_CC1200_SPI_CS_PIN 0 #define AO_CC1200_SPI_BUS AO_SPI_2_PD1_PD3_PD4 #define AO_CC1200_SPI stm_spi2 -#define AO_CC1200_SPI_SPEED AO_SPI_SPEED_FAST #define AO_CC1200_INT_PORT (&stm_gpiod) #define AO_CC1200_INT_PIN (5) diff --git a/src/telelcotwo-v0.1/ao_pins.h b/src/telelcotwo-v0.1/ao_pins.h index 3ef88c74..cf93976e 100644 --- a/src/telelcotwo-v0.1/ao_pins.h +++ b/src/telelcotwo-v0.1/ao_pins.h @@ -94,7 +94,6 @@ #define AO_CC1200_SPI_CS_PIN 7 #define AO_CC1200_SPI_BUS AO_SPI_2_PB13_PB14_PB15 #define AO_CC1200_SPI stm_spi2 -#define AO_CC1200_SPI_SPEED AO_SPI_SPEED_FAST #define AO_CC1200_INT_PORT (&stm_gpiob) #define AO_CC1200_INT_PIN (11) diff --git a/src/telemega-v0.1/ao_pins.h b/src/telemega-v0.1/ao_pins.h index 0208fafa..ea450354 100644 --- a/src/telemega-v0.1/ao_pins.h +++ b/src/telemega-v0.1/ao_pins.h @@ -19,7 +19,6 @@ #ifndef _AO_PINS_H_ #define _AO_PINS_H_ -#define HAS_TASK_QUEUE 1 /* 8MHz High speed external crystal */ #define AO_HSE 8000000 diff --git a/src/telemega-v1.0/ao_pins.h b/src/telemega-v1.0/ao_pins.h index a154225e..fa953460 100644 --- a/src/telemega-v1.0/ao_pins.h +++ b/src/telemega-v1.0/ao_pins.h @@ -19,7 +19,6 @@ #ifndef _AO_PINS_H_ #define _AO_PINS_H_ -#define HAS_TASK_QUEUE 1 /* 8MHz High speed external crystal */ #define AO_HSE 8000000 diff --git a/src/telemega-v2.0/ao_pins.h b/src/telemega-v2.0/ao_pins.h index ba302c74..4f3b73f7 100644 --- a/src/telemega-v2.0/ao_pins.h +++ b/src/telemega-v2.0/ao_pins.h @@ -19,7 +19,6 @@ #ifndef _AO_PINS_H_ #define _AO_PINS_H_ -#define HAS_TASK_QUEUE 1 /* 8MHz High speed external crystal */ #define AO_HSE 8000000 @@ -311,7 +310,6 @@ struct ao_adc { #define AO_CC1200_SPI_CS_PIN 5 #define AO_CC1200_SPI_BUS AO_SPI_2_PB13_PB14_PB15 #define AO_CC1200_SPI stm_spi2 -#define AO_CC1200_SPI_SPEED AO_SPI_SPEED_FAST #define AO_CC1200_INT_PORT (&stm_gpioe) #define AO_CC1200_INT_PIN 1 diff --git a/src/telemega-v3.0/ao_pins.h b/src/telemega-v3.0/ao_pins.h index ce223907..29b5cc1d 100644 --- a/src/telemega-v3.0/ao_pins.h +++ b/src/telemega-v3.0/ao_pins.h @@ -19,7 +19,6 @@ #ifndef _AO_PINS_H_ #define _AO_PINS_H_ -#define HAS_TASK_QUEUE 1 /* 8MHz High speed external crystal */ #define AO_HSE 8000000 @@ -311,7 +310,6 @@ struct ao_adc { #define AO_CC1200_SPI_CS_PIN 5 #define AO_CC1200_SPI_BUS AO_SPI_2_PB13_PB14_PB15 #define AO_CC1200_SPI stm_spi2 -#define AO_CC1200_SPI_SPEED AO_SPI_SPEED_FAST #define AO_CC1200_INT_PORT (&stm_gpioe) #define AO_CC1200_INT_PIN 1 diff --git a/src/telemega-v4.0/ao_pins.h b/src/telemega-v4.0/ao_pins.h index 84af615c..fdf29071 100644 --- a/src/telemega-v4.0/ao_pins.h +++ b/src/telemega-v4.0/ao_pins.h @@ -19,7 +19,6 @@ #ifndef _AO_PINS_H_ #define _AO_PINS_H_ -#define HAS_TASK_QUEUE 1 /* 8MHz High speed external crystal */ #define AO_HSE 8000000 @@ -306,7 +305,6 @@ struct ao_adc { #define AO_CC1200_SPI_CS_PIN 5 #define AO_CC1200_SPI_BUS AO_SPI_2_PB13_PB14_PB15 #define AO_CC1200_SPI stm_spi2 -#define AO_CC1200_SPI_SPEED AO_SPI_SPEED_FAST #define AO_CC1200_INT_PORT (&stm_gpioe) #define AO_CC1200_INT_PIN 1 @@ -351,7 +349,6 @@ struct ao_adc { #define AO_ADXL375_SPI_INDEX (AO_SPI_1_PB3_PB4_PB5 | AO_SPI_MODE_3) #define AO_ADXL375_CS_PORT (&stm_gpiod) #define AO_ADXL375_CS_PIN 4 -#define AO_ADXL375_SPI_SPEED AO_SPI_SPEED_4MHz #define AO_ADXL375_AXIS x #define AO_ADXL375_INVERT 1 diff --git a/src/telemetrum-v2.0/ao_pins.h b/src/telemetrum-v2.0/ao_pins.h index e8c97ff4..aa49483e 100644 --- a/src/telemetrum-v2.0/ao_pins.h +++ b/src/telemetrum-v2.0/ao_pins.h @@ -19,7 +19,6 @@ #ifndef _AO_PINS_H_ #define _AO_PINS_H_ -#define HAS_TASK_QUEUE 1 /* 8MHz High speed external crystal */ #define AO_HSE 8000000 diff --git a/src/telemetrum-v3.0/ao_pins.h b/src/telemetrum-v3.0/ao_pins.h index 68bec1be..a1d4aa28 100644 --- a/src/telemetrum-v3.0/ao_pins.h +++ b/src/telemetrum-v3.0/ao_pins.h @@ -19,7 +19,6 @@ #ifndef _AO_PINS_H_ #define _AO_PINS_H_ -#define HAS_TASK_QUEUE 1 /* 8MHz High speed external crystal */ #define AO_HSE 8000000 @@ -260,7 +259,6 @@ struct ao_adc { #define AO_CC1200_SPI_CS_PIN 2 #define AO_CC1200_SPI_BUS AO_SPI_2_PB13_PB14_PB15 #define AO_CC1200_SPI stm_spi2 -#define AO_CC1200_SPI_SPEED AO_SPI_SPEED_FAST #define AO_CC1200_INT_PORT (&stm_gpioa) #define AO_CC1200_INT_PIN (3) @@ -283,7 +281,6 @@ struct ao_adc { #define AO_ADXL375_SPI_INDEX (AO_SPI_1_PB3_PB4_PB5 | AO_SPI_MODE_3) #define AO_ADXL375_CS_PORT (&stm_gpiob) #define AO_ADXL375_CS_PIN 9 -#define AO_ADXL375_SPI_SPEED AO_SPI_SPEED_4MHz #define AO_ADXL375_AXIS x #define AO_ADXL375_INVERT 1 diff --git a/src/telemini-v3.0/ao_pins.h b/src/telemini-v3.0/ao_pins.h index ae8534b9..a734ff0a 100644 --- a/src/telemini-v3.0/ao_pins.h +++ b/src/telemini-v3.0/ao_pins.h @@ -106,7 +106,6 @@ #define AO_MS5607_MISO_PIN 4 #define AO_MS5607_MISO_MASK (1 << AO_MS5607_MISO_PIN) #define AO_MS5607_SPI_INDEX AO_SPI_1_PB3_PB4_PB5 -#define AO_MS5607_SPI_SPEED AO_SPI_SPEED_12MHz /* CC1200 */ @@ -119,7 +118,6 @@ #define AO_CC1200_SPI_CS_PIN 0 #define AO_CC1200_SPI_BUS AO_SPI_1_PA5_PA6_PA7 #define AO_CC1200_SPI stm_spi1 -#define AO_CC1200_SPI_SPEED AO_SPI_SPEED_12MHz #define AO_CC1200_INT_PORT (&stm_gpiob) #define AO_CC1200_INT_PIN 1 diff --git a/src/telestatic-v3.0/ao_pins.h b/src/telestatic-v3.0/ao_pins.h index aad17664..866206ce 100644 --- a/src/telestatic-v3.0/ao_pins.h +++ b/src/telestatic-v3.0/ao_pins.h @@ -143,7 +143,6 @@ #define AO_CC1200_SPI_CS_PIN 3 #define AO_CC1200_SPI_BUS AO_SPI_2_PB13_PB14_PB15 #define AO_CC1200_SPI stm_spi2 -#define AO_CC1200_SPI_SPEED AO_SPI_SPEED_FAST #define AO_CC1200_INT_PORT (&stm_gpiob) #define AO_CC1200_INT_PIN (11) diff --git a/src/test/ao_micropeak_test.c b/src/test/ao_micropeak_test.c index 059c2284..952460d0 100644 --- a/src/test/ao_micropeak_test.c +++ b/src/test/ao_micropeak_test.c @@ -46,10 +46,10 @@ static void ao_led_on(uint8_t led) { static void ao_led_off(uint8_t led) { } -static void ao_delay_until(uint16_t target) { +static void ao_delay_until(AO_TICK_TYPE target) { } -static uint16_t ao_time(void) { +static AO_TICK_TYPE ao_time(void) { return 0; } @@ -57,7 +57,7 @@ static uint16_t ao_time(void) { #include "ao_microkalman.c" #include "ao_convert_pa.c" -uint16_t now; +AO_TICK_TYPE now; uint8_t running; void ao_log_micro_data() { diff --git a/src/tmgps-v2.0/ao_pins.h b/src/tmgps-v2.0/ao_pins.h index b4dcc10c..dd030eee 100644 --- a/src/tmgps-v2.0/ao_pins.h +++ b/src/tmgps-v2.0/ao_pins.h @@ -19,7 +19,6 @@ #ifndef _AO_PINS_H_ #define _AO_PINS_H_ -#define HAS_TASK_QUEUE 1 /* 8MHz High speed external crystal */ #define AO_HSE 8000000 diff --git a/src/vidtime/ao_pins.h b/src/vidtime/ao_pins.h index fe9d3879..649d52a7 100644 --- a/src/vidtime/ao_pins.h +++ b/src/vidtime/ao_pins.h @@ -18,7 +18,6 @@ #ifndef _AO_PINS_H_ #define _AO_PINS_H_ -#define HAS_TASK_QUEUE 1 #define IS_FLASH_LOADER 0 diff --git a/telegps/Makefile.am b/telegps/Makefile.am index 0e75abf1..26e5dfb8 100644 --- a/telegps/Makefile.am +++ b/telegps/Makefile.am @@ -153,7 +153,7 @@ LINUX_EXTRA=telegps-fat $(desktop_file).in MACOSX_INFO_PLIST=Info.plist MACOSX_README=ReadMe-Mac.rtf -MACOSX_INSTALL=../altosui/install-macosx +MACOSX_INSTALL=../altosui/install-macosx ../altosui/ask-pass MACOSX_FILES=$(FAT_FILES) libaltos.dylib $(MACOSX_INFO_PLIST) $(MACOSX_README) $(DOC) $(MACOSX_ICONS) $(MACOSX_INSTALL) MACOSX_EXTRA=$(FIRMWARE) diff --git a/telegps/TeleGPS.app/Contents/MacOS/JavaApplicationStub b/telegps/TeleGPS.app/Contents/MacOS/JavaApplicationStub index 16966918..145a260b 100755 --- a/telegps/TeleGPS.app/Contents/MacOS/JavaApplicationStub +++ b/telegps/TeleGPS.app/Contents/MacOS/JavaApplicationStub @@ -1,4 +1,16 @@ #!/bin/bash +# +# Fix fonts. I don't know why the getting the +# basename of the app set to . matters, but it does +# +case "$0" in + /*) + cd `dirname "$0"` + ./`basename "$0"` "$@" + exit $? + ;; +esac +export FREETYPE_PROPERTIES=truetype:interpreter-version=35 ################################################################################## # # # universalJavaApplicationStub # diff --git a/telegps/TeleGPSConfigUI.java b/telegps/TeleGPSConfigUI.java index 7c5d186e..465916ec 100644 --- a/telegps/TeleGPSConfigUI.java +++ b/telegps/TeleGPSConfigUI.java @@ -211,7 +211,7 @@ public class TeleGPSConfigUI Insets il = new Insets(4,4,4,4); Insets ir = new Insets(4,4,4,4); - pane = getContentPane(); + pane = getScrollablePane(); pane.setLayout(new GridBagLayout()); /* Product */